Quantum convolutional neural networks

oracq.algorithms.qml.qcnn

Implementation of the quantum convolutional neural network (QCNN, arXiv:1911.01117, ICLR 2020).

The paper writes the CNN convolution as an im2col matrix product A^l F^l = Y^{l+1} (Eq. 5-7); on the quantum side, QRAM loads the row/column vectors, a Hadamard-type circuit estimates the inner product (Eq. 16-19), amplitude estimation encodes P_pq into a register and arithmetic recovers Y_pq=(2P-1)||A_p|| ||F_q|| (Eq. 22-25), Boolean circuits implement capReLu (a ReLU with cap C), conditional rotation moves pixel values into amplitudes (Eq. 28-29), and after amplitude amplification and l_inf tomography sampling the values are written back into the next layer’s QRAM under the online overwrite rule while pooling completes at the same time (§5.2.2).

This file provides the classical substrate first: the layer specification, im2col, the classical forward mirror, and the row-tree QRAM (including the pooling overwrite rule); the quantum building blocks are implemented equation by equation in qcnn_layer.py per §5.1 of the paper. The semantic validation of both files lives in tests/core/test_qcnn.py.

oracq.algorithms.qml.qcnn.tensor_get(x, shape, i, j, d)[source]

Read the element at (i, j, d) of a row-major flat tensor with channels last (H×W×D).

Parameters:
  • x – Tensor data stored flat in row-major order.

  • shape – Shape tuple of the form (H, W, D).

  • i – Row coordinate.

  • j – Column coordinate.

  • d – Channel coordinate.

Returns:

The element value, i.e. x[(i*W+j)*D+d].

class oracq.algorithms.qml.qcnn.ConvSpec(input_shape, kernel_shape, cap=5.0, pool=1, pool_kind='max')[source]

Bases: object

Single convolution layer specification: input H×W×D, kernel h×w×D×D’, cap C, and P×P pooling.

input_shape
kernel_shape
cap = 5.0
pool = 1
pool_kind = 'max'
property output_shape

Output shape of the valid convolution, i.e. (H-kh+1, W-kw+1, D').

property pooled_shape

Output shape after pooling; identical to output_shape when pool is 1.

Raises:

ValueError – The output spatial dimensions are not divisible by the pooling window.

oracq.algorithms.qml.qcnn.im2col(x, spec)[source]

Unroll the input tensor into A^l (Eq. 6): each row is one receptive field stacked by channel.

Parameters:
  • x – Input tensor data stored flat in row-major order (H×W×D).

  • spec – Convolution layer specification, determining the receptive field size and the channel counts.

Returns:

The unrolled matrix, one receptive field per row, stacked in (d, ki, kj) order.

Return type:

list[list[float]]

oracq.algorithms.qml.qcnn.kernel_columns(kernel, spec)[source]

Columns of F^l (Eq. 6): each column is one kernel vectorized in (d, ki, kj) order.

Parameters:
  • kernel – Flat sequence of convolution kernel coefficients, matching the kernel shape of the specification.

  • spec – Convolution layer specification, determining the kernel count and the vectorization order.

Returns:

Coefficient vectors, one column per output-channel kernel.

Return type:

list[list[float]]

oracq.algorithms.qml.qcnn.cap_relu(value, cap)[source]

capReLU (paper §5.1.6): min(max(x, 0), cap).

Parameters:
  • value – Scalar to activate.

  • cap – Activation cap, must be positive.

Returns:

The activation value clamped to [0, cap].

Return type:

float

oracq.algorithms.qml.qcnn.convolution_forward(x, kernel, spec)[source]

Classical mirror: A F = Y followed by capReLU, then pooling per Eq. 39.

Parameters:
  • x – Input tensor data stored flat in row-major order.

  • kernel – Flat sequence of convolution kernel coefficients.

  • spec – Convolution layer specification, determining the receptive field, the activation cap, and the pooling kind.

Returns:

The pooled output matrix, rows for spatial positions and columns for output channels.

Return type:

list[list[float]]

oracq.algorithms.qml.qcnn.pool_tensor(y_rows, spec)[source]

Pool the (H^{l+1}W^{l+1})×D^{l+1} row-major matrix per Eq. 39.

Parameters:
  • y_rows – Convolution output matrix, one spatial position per row.

  • spec – Convolution layer specification; returned as-is when pool is 1.

Returns:

The pooled matrix; max takes the window high value and average the window mean.

Return type:

list[list[float]]

class oracq.algorithms.qml.qcnn.QCNNQRAM(rows)[source]

Bases: object

The QRAM data structure of paper §5.2 (classical side): one partial-norm tree per row.

The tree is a 1-based complete binary heap: leaves store row elements and internal nodes store squared partial sums; it supports the row-value and row-norm queries needed by the |p>|0> → |p>|A_p> semantics, as well as the online pooling overwrite of §5.2.2 (max keeps the high value, average spreads it).

width
count
leaf_start
tree_size
trees
leaves
row(p)[source]

Return the list of values of row p (a reference to internal storage, not a copy).

Parameters:

p – Row index, in 0..number of rows − 1.

Returns:

Current values of each column in that row.

Return type:

list[float]

norm(p)[source]

Euclidean norm of row p, the square root of the root of the squared-partial-sum tree.

Parameters:

p – Row index, in 0..number of rows − 1.

Returns:

Euclidean norm of that row vector.

Return type:

float

update_with_pooling(p, r, value, kind, state=None)[source]

Online overwrite (§5.2.2): max writes only when the new value is higher, average spreads it.

state is the accumulated count at (p, r) (needed by average pooling); the new state is returned.

Parameters:
  • p – Row index, in 0..number of rows − 1.

  • r – Column index, in 0..row width − 1.

  • value – Candidate value to overwrite with.

  • kind – Pooling kind, max or average.

  • state – Accumulated count at this position; used by average pooling only.

Returns:

The updated accumulated count; returned unchanged under max pooling.

Return type:

int | None