Migration guide

Migration guide (v0.3 to v.0.4)

Migrating dependency versions for MerLin 0.4

MerLin 0.4 requires Perceval >=1.2.1. Previous MerLin versions supported Perceval <=1.1.

MerLin 0.4 also supports PyTorch 2.11 and 2.12. See Compatibility for the supported MerLin, Perceval, PyTorch, and Python version combinations.

Migrating from removed computation_space argument in the QuantumLayer

Warning

Deprecated since version 0.4: The use of the computation_space argument in the QuantumLayer’s constructor is no longer supported as 0.4.0. Use the computation_space flag inside measurement_strategy instead. For example, MeasurementStrategy.probs(computation_space=...).

To define the computation_space of a QuantumLayer, a measurement strategy factory method must be used. For example, to use the probabilities measurement strategy with the Fock space computation space:

# Deprecated (legacy enum + separate computation_space)
# QuantumLayer(..., measurement_strategy=MeasurementStrategy.PROBABILITIES,
#             computation_space=ComputationSpace.FOCK)

# Recommended
QuantumLayer(..., measurement_strategy=MeasurementStrategy.probs(ComputationSpace.FOCK))

Migrating from no_bunching (deprecated)

Migrating from removed amplitude_encoding flag in the QuantumLayer

Warning

The amplitude_encoding=True constructor parameter was removed in 0.4. Pass a StateVector or a complex torch.Tensor to forward() instead.

To use amplitude encoding in a QuantumLayer, pass a StateVector or a complex torch.Tensor at the forward call. The constructor no longer needs an amplitude-encoding flag.

import torch
from merlin import CircuitBuilder, QuantumLayer, MeasurementStrategy, ComputationSpace
from merlin.core import EncodingSpace, StateVector

builder = CircuitBuilder(n_modes=4)
builder.add_entangling_layer()

layer = QuantumLayer(
    input_size=0,
    builder=builder,
    n_photons=2,
    measurement_strategy=MeasurementStrategy.probs(
        computation_space=ComputationSpace.FOCK
    ),
)

# Option 1: StateVector input
input_state = StateVector.from_tensor(
    tensor=torch.rand(1, 10),
    n_modes=4,
    n_photons=2,
    encoding=EncodingSpace.FOCK,
)
layer(input_state)

# Option 2: complex tensor
input_state = torch.rand(1, layer.output_size, dtype=torch.complex64)
layer(input_state)

If you previously built full Fock-sized tensors manually, prefer a logical encoding when the data has one. For example, a two-qubit dual-rail state can be passed as four logical amplitudes instead of a ten-entry full-Fock vector:

import torch
from merlin.core import EncodingSpace, StateVector

logical = torch.tensor([1.0, 0.0, 0.0, 1.0], dtype=torch.complex64)
input_state = StateVector.from_tensor(
    logical,
    encoding=EncodingSpace.DUAL_RAIL,
)

StateVector normalizes lazily when a normalized dense view or layer execution needs it, so explicit pre-normalization is not required for this construction.

See Encoding Spaces for Fock, unbunched, dual-rail, partitioned, and QLOQ examples.

Migrating from tensor input_state values

Warning

Passing a torch.Tensor as an input_state value is removed in 0.4. Build a StateVector with from_tensor() and pass that object instead.

Tensor-valued input_state arguments used to represent amplitude data. That state metadata now belongs in StateVector, which carries the tensor together with its mode, photon, and encoding-space information. This applies to constructors and mutators such as QuantumLayer.set_input_state().

import torch
from merlin import QuantumLayer, MeasurementStrategy, ComputationSpace
from merlin.core import EncodingSpace, StateVector

amplitudes = torch.rand(1, 10, dtype=torch.complex64)
input_state = StateVector.from_tensor(
    amplitudes,
    n_modes=4,
    n_photons=2,
    encoding=EncodingSpace.FOCK,
)

layer = QuantumLayer(
    circuit=circuit,
    input_state=input_state,
    measurement_strategy=MeasurementStrategy.probs(
        computation_space=ComputationSpace.FOCK
    ),
)

For FidelityKernel, input_state remains a Fock occupation list such as [1, 0, 1, 0]. Tensor amplitude states are not valid kernel input states; use a QuantumLayer with StateVector for those workflows. The same rule applies to feed-forward blocks: use a Fock occupation list, pcvl.BasicState, pcvl.StateVector, or StateVector, not a raw tensor.

v.0.3 deprecations are now errors

Deprecations in the next section are now errors. Please consult the following section for other migration notes.

Migration guide (v0.2 to v.0.3)

Migrating from removed no_bunching

Warning

Removed in version 0.4: no_bunching is removed in version 0.4. Use explicit computation_space configuration instead.

The no_bunching flag is removed.

If you are using a QuantumLayer and you need to control how Fock states are truncated or encoded, define the computation_space inside the measurement_strategy instead.

If you are using a Kernel, define the encoding or truncation of the Fock states in the computation_space parameter.

Map the legacy intent as follows:

  • no_bunching=Falsecomputation_space=ComputationSpace.FOCK (full Fock space)

  • no_bunching=Truecomputation_space=ComputationSpace.UNBUNCHED (one photon per mode)

  • Dual-rail encodings → computation_space=ComputationSpace.DUAL_RAIL

This keeps measurement strategy selection orthogonal to simulation space configuration.

Migrating from legacy MeasurementStrategy

Warning

Deprecated since version 0.3: Enum-style and string access is deprecated and will be removed from MeasurementStrategy in v0.4. Use the new factory methods instead: MeasurementStrategy.probs(computation_space=...), MeasurementStrategy.mode_expectations(computation_space=...), MeasurementStrategy.amplitudes(computation_space=...). See this migration section for the mapping.

Old to new mappings

Deprecated

Recommended replacement

MeasurementStrategy.PROBABILITIES

MeasurementStrategy.probs(computation_space=...)

MeasurementStrategy.MODE_EXPECTATIONS

MeasurementStrategy.mode_expectations(computation_space=...)

MeasurementStrategy.AMPLITUDES

MeasurementStrategy.amplitudes(computation_space=...)

MeasurementStrategy.NONE

MeasurementStrategy.amplitudes(computation_space=...)

"PROBABILITIES" (string)

MeasurementStrategy.probs(computation_space=...)

Computation space now lives inside the strategy.

# Deprecated (legacy enum + separate computation_space)
# QuantumLayer(..., measurement_strategy=MeasurementStrategy.PROBABILITIES,
#             computation_space=ComputationSpace.FOCK)

# Recommended
QuantumLayer(..., measurement_strategy=MeasurementStrategy.probs(ComputationSpace.FOCK))