merlin.builder.circuit_builder module

Circuit builder for constructing quantum circuits declaratively.

class merlin.builder.circuit_builder.Any(*args, **kwargs)

Bases: object

Special type indicating an unconstrained type.

  • Any is compatible with every type.

  • Any assumed to have all methods.

  • All values assumed to be instances of Any.

Note that all the above statements are true from the point of view of static type checkers. At runtime, Any should not be used with instance checks.

class merlin.builder.circuit_builder.BeamSplitter(targets, theta_role=ParameterRole.FIXED, theta_value=0.7854, phi_role=ParameterRole.FIXED, phi_value=0.0, theta_name=None, phi_name=None)

Bases: object

Beam splitter description.

get_params()

Describe which phase shifter angles should be exposed as parameters.

Return type:

dict[str, Any]

Returns:

Dict[str, Any]: Parameter placeholders keyed by their symbolic names.

phi_name: Optional[str] = None
phi_role: ParameterRole = 'fixed'
phi_value: float = 0.0
targets: tuple
theta_name: Optional[str] = None
theta_role: ParameterRole = 'fixed'
theta_value: float = 0.7854
class merlin.builder.circuit_builder.Circuit(n_modes, components=<factory>, metadata=<factory>)

Bases: object

Simple circuit container.

add(component)

Append a component and return the circuit for chained calls.

Return type:

Circuit

Args:

component: Circuit element (rotation, beam splitter, measurement, etc.).

Returns:

Circuit: self to support fluent-style chaining.

clear()

Remove every component and metadata entry from the circuit.

components: list[Any]
property depth: int

Estimate logical depth by summing component depths when available.

get_parameters()

Collect parameter placeholders exposed by each component.

Return type:

dict[str, Any]

Returns:

Dict[str, Any]: Mapping from parameter name to default value (or None).

metadata: dict[str, Any]
n_modes: int
property num_components: int

Return the count of registered components.

class merlin.builder.circuit_builder.CircuitBuilder(n_modes)

Bases: object

Builder for quantum circuits using a declarative API.

add_angle_encoding(modes=None, name=None, *, scale=1.0, subset_combinations=False, max_order=None)

Convenience method for angle-based input encoding.

Return type:

CircuitBuilder

Args:

modes: Optional list of circuit modes to target. Defaults to all modes. name: Prefix used for generated input parameters. Defaults to "px". scale: Global scaling factor applied before angle mapping. subset_combinations: When True, generate higher-order feature

combinations (up to max_order) similar to the legacy FeatureEncoder.

max_order: Optional cap on the size of feature combinations when

subset_combinations is enabled. None uses all orders.

Returns:

CircuitBuilder: self for fluent chaining.

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.

Return type:

CircuitBuilder

Args:
modes: 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: Whether internal phase shifters should be trainable. model: "mzi" or "bell" to select the internal interferometer template. name: Optional prefix used for generated parameter names. trainable_inner: Override for the internal (between-beam splitter) phase shifters. trainable_outer: Override for the output phase shifters at the exit of the interferometer.

Raises:

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

Returns:

CircuitBuilder: self for fluent chaining.

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.

Return type:

CircuitBuilder

Args:

modes: Single mode, list of modes, module group or None (all modes). axis: Axis of rotation for each inserted phase shifter. trainable: Promote the rotations to trainable parameters (legacy flag). as_input: Mark the rotations as input-driven parameters (legacy flag). angle: Optional fixed value for the rotations (alias of value). value: Optional fixed value for the rotations (alias of angle). name: Optional stem used for generated parameter names. role: Explicit ParameterRole taking precedence over other flags.

Returns:

CircuitBuilder: self for fluent chaining.

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.

Return type:

CircuitBuilder

Args:
targets: Tuple or list of tuples describing explicit mode pairs. When

omitted, nearest neighbours over modes (or all modes) are used.

depth: Number of sequential passes to apply (>=1). theta: Baseline mixing angle for fixed beam splitters. phi: Baseline relative phase for fixed beam splitters. trainable: Convenience flag to mark both theta and phi trainable. trainable_theta: Whether the mixing angle should be trainable. trainable_phi: Whether the relative phase should be trainable. modes: Optional mode list/module group used when targets is omitted. name: Optional stem used for generated parameter names.

