merlin.builder.circuit_builder module
Circuit builder for constructing quantum circuits declaratively.
- class merlin.builder.circuit_builder.ModuleGroup(modes)
Bases:
objectHelper class for a group of circuit modes.
- class merlin.builder.circuit_builder.CircuitBuilder(n_modes)
Bases:
objectBuilder for quantum circuits using a declarative API.
- Parameters:
n_modes (int) – Number of photonic modes available in the circuit.
- add_angle_encoding(modes=None, name=None, *, scale=1.0, subset_combinations=False, max_order=None)
Convenience method for angle-based input encoding.
- Parameters:
modes (list[int] | None) – Optional list of circuit modes to target. Defaults to all modes.
name (str | None) – Prefix used for generated input parameters. Defaults to
"px".scale (float) – Global scaling factor applied before angle mapping.
subset_combinations (bool) – When
True, generate higher-order feature combinations up tomax_order.max_order (int | None) – Optional cap on the size of feature combinations when
subset_combinationsis enabled.Noneuses all orders.
- Returns:
selffor fluent chaining.- Return type:
- add_entangling_layer(modes=None, *, trainable=True, model='mzi', name=None, trainable_inner=None, trainable_outer=None)
Add an entangling layer spanning a range of modes.
- Parameters:
modes (list[int] | None) – Optional list describing the span.
Nonetargets all modes; one element targetsmodes[0]through the final mode; two elements target the inclusive range[modes[0], modes[1]].trainable (bool) – Whether internal phase shifters should be trainable.
model (str) –
"mzi"or"bell"to select the internal interferometer template.name (str | None) – Optional prefix used for generated parameter names.
trainable_inner (bool | None) – Override for the internal phase shifters.
trainable_outer (bool | None) – Override for the output phase shifters.
- Returns:
selffor fluent chaining.- Return type:
- Raises:
ValueError – If the provided modes are invalid or span fewer than two modes.
- add_memristive_ps(mode, update_rule, initial_state, name=None, detach_at_each_forward=True)
Add a memristive phase shifter that will update in regards to the update rule after each forward pass.
- Parameters:
mode (int) – Circuit mode to target.
update_rule (Callable) – Callable with signature
update_rule(state: torch.Tensor, output: torch.Tensor | StateVector | ProbabilityDistribution | PartialMeasurement) -> torch.Tensor. The update rule receives the current memristive state and the layer output, and must return a new state tensor of shape[batch_size].initial_state (float) – The initial value of the phase shifter. This will be the value used after each
reset()call.name (str | None) – Prefix used for the generated memristive phase shifter parameter. Defaults to
"mem".detach_at_each_forward (bool) –
Controls gradient flow through the memristive recurrence (state → new_state):
True(default): The new state is detached at each forward, preventing gradients from flowing through the recurrence chain. Earlier inputs receive zero gradients from the memristive state.False: The new state retains gradients, allowing full gradient flow through the entire recurrence history. All inputs can receive gradients through the accumulated state chain.
- Returns:
selffor fluent chaining.- Return type:
- add_rotations(modes=None, *, axis='z', trainable=False, as_input=False, angle=None, value=None, name=None, role=None)
Add one or multiple rotations across the provided modes.
- Parameters:
modes (int | list[int] | ModuleGroup | None) – Single mode, list of modes, module group, or
Noneto target all modes.axis (str) – Axis of rotation for each inserted phase shifter.
trainable (bool) – Promote the rotations to trainable parameters.
as_input (bool) – Mark the rotations as input-driven parameters.
angle (float | None) – Optional fixed value for the rotations. Alias of
value.value (float | None) – Optional fixed value for the rotations. Alias of
angle.name (str | None) – Optional stem used for generated parameter names.
role (str | ParameterRole | None) – Explicit
ParameterRoletaking precedence over other flags.
- Returns:
selffor fluent chaining.- Return type:
- add_superpositions(targets=None, *, depth=1, theta=0.785398, phi=0.0, trainable=None, trainable_theta=None, trainable_phi=None, modes=None, name=None)
Add one or more superposition (beam splitter) components.
- Parameters:
targets (tuple[int, int] | list[tuple[int, int]] | None) – Explicit mode pairs. When omitted, nearest neighbours over
modesor all modes are used.depth (int) – Number of sequential passes to apply.
theta (float) – Baseline mixing angle for fixed beam splitters.
phi (float) – Baseline relative phase for fixed beam splitters.
trainable (bool | None) – Convenience flag to mark both
thetaandphitrainable.trainable_theta (bool | None) – Whether the mixing angle should be trainable.
trainable_phi (bool | None) – Whether the relative phase should be trainable.
modes (list[int] | ModuleGroup | None) – Optional mode list or module group used when
targetsis omitted.name (str | None) – Optional stem used for generated parameter names.
- Returns:
selffor fluent chaining.- Return type:
- property angle_encoding_specs: dict[str, dict[str, Any]]
Return metadata describing configured angle encodings.
- build()
Build and return the circuit.
- Returns:
Circuit instance populated with components.
- Return type:
- classmethod from_circuit(circuit)
Create a builder from an existing circuit.
- Parameters:
circuit (merlin.core.circuit.Circuit) – Circuit object whose components should seed the builder.
- Returns:
A new builder instance wrapping the provided circuit.
- Return type:
- to_pcvl_circuit(pcvl_module=None)
Convert the constructed circuit into a Perceval circuit.
- Parameters:
pcvl_module (Any) – Optional Perceval module. If
None, attempts to importperceval.- Returns:
A
pcvl.Circuitinstance mirroring the components tracked by this builder.- Return type:
Any
- Raises:
ImportError – If
percevalis not installed and no module is provided.
The different components of the builder with their arguments and example of code
Below are the components available in the CircuitBuilder class.
add_rotations
Adds one or multiple phase shifters across the specified modes.
Arguments:
modes(int | list[int] | ModuleGroup | None): Modes receiving the rotations. Defaults to all modes.axis(str): Axis of rotation. Default:"z".angle(float): Fixed rotation angle for non-trainable cases.trainable(bool): Promote the rotations to trainable parameters.name(str): Optional stem used for generated parameter names.role(ParameterRole): Explicitly set the parameter role.
builder = CircuitBuilder(n_modes=6)
builder.add_rotations(modes=3, angle=np.pi / 4)
builder = CircuitBuilder(n_modes=6)
builder.add_rotations(trainable=True, name="rotation")
add_angle_encoding
Adds angle-based input encoding to the circuit.
Arguments:
modes(list[int]): Modes to target for encoding.name(str): Prefix for generated input parameters.scale(float): Scaling factor for angle mapping.
builder = CircuitBuilder(n_modes=6)
builder.add_angle_encoding(modes=list(range(6)), name="input", scale=np.pi)
This will show as a rotation layer as data is encoded in phase shifters.
add_entangling_layer
Adds an entangling layer spanning a range of modes using a generic interferometer.
Arguments:
modes(list[int]): Modes to span.trainable(bool): Whether the entangling layer is trainable.model(str): Choose"mzi"(default) or"bell"to select the interferometer template.name(str): Optional prefix for parameter names.trainable_inner(bool | None): Override to control whether the internal phases of the MZIs remain trainable.trainable_outer(bool | None): Override to control the output phases at the end of the interferometer.
builder = CircuitBuilder(n_modes=6)
builder.add_entangling_layer(trainable=True, name="U1")
To span it on different modes:
builder = CircuitBuilder(n_modes=6)
builder.add_entangling_layer(trainable=True, name="U1", modes=[0, 3])
Switching to a Bell-style interferometer is as simple as:
builder.add_entangling_layer(model="bell", name="bell_block")
add_superposition
Adds one or more beam splitters with optional depth.
Arguments:
targets(tuple[int, int] | list[tuple[int, int]]): Explicit mode pairs receiving beam splitters. When omitted, nearest neighbours acrossmodes(or all modes) are used.depth(int): Number of successive passes to apply.theta(float): Mixing angle for fixed beam splitters.phi(float): Relative phase for fixed beam splitters.trainable(bool): Convenience flag marking both parameters trainable.trainable_theta(bool): Whether the mixing angle is trainable.trainable_phi(bool): Whether the relative phase is trainable.modes(list[int]orModuleGroup): Mode span used whentargetsis omitted.name(str): Optional prefix for generated parameter names.
builder = CircuitBuilder(n_modes=6)
builder.add_superpositions(targets=(0, 1), trainable_theta=True, name="bs")
builder = CircuitBuilder(n_modes=6)
builder.add_superpositions(depth=2, name="mix")
add_memristive_ps
Adds a memristive phase-shifter.
Arguments:
mode(int): Circuit mode to target.update_rule(callable): Update rule to change the angle of the phase shifter after each forward pass of associated theQuantumLayerobject. The function must take twopositional arguments: update_rule(state,output). Here is the expected signature: .. code-block:: python
def update_rule(state: torch.Tensor,output: torch.Tensor | StateVector | ProbabilityDistribution | PartialMeasurement)-> torch.Tensor
The update rule must also handle batch inputs and return a tensor of size
[batch_size], just like the state parameter. The output will be the same as the correspondingQuantumLayerforward.
initial_state(float): The initial value of the phase shifter. This will be the value used after eachreset()call.name(str): Prefix used for the generated memristive phase shifter parameter. Defaults to"mem".detach_at_each_forward(bool): Controls gradient flow through memristive state recurrence. WhenTrue(default), new states are detached after computation, blocking gradients through the state chain. WhenFalse, gradients flow through the entire state history. Default value isTrue.
Build
Finalizes and returns the constructed circuit.