QuantumCore

Hands-on lab · 1 step

Train a QCNN to tell horizontal from vertical bars

Train the 4-qubit quantum convolutional neural network of the lesson, with 1212 shared weights, on 2×22\times2 images of horizontal and vertical bars. Your TypeScript function receives 4040 training images and returns the weights p0 to p11. You write the loss, the gradient and the optimiser. For the gradient, the engine's parameterShiftGradient applies the two-term rule to the RYR_Y weights and the four-term rule to the CRZCR_Z/CRXCR_X pooling weights. The grader binds your weights into the fixed QCNN circuit and classifies 100100 held-out images by sign⟨Z3⟩\mathrm{sign}\langle Z_3\rangle; at least 90%90\% must be correct.

0/1 step passedBest score 0/100

Step 1: Implement trainQCNN

Complete the TypeScript function

trainQCNN(Xtrain: number[][], ytrain: number[]): Record<string, number>

The model. qcnnTemplate() from 'quantumcore/qml' is the circuit the grader uses. It has four data parameters x0 to x3 and twelve weights p0 to p11; qubit 00 is the most significant bit and RP(θ)=e−iθP/2R_P(\theta)=e^{-i\theta P/2}. In time order:

  1. Encoding: RY(πxq)R_Y(\pi x_q) on qubit q=0,1,2,3q=0,1,2,3, so a pixel value xq∈[0,1]x_q\in[0,1] sets ⟨Zq⟩=cos⁡πxq\langle Z_q\rangle=\cos\pi x_q.
  2. Convolution layer 1: the block Cij(a0,a1,a2,a3)=RY(i)(a0) RY(j)(a1) CNOT(i,j) RY(i)(a2) RY(j)(a3) CNOT(j,i)C_{ij}(a_0,a_1,a_2,a_3)=R_Y^{(i)}(a_0)\,R_Y^{(j)}(a_1)\,\mathrm{CNOT}(i,j)\,R_Y^{(i)}(a_2)\,R_Y^{(j)}(a_3)\,\mathrm{CNOT}(j,i) (time order) on the pairs (0,1)(0,1), (2,3)(2,3), (1,2)(1,2), (3,0)(3,0), all with the same weights (a0,…,a3)=(p0,…,p3)(a_0,\dots,a_3)=(p_0,\dots,p_3).
  3. Pooling layer 1: Pc→t(b0,b1)=CRZ(c,t,b0) X(c) CRX(c,t,b1) X(c)P_{c\to t}(b_0,b_1)=CR_Z(c,t,b_0)\,X(c)\,CR_X(c,t,b_1)\,X(c), which rotates qubit tt by RZ(b0)R_Z(b_0) if qubit cc is ∣1⟩\lvert1\rangle and by RX(b1)R_X(b_1) if it is ∣0⟩\lvert0\rangle, on 0→10\to1 and 2→32\to3 with the shared weights (b0,b1)=(p4,p5)(b_0,b_1)=(p_4,p_5). Qubits 00 and 22 are not used again.
  4. Convolution layer 2: C13(p6,p7,p8,p9)C_{13}(p_6,p_7,p_8,p_9).
  5. Pooling layer 2: P1→3(p10,p11)P_{1\to3}(p_{10},p_{11}).
  6. Readout: f(x)=⟨Z3⟩f(x)=\langle Z_3\rangle (Pauli word IIIZ), prediction y^=sign f(x)\hat y=\mathrm{sign}\,f(x); f=0f=0 counts as wrong.

The data. Xtrain holds 4040 images, each an array [x0, x1, x2, x3] of pixel values in [0,1][0,1] in the order q0 q1q_0\,q_1 (top row), q2 q3q_2\,q_3 (bottom row). ytrain[m] is +1+1 for a horizontal bar (pattern 1100 or 0011) and −1-1 for a vertical bar (1010 or 0101). A pixel that is on has a value in [0.75,1)[0.75,1) and a pixel that is off a value in [0,0.25)[0,0.25). The training set has 2020 images of each class.

What to write. A training loop that lowers a loss over the training set, for example the mean squared error L(p)=1M∑m(fp(xm)−ym)2L(p)=\frac1M\sum_m\big(f_p(x_m)-y_m\big)^2 with ∂L/∂pk=2M∑m(fp(xm)−ym) ∂fp(xm)/∂pk\partial L/\partial p_k=\frac2M\sum_m\big(f_p(x_m)-y_m\big)\,\partial f_p(x_m)/\partial p_k. Compute ∂f/∂pk\partial f/\partial p_k with the parameter-shift rule: either the engine's parameterShiftGradient(template, observable, { bindings, params }) from 'quantumcore', which applies the four-term rule to the controlled pooling rotations and sums over every gate that shares a weight, or your own function from the parameter-shift lab. The lesson proves that for these pooling gates the plain two-term rule is exact as well, because each pooled qubit is used only as a control afterwards; with your own function you must still sum the contributions of every gate that shares a weight. Any optimiser is allowed: gradient descent, Adam, or several random restarts. The starter code initialises the weights at random and returns them untrained.

What to return. An object with exactly the keys p0 to p11, each a finite number.

Grading. The function runs once, with the training set as its arguments, in a time limit of 60 seconds. The reference solution (Adam, 3030 full-batch steps, 40⋅6540\cdot65 circuit evaluations per step) needs about 22 seconds. The check shape verifies the returned keys. The check model binds your weights into qcnnTemplate() on the server and computes the accuracy on 100100 held-out images from the same distribution. These images are never sent to your browser, so the score cannot be tuned against them. The required accuracy is at least 0.90.9; the reference reaches test accuracy 1.00 on the 100 held-out images.

About the shortcut. The module 'quantumcore/qml' also exports a reference trainQCNN (with qcnnPredict and barsDataset), which the lesson uses. Calling it would pass this lab without doing the exercise. The grader only sees the returned weights, so it cannot tell who trained them: this rule is not enforced, and the exercise only works if you write the loop yourself.

TypeScript: export trainQCNN · 1 test · imports: quantumcore, quantumcore/qml
Run the tests first; the results of your latest run are submitted.