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:
ModuleGenerative 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 throughoutput_adapterinforward().- 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 createscountheads with the same configuration and independent trainable initializations. All heads must expose the sameinput_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
GeneratorMeasurementsto a tensor. Built-in adapters inherit from the abstractOutputAdapterextension interface, but custom adapters only need to be PyTorch modules with a compatibleforwardmethod.latent (LatentDistribution | None) – Latent distribution used by
sample_latent()andgenerate(). If omitted,NormalLatentwith the inferred latent dimension andstd=2*piis used. Default isNone.count (int | None) – Number of independent copies to create when
layersis a singleQuantumLayer. Heads have separate trainable parameters, and heads after the first are reinitialized to match repeated construction from the same layer recipe. Must be omitted whenlayersis a sequence. Default isNone.
- Raises:
TypeError – If
layersis neither a singleQuantumLayernor a sequence ofQuantumLayer, ifoutput_adapteris not atorch.nn.Module, or iflatentis not aLatentDistribution, or ifcountdoes 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
countis 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:
- 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:
- latent: LatentDistribution
- 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:
- Raises:
TypeError – If
zis not atorch.Tensor.ValueError – If
zdoes not have shape(batch_size, latent_dim).
- 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:
- to(*args, **kwargs)
Move the generator and quantum-layer runtime state.
- Parameters:
*args (Any) – Positional arguments forwarded to
torch.nn.Module.to().**kwargs (Any) – Keyword arguments forwarded to
torch.nn.Module.to().
- Returns:
The updated generator instance.
- Return type:
- class merlin.models.photonic_generator.NormalLatent(dim, mean=0.0, std=1.0)
Bases:
LatentDistributionIndependent normal latent distribution.
- Parameters:
- Raises:
ValueError – If
stdis 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:
- Raises:
TypeError – If
batch_sizedoes not have int type.ValueError – If
batch_sizeis not positive.
- class merlin.models.photonic_generator.VectorAdapter(size)
Bases:
OutputAdapterConcatenate 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:
TypeError – If
sizedoes not have int type.ValueError – If
sizeis not positive.
- 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:
- 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:
OutputAdapterAdapt 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. IfTrue, 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 isFalse.normalize_patches (bool) – Whether to divide each headwise patch by its per-sample maximum after crop/pad. Requires
headwise=True. Default isFalse.
- Raises:
TypeError – If
shapeis not a tuple of integers, or ifheadwiseornormalize_patchesdo not have bool type.ValueError – If
shapedoes not have length 2 or 3, or if any dimension is not positive, or ifnormalize_patches=Trueis requested withoutheadwise=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:
- Raises:
ValueError – If
headwise=Trueand 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:
objectRaw outputs produced by a PhotonicGenerator.
- Parameters:
outputs (tuple[torch.Tensor | merlin.core.partial_measurement.PartialMeasurement, ...]) – Per-layer batched outputs. Tensor outputs have their first dimension as the latent batch dimension. Partial measurements keep their native Merlin representation.
output_keys (tuple[tuple[Any, ...], ...]) – Per-layer output-basis metadata copied from each underlying
QuantumLayer.
-
outputs:
tuple[Tensor|PartialMeasurement,...]
- class merlin.models.photonic_generator.LatentDistribution(dim)
Bases:
ABCAbstract base class for PhotonicGenerator latent samplers.
Users normally rely on
NormalLatent, which is the default sampler created byPhotonicGenerator. SubclassLatentDistributionwhen a generator needs a custom latent sampling rule.- Parameters:
dim (int) – Dimension of the latent vector sampled for each batch item.
- Raises:
TypeError – If
dimdoes not have int type.ValueError – If
dimis not positive.
- 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:
- Raises:
NotImplementedError – If called from a subclass that delegates to the abstract base implementation.
- class merlin.models.photonic_generator.OutputAdapter(*args, **kwargs)
-
Abstract base class for custom generator output adapters.
Users normally use
VectorAdapterorImageAdapterdirectly. SubclassOutputAdapterwhen 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:
- Raises:
NotImplementedError – If called from a subclass that delegates to the abstract base implementation.