QuantumCore

Hands-on lab · 2 steps

Quantum-kernel SVM on two moons

Build the complete quantum-kernel classifier of the lesson in Python. First implement the fidelity kernel K(x,x′)=∣⟨ϕ(x)∣ϕ(x′)⟩∣2K(x,x')=\lvert\langle\phi(x)\vert\phi(x')\rangle\rvert^2 of the two-qubit ZZ feature map with one repetition by simulating its circuit with NumPy; the grader compares your matrices with the platform's statevector engine and checks symmetry and positive semidefiniteness. Then train scikit-learn's SVC(kernel="precomputed", C=1.0) on the 70×7070\times70 training Gram matrix of the two-moons data scaled to [0,π][0,\pi] and predict the 3030 held-out points; the grader computes the test accuracy from your predictions and requires at least 0.900.90 (the reference pipeline reaches 28/3028/30).

0/2 steps passedBest score 0/100

Step 1: The ZZ feature-map kernel

Write the Python function zz_kernel``(X1, X2) that returns the m1×m2m_1\times m_2 NumPy array

Kij=∣⟨ϕ(ai)∣ϕ(bj)⟩∣2,ai=X1[i],bj=X2[j]∈R2,K_{ij}=\big\lvert\langle\phi(a_i)\vert\phi(b_j)\rangle\big\rvert^2,\qquad a_i=\texttt{X1[i]},\quad b_j=\texttt{X2[j]}\in\mathbb R^2,

for the two-qubit ZZ feature map with one repetition,

∣ϕ(x)⟩=CNOT01 P1(2(π−x0)(π−x1)) CNOT01 P0(2x0) P1(2x1) (H⊗H)∣00⟩,\lvert\phi(x)\rangle=\mathrm{CNOT}_{01}\,P_1\big(2(\pi-x_0)(\pi-x_1)\big)\,\mathrm{CNOT}_{01}\,P_0(2x_0)\,P_1(2x_1)\,(H\otimes H)\lvert00\rangle,

where the rightmost gate acts first, Pq(λ)P_q(\lambda) is the phase gate on qubit qq and CNOT01\mathrm{CNOT}_{01} has control 00 and target 11:

H=12(111−1),P(λ)=(100eiλ),CNOT01=(1000010000010010).H=\frac1{\sqrt2}\begin{pmatrix}1&1\\1&-1\end{pmatrix},\qquad P(\lambda)=\begin{pmatrix}1&0\\0&e^{i\lambda}\end{pmatrix},\qquad \mathrm{CNOT}_{01}=\begin{pmatrix}1&0&0&0\\0&1&0&0\\0&0&0&1\\0&0&1&0\end{pmatrix}.

Qubit 00 is the most significant bit of the basis index ∣q0q1⟩\lvert q_0q_1\rangle, so a gate UU on qubit 00 is np.kron(U, I2) and a gate VV on qubit 11 is np.kron(I2, V). Use NumPy only (import numpy as np).

Visible test two-by-two: A={(0.3, 1.2), (1.0, 0.4)}A=\{(0.3,\,1.2),\,(1.0,\,0.4)\} and B={(0.3, 1.2), (2.5, 2.9)}B=\{(0.3,\,1.2),\,(2.5,\,2.9)\}. Since b0=a0b_0=a_0, K00=1K_{00}=1; the reference matrix is

K≈(1.00000000000.40959839110.27548599330.1050335728),K\approx\begin{pmatrix}1.0000000000&0.4095983911\\ 0.2754859933&0.1050335728\end{pmatrix},

compared entrywise with absolute tolerance 10−910^{-9}.

Hidden tests (the arguments reach your browser, the expected values do not): three pairs of point sets in [0,π)2[0,\pi)^2 of sizes 4×34\times3, 5×55\times5 and 3×63\times6, each compared with the engine's kernel at tolerance 10−910^{-9}.

Structural tests symmetric-6 and psd-6: for six points XX, the matrix K(X,X)K(X,X) must satisfy max⁡ij∣Kij−Kji∣≤10−9\max_{ij}\lvert K_{ij}-K_{ji}\rvert\le10^{-9} and have smallest eigenvalue at least −10−9-10^{-9}. Both hold automatically for a correct fidelity kernel; the lesson proves it.

The platform's engine builds the same map with RZ(λ)=e−iλ/2P(λ)R_Z(\lambda)=e^{-i\lambda/2}P(\lambda) instead of P(λ)P(\lambda); the states differ by the global phase e−i(x0+x1+φ01)e^{-i(x_0+x_1+\varphi_{01})} and the kernels are identical, so either gate gives full marks.

Python: define zz_kernel, zz_kernel, zz_kernel · 6 tests · packages: numpy, scikit-learn
Run the tests first; the results of your latest run are submitted.

Python runs in your browser (Pyodide): the interpreter (≈ 9 MB) is downloaded on first use.

Step 2: Train and evaluate the quantum-kernel SVM

Write train_and_predict``(X_train, y_train, X_test) that trains a soft-margin support vector machine on the precomputed ZZ kernel and returns the predicted labels of the test points as a NumPy array (or list) of 0/10/1 values:

  1. Ktrain=K_{\text{train}}= zz_kernel(X_train, X_train), the 70×7070\times70 Gram matrix K(xi,xj)K(x_i,x_j);
  2. Ktest=K_{\text{test}}= zz_kernel(X_test, X_train), the 30×7030\times70 matrix whose row tt holds K(xt∗,xi)K(x^\ast_t,x_i) for all training points;
  3. fit SVC(kernel="precomputed", C=1.0) from sklearn.svm on (Ktrain,ytrain)(K_{\text{train}},y_{\text{train}}) and return predict on KtestK_{\text{test}}.

The classifier is y^(x)=1[f(x)>0]\hat y(x)=\mathbb 1\big[f(x)>0\big] with f(x)=∑iαiyiK(xi,x)+bf(x)=\sum_i\alpha_iy_iK(x_i,x)+b, where scikit-learn internally maps the labels 0/10/1 to ∓1\mp1, solves the dual problem for α\alpha and fixes bb from the Karush–Kuhn–Tucker conditions.

Each step runs its own source, so define zz_kernel again in this step (copy your passing function from step 1); the starter shows both signatures.

Data (passed as arguments): the two-moons sample make_moons(n_samples=100, noise=0.1, random_state=0) of scikit-learn, each feature min–max scaled over all 100100 rows to [0,π][0,\pi]; rows 00–6969 are X_train, y_train, rows 7070–9999 are X_test.

Hidden test moons: the grader compares your 3030 predictions with the true test labels, which never leave the server, and requires a test accuracy of at least 0.900.90, i.e. at least 2727 of 3030 correct. The reference pipeline reaches 28/30≈0.933328/30\approx0.9333.

Python: define train_and_predict · 1 test · packages: numpy, scikit-learn
Run the tests first; the results of your latest run are submitted.

Python runs in your browser (Pyodide): the interpreter (≈ 9 MB) is downloaded on first use.