merlin.models.photonic_generator module

Photonic generator model built from QuantumLayer heads.

The generator is a thin PyTorch model abstraction: it runs one latent batch through one or more QuantumLayer heads and delegates task-specific output shaping to an adapter.

The repeated-head image workflow is intended to support photonic QGAN-style generators such as the architecture introduced in Optica Quantum 2, 458 (2024).

Direct-use classes

class merlin.models.photonic_generator.PhotonicGenerator(layers, output_adapter, latent=None, *, count=None)

Bases: Module

Generative model composed from one or more QuantumLayer heads.

Each generator head receives the same latent batch. The raw per-head measurements are exposed through measure() and converted to task-native samples through output_adapter in forward().

Parameters:
  • layers (merlin.algorithms.layer.QuantumLayer | Sequence[merlin.algorithms.layer.QuantumLayer]) – Quantum generator head template or non-empty sequence of quantum generator heads. If a single layer is provided with count, Merlin creates count heads with the same configuration and independent trainable initializations. All heads must expose the same input_size. Amplitude-output measurement strategies are not supported because they do not directly represent classical generated samples.

  • output_adapter (torch.nn.Module) – Module that maps GeneratorMeasurements to a tensor. Built-in adapters inherit from the abstract OutputAdapter extension interface, but custom adapters only need to be PyTorch modules with a compatible forward method.

  • latent (LatentDistribution | None) – Latent distribution used by sample_latent() and generate(). If omitted, NormalLatent with the inferred latent dimension and std=2*pi is used. Default is None.

  • count (int | None) – Number of independent copies to create when layers is a single QuantumLayer. Heads have separate trainable parameters, and heads after the first are reinitialized to match repeated construction from the same layer recipe. Must be omitted when layers is a sequence. Default is None.

Raises:
  • TypeError – If layers is neither a single QuantumLayer nor a sequence of QuantumLayer, if output_adapter is not a torch.nn.Module, or if latent is not a LatentDistribution, or if count does not have int type when provided.

  • ValueError – If no layers are provided, if layer input sizes differ, if a layer uses amplitude outputs, or if the latent distribution dimension does not match the inferred latent dimension, or if count is not positive.

forward(z)

Generate samples from latent vectors.

Parameters:

z (torch.Tensor) – Latent input tensor with shape (batch_size, latent_dim).

Returns:

Task-native generated samples produced by output_adapter.

Return type:

torch.Tensor

generate(batch_size, *, device=None, dtype=None)

Sample latent vectors and generate classical samples.

Parameters:
  • batch_size (int) – Number of samples to generate.

  • device (torch.device | None) – Device on which latent vectors are sampled. If omitted, the generator chooses a device from its parameters and buffers. Default is None.

  • dtype (torch.dtype | None) – Floating dtype of sampled latent vectors. If omitted, the generator chooses a dtype from its parameters and buffers. Default is None.

Returns:

Generated samples returned by output_adapter.

Return type:

torch.Tensor

latent: LatentDistribution
property latent_dim: int

Dimension of the latent vectors accepted by the generator.

layers: nn.ModuleList
measure(z)

Evaluate every quantum generator head on a latent batch.

Parameters:

z (torch.Tensor) – Latent input tensor with shape (batch_size, latent_dim).

Returns:

Per-layer outputs and output-key metadata.

Return type:

GeneratorMeasurements

Raises:
output_adapter: nn.Module
sample_latent(batch_size, *, device=None, dtype=None)

Sample latent vectors from the configured latent distribution.

Parameters:
  • batch_size (int) – Number of latent vectors to sample.

  • device (torch.device | None) – Device on which the tensor is created. If omitted, the generator uses the first parameter or buffer device, falling back to CPU. Default is None.

  • dtype (torch.dtype | None) – Floating dtype of the returned tensor. If omitted, the generator uses the first floating parameter or buffer dtype, falling back to the current PyTorch default dtype. Default is None.

Returns:

Tensor with shape (batch_size, latent_dim).

Return type:

torch.Tensor

to(*args, **kwargs)

Move the generator and quantum-layer runtime state.

Parameters:
Returns:

The updated generator instance.

Return type:

PhotonicGenerator

class merlin.models.photonic_generator.NormalLatent(dim, mean=0.0, std=1.0)

Bases: LatentDistribution

Independent normal latent distribution.

Parameters:
  • dim (int) – Dimension of the latent vector sampled for each batch item.

  • mean (float) – Mean of the normal distribution. Default is 0.0.

  • std (float) – Standard deviation of the normal distribution. Default is 1.0.

Raises:

ValueError – If std is not positive.

sample(batch_size, *, device=None, dtype=None)

Sample normally distributed latent vectors.

