QubitLab
IDELearnPlaygroundDocsCommunity
Log in
QubitLab
IDELearnPlaygroundDocsCommunity
Log in
HomeLearnCatalogRanksPlaygroundDocs
  1. Docs
  2. Quantum machine learning by hand
Learn
  • Quantum basics
  • OpenQASM 3 cheat sheet
  • All gates, with the math
  • Every gate, interactive
  • Entanglement: how CNOT connects qubits
Circuits
  • Dynamic circuits: if/else, loops and conditions
Lessons
  • Learning path: from one qubit to algorithms
  • Quantum machine learning by hand
Run
  • Compile (transpile): levels, basis gates, topology
  • Simulators, noise, T1/T2 and fake backends
  • Python in the Playground
  • GitHub and git in the Playground
  • Articles and sharing
Analyze
  • Metrics: comparing distributions
  • Q-sphere and Bloch spheres
Hardware
  • Real IBM Quantum hardware
  • Device topology and calibration heat maps
  • Benchmark circuits: MQT Bench and QASMBench
Advanced
  • Circuit cutting, in depth
Story
  • The story of quantum computing
  • The Hamiltonian: where gates come from
  • What to expect next
Documentation/Lessons/Quantum machine learning by hand

Quantum machine learning by hand

In quantum machine learning a circuit is a function with parameters: its expectation value is the output, and you train the parameters. This chapter builds that idea step by step with QubitLab circuits: qubit rotation, gradients by the parameter-shift rule, data encoding, a variational classifier, kernels, and the VQE loop. Every part has an exercise that opens in the IDE.

Part 1 · A circuit is a function with parameters

In PennyLane a QNode binds a quantum function to a device: the function takes classical numbers, applies gates, and returns a measurement such as the expectation value ⟨Z⟩. The smallest example is one qubit with RX(φ₁) then RY(φ₂): its output is ⟨Z⟩ = cos φ₁ cos φ₂, a number between −1 and 1. In QubitLab the same circuit is OpenQASM with angles, and ⟨Z⟩ = p(0) − p(1) from the Probabilities tab.

# PennyLane
dev = qml.device("default.qubit", wires=1)

@qml.qnode(dev)
def circuit(params):
    qml.RX(params[0], wires=0)
    qml.RY(params[1], wires=0)
    return qml.expval(qml.PauliZ(0))

# QubitLab (OpenQASM 3): the same function
# rx(phi1) q[0]; ry(phi2) q[0];  → <Z> = p(0) − p(1)
Same circuit in both languages. PennyLane is not installed in QubitLab: write the circuit in Qiskit or OpenQASM 3, and the IDE's Python editor translates Qiskit-style code to OpenQASM.
⟨Z⟩(φ1​,φ2​)=cosφ1​cosφ2​
Output of RX(φ₁)·RY(φ₂) on |0⟩ measured in Z. Minimising it drives the qubit to |1⟩ where ⟨Z⟩ = −1.
Exercise

Exercise 1 · Qubit rotation

Start from the angles (0.2, 0.3): the cost cos φ₁ cos φ₂ is 0.936, close to its maximum. An optimiser would walk downhill to the minimum −1. Skip it: set the angles to the optimum by hand and confirm ⟨Z⟩ = −1 from the probabilities.

OPENQASM 3.0;
include "stdgates.inc";
qubit[1] q;
bit[1] c;
rx(0.2) q[0];
ry(0.3) q[0];
c[0] = measure q[0];
Open in IDE
Hint

cos φ₁ cos φ₂ = −1 needs cos φ₂ = −1 with φ₁ = 0.

Check your answer

rx(0) ry(pi) gives |1⟩ with probability 100 %, so ⟨Z⟩ = 0 − 1 = −1. At the starting point p(1) ≈ 0.032, matching cost 0.936.

Part 2 · Gradients without backprop: the parameter-shift rule

You cannot differentiate through a real quantum computer, but for any gate of the form e^{-iθG/2} with G having eigenvalues ±1 (every Pauli rotation RX, RY, RZ, and controlled versions) the derivative of an expectation value is exactly a difference of two evaluations shifted by ±π/2. No finite-difference error, just two extra circuit runs per parameter.

∂θ∂f​=2f(θ+2π​)−f(θ−2π​)​
Parameter-shift rule for a Pauli rotation; f is any expectation value of the circuit.
Exercise

