merlin.algorithms.layer_utils module

Utilities and helpers for QuantumLayer initialization and configuration.

Note

This module contains internal-but-documented helpers used during QuantumLayer initialization and input preparation.

class merlin.algorithms.layer_utils.EncodingModeConfig(amplitude_encoding, input_size, n_photons, input_parameters)

Bases: object

Store the validated encoding configuration.

Parameters:
  • amplitude_encoding (bool) – Whether amplitude encoding is enabled.

  • input_size (int | None) – Resolved classical input size.

  • n_photons (int | None) – Resolved photon count.

  • input_parameters (list[str]) – Resolved list of input parameter prefixes.

amplitude_encoding: bool
input_parameters: list[str]
input_size: Optional[int]
n_photons: Optional[int]
class merlin.algorithms.layer_utils.CircuitSource(source_type, builder, circuit, experiment, trainable_parameters, input_parameters, angle_encoding_specs)

Bases: object

Store the resolved circuit source configuration.

Parameters:
  • source_type (Literal["builder", "circuit", "experiment"]) – Kind of source provided by the caller.

  • builder (CircuitBuilder | None) – Builder instance when source_type == "builder".

  • circuit (pcvl.Circuit | None) – Perceval circuit when source_type == "circuit".

  • experiment (pcvl.Experiment | None) – Perceval experiment when source_type == "experiment".

  • trainable_parameters (list[str]) – Resolved trainable parameter prefixes.

  • input_parameters (list[str]) – Resolved input parameter prefixes.

  • angle_encoding_specs (dict[str, dict[str, Any]]) – Stored angle encoding metadata extracted from the builder, if any.

angle_encoding_specs: dict[str, dict[str, Any]]
builder: Optional[CircuitBuilder]
circuit: Optional[Circuit]
experiment: Optional[Experiment]
input_parameters: list[str]
source_type: Literal['builder', 'circuit', 'experiment']
trainable_parameters: list[str]
class merlin.algorithms.layer_utils.ResolvedCircuit(circuit, experiment, noise, has_custom_noise)

Bases: object

Store the resolved circuit and experiment pair.

Parameters:
  • circuit (pcvl.Circuit) – Resolved circuit instance.

  • experiment (pcvl.Experiment) – Experiment wrapping the resolved circuit.

  • noise (Any | None) – Attached experiment noise model, if present.

  • has_custom_noise (bool) – Whether the experiment exposes a non-empty custom noise model.

circuit: Circuit
experiment: Experiment
has_custom_noise: bool
noise: Optional[Any]
class merlin.algorithms.layer_utils.NoiseAndDetectorConfig(photon_survival_probs, has_custom_noise, detectors, has_custom_detectors, detector_warnings, noise_groups)

Bases: object

Store extracted noise and detector configuration.

Parameters:
  • photon_survival_probs (list[float]) – Photon survival probabilities derived from the experiment noise model.

  • has_custom_noise (bool) – Whether a custom noise model is present.

  • detectors (list[pcvl.Detector]) – Resolved detector list for every mode.

  • has_custom_detectors (bool) – Whether the experiment defines non-default detectors.

  • detector_warnings (list[str]) – Compatibility warnings emitted while resolving detector behavior.

  • noise_groups (NoiseGroups | None) – The noise groups applied to the circuit to be ran.

detector_warnings: list[str]
detectors: list[Detector]
has_custom_detectors: bool
has_custom_noise: bool
noise_groups: Optional[NoiseGroups]
photon_survival_probs: list[float]
class merlin.algorithms.layer_utils.NoiseGroups(source, circuit, post_measurement)

Bases: object

Stores the classified noise sources

Parameters:
  • source (dict[str, float | bool | None] | None) – Source noises e.g. {“indistinguishability”: 0.9, “g2”: 0.05, “g2_distinguishable”: True}, or None when no source noise is present.

  • circuit (dict[str, float | None] | None) – Circuit noises e.g. {“phase_error”: 0.05, “phase_imprecision”: 0.1}, or None when no circuit noise is present.

  • post_measurement (dict[str, float | None] | None) – Post measurement noises e.g. {“brightness”: 0.3, “transmittance”: 0.9}, or None when no post-measurement noise is present.

circuit: Optional[dict[str, Optional[float]]]
post_measurement: Optional[dict[str, Optional[float]]]
source: Optional[dict[str, UnionType[float, bool, None]]]
class merlin.algorithms.layer_utils.InitializationContext(device, dtype, complex_dtype, amplitude_encoding, input_size, circuit, experiment, noise, has_custom_noise, input_state, n_photons, trainable_parameters, input_parameters, angle_encoding_specs, photon_survival_probs, detectors, has_custom_detectors, computation_space, measurement_strategy, warnings, return_object, noise_groups, n_phase_error_samples)

