merlin.core.layer module

Main QuantumLayer implementation with bug fixes and index_photons support.

class merlin.core.layer.Ansatz(PhotonicBackend, input_size, output_size=None, output_mapping_strategy=OutputMappingStrategy.LINEAR, device=None, dtype=None)

Bases: object

Complete configuration for a quantum neural network layer.

class merlin.core.layer.AnsatzFactory

Bases: object

Factory for creating quantum layer ansatzes (complete configurations).

static create(PhotonicBackend, input_size, output_size=None, output_mapping_strategy=OutputMappingStrategy.LINEAR, device=None, dtype=None)

Create a complete ansatz configuration.

Return type:

Ansatz

Args:

PhotonicBackend (PhotonicBackend): The backend configuration to use. input_size (int): Size of the input feature vector. output_size (int | None): Size of the output vector. If None, it is defined by the backend. output_mapping_strategy (OutputMappingStrategy): Strategy for mapping outputs. device (torch.device | None): Device to run computations on. dtype (torch.dtype | None): Data type for computations.

Returns:

Ansatz: A complete ansatz configuration for the quantum layer.

class merlin.core.layer.AutoDiffProcess(sampling_method='multinomial')

Bases: object

Handles automatic differentiation backend and sampling noise integration.

autodiff_backend(needs_gradient, apply_sampling, shots)

Determine sampling configuration based on gradient requirements.

Return type:

tuple[bool, int]

enum merlin.core.layer.CircuitType(value)

Bases: Enum

Quantum circuit topology types.

Valid values are as follows:

PARALLEL_COLUMNS = <CircuitType.PARALLEL_COLUMNS: 'parallel_columns'>
SERIES = <CircuitType.SERIES: 'series'>
PARALLEL = <CircuitType.PARALLEL: 'parallel'>
class merlin.core.layer.ComputationProcessFactory

Bases: object

Factory for creating computation processes.

static create(circuit, input_state, trainable_parameters, input_parameters, reservoir_mode=False, no_bunching=None, output_map_func=None, index_photons=None, **kwargs)

Create a computation process.

Return type:

ComputationProcess

merlin.core.layer.Experiment

alias of PhotonicBackend

class merlin.core.layer.OutputMapper

Bases: object

Handles mapping quantum probability distributions to classical outputs.

This class provides factory methods for creating different types of output mappers that convert quantum probability distributions to classical neural network outputs.

static create_mapping(strategy, input_size, output_size)

Create an output mapping based on the specified strategy.

Args:

strategy: The output mapping strategy to use input_size: Size of the input probability distribution output_size: Desired size of the output tensor

Returns:

A PyTorch module that maps input_size to output_size

Raises:

ValueError: If strategy is unknown or sizes are incompatible for ‘none’ strategy

enum merlin.core.layer.OutputMappingStrategy(value)

Bases: Enum

Strategy for mapping quantum probability distributions to classical outputs.

Valid values are as follows:

LINEAR = <OutputMappingStrategy.LINEAR: 'linear'>
GROUPING = <OutputMappingStrategy.GROUPING: 'grouping'>
LEXGROUPING = <OutputMappingStrategy.LEXGROUPING: 'lexgrouping'>
MODGROUPING = <OutputMappingStrategy.MODGROUPING: 'modgrouping'>
NONE = <OutputMappingStrategy.NONE: 'none'>
class merlin.core.layer.QuantumLayer(input_size, output_size=None, ansatz=None, circuit=None, input_state=None, n_photons=None, trainable_parameters=(), input_parameters=(), output_mapping_strategy=OutputMappingStrategy.LINEAR, device=None, dtype=None, shots=0, sampling_method='multinomial', no_bunching=True, index_photons=None)

Bases: Module

Enhanced Quantum Neural Network Layer with factory-based architecture.

This layer can be created either from: 1. An Ansatz object (from AnsatzFactory) - for auto-generated circuits 2. Direct parameters - for custom circuits (backward compatible)

Args:
index_photons (List[Tuple[int, int]], optional): List of tuples (min_mode, max_mode)

constraining where each photon can be placed. The first_integer is the lowest index layer a photon can take and the second_integer is the highest index. If None, photons can be placed in any mode from 0 to m-1.

forward(*input_parameters, apply_sampling=None, shots=None)

Forward pass through the quantum layer.

Return type:

Tensor

get_index_photons_info()

Get information about index_photons constraints.

Return type:

dict

Returns:

dict: Information about photon placement constraints

prepare_parameters(input_parameters)

Prepare parameter list for circuit evaluation.

Return type:

list[Tensor]

set_sampling_config(shots=None, method=None)

Update sampling configuration.

classmethod simple(input_size, n_params=100, shots=0, reservoir_mode=False, output_size=None, output_mapping_strategy=OutputMappingStrategy.NONE, device=None, dtype=None, no_bunching=True)

Simplified interface for creating a QuantumLayer.

Uses SERIES circuit type with PERIODIC state pattern as defaults. Automatically calculates the number of modes based on n_params.

Args:

input_size (int): Size of the input vector n_params (int): Total number of parameters desired (default: 100). Formula: n_params = 2 * n_modes^2 shots (int): Number of shots for sampling (default: 0) reservoir_mode (bool): Whether to use reservoir mode (default: False) output_size (int, optional): Output dimension. If None, uses distribution size output_mapping_strategy: How to map quantum output to classical output device: PyTorch device dtype: PyTorch dtype no_bunching: Whether to exclude states with multiple photons per mode

Returns:

QuantumLayer: Configured quantum layer instance

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 complex dtypes. In addition, this method will only cast the floating point or complex parameters and buffers to dtype (if given). The integral parameters and buffers will be moved device, if that is given, but with dtypes unchanged. When non_blocking is 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)

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)
enum merlin.core.layer.StatePattern(value)

Bases: Enum

Input photon state patterns.

Valid values are as follows:

DEFAULT = <StatePattern.DEFAULT: 'default'>
SPACED = <StatePattern.SPACED: 'spaced'>
SEQUENTIAL = <StatePattern.SEQUENTIAL: 'sequential'>
PERIODIC = <StatePattern.PERIODIC: 'periodic'>