Returns:

CircuitBuilder: self for fluent chaining.

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

Return metadata describing configured angle encodings.

Returns:

Dict[str, Dict[str, Any]]: Mapping from encoding prefix to combination metadata.

build()

Build and return the circuit.

Return type:

Circuit

Returns:

Circuit: Circuit instance populated with components.

classmethod from_circuit(circuit)

Create a builder from an existing circuit.

Return type:

CircuitBuilder

Args:

circuit: Circuit object whose components should seed the builder.

Returns:

CircuitBuilder: A new builder instance wrapping the provided circuit.

property input_parameter_prefixes: list[str]

Expose the order-preserving set of input prefixes.

Returns:

List[str]: Input parameter stems emitted during encoding.

to_pcvl_circuit(pcvl_module=None)

Convert the constructed circuit into a Perceval circuit.

Args:

pcvl_module: Optional Perceval module. If None, attempts to import perceval.

Returns:

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

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:

List[str]: Trainable parameter stems discovered so far.

class merlin.builder.circuit_builder.EntanglingBlock(targets='all', pattern='nearest_neighbor', depth=1, trainable=True, name_prefix=None)

Bases: object

Entangling block description.

depth: int = 1
get_params()

Entangling blocks themselves carry no direct parameters.

Return type:

dict[str, Any]

Returns:

Dict[str, Any]: Always empty because entangling blocks are metadata-only.

name_prefix: Optional[str] = None
pattern: str = 'nearest_neighbor'
targets: str | list[int] = 'all'
trainable: bool = True
class merlin.builder.circuit_builder.GenericInterferometer(start_mode, span, trainable=True, name_prefix=None, model='mzi', trainable_inner=None, trainable_outer=None)

Bases: object

Generic interferometer block spanning multiple modes.

get_params()

Return placeholder names for every internal interferometer parameter.

Return type:

dict[str, Any]

Returns:

Dict[str, Any]: Mapping of generated parameter names to None placeholders.

model: str = 'mzi'
name_prefix: Optional[str] = None
span: int
start_mode: int
trainable: bool = True
trainable_inner: Optional[bool] = None
trainable_outer: Optional[bool] = None
class merlin.builder.circuit_builder.ModuleGroup(modes)

Bases: object

Helper class for grouping modules.

enum merlin.builder.circuit_builder.ParameterRole(value)

Bases: Enum

Clear role definition for parameters.

Valid values are as follows:

FIXED = <ParameterRole.FIXED: 'fixed'>
INPUT = <ParameterRole.INPUT: 'input'>
TRAINABLE = <ParameterRole.TRAINABLE: 'trainable'>
class merlin.builder.circuit_builder.Rotation(target, role=ParameterRole.FIXED, value=0.0, axis='z', custom_name=None)

Bases: object

Rotation gate description.

The actual parameter name will be generated by the backend based on role.

axis: str = 'z'
custom_name: Optional[str] = None
get_params()

Return declared parameter placeholders for the rotation.

Non-fixed rotations expose either their custom name or the automatically generated identifier so that downstream tooling can bind data or trainable tensors to the gate.

Return type:

dict[str, Any]

Returns:

Dict[str, Any]: Mapping from parameter name to placeholder value.

role: ParameterRole = 'fixed'
target: int
value: float = 0.0
class merlin.builder.circuit_builder.combinations(iterable, r)

Bases: object

Return successive r-length combinations of elements in the iterable.

combinations(range(4), 3) –> (0,1,2), (0,1,3), (0,2,3), (1,2,3)

The different components of the builder with their arguments and example of code

Below are the components available in the CircuitBuilder class:

  1. 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.

A Rotation component built with CircuitBuilder A Rotation layer built with CircuitBuilder
  1. 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.

This will show as a rotation layer as data is encoded in phase shifters.

  1. add_entangling_layer: - Adds an entangling layer spanning a range of modes (implemented with 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.

An entangling layer built with CircuitBuilder

And to span it on different modes .. code-block:: python

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:

An entangling layer built with CircuitBuilder
  1. add_superpositions: - 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.

A Superposition component (beam splitter) A Entangling layer of depth 2
  1. build:
    • Finalizes and returns the constructed circuit.