Exercise 2 · Shift it by hand

At the angles (0.8, 0.3) the circuit gives f = cos(0.8)·cos(0.3) ≈ 0.6656, and the exact gradient is (−0.6853, −0.2059). Reproduce ∂f/∂φ₁ on the quantum side: run the circuit with φ₁ = 0.8 + π/2 and with φ₁ = 0.8 − π/2, convert each probability pair into ⟨Z⟩ = p(0) − p(1), and take half the difference.

OPENQASM 3.0;
include "stdgates.inc";
qubit[1] q;
bit[1] c;
// shifted +pi/2 (run again with 0.8 - pi/2)
rx(0.8 + pi/2) q[0];
ry(0.3) q[0];
c[0] = measure q[0];
Open in IDE
Hint

Use the ideal statevector target (exact probabilities), not shots, or the noise hides the digits.

Check your answer

f(+) = cos(2.3708)·cos(0.3) ≈ −0.6853 and f(−) = cos(−0.7708)·cos(0.3) ≈ +0.6853, so the gradient is (−0.6853 − 0.6853)/2 = −0.6853, exactly −sin(0.8)cos(0.3).

Part 3 · Getting data into qubits

EncodingHowQubits for d featuresUsed in
Basisbitstring → computational basis state (X gates)dParity classifier (Part 4)
Anglefeature xᵢ → RY(xᵢ) on qubit idMost NISQ classifiers
Amplitudenormalised vector → amplitudes (state preparation)log₂ dSmall datasets such as Iris (2 features + 2 padding → 2 qubits)
Exercise

Exercise 3 · Angle-encode a point

Encode x = (0.3, 1.2) with RY on two qubits and read the Bloch view in Debug mode. Then encode x = (0.3 + 2π, 1.2): why does the circuit not change?

OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q;
bit[2] c;
ry(0.3) q[0];
ry(1.2) q[1];
c = measure q;
Open in IDE
Hint

RY(θ) tilts the Bloch arrow by θ from +Z towards +X.

Check your answer

q0 → (sin 0.3, 0, cos 0.3) = (0.30, 0, 0.96), q1 → (0.93, 0, 0.36). Angles are periodic, so features must be scaled into one period (PennyLane rescales inputs for this reason).

Part 4 · A variational classifier

A good first classifier learns the parity of a 4-bit string (is the number of 1s even or odd?). Basis-encode the input, apply a few layers of (a general rotation on every qubit, then CNOTs that link each qubit to the next and the last back to the first), read ⟨Z₀⟩ plus a trainable bias, and lower the square loss with any gradient-based optimiser. Parity is a fair test because no single input bit predicts the answer: the circuit has to combine all four. For real-valued data, amplitude encoding packs several features into fewer qubits.

Rot(ϕ,θ,ω)=RZ​(ω)RY​(θ)RZ​(ϕ)=eiαU(θ, ω, ϕ),L=N1​i∑​(yi​−f(xi​))2
PennyLane's Rot gate is QubitLab's U up to a global phase; L is the square loss used for training.
Exercise

Exercise 4 · One classifier layer

Build one layer of the parity classifier on the input 0101: basis encoding, a U rotation on every qubit, then the CNOT ring. Debug it: how many qubits are entangled after the ring, and what is ⟨Z₀⟩ = p(q0=0) − p(q0=1)?

OPENQASM 3.0;
include "stdgates.inc";
qubit[4] q;
bit[4] c;
// basis encoding of 0101 (q0 = rightmost bit)
x q[0];
x q[2];
// Rot = U(theta, omega, phi) on every qubit
U(0.4, 0.1, 0.2) q[0];
U(0.9, 0.3, 0.1) q[1];
U(0.2, 0.5, 0.4) q[2];
U(0.7, 0.2, 0.6) q[3];
// ring of CNOTs
cx q[0], q[1];
cx q[1], q[2];
cx q[2], q[3];
cx q[3], q[0];
c = measure q;
Open in IDE
Hint

Sum p over outcomes whose last bit is 0, minus the rest. The Probabilities tab lists every outcome.

Check your answer

All four qubits are tagged entangled after the ring (each purity < 0.99). The most likely outcome is |0011⟩ at 68 % and ⟨Z₀⟩ ≈ −0.466 for these angles. Training adjusts the 12 angles and the bias until sign(⟨Z₀⟩ + b) equals the label: 0101 has an even number of ones, so its label is −1 in the usual convention y ∈ {−1, 1}.

