merlin.builder.circuit_builder module

Circuit builder for constructing quantum circuits declaratively.

class merlin.builder.circuit_builder.ModuleGroup(modes)

Bases: object

Helper class for a group of circuit modes.

Parameters:

modes (list[int]) – Modes spanned by the grouped module.

class merlin.builder.circuit_builder.CircuitBuilder(n_modes)

Bases: object

Builder 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 to max_order.

  • max_order (int | None) – Optional cap on the size of feature combinations when subset_combinations is enabled. None uses all orders.

Returns:

self for fluent chaining.

Return type:

CircuitBuilder

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. None targets all modes; one element targets modes[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:

self for fluent chaining.

Return type:

CircuitBuilder

Raises:

ValueError – If the provided modes are invalid or span fewer than two modes.

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 None to 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 ParameterRole taking precedence over other flags.

Returns:

self for fluent chaining.

Return type:

CircuitBuilder

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 modes or 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 theta and phi trainable.

  • 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 targets is omitted.

  • name (str | None) – Optional stem used for generated parameter names.

Returns:

self for fluent chaining.

Return type:

CircuitBuilder

property angle_encoding_specs: dict[str, dict[str, Any]]

Return metadata describing configured angle encodings.

Returns:

Mapping from encoding prefix to combination metadata.

Return type:

dict[str, dict[str, Any]]

build()

Build and return the circuit.

Returns:

Circuit instance populated with components.

Return type:

merlin.core.circuit.Circuit

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:

CircuitBuilder

property input_parameter_prefixes: list[str]

Expose the order-preserving set of input prefixes.

Returns:

Input parameter stems emitted during encoding.

Return type:

list[str]

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 import perceval.

Returns:

A pcvl.Circuit instance mirroring the components tracked by this builder.

Return type:

Any

Raises:

ImportError – If perceval is not installed and no module is provided.

property trainable_parameter_prefixes: list[str]

Expose the unique set of trainable prefixes in insertion order.

Returns:

Trainable parameter stems discovered so far.

Return type:

list[str]

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)
A Rotation component built with CircuitBuilder
builder = CircuitBuilder(n_modes=6)
builder.add_rotations(trainable=True, name="rotation")
A Rotation layer built with CircuitBuilder

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")
An entangling layer built with CircuitBuilder

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")
An entangling layer built with CircuitBuilder

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 across modes (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] or ModuleGroup): Mode span used when targets is 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")
A Superposition component (beam splitter)
builder = CircuitBuilder(n_modes=6)
builder.add_superpositions(depth=2, name="mix")
An entangling layer of depth 2

Build

Finalizes and returns the constructed circuit.