merlin.models.qcnn module
Quantum convolutional neural network model definitions.
- class merlin.models.qcnn.QCNNClassifier(input_shape, num_classes, stages=None)
Bases:
ModuleQuantum convolutional neural network classifier.
QCNNClassifierbuilds a trainable PyTorch model from a sequence of quantum convolution and quantum pooling stages followed by a quantum dense and a readout stage. The model is designed for square, single-channel image-like tensors. Each input image is amplitude-encoded into a two-photonStateVector: one photon occupies a mode in the first register, the other occupies a mode in the second register, and each pixel value scales the basis state identified by its row and column.The resulting state vector is propagated through a
torch.nn.Sequentialpipeline.QConvstages apply trainable Perceval beam-splitter circuits independently to each register. Within a given register, all convolution windows share the same trainable parameter; the two registers keep distinct trainable parameters.QPoolstages partially measure selected modes, reinsert measured photons in the reduced register, continue the remaining QCNN pipeline on each valid measurement branch, and combine branch logits weighted by their probabilities. The finalQDensestage applies a dense trainable photonic circuit, maps output probabilities to a tensor, and feeds them to a classical linear readout that returns class logits.- Parameters:
input_shape (tuple | list) – Spatial shape of the input image, written as
(height, width). The current implementation requires a positive square shape.num_classes (int) – Number of output classes produced by the final readout layer.
stages (list[QCNNClassifier.QConv | QCNNClassifier.QPool | QCNNClassifier.QDense] | None) – Optional stage specification. If omitted, the classifier uses
QConv(kernel_size=2, stride=2),QPool(kernel_size=2), thenQDense(). Default isNone. An empty list is invalid and raisesValueError.
- stages
User-provided stage specification.
- Type:
list[QCNNClassifier.QConv | QCNNClassifier.QPool | QCNNClassifier.QDense] | None
- layers
Executable PyTorch module containing the named quantum stages and readout. Individual layers can be inspected with integer indexing, for example
classifier.layers[0].- Type:
- Raises:
TypeError – If
input_shapeis not a tuple or list of integers, ifnum_classesis not an integer, or ifstagesis neitherNonenor a list.ValueError – If
input_shapeis not positive and square, ifnum_classesis not positive, or ifstagesdoes not satisfy the QCNN stage constraints.
- class QConv(kernel_size, stride)
Bases:
_StageQuantum convolution stage specification.
A convolution stage applies the same construction rule to both quantum registers. Each sliding window is represented by a trainable beam-splitter mesh spanning
kernel_sizeadjacent modes, and windows advance bystridemodes. The convolution windows within one register share a single trainable beam-splitter parameter.- Parameters:
- Raises:
TypeError – If
kernel_sizeorstrideis not an integer.ValueError – If
kernel_sizeorstrideis not positive.
- class QDense
Bases:
_StageDense quantum readout stage specification.
The dense stage is mandatory and must appear as the final QCNN stage. It applies a trainable beam-splitter circuit across all remaining modes before the classical readout layer.
- class QPool(kernel_size)
Bases:
_StageQuantum pooling stage specification.
A pooling stage partially measures one mode per pooling window in each register. Valid measurement branches are propagated through the remaining stages and recombined by their probabilities.
- Parameters:
kernel_size (int) – Number of adjacent modes covered by each pooling window.
- Raises:
TypeError – If
kernel_sizeis not an integer.ValueError – If
kernel_sizeis less than or equal to1.
- class _Stage(type)
Bases:
objectBase container for a QCNN stage.
- Parameters:
type (
QCNNClassifier._QCNNStageTypes) – Internal identifier of the stage kind.
- amplitude_encode(x)
Encode image pixels as amplitudes of a two-photon state vector.
Pixel
x[:, :, i, j]scales the basis state with one photon in modeiof the first register and one photon in modeinput_shape[0] + jof the second register. The resulting state vector is normalized before being passed to the quantum layers.- Parameters:
x (torch.Tensor) – Input tensor with shape
(batch_size, 1, input_shape[0], input_shape[1]).- Returns:
Normalized amplitude-encoded batch with shape
(batch_size, basis_size). The basis size is determined bysum(input_shape)modes and two photons.- Return type:
- build_conv_circuit(shape, stage)
Build a quantum convolution circuit for both registers.
The two registers remain separate: no beam splitter is added between modes belonging to different registers. Each register receives the same sliding-window convolution pattern. All convolution windows in the first register share
px_first_registeras their beam-splitter parameter, and all convolution windows in the second register sharepx_second_register.- Parameters:
shape (tuple[int, int]) – Current dimensions of the two quantum registers.
stage (QCNNClassifier.QConv) – Convolution stage specification.
- Returns:
Perceval circuit implementing the convolution stage.
- Return type:
- build_dense_circuit(shape)
Build the dense quantum readout circuit.
The circuit is a trainable beam-splitter mesh spanning all remaining modes, following the dense QCNN construction presented by Monbroussou et al.
- build_qcnn_model()
Build the executable quantum-classical QCNN pipeline.
Each resolved stage is converted into a
QuantumLayer. Quantum convolution layers return amplitudes so that later quantum stages can continue operating on state vectors. Quantum pooling layers returnPartialMeasurementobjects for branch processing. The final dense quantum layer returns probabilities that are consumed by a classicaltorch.nn.Linearreadout.- Returns:
Sequential module containing all quantum stages followed by the linear readout.
- Return type:
- Raises:
TypeError – If an unknown stage type is encountered while building the model.
- build_single_conv(i, kernel_size, circuit, parameter)
Add one trainable convolution window to a circuit.
A single window is implemented as a down-and-up beam-splitter mesh so a photon can mix across the modes covered by
kernel_size. Every beam splitter inserted by this window uses the suppliedparameterso the caller can share trainable parameters across several windows.- Parameters:
i (int) – First mode of the convolution window.
kernel_size (int) – Number of modes covered by the window.
circuit (pcvl.Circuit) – Circuit to mutate with the trainable beam splitters.
parameter (
pcvl.P) – Shared Perceval parameter used as thethetavalue for every beam splitter in the convolution window.
- Returns:
Circuit with the added convolution window.
- Return type:
- export_config()
Export a serializable architecture configuration.
Weights are intentionally excluded. The returned dictionary can be used to reconstruct an equivalent
QCNNClassifierarchitecture by rebuilding the stage objects from their serializedtypeentries.- Returns:
Serializable architecture metadata containing
input_shape,num_classes, and the resolved stage list understages.- Return type:
- forward(x)
Evaluate the classifier on a batch of images.
The input tensor is amplitude-encoded, propagated through the resolved quantum stages, and finally mapped to class logits by the readout layer. If a pooling stage is encountered, its measurement branches are handled by
postprocess_pooling(), which continues the remaining stages on each valid branch and returns the probability-weighted logits.- Parameters:
x (torch.Tensor) – Input tensor with shape
(batch_size, 1, input_shape[0], input_shape[1]). The second dimension is the channel dimension; only one channel is currently supported.- Returns:
Logits with shape
(batch_size, num_classes).- Return type:
- Raises:
TypeError – If the model pipeline does not return a tensor.
ValueError – If
xdoes not have the expected rank, channel count, or spatial dimensions, or if the output logits do not have the expected shape.
- classmethod from_config(config)
Build a classifier from
export_config()metadata.- Parameters:
config (dict) – Serialized architecture metadata containing
input_shape,num_classes, andstages.- Returns:
Reconstructed classifier with the same architecture.
- Return type:
- Raises:
ValueError – If a serialized stage type is unknown.
- postprocess_pooling(x, layer_index)
Process pooling measurement branches and combine their logits.
Each valid measurement branch is checked against the two-register QCNN constraints, measured photons are reinserted into the reduced state, and the branch is propagated through the remaining layers. Branch outputs are weighted by their measurement probabilities and summed.
- Parameters:
x (PartialMeasurement) – Partial measurement returned by a quantum pooling layer.
layer_index (int) – Index of the next layer to execute after the pooling layer.
- Returns:
Probability-weighted logits with shape
(batch_size, num_classes).- Return type:
- Raises:
TypeError – If a remaining pipeline branch does not return a tensor.
ValueError – If a branch state has an unexpected photon count, if branch logits or probabilities have incompatible shapes, or if a forbidden measurement outcome has non-zero probability.
- recursive_forward(x, layer_index)
Continue the QCNN pipeline from a specific layer index.
This helper is used after pooling, where each valid measurement branch contains a separate state vector. The branch state is propagated through the remaining layers, and nested pooling stages are post-processed in the same way as in
forward().- Parameters:
x (merlin.core.state_vector.StateVector) – Branch state vector with shape
(batch_size, basis_size).layer_index (int) – Index of the next layer to execute in
self.layers.
- Returns:
Result produced by the remaining pipeline. In normal classifier use this resolves to logits with shape
(batch_size, num_classes).- Return type:
torch.Tensor | merlin.core.state_vector.StateVector | PartialMeasurement
- Raises:
TypeError – If a pooling layer does not return a
PartialMeasurement, or if pooling post-processing does not return a tensor.
- reinsert_photon(state_vector, reinsert_mode)
Insert one photon into a state-vector basis.
The operation maps amplitudes from the current basis to the basis with one additional photon while preserving the PyTorch computation graph. Amplitudes whose source states already contain a photon in
reinsert_modeare skipped because inserting there would violate the QCNN branch structure.- Parameters:
state_vector (merlin.core.state_vector.StateVector) – State vector before photon reinsertion.
reinsert_mode (int) – Mode in which to reinsert the measured photon.
- Returns:
New state vector with the same number of modes and one additional photon.
- Return type:
- resolve_pooling_modes(shape, stage)
Resolve measured modes and output shape for a pooling stage.
The first mode of every pooling window is measured. A photon detected in that mode is reinserted into the following mode after the measurement branch is reduced, which preserves the two-photon QCNN representation for downstream layers.
- Parameters:
shape (tuple[int, int]) – Current dimensions of the two quantum registers.
stage (QCNNClassifier.QPool) – Pooling stage specification.
- Returns:
Measured modes, reinsertion modes, and the reduced register shape.
- Return type:
- Raises:
ValueError – If pooling would produce registers with different dimensions.
- resolve_stages()
Validate the stage specification and return the executable sequence.
When no stage sequence is supplied, a default three-stage architecture is created. Custom stage sequences must end with exactly one dense stage, must use convolution kernels that fit the current register dimension, and must use pooling kernels that evenly reduce the current register dimension.
- Returns:
Validated stage sequence used to build the QCNN.
- Return type:
list[QCNNClassifier.QConv | QCNNClassifier.QPool | QCNNClassifier.QDense]
- Raises:
ValueError – If the stage order or stage parameters are incompatible with the current register dimensions, or if an unknown stage type is present.
- property resolved_stages: list[merlin.models.qcnn.QCNNClassifier._Stage]
Validated stage sequence used to build the model.
- summary()
Return a concise, human-readable description of the architecture.
- Returns:
String containing input shape, number of classes, and resolved stage sequence.
- Return type:
- to(*args, **kwargs)
Move the classifier and quantum-layer runtime state to a device or dtype.
- verify_outcome(outcome, probabilities)
Validate whether a pooling measurement outcome is physically usable.
A valid QCNN pooling outcome measures at most one photon per register and only contains
0or1occupation values. Forbidden outcomes are expected to have zero probability and raise aValueErrorif they do not.- Parameters:
outcome (Sequence[int]) – Measured occupation pattern for the pooled modes.
probabilities (torch.Tensor) – Branch probabilities for every batch item.
- Returns:
Whether the outcome can be propagated through the QCNN pipeline.
- Return type:
- Raises:
ValueError – If
outcomedoes not contain one measured pattern per register, or if a forbidden outcome has non-zero probability.