Bases: object

Store immutable QuantumLayer initialization state.

Parameters:
  • device (torch.device | None) – Target device for the layer.

  • dtype (torch.dtype) – Real dtype used by the layer.

  • complex_dtype (torch.dtype) – Complex dtype paired with dtype.

  • amplitude_encoding (bool) – Whether amplitude encoding is enabled.

  • input_size (int | None) – Resolved classical input size.

  • circuit (pcvl.Circuit) – Resolved circuit.

  • experiment (pcvl.Experiment) – Resolved experiment.

  • noise (Any | None) – Attached noise model, if any.

  • has_custom_noise (bool) – Whether the experiment defines custom noise.

  • input_state (merlin.core.state_vector.StateVector | pcvl.BasicState | None) – Normalized input state.

  • n_photons (int | None) – Resolved photon count.

  • trainable_parameters (list[str]) – Trainable parameter prefixes.

  • input_parameters (list[str]) – Classical input parameter prefixes.

  • angle_encoding_specs (dict[str, dict[str, Any]]) – Angle encoding metadata extracted from the builder.

  • photon_survival_probs (list[float]) – Photon survival probabilities derived from the experiment.

  • detectors (list[pcvl.Detector]) – Resolved detector list.

  • has_custom_detectors (bool) – Whether custom detectors are configured.

  • computation_space (ComputationSpace) – Resolved computation space.

  • measurement_strategy (MeasurementStrategyLike) – Measurement strategy used by the layer.

  • warnings (list[str]) – Initialization warnings to surface to the caller.

  • return_object (bool) – Whether the layer returns structured objects instead of tensors.

  • noise_groups (NoiseGroups | None) – The noise groups applied to the circuit to be ran.

amplitude_encoding: bool
angle_encoding_specs: dict[str, dict[str, Any]]
circuit: Circuit
complex_dtype: dtype
computation_space: ComputationSpace
detectors: list[Detector]
device: Optional[device]
dtype: dtype
experiment: Experiment
has_custom_detectors: bool
has_custom_noise: bool
input_parameters: list[str]
input_size: Optional[int]
input_state: UnionType[StateVector, BasicState, None]
measurement_strategy: MeasurementStrategy | _LegacyMeasurementStrategy
n_phase_error_samples: int
n_photons: Optional[int]
noise: Optional[Any]
noise_groups: Optional[NoiseGroups]
photon_survival_probs: list[float]
return_object: bool
trainable_parameters: list[str]
warnings: list[str]
merlin.algorithms.layer_utils.validate_encoding_mode(amplitude_encoding, input_size, n_photons, input_parameters)

Validate amplitude-encoding constraints.

Parameters:
  • amplitude_encoding (bool) – Removed compatibility flag. If True, a clear migration error is raised.

  • input_size (int | None) – User-provided classical input size.

  • n_photons (int | None) – User-provided photon count.

  • input_parameters (list[str] | None) – User-provided classical input parameter prefixes.

Returns:

Validated and normalized encoding configuration.

Return type:

EncodingModeConfig

Raises:

ValueError – If amplitude encoding is requested.

merlin.algorithms.layer_utils.prepare_input_state(input_state, n_photons, computation_space, device, complex_dtype, experiment=None, circuit_m=None, amplitude_encoding=False)

Normalize input_state to canonical form.

Parameters:
  • input_state (StateVector | pcvl.StateVector | pcvl.BasicState | list | tuple | None) – The input state in various formats. StateVector is the canonical type. Build a StateVector with StateVector.from_tensor() before passing amplitude tensors as input_state.

  • n_photons (int | None) – Number of photons (used for default state generation).

  • computation_space (ComputationSpace) – The computation space configuration.

  • device (torch.device | None) – Target device for tensors.

  • complex_dtype (torch.dtype) – Complex dtype for tensor conversion.

  • experiment (pcvl.Experiment | None) – Optional experiment whose input_state takes precedence.

  • circuit_m (int | None) – Number of modes in the circuit (for default state generation).

  • amplitude_encoding (bool) – Removed compatibility flag. If True, a clear migration error is raised.

Returns:

The normalized input state and resolved photon count.

Return type:

tuple[merlin.core.state_vector.StateVector | pcvl.BasicState | None, int | None]

Raises:

ValueError – If amplitude encoding is requested, if torch.Tensor is passed as input_state, if neither input_state nor n_photons is provided, or if StateVector is empty.