Part 5 · Quantum kernels

A quantum kernel starts from a feature map |φ(x)⟩ = U(x)|0⟩ and the kernel k(x, x′) = |⟨φ(x)|φ(x′)⟩|². You never train the quantum part; a classical SVM uses the kernel matrix. On hardware the overlap is measured by running U(x) followed by U†(x′) and reading the probability of |0…0⟩.

k(x,x′)=​⟨0∣U†(x′)U(x)∣0⟩​2=p(0…0)
Kernel as the probability of returning to |0…0⟩ after the inverse feature map.
Exercise

Exercise 5 · Measure a kernel entry

Angle-encode x = (0.3, 1.2) then undo with x′ = (0.5, 1.0): k(x, x′) is the probability of 00. Predict it from cos² of half the angle differences before you run.

OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q;
bit[2] c;
// U(x)
ry(0.3) q[0];
ry(1.2) q[1];
// U^dagger(x')
ry(-0.5) q[0];
ry(-1.0) q[1];
c = measure q;
Open in IDE
Hint

For RY the overlap on one qubit is cos²((x − x′)/2).

Check your answer

k = cos²(−0.1) · cos²(0.1) ≈ 0.990 · 0.990 = 0.980, and the Probabilities tab shows |00⟩ at 98.0 %.

Part 6 · The variational loop (VQE)

IBM's 'Variational algorithm design' course names the parts: a reference state, an ansatz (variational form), a cost function built from expectation values, and a classical optimisation loop. VQE minimises ⟨ψ(θ)|H|ψ(θ)⟩ for a chemistry Hamiltonian H written as Paulis. QubitLab's cutting flow already reconstructs expectation values of Pauli strings, and the exercise below evaluates one term of the H₂ Hamiltonian by hand.

E(θ)=⟨ψ(θ)∣H∣ψ(θ)⟩,H=k∑​ck​Pk​,θ∗=argθmin​E(θ)
Each Pauli term P_k is measured separately; the optimiser only sees the weighted sum.
Exercise

Exercise 6 · One VQE term

The two-qubit H₂ ansatz is RY(θ) on q0 followed by CNOT. For θ = 0.4 compute ⟨ZZ⟩ = p(00) + p(11) − p(01) − p(10) from the probabilities, then ⟨ZI⟩. Try θ = π/2.

OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q;
bit[2] c;
ry(0.4) q[0];
cx q[0], q[1];
c = measure q;
Open in IDE
Hint

After the CNOT only 00 and 11 appear, so ⟨ZZ⟩ is 1 for every θ; ⟨ZI⟩ = cos θ.

Check your answer

p(00) = cos²(0.2) ≈ 0.961, p(11) ≈ 0.039: ⟨ZZ⟩ = 1, ⟨ZI⟩ = 0.961 − 0.039 = 0.921 = cos 0.4. At θ = π/2 the state is the Bell state and ⟨ZI⟩ = 0. A real VQE would combine such terms with the H₂ coefficients and let an optimiser move θ.

Keep going

  • PennyLane · Basic tutorial: qubit rotation The RX·RY circuit, its gradient and gradient descent to |1⟩ in ~40 steps.
  • PennyLane · Variational classifier Parity with basis encoding, Iris with amplitude encoding; Rot layers and CNOT rings.
  • PennyLane · Parameter-shift rules Why the ±π/2 shift gives exact gradients for Pauli rotations.
  • IBM · Quantum machine learning Classical ML review, data encoding, quantum kernels, QVCs and QNNs.
  • IBM · Variational algorithm design Reference states, ansätze, cost functions, optimisation loops, applications.
← Previous
Learning path: from one qubit to algorithms
Next →
Compile (transpile): levels, basis gates, topology
On this page
  • Part 1 · A circuit is a function with parameters
  • Part 2 · Gradients without backprop: the parameter-shift rule
  • Part 3 · Getting data into qubits
  • Part 4 · A variational classifier
  • Part 5 · Quantum kernels
  • Part 6 · The variational loop (VQE)
  • Keep going
Try it in the IDE →
QubitLab
IDELearnPlaygroundDocsCommunity
Log in
QubitLab
IDELearnPlaygroundDocsCommunity
Log in