Parameters:
  • batch_size (int) – Number of latent vectors to sample.

  • device (torch.device | None) – Device on which the tensor is created. If omitted, CPU is used.

  • dtype (torch.dtype | None) – Floating dtype of the returned tensor. If omitted, the current PyTorch default dtype is used.

Returns:

Tensor with shape (batch_size, dim).

Return type:

torch.Tensor

Raises:
  • TypeError – If batch_size does not have int type.

  • ValueError – If batch_size is not positive.

class merlin.models.photonic_generator.VectorAdapter(size)

Bases: OutputAdapter

Concatenate tensor measurements into fixed-width vectors.

The adapter flattens every tensor output after its batch dimension, concatenates the flattened outputs, and center-crops or zero-pads to size.

Parameters:

size (int) – Number of features in each generated vector.

Raises:
forward(measurements)

Return fixed-width vectors from tensor measurements.

Parameters:

measurements (GeneratorMeasurements) – Raw generator measurements. All outputs must be batched tensors with a common first dimension.

Returns:

Tensor with shape (batch_size, size).

Return type:

torch.Tensor

Raises:
  • TypeError – If any measurement output is not a tensor.

  • ValueError – If no outputs are provided, if tensor outputs are not batched, or if batch dimensions differ.

size: int
class merlin.models.photonic_generator.ImageAdapter(shape, *, headwise=False, normalize_patches=False)

Bases: OutputAdapter

Adapt tensor measurements to GAN-native image tensors.

Parameters:
  • shape (tuple[int, int] | tuple[int, int, int]) – Image shape. (height, width) produces single-channel output with shape (batch_size, 1, height, width). (channels, height, width) preserves the specified channel count.

  • headwise (bool) – Whether to adapt each generator head to an equal-sized image patch before concatenation. If False, all heads are flattened, concatenated, and center-cropped or padded once to the total image feature count. If True, each head is center-cropped or padded to an equal patch size before the patches are concatenated. Center-cropping discards features symmetrically from the flattened vector. Default is False.

  • normalize_patches (bool) – Whether to divide each headwise patch by its per-sample maximum after crop/pad. Requires headwise=True. Default is False.

Raises:
  • TypeError – If shape is not a tuple of integers, or if headwise or normalize_patches do not have bool type.

  • ValueError – If shape does not have length 2 or 3, or if any dimension is not positive, or if normalize_patches=True is requested without headwise=True.

forward(measurements)

Return image tensors from raw generator measurements.

Parameters:

measurements (GeneratorMeasurements) – Raw generator measurements accepted by VectorAdapter.

Returns:

Tensor with shape (batch_size, channels, height, width).

Return type:

torch.Tensor

Raises:

ValueError – If headwise=True and the image feature count is not divisible by the number of generator heads.

headwise: bool
normalize_patches: bool
shape: tuple[int, int, int]

Extension interfaces

LatentDistribution and OutputAdapter are abstract base classes for custom samplers and adapters. They are not meant to be instantiated directly.

class merlin.models.photonic_generator.GeneratorMeasurements(outputs, output_keys)

Bases: object

Raw outputs produced by a PhotonicGenerator.

Parameters:
output_keys: tuple[tuple[Any, ...], ...]
outputs: tuple[Tensor | PartialMeasurement, ...]
class merlin.models.photonic_generator.LatentDistribution(dim)

Bases: ABC

Abstract base class for PhotonicGenerator latent samplers.

Users normally rely on NormalLatent, which is the default sampler created by PhotonicGenerator. Subclass LatentDistribution when a generator needs a custom latent sampling rule.

Parameters:

dim (int) – Dimension of the latent vector sampled for each batch item.

Raises:
dim: int
abstract sample(batch_size, *, device=None, dtype=None)

Sample a latent batch.

Parameters:
  • batch_size (int) – Number of latent vectors to sample.

  • device (torch.device | None) – Device on which the tensor is created. If omitted, the concrete distribution chooses its default.

  • dtype (torch.dtype | None) – Floating dtype of the returned tensor. If omitted, the concrete distribution chooses its default.

Returns:

Tensor with shape (batch_size, dim).

Return type:

torch.Tensor

Raises:

NotImplementedError – If called from a subclass that delegates to the abstract base implementation.

class merlin.models.photonic_generator.OutputAdapter(*args, **kwargs)

Bases: Module, ABC

Abstract base class for custom generator output adapters.

Users normally use VectorAdapter or ImageAdapter directly. Subclass OutputAdapter when raw quantum measurements need a custom mapping to generated samples.

abstract forward(measurements)

Adapt raw generator measurements.

Parameters:

measurements (GeneratorMeasurements) – Raw outputs and output-key metadata returned by PhotonicGenerator.measure().

Returns:

Task-native generated samples.

Return type:

torch.Tensor

Raises:

NotImplementedError – If called from a subclass that delegates to the abstract base implementation.