Warns:

UserWarning – When both experiment.input_state and input_state are provided.

merlin.algorithms.layer_utils.validate_and_resolve_circuit_source(builder, circuit, experiment, trainable_parameters, input_parameters)

Validate and normalize the circuit source selection.

Parameters:
  • builder (CircuitBuilder | None) – Builder source, if provided.

  • circuit (pcvl.Circuit | None) – Circuit source, if provided.

  • experiment (pcvl.Experiment | None) – Experiment source, if provided.

  • trainable_parameters (list[str] | None) – User-provided trainable parameter prefixes.

  • input_parameters (list[str] | None) – User-provided input parameter prefixes.

Returns:

Resolved circuit-source configuration.

Return type:

CircuitSource

Raises:

ValueError – If zero or multiple circuit sources are provided, or if builder-derived prefixes are mixed with explicit parameter prefixes.

merlin.algorithms.layer_utils.vet_experiment(experiment)

Check experiment constraints.

Parameters:

experiment (pcvl.Experiment) – Experiment to validate.

Returns:

Summary of experiment properties relevant to QuantumLayer support.

Return type:

dict[str, bool]

Raises:

ValueError – If the experiment uses unsupported features such as post-selection, heralding, feed-forward, time dependence, or minimum-photon filters.

merlin.algorithms.layer_utils.resolve_circuit(circuit_source, pcvl_module, noise=None)

Resolve a builder, circuit, or experiment into a unified circuit form.

Parameters:
  • circuit_source (CircuitSource) – Resolved circuit source configuration.

  • pcvl_module (Any) – Perceval module used to instantiate experiments when needed.

  • noise (pcvl.NoiseModel | None) – The resolved NoiseModel of the layer. Defaults to None (no noise).

Returns:

Unified circuit and experiment wrapper.

Return type:

ResolvedCircuit

Raises:

RuntimeError – If the provided circuit_source is internally inconsistent.

merlin.algorithms.layer_utils.setup_noise_and_detectors(experiment, circuit, computation_space, measurement_strategy, backend=None, noise=None, return_object=False)

Extract and validate photon-loss and detector configuration.

Parameters:
  • experiment (pcvl.Experiment) – Experiment from which noise and detectors are extracted.

  • circuit (pcvl.Circuit) – Resolved circuit used to determine the number of modes.

  • computation_space (ComputationSpace) – Logical computation space requested by the layer.

  • measurement_strategy (MeasurementStrategyLike) – Measurement strategy used to validate detector and noise compatibility.

  • backend (str | None) – Backend identifier used when validating supported noisy measurement configurations. If omitted, no backend-specific validation is applied. Default value is None.

  • noise (pcvl.NoiseModel | None) – Noise model to validate and classify. If omitted, the simulation is treated as noise-free unless detector configuration requires validation. Default value is None.

  • return_object (bool) – Whether the layer returns structured objects instead of tensors. Default value is False.

Returns:

Extracted and validated noise/detector configuration including photon survival probabilities, detector settings, and classified noise groups.

Return type:

NoiseAndDetectorConfig

Raises:
  • RuntimeError – If amplitude readout is requested together with custom detectors.

  • NotImplementedError – If a non-SLOS backend is specified.

  • ValueError – If measurement strategy is incompatible with noisy simulation, including amplitude readout with active noise.

merlin.algorithms.layer_utils.apply_angle_encoding(x, spec)

Apply custom angle encoding using stored metadata.

Parameters:
  • x (torch.Tensor) – Input tensor to encode. May be one- or two-dimensional.

  • spec (dict[str, Any]) – Angle encoding metadata containing feature combinations and scales.

Returns:

Encoded tensor matching the requested combinations.

Return type:

torch.Tensor

Raises:

ValueError – If x has unsupported rank or does not provide enough features for a requested combination.

merlin.algorithms.layer_utils.compute_new_memristive_ps_angles(memristive_metadata, memristive_state, output)

Computes the new memristive phase shifter angles per the batch’s output.

Parameters:
Returns:

The new states of all memristive phase shifters

Return type:

list[torch.Tensor]

merlin.algorithms.layer_utils.prepare_input_encoding(x, prefix=None, angle_encoding_specs=None)

Prepare input encoding for a given parameter prefix.

Parameters:
  • x (torch.Tensor) – Input tensor to encode.

  • prefix (str | None) – Prefix identifying the relevant angle encoding specification.

  • angle_encoding_specs (dict[str, dict[str, Any]] | None) – Available angle encoding specifications.

Returns:

Encoded tensor if a matching specification is found, otherwise the input tensor unchanged.

Return type:

torch.Tensor

merlin.algorithms.layer_utils.split_inputs_by_prefix(prefixes, tensor, angle_encoding_specs, spec_mappings=None)

Split a logical input tensor into per-prefix chunks when possible.

Parameters:
  • prefixes (list[str]) – Ordered parameter prefixes to split against.

  • tensor (torch.Tensor) – Input tensor containing all logical features.

  • angle_encoding_specs (dict[str, dict[str, Any]]) – Angle encoding specifications keyed by prefix.

  • spec_mappings (dict[str, list[str]] | None) – Optional spec mappings used as a fallback for feature counting.

Returns:

Per-prefix tensor slices when the split is possible, otherwise None.

Return type:

list[torch.Tensor] | None

merlin.algorithms.layer_utils.feature_count_for_prefix(prefix, angle_encoding_specs, spec_mappings=None)

Infer the number of raw features associated with an encoding prefix.

Parameters:
  • prefix (str) – Encoding prefix to inspect.

  • angle_encoding_specs (dict[str, dict[str, Any]]) – Angle encoding specifications keyed by prefix.

  • spec_mappings (dict[str, list[str]] | None) – Optional spec mappings used as a fallback.

Returns:

Number of raw features associated with prefix, or None if it cannot be inferred.

Return type:

int | None

merlin.algorithms.layer_utils.normalize_output_key(key)

Normalize an output key to tuple[int, ...].

Parameters:

key (Iterable[int] | torch.Tensor | Sequence[int]) – Output key in iterable or tensor form.

Returns:

Normalized tuple representation of the output key.

Return type:

tuple[int, …]

merlin.algorithms.layer_utils.classify_noise(noise)

From a noise model, create a NoiseGroups object splitting the noise inputs.

Parameters:

noise (pcvl.NoiseModel | None) – The noise model to apply to the circuit

Returns:

The NoiseGroups object that contains the noise sources per category.

Return type:

NoiseGroups | None

merlin.algorithms.layer_utils.validate_noisy_measurement_strategy(strategy, output, noise=None, noise_groups=None, empty_detectors=False, return_object=False, measurement_kind=None)

Validate the noise model and QuantumLayer configurations so that they match.

Validates that the noise model, measurement strategy, backend, and output configuration are compatible.

Parameters:
  • strategy (str | None) – The simulation backend used (e.g., “slos”). If provided and not “slos”, raises NotImplementedError. Default is None.

  • output (str) – The measurement strategy output type (e.g., “amplitudes”, “probabilities”, “mode_expectations”). Must be “probabilities” when noise is present.

  • noise (pcvl.NoiseModel | None) – The noise model to validate. Default is None.

  • noise_groups (NoiseGroups | None) – Classified active noise groups. Neutral noise models should pass None here so they are not treated as active noise. Default is None.

  • empty_detectors (bool) – Whether the circuit has no custom detectors. Used to determine early returns when there is no noise. Default is False.

  • return_object (bool) – Whether the layer returns structured objects instead of tensors. Cannot be True when active noise is present. Default is False.

  • measurement_kind (MeasurementKind | None) – Resolved measurement kind. Used to reject partial measurement with active noise. Default is None.

Returns:

The input noise model.

Return type:

pcvl.NoiseModel | None

Raises:
  • NotImplementedError – If return_object=True and active noise is present, or if the backend strategy is not “slos”.

  • ValueError – If output measurement strategy is incompatible with noisy simulation (e.g., “amplitudes” or “mode_expectations” with noise).

merlin.algorithms.layer_utils.normalize_noise(layer_noise, experiment_noise)

Normalize and resolve noise models from multiple QuantumLayer sources.

Resolves conflicting noise model sources and validates g2_distinguishable settings for coherence consistency. When both sources provide a noise model, they must be identical. Automatically corrects g2_distinguishable when indistinguishability is 1.0 (fully indistinguishable photons).

Parameters:
  • layer_noise (pcvl.NoiseModel | None) – The noise model declared via the noise argument of QuantumLayer.

  • experiment_noise (pcvl.NoiseModel | None) – The noise model declared via experiment.noise in QuantumLayer.

Returns:

The resolved and validated noise model with corrected g2_distinguishable and g2 settings as needed.

Return type:

pcvl.NoiseModel

Raises:

ValueError – If both layer_noise and experiment_noise are None, or if both are provided but not identical.

Warns:

UserWarning – When g2_distinguishable is automatically corrected from True to False due to fully indistinguishable photons (indistinguishability == 1.0).