merlin.core.encoding_space

Input encoding definitions and mapping helpers.

EncodingSpace

class merlin.core.encoding_space.EncodingSpace(modes_per_photon=None, *, family=None, kind=None, qubit_groups=None)

Bases: object

Validated input encoding definition.

Instances describe how a compact logical basis should be interpreted before it is embedded into Merlin’s canonical Fock ordering.

family: str
kind: str
modes_per_photon: Optional[tuple[int, ...]]
qubit_groups: Optional[tuple[int, ...]]
FOCK: ClassVar[EncodingSpace] = EncodingSpace(family='builtin', kind='fock')
UNBUNCHED: ClassVar[EncodingSpace] = EncodingSpace(family='builtin', kind='unbunched')
DUAL_RAIL: ClassVar[EncodingSpace] = EncodingSpace(family='partitioned', kind='dual_rail')
property parameters: dict[str, tuple[int, ...]]

Return a copy of the encoding parameters for introspection.

property n_modes: int | None

Return the total mode count for partitioned encodings.

property n_photons: int | None

Return the photon count for partitioned encodings.

classmethod qloq(qubit_groups)

Create a partitioned QLOQ encoding from qubit group sizes.

Return type:

EncodingSpace

basis_size(*, n_modes=None, n_photons=None)

Return the number of logical basis states for this encoding.

Return type:

int

resolved_modes_per_photon(*, n_modes=None, n_photons=None)

Return the resolved partition layout when the encoding is partitioned.

Return type:

Optional[tuple[int, ...]]

logical_basis_size(*, n_modes=None, n_photons=None)

Return the logical tensor width expected before Fock embedding.

Parameters:
  • n_modes (int | None) – Number of photonic modes used to resolve built-in encodings. If omitted, custom partitioned encodings use their own configured mode count. Default value is None.

  • n_photons (int | None) – Number of photons used to resolve built-in encodings. If omitted, custom partitioned encodings use their own configured photon count. Default value is None.

Returns:

Number of logical amplitude components expected for this encoding.

Return type:

int

Raises:

ValueError – If the encoding cannot resolve n_modes and n_photons.

embed(tensor, *, n_modes=None, n_photons=None)

Embed a logical amplitude tensor into canonical full-Fock ordering.

Parameters:
  • tensor (torch.Tensor) – Logical amplitude tensor. The final dimension stores amplitudes in this encoding’s logical basis order; all leading dimensions are preserved as batch axes.

  • n_modes (int | None) – Number of photonic modes used to resolve built-in encodings. If omitted, custom partitioned encodings use their own configured mode count. Default value is None.

  • n_photons (int | None) – Number of photons used to resolve built-in encodings. If omitted, custom partitioned encodings use their own configured photon count. Default value is None.

Returns:

Amplitude tensor with the same leading dimensions as tensor and final dimension equal to the full Fock basis size.

Return type:

torch.Tensor

Raises:

ValueError – If tensor is scalar, if its final dimension does not match the logical basis size, or if the encoding cannot resolve n_modes and n_photons.

logical_basis_states(*, n_modes=None, n_photons=None)

Return logical basis labels in stable embedding order.

For a partitioned encoding, each tuple stores the local mode selected by each photon partition. For EncodingSpace(modes_per_photon=[2, 2]), the output is:

((0, 0), (0, 1), (1, 0), (1, 1))
Return type:

tuple[tuple[int, ...], ...]

fock_basis_states(*, n_modes=None, n_photons=None)

Return mapped Fock states in the same order as logical_basis_states.

For a [2, 2] partitioned encoding, the first photon occupies one of modes 0 or 1 and the second occupies one of modes 2 or 3:

((1, 0, 1, 0), (1, 0, 0, 1), (0, 1, 1, 0), (0, 1, 0, 1))
Return type:

tuple[tuple[int, ...], ...]

logical_to_fock_map(*, n_modes=None, n_photons=None)

Return the logical-to-Fock mapping in stable order.

The keys are compact logical labels and the values are occupation-count Fock states in Merlin’s canonical mode layout. For EncodingSpace(modes_per_photon=[3, 2]), the mapping order is:

(0, 0) -> (1, 0, 0, 1, 0)
(0, 1) -> (1, 0, 0, 0, 1)
(1, 0) -> (0, 1, 0, 1, 0)
(1, 1) -> (0, 1, 0, 0, 1)
(2, 0) -> (0, 0, 1, 1, 0)
(2, 1) -> (0, 0, 1, 0, 1)
Return type:

dict[tuple[int, ...], tuple[int, ...]]

logical_to_fock_indices(*, n_modes=None, n_photons=None)

Return full-Fock indices for each logical basis label.

The returned indices refer to the full Fock basis for the resolved n_modes and n_photons. For EncodingSpace(modes_per_photon=[2, 2]), the output is:

{(0, 0): 2, (0, 1): 3, (1, 0): 5, (1, 1): 6}
Return type:

dict[tuple[int, ...], int]

Built-ins

EncodingSpace.FOCK

Tensor amplitudes are already in Merlin’s canonical full-Fock ordering.

EncodingSpace.UNBUNCHED

Logical amplitudes enumerate collision-free states and are embedded into the full Fock basis.

EncodingSpace.DUAL_RAIL

Each logical qubit is represented by one photon shared over two modes.

Custom partitioned encodings are created with EncodingSpace(modes_per_photon=[...]). QLOQ partitioned encodings are created with EncodingSpace.qloq().

See Encoding Spaces for runnable examples of each encoding.