merlin.algorithms.feed_forward module
- class merlin.algorithms.feed_forward.ACircuit(m, name=None)
Bases:
AParametrizedComponent,ABCAbstract linear optics circuit class. A circuit is defined by a dimension m, and by parameters. Parameters can be fixed (value) or variables.
- property U
get the symbolic unitary matrix
- compute_unitary(assign=None, use_symbolic=False, use_polarization=None)
Compute the unitary matrix corresponding to the current circuit
- Parameters:
use_polarization (
Optional[bool]) –assign (
dict) – assign values to some parametersuse_symbolic (
bool) – if the matrix should use symbolic calculation
- Return type:
Matrix- Returns:
the unitary matrix, will be a
MatrixSif symbolic, or a ~`MatrixN` if not.
- definition()
- depths()
- abstract describe()
- Return type:
str
- identify(unitary_matrix, phases, precision=None, max_try=10, allow_error=False)
Identify an instance of the current circuit (should be parameterized) such as \(Q.C=U.P\) where \(Q\) and \(P\) are single-mode phase shifts (resp. \([q1, q2, ..., qn]\), and \([p1, p2, ...,pn]\)). This is solved through \(n^2\) equations: \(q_i * C_{i,j}(x,y, ...) = UP_{i,j} * p_j\)
- Parameters:
unitary_matrix – the matrix to identify
phases – phase shift parameters
max_try – the resolution is using parameter search starting on a random points, it might fail, this parameter sets the maximal number of times to try
- Return type:
None
- inverse(v, h)
- match(pattern, pos=None, pattern_pos=None, match=None, actual_pos=0, actual_pattern_pos=0)
- Return type:
Optional[Match]
- ncomponents()
- property requires_polarization
- transfer_from(c, force=False)
transfer parameters from a Circuit to another - should be the same circuit
- class merlin.algorithms.feed_forward.BranchState(amplitudes, weight, remaining_n, measurement_key, basis_keys)
Bases:
object-
basis_keys:
tuple[tuple[int,...],...]
-
measurement_key:
tuple[Optional[int],...]
-
remaining_n:
int
-
basis_keys:
- enum merlin.algorithms.feed_forward.ComputationSpace(value)
Bases:
str,EnumEnumeration of supported computational subspaces.
- Member Type:
str
Valid values are as follows:
- FOCK = <ComputationSpace.FOCK: 'fock'>
- UNBUNCHED = <ComputationSpace.UNBUNCHED: 'unbunched'>
- DUAL_RAIL = <ComputationSpace.DUAL_RAIL: 'dual_rail'>
The
Enumand its members also have the following methods:- classmethod default(*, no_bunching)
Derive the default computation space from the legacy no_bunching flag.
- Return type:
- classmethod coerce(value)
Normalize user-provided values (enum instances or case-insensitive strings).
- Return type:
- class merlin.algorithms.feed_forward.DetectorTransform(simulation_keys, detectors, *, dtype=None, device=None, partial_measurement=False)
Bases:
ModuleLinear map applying per-mode detector rules to a Fock probability vector.
- Args:
- simulation_keys: Iterable describing the raw Fock states produced by the
simulator (as tuples or lists of integers).
- detectors: One detector per optical mode. Each detector must expose the
detect()method fromperceval.Detector.- dtype: Optional torch dtype for the transform matrix. Defaults to
torch.float32.
device: Optional device used to stage the transform matrix. partial_measurement: When
True, only the modes whose detector entry isnot
Noneare measured. The transform then operates on complex amplitudes and returns per-outcome dictionaries (seeforward()).
- forward(tensor)
Apply the detector transform.
- Args:
- tensor: Probability distribution (complete mode) or amplitudes
(partial measurement). The last dimension must match the simulator basis.
- Returns:
Complete mode: real probability tensor expressed in the detector basis.
Partial mode: list indexed by remaining photon count. Each entry is a dictionary whose keys are full-length mode tuples (unmeasured modes set to
None) and whose values are lists of (probability, normalized remaining-mode amplitudes) pairs – one per perfect measurement branch.
- property is_identity: bool
Whether the transform reduces to the identity (ideal PNR detectors).
- property output_keys: list[tuple[int, ...]]
Return the classical detection outcome keys.
- property output_size: int
Number of classical outcomes produced by the detectors.
- property partial_measurement: bool
Return True when the transform runs in partial measurement mode.
- remaining_basis(remaining_n=None)
Return the ordered Fock-state basis for the unmeasured modes.
- Return type:
list[tuple[int,...]]
- Args:
- remaining_n: Optional photon count used to select a specific block.
When omitted, the method returns the concatenation of every remaining-mode basis enumerated during detector initialisation.
- Returns:
List of tuples describing the photon distribution over the unmeasured modes.
- class merlin.algorithms.feed_forward.FFCircuitProvider(m, offset, default_circuit, name=None)
Bases:
AFFConfigurator- DEFAULT_NAME = 'FFC'
For any measurement, FFCircuitProvider will return a circuit or a processor, picked from known mapping of configurations. Each configuration links a measurement to a circuit or processor. If a measurement is received and was not set in the mapping, a mandatory default circuit or processor is returned.
- Parameters:
m – The number of classical modes that are detected (after a detector)
offset – The distance between the configurator and the first mode of the implemented circuits. For positive values, it is the number of empty modes between the configurator and the configured circuit below. For negative values, it is the same but the circuit is located above the configurator (the number of empty modes is abs(offset) - 1, so an offset of -1 means that there is no empty modes between the configurator and the circuit). All circuits are considered to have the size of the biggest possible circuit in this configurator.
default_circuit – The circuit to be used if the measured state does not befall into one of the declared cases
- add_configuration(state, circuit)
- Return type:
- property circuit_map
- circuit_template()
Return a fitting representation of the controlled circuit or processor.
- Return type:
- configure(measured_state)
Gives the circuit or processor that must be configured given the measured state
- Parameters:
measured_state (
FockState) – The state of size self.m that corresponds to the measurements of the modes on which the configurator is located.- Return type:
- Returns:
The processor or circuit that must be set
- reset_map()
- class merlin.algorithms.feed_forward.FFStage(unitary, active_modes, measured_modes, detectors, provider)
Bases:
object-
active_modes:
tuple[int,...]
-
detectors:
dict[int,Optional[Detector]]
-
measured_modes:
tuple[int,...]
-
provider:
Optional[FFCircuitProvider]
-
active_modes:
- class merlin.algorithms.feed_forward.FeedForwardBlock(experiment, *, input_state=None, trainable_parameters=None, input_parameters=None, computation_space=ComputationSpace.FOCK, measurement_strategy=MeasurementStrategy.PROBABILITIES, device=None, dtype=None)
Bases:
ModuleFeed-forward photonic block constructed directly from a Perceval experiment.
The block introspects the provided
pcvl.Experiment, splits it into unitary / detector /FFCircuitProviderstages and turns each segment into one or moreQuantumLayerinstances. At run time the block executes every stage, branching on every partial measurement outcome and accumulating the classical probability for each branch.Parameters
- experiment:
Perceval experiment containing the full feed-forward definition. The current implementation requires noise-free experiments (
NoiseModel()orNone).- input_state:
Initial quantum state. May be provided as a Fock occupation list,
pcvl.BasicState,pcvl.StateVector, or a tensor whose components represent amplitudes in the experiment Fock basis (the tensor is only required for amplitude-encoding inputs).- trainable_parameters:
Optional list of Perceval parameter prefixes that should remain learnable across all stages.
- input_parameters:
Perceval parameter prefixes that receive classical inputs. They are consumed by the first stage only; once the first detection happens all branches switch to amplitude encoding and the classical tensor is ignored.
- computation_space:
Currently restricted to
FOCK.- measurement_strategy:
Controls how classical outputs are produced:
MeasurementStrategy.PROBABILITIES(default) returns a tensor of shape(batch_size, num_output_keys)whose columns match the fully specified Fock states stored in :pyattr:`output_keys`.MeasurementStrategy.MODE_EXPECTATIONScollapses every branch into a single tensor of shape(batch_size, num_modes)that contains the per-mode photon expectations aggregated across all measurement keys. The :pyattr:`output_keys` attribute is retained for metadata while :pyattr:`output_state_sizes` reportsnum_modesfor every key.MeasurementStrategy.AMPLITUDESyields a list of tuples(measurement_key, branch_probability, remaining_photons, amplitudes)so callers can reason about the mixed state left by each branch.
- describe()
Return a multi-line description of the feed-forward stages.
The summary lists, in order, the global modes that remain active at each step, the subset of measured modes, and the type of feed-forward configurator attached to the stage. It is primarily intended for debugging or for logging experiment structure.
- Return type:
str
- forward(x=None)
Execute the feed-forward experiment.
Parameters
- x:
Classical feature tensor. Only the first stage consumes classical inputs; subsequent stages operate purely in amplitude-encoding mode. When the experiment does not expose classical inputs this argument may be omitted (or
None), in which case an empty tensor is automatically supplied.
Returns
- torch.Tensor | list
PROBABILITIESreturns a tensor of shape(batch_size, len(output_keys))aligned with the fully specified Fock states in :pyattr:`output_keys`.MODE_EXPECTATIONSproduces a tensor of shape(batch_size, total_modes)where the columns already encode the per-mode expectations aggregated across all measurement keys (:pyattr:`output_state_sizes` storestotal_modesfor every key).AMPLITUDESyields a list of tuples(measurement_key, branch_probability, remaining_photons, amplitudes)describing every branch of the resulting mixed state.
- property output_keys: list[tuple[int, ...]]
Return the measurement keys associated with the most recent classical forward pass.
The list is populated after
forward()completes. For thePROBABILITIESstrategy the list lines up with the tensor columns. ForMODE_EXPECTATIONSit is retained for reference even though the returned tensor already aggregates all measurement outcomes. Calling the property before running the block raisesRuntimeError.
- property output_state_sizes: dict[tuple[int, ...], int]
Return the number of remaining Fock states represented by each entry in
output_keys.Only available when
measurement_strategyisPROBABILITIESorMODE_EXPECTATIONS. ForPROBABILITIESthe value is always1because each key now denotes a fully specified Fock state, while forMODE_EXPECTATIONSit equals the total number of modes contributing to the expectation vector.
- enum merlin.algorithms.feed_forward.MeasurementStrategy(value)
Bases:
EnumStrategy for measuring quantum states or counts and possibly apply mapping to classical outputs.
Valid values are as follows:
- PROBABILITIES = <MeasurementStrategy.PROBABILITIES: 'probabilities'>
- MODE_EXPECTATIONS = <MeasurementStrategy.MODE_EXPECTATIONS: 'mode_expectations'>
- AMPLITUDES = <MeasurementStrategy.AMPLITUDES: 'amplitudes'>
- class merlin.algorithms.feed_forward.NoiseModel(brightness=None, indistinguishability=None, g2=None, g2_distinguishable=None, transmittance=None, phase_imprecision=None, phase_error=None)
Bases:
objectThe NoiseModel class contains all noise parameters which are supported by Perceval. Default value of each parameter means “no noise”, so a NoiseModel constructed with all default parameters leads to a perfect simulation.
- Parameters:
brightness (
float) – first lens brightness of a quantum dotindistinguishability (
float) – chance two photons are indistinguishableg2 (
float) – g²(0) - second order intensity autocorrelation at zero time delay. This parameter is correlated with how often two photons are emitted by the source instead of a single one.g2_distinguishable (
bool) – g2-generated photons indistinguishabilitytransmittance (
float) – system-wide transmittance (warning, can interfere with the brightness parameter)phase_imprecision (
float) – maximum precision of the phase shifters (0 means infinite precision)phase_error (
float) – maximum random noise on the phase shifters (in radian)
- set_value(param_name, value)
- class merlin.algorithms.feed_forward.OutputMapper
Bases:
objectHandles mapping quantum state amplitudes or probabilities to classical outputs.
This class provides factory methods for creating different types of output mappers that convert quantum state amplitudes or probabilities to classical outputs.
- static create_mapping(strategy, computation_space=ComputationSpace.FOCK, keys=None)
Create an output mapping based on the specified strategy.
- Args:
strategy: The measurement mapping strategy to use no_bunching: (Only used for ModeExpectations measurement strategy) If True (default), the per-mode probability of finding at least one photon is returned.
Otherwise, it is the per-mode expected number of photons that is returned.
- keys: (Only used for ModeExpectations measurement strategy) List of tuples that represent the possible quantum Fock states.
For example, keys = [(0,1,0,2), (1,0,1,0), …]
- Returns:
A PyTorch module that maps the per state amplitudes or probabilities to the desired format.
- Raises:
ValueError: If strategy is unknown
- class merlin.algorithms.feed_forward.QuantumLayer(input_size=None, builder=None, circuit=None, experiment=None, input_state=None, n_photons=None, trainable_parameters=None, input_parameters=None, amplitude_encoding=False, computation_space=None, measurement_strategy=MeasurementStrategy.PROBABILITIES, device=None, dtype=None, **kwargs)
Bases:
ModuleEnhanced Quantum Neural Network Layer with factory-based architecture.
This layer can be created either from a
CircuitBuilderinstance or a pre-compiledpcvl.Circuit.- Merlin integration (optimal design):
merlin_leaf = True marks this module as an indivisible execution leaf.
force_simulation (bool) defaults to False. When True, the layer MUST run locally.
supports_offload() reports whether remote offload is possible (via export_config()).
- should_offload(processor, shots) encapsulates the current offload policy:
return supports_offload() and not force_local
- angle_encoding_specs: dict[str, dict[str, Any]]
- as_simulation()
Temporarily force local simulation within the context.
- experiment: pcvl.Experiment | None
- export_config()
Export a standalone configuration for remote execution.
- Return type:
dict
- property force_local: bool
When True, this layer must run locally (Merlin will not offload it).
- forward(*input_parameters, shots=None, sampling_method=None, simultaneous_processes=None)
Forward pass through the quantum layer.
When
self.amplitude_encodingisTruethe first positional argument must contain the amplitude-encoded input state (either[num_states]or[batch_size, num_states]). Remaining positional arguments are treated as classical inputs and processed via the standard encoding pipeline.- Sampling is controlled by:
shots (int): number of samples; if 0 or None, return exact amplitudes/probabilities.
sampling_method (str): e.g. “multinomial”.
- get_experiment()
- Return type:
Optional[Experiment]
- property has_custom_detectors: bool
- input_parameters: list[str]
- merlin_leaf: bool = True
- noise_model: Any | None
- property output_keys
Return the Fock basis associated with the layer outputs.
- property output_size: int
- prepare_parameters(input_parameters)
Prepare parameter list for circuit evaluation.
- Return type:
list[Tensor]
- set_force_simulation(value)
- Return type:
None
- set_input_state(input_state)
- set_sampling_config(shots=None, method=None)
Deprecated: sampling configuration must be provided at call time in forward.
- should_offload(_processor=None, _shots=None)
Return True if this layer should be offloaded under current policy.
- Return type:
bool
- classmethod simple(input_size, n_params=90, output_size=None, device=None, dtype=None, no_bunching=True, **kwargs)
Create a ready-to-train layer with a 10-mode, 5-photon architecture.
The circuit is assembled via
CircuitBuilderwith the following layout:A fully trainable entangling layer acting on all modes;
A full input encoding layer spanning all encoded features;
A non-trainable entangling layer that redistributes encoded information;
Optional trainable Mach-Zehnder blocks (two parameters each) to reach the requested
n_paramsbudget;A final entangling layer prior to measurement.
- Args:
input_size: Size of the classical input vector. n_params: Number of trainable parameters to allocate across the additional MZI blocks. Values
below the default entangling budget trigger a warning; values above it must differ by an even amount because each added MZI exposes two parameters.
output_size: Optional classical output width. device: Optional target device for tensors. dtype: Optional tensor dtype. no_bunching: Whether to restrict to states without photon bunching.
- Returns:
QuantumLayer configured with the described architecture.
- supports_offload()
Return True if this layer is technically offloadable.
- Return type:
bool
- to(*args, **kwargs)
Move and/or cast the parameters and buffers.
This can be called as
- to(device=None, dtype=None, non_blocking=False)
- to(dtype, non_blocking=False)
- to(tensor, non_blocking=False)
- to(memory_format=torch.channels_last)
Its signature is similar to
torch.Tensor.to(), but only accepts floating point or complexdtypes. In addition, this method will only cast the floating point or complex parameters and buffers todtype(if given). The integral parameters and buffers will be moveddevice, if that is given, but with dtypes unchanged. Whennon_blockingis set, it tries to convert/move asynchronously with respect to the host if possible, e.g., moving CPU Tensors with pinned memory to CUDA devices.See below for examples.
Note
This method modifies the module in-place.
- Args:
- device (
torch.device): the desired device of the parameters and buffers in this module
- dtype (
torch.dtype): the desired floating point or complex dtype of the parameters and buffers in this module
- tensor (torch.Tensor): Tensor whose dtype and device are the desired
dtype and device for all parameters and buffers in this module
- memory_format (
torch.memory_format): the desired memory format for 4D parameters and buffers in this module (keyword only argument)
- device (
- Returns:
Module: self
Examples:
>>> # xdoctest: +IGNORE_WANT("non-deterministic") >>> linear = nn.Linear(2, 2) >>> linear.weight Parameter containing: tensor([[ 0.1913, -0.3420], [-0.5113, -0.2325]]) >>> linear.to(torch.double) Linear(in_features=2, out_features=2, bias=True) >>> linear.weight Parameter containing: tensor([[ 0.1913, -0.3420], [-0.5113, -0.2325]], dtype=torch.float64) >>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_CUDA1) >>> gpu1 = torch.device("cuda:1") >>> linear.to(gpu1, dtype=torch.half, non_blocking=True) Linear(in_features=2, out_features=2, bias=True) >>> linear.weight Parameter containing: tensor([[ 0.1914, -0.3420], [-0.5112, -0.2324]], dtype=torch.float16, device='cuda:1') >>> cpu = torch.device("cpu") >>> linear.to(cpu) Linear(in_features=2, out_features=2, bias=True) >>> linear.weight Parameter containing: tensor([[ 0.1914, -0.3420], [-0.5112, -0.2324]], dtype=torch.float16) >>> linear = nn.Linear(2, 2, bias=None).to(torch.cdouble) >>> linear.weight Parameter containing: tensor([[ 0.3741+0.j, 0.2382+0.j], [ 0.5593+0.j, -0.4443+0.j]], dtype=torch.complex128) >>> linear(torch.ones(3, 2, dtype=torch.cdouble)) tensor([[0.6122+0.j, 0.1150+0.j], [0.6122+0.j, 0.1150+0.j], [0.6122+0.j, 0.1150+0.j]], dtype=torch.complex128)
- trainable_parameters: list[str]
- training: bool
- class merlin.algorithms.feed_forward.Sequence
Bases:
Reversible,CollectionAll the operations on a read-only sequence.
Concrete subclasses must override __new__ or __init__, __getitem__, and __len__.
- count(value) integer -- return number of occurrences of value
- index(value[, start[, stop]]) integer -- return first index of value.
Raises ValueError if the value is not present.
Supporting start and stop arguments is optional, but recommended.
- class merlin.algorithms.feed_forward.StageRuntime(circuit, pre_layer, detector_transform, conditional_circuits, conditional_default_key, measured_modes, global_measured_modes, active_modes, detectors, provider, pre_layers=<factory>, detector_cache=<factory>, conditional_layer_cache=<factory>, trainable_parameters=None, initial_amplitudes=None, classical_input_size=0)
Bases:
object-
active_modes:
tuple[int,...]
-
classical_input_size:
int= 0
-
conditional_default_key:
Optional[tuple[int,...]]
-
conditional_layer_cache:
dict[tuple[tuple[int,...],int],QuantumLayer]
-
detector_cache:
dict[int,DetectorTransform]
-
detector_transform:
Optional[DetectorTransform]
-
detectors:
dict[int,Optional[Detector]]
-
global_measured_modes:
tuple[int,...]
-
measured_modes:
tuple[int,...]
-
pre_layer:
Optional[QuantumLayer]
-
pre_layers:
dict[int,QuantumLayer]
-
provider:
Optional[FFCircuitProvider]
-
trainable_parameters:
Optional[list[str]] = None
-
active_modes:
- merlin.algorithms.feed_forward.dataclass(cls=None, /, *, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, weakref_slot=False)
Add dunder methods based on the fields defined in the class.
Examines PEP 526 __annotations__ to determine fields.
If init is true, an __init__() method is added to the class. If repr is true, a __repr__() method is added. If order is true, rich comparison dunder methods are added. If unsafe_hash is true, a __hash__() method is added. If frozen is true, fields may not be assigned to after instance creation. If match_args is true, the __match_args__ tuple is added. If kw_only is true, then by default all fields are keyword-only. If slots is true, a new class with a __slots__ attribute is returned.
- merlin.algorithms.feed_forward.field(*, default=<dataclasses._MISSING_TYPE object>, default_factory=<dataclasses._MISSING_TYPE object>, init=True, repr=True, hash=None, compare=True, metadata=None, kw_only=<dataclasses._MISSING_TYPE object>)
Return an object to identify dataclass fields.
default is the default value of the field. default_factory is a 0-argument function called to initialize a field’s value. If init is true, the field will be a parameter to the class’s __init__() function. If repr is true, the field will be included in the object’s repr(). If hash is true, the field will be included in the object’s hash(). If compare is true, the field will be used in comparison functions. metadata, if specified, must be a mapping which is stored but not otherwise examined by dataclass. If kw_only is true, the field will become a keyword-only parameter to __init__().
It is an error to specify both default and default_factory.
- merlin.algorithms.feed_forward.pcvl_to_tensor(state_vector, computation_space=ComputationSpace.FOCK, dtype=torch.complex64, device=device(type='cpu'))
Convert a Perceval StateVector into a torch Tensor.
- Return type:
- Args:
state_vector: Perceval StateVector. computation_space: Computation space of the state vector following combinadics ordering. dtype: Desired torch dtype of the output Tensor. device: Desired torch device of the output Tensor.
- Returns:
Equivalent torch Tensor.
- Raises:
- ValueError: If the StateVector includes states with incompatible photon number for the specified computation space,
or non consistent number of photons across the states.