Lesson 41 · 80 min · advanced
The Inversion (Compute–Uncompute) Test
The inversion test estimates a fidelity kernel with no extra qubits: prepare , run the inverse circuit , and measure; the probability of the all-zeros outcome is . This lesson proves that identity, proves that the inverse of a circuit is the reversed sequence of inverted gates and tabulates the inverses of the standard gates, inverts the ZZ feature map gate by gate, shows that product encodings collapse to with , counts qubits, gates, CNOTs and depth against the SWAP test, proves that the inversion-test estimator has the smaller variance, , and explains why hardware noise biases the measured all-zeros probability.
Prerequisites: Quantum Kernels & Fidelity Kernels
Objectives and key results
Prove that the all-zeros probability of equals the fidelity kernel and interpret the other outcomes.
Prove and, by induction, that the inverse of a gate sequence is the reversed sequence of inverted gates; invert , Pauli, , , rotation, phase, CNOT, CZ, SWAP and controlled-rotation gates.
Write down the inverse of the two-qubit ZZ feature map gate by gate and simplify the resulting inversion-test circuit.
Show that for product encodings the inversion test collapses to and compute the complete outcome distribution.
Compare the inversion test and the SWAP test in qubits, gates, CNOTs and depth, and state when the SWAP test is unavoidable.
Prove that the inversion-test estimator needs fewer shots than the SWAP-test estimator, by the factor , and explain the bias that noise introduces into the measured all-zeros probability.
- identity · Inversion test
- theorem · Adjoint of a circuit
- formula · Collapse of product R_X encodings
- formula · Resources
- theorem · Shot variances
The all-zeros probability is the kernel#
The previous lessons gave two ways of reading a fidelity kernel off a quantum computer. The SWAP test places both feature states side by side on qubits and lets an ancilla interfere them; it never needs to know how the states were made. When the states come from known circuits, as they always do in a quantum kernel method, there is a cheaper route: prepare , then run the preparation of backwards. If the two states coincide, the backwards circuit returns the register exactly to ; if they differ, it returns it only partially, and the probability of finding all qubits in measures how close the two states are. The construction is called the inversion test or the compute–uncompute test, and it is the kernel estimator used in the quantum-kernel experiments of Havlíček et al. (2019). This lesson proves why it works, how to build the inverse of a circuit, what it costs compared with the SWAP test, how many shots it needs, and what noise does to it.
Definition
Inversion (compute–uncompute) test
Let be a quantum feature map on qubits with feature states . For two inputs the inversion-test circuit is i.e. first the encoding circuit of (compute), then the inverse of the encoding circuit of (uncompute). The test runs on , measures all qubits in the computational basis, and records whether the outcome is the all-zeros string . After shots with all-zeros outcomes, the estimate of the kernel is .
The inversion test measures the fidelity kernel
For every unitary feature map and all inputs , More generally, the outcome has probability with ; the states form an orthonormal basis, so the outcomes together have probability . Exchanging the roles of and does not change .
Proof (7 steps)
- Step 1:Born rule: measuring every qubit of the pure state in the computational basis returns the string with the squared modulus of the amplitude .
- Step 2:The adjoint of a product is the reversed product of adjoints, (proved in the next section), applied to the matrix and the column vector ; for this is the bra of the feature state of .
- Step 3:Associativity of the matrix product: the row vector multiplies the column vector .
- Step 4:Set . Conjugate symmetry and show that the order of the two states inside the modulus is irrelevant.
- Step 5:A unitary maps the orthonormal computational basis to an orthonormal basis of .
- Step 6:Parseval's identity in the basis : the other outcomes record the components of orthogonal to .
- Step 7:The same computation with and exchanged; the kernel is symmetric. Either circuit order estimates the same number.
∎
Circuit · 2 qubits
The lab's inversion test for the product encoding: (compute), then (uncompute), for and . The histogram shows ; the outcomes , , carry the remaining .
- |00⟩0.7486
- |01⟩0.1338
- |10⟩0.0997
- |11⟩0.0178
Quick check
An inversion test on qubits returns in of shots. What do the other shots tell you?
Inverting a circuit#
To run the inversion test one must build as a circuit. A unitary satisfies , so undoes ; the question is how to obtain it from the gate list of without ever forming a matrix. The answer rests on one identity for adjoints of products, followed by an induction over the number of gates, and on a short table of inverses of the individual gates.
The adjoint of a product is the reversed product of the adjoints
For complex matrices and , where is the conjugate transpose, . In particular, if and are unitary, so is , and .
Proof (4 steps)
- Step 1:Definition of the conjugate transpose and of the matrix product, for and .
- Step 2:Complex conjugation is additive and multiplicative, and , and complex numbers commute, so each product can be written with the factor first.
- Step 3:The last sum is entry of the product of an and a matrix.
- Step 4:For unitary square use the identity just proved, associativity, and ; a square matrix with a left inverse is invertible, with the same two-sided inverse.
∎
The inverse of a circuit is the reversed sequence of inverted gates
Let a circuit apply the gates in this time order, each a unitary acting on a subset of the qubits (as on the full register). Then and i.e. the inverse circuit applies in this time order, each on the same qubits as the original gate. The inverse circuit has the same number of gates and the same depth as .
Proof (6 steps)
- Step 1:Base case: a one-gate circuit is inverted by the inverse of its gate.
- Step 2:Induction step: adding a gate at the end of the circuit multiplies the unitary from the left; apply the lemma with , .
- Step 3:Insert the induction hypothesis . As a time-ordered circuit the product is read from the right: is applied first and last.
- Step 4:Direct check that the reversed circuit undoes the original one: the product telescopes from the middle outwards, each .
- Step 5:A gate on the qubits is the tensor product of its small matrix with the identity on the remaining qubits , and entrywise; so each inverted gate acts on the same qubits as the original one.
- Step 6:Gates in one moment act on disjoint qubits, so their inverses do too; reversing the list of moments gives a valid layering of with the same depth , and the gate count is unchanged.
∎
Inverses of the standard gates. The proposition reduces the problem to inverting single gates. The table lists every gate of the circuit builder; the proposition after it proves each line.
| gate | matrix or definition | inverse |
|---|---|---|
| , , , | Hermitian and unitary | itself |
| , , | real symmetric permutation or diagonal matrices | itself |
| , | real symmetric permutation matrices | itself |
| phase gate | ||
| phase gate | ||
| , | ||
Self-inverse gates are copied unchanged into the inverse circuit, and become and , and every parameterised gate keeps its qubits and gets its angle negated. Together with the reversal of the order this is the whole recipe: reverse the order and negate the angles.
Inverses of the standard gates
are their own inverses; and as in the table; for and all real ,
Proof (7 steps)
- Step 1:A matrix that is both Hermitian and unitary squares to the identity. are Hermitian by inspection and is a real combination of Hermitian matrices.
- Step 2:Both are Hermitian (sums of tensor products of Hermitian factors, resp. real diagonal) and unitary, hence self-inverse. , and are permutation matrices of involutions of the basis states (swapping two bits, flipping a bit under a condition that the flip does not change, exchanging two bits under a control), so applying them twice restores every basis state.
- Step 3:The exponential series converges absolutely, the adjoint is linear and continuous, and by the lemma applied times.
- Step 4:Use the previous line with , , and for the Pauli matrices.
- Step 5:An explicit check with (exponential series with ): the cross terms cancel and .
- Step 6:The adjoint of a diagonal matrix conjugates its diagonal, and . Since and , their inverses are phase gates with negated angles, which are not equal to and .
- Step 7:, projectors are Hermitian, and the rotation line above. The same argument inverts every controlled- gate to controlled-, e.g. and .
∎
Worked inverse: the two-qubit ZZ feature map with one repetition
- Step 1:The ZZ feature map of Havlíček et al. (2019) with one repetition, in time order (seven gates, depth ). The last three gates implement , because conjugating by a CNOT gives .
- Step 2:The unitary is the product in reverse time order. All gates between the Hadamards are diagonal, and because and commuting exponents add.
- Step 3:The proposition: reverse the factors and invert each one. The CNOTs and Hadamards are self-inverse and every angle is negated.
- Step 4:The same inverse read as a circuit in time order, gate by gate: the last gate of comes first. This is exactly the gate list that the engine function adjointCircuit returns in the code cell below.
- Step 5:The numerical angles of the uncompute half for the lab point ; the compute half uses , and .
- Step 6:Concatenate both halves: gates and depth as written. In the middle, cancels, and since all diagonal factors commute the circuit compiles to , , , , , , : gates, depth .
- Step 7:Diagonal exponents commute, so their exponents subtract.
- Step 8:, and the diagonal unitary multiplies the basis state with , by . For the lab points , , and the formula gives , the value printed by the code cells.
Result
Quick check
A two-qubit encoding applies, in time order, on qubit , then , then on qubit . Which time-ordered gate list implements its inverse?
Product R_X encodings collapse#
For the product (angle) encodings of the lesson Angle & Phase Encoding the inversion test simplifies dramatically: the compute and uncompute rotations on each qubit merge into a single rotation by the difference of the features. This explains the closed form of the previous lesson from the circuit side and gives the complete outcome distribution that the lab checks.
The inversion test of a product R_X encoding is a product of R_X rotations
Let , with feature on qubit . Then and the outcome of the inversion test has probability The same holds for in place of .
Proof (7 steps)
- Step 1:and . Gates on different qubits commute, , so the reversed order of the circuit proposition is immaterial here.
- Step 2:The mixed-product rule : each qubit sees only its own two rotations.
- Step 3:Abbreviate , and use and ; the term .
- Step 4:The addition theorems for cosine and sine. Equivalently, because the two exponents are multiples of the same matrix and therefore commute.
- Step 5:Set , . Compute and uncompute merge into one rotation by the feature difference .
- Step 6:First column of ; the output is a product state.
- Step 7:The amplitude of in a product state is the product of the one-qubit amplitudes; . For this is the product-kernel formula of the previous lesson. For the same steps apply with in place of (also ), and .
∎
Worked example: x = (0.3, 1.2), x′ = (1.0, 0.4)
- Step 1:The collapse theorem with the lab points; qubit is rotated by , qubit by .
- Step 2:The one-qubit outcome probabilities; cosine is even, so the sign of does not matter.
- Step 3:Both qubits return : the kernel value of the previous lesson's lab.
- Step 4:Exactly one qubit flips. The outcome string lists qubit first, so means qubit returned .
- Step 5:Both flip. The four numbers factorise as .
- Step 6:The lab's first diagnostic: appending instead of adds the features instead of subtracting them.
- Step 7:The second diagnostic: the inverse rotations of and placed on the wrong qubits compare with the swapped point .
Result
Unitary verified: (max deviation 1.1e-16)
The comparer shows the two kernel circuits for the lab points side by side: on the left the SWAP test on qubits, which returns ancilla outcome with probability ; on the right the inversion test on qubits, which returns with probability . Both read off the same kernel. The first column of the matrix above is the output state , whose squared moduli are the four probabilities of the worked example.
Why the two-gate circuit also passes the lab. The collapse theorem says that the four-gate circuit , , , and the two-gate circuit , are the same unitary, so they produce the same state and the same distribution, and the grader, which simulates the circuit, cannot and should not tell them apart. A compiler does exactly this merge, and on hardware the compiled inversion test of a product encoding has depth . The collapse is special to encodings whose compute and uncompute gates commute qubit by qubit; for entangling maps such as the ZZ map only part of the circuit merges, as the worked inverse above showed. For the same reason the reversed circuit passes: cosine and sine squared are even, so its distribution is identical.
Quick check
Two features are encoded with rotations. The inversion test is run for and . What is ? Give four decimals.
Resources: inversion test versus SWAP test#
Both tests estimate the same kernel, but they spend different resources. Write for the number of gates, for the number of CNOTs and for the depth of one encoding circuit on qubits; the encoding of has the same structure with different angles. Depth is counted in moments: gates on disjoint qubits share a moment, and each gate is placed in the earliest moment after the last gate on any of its qubits (greedy left-packing).
Qubits, gates, CNOTs and depth of the two kernel circuits
The inversion test uses qubits, gates, CNOTs and depth at most . The SWAP test uses qubits, gates (counting each controlled-SWAP as one gate) and depth at most and at least . With and the standard -CNOT Toffoli, the SWAP test needs CNOTs, and its depth stays .
Proof (8 steps)
- Step 1:Inversion test, qubits: compute and uncompute act on the same register and no ancilla is needed.
- Step 2:has one inverted gate for each gate of (circuit proposition), and the inverse of a CNOT is a CNOT.
- Step 3:The moments of followed by the moments of form a valid layering; left-packing can only shorten it when a gate at the junction finds an idle qubit.
- Step 4:SWAP test, qubits: one ancilla and one register per feature state.
- Step 5:The two preparations, the two Hadamards on the ancilla, and one controlled-SWAP per qubit pair , .
- Step 6:The two preparations act on disjoint registers and run in parallel, and the first Hadamard acts on the idle ancilla during the first moment. Every controlled-SWAP involves the ancilla, so no two of them share a moment: they occupy distinct moments after the first Hadamard, and the last Hadamard comes after all of them, which gives the lower bound.
- Step 7:Three CNOTs swap two qubits (). To control the swap it suffices to control the middle CNOT: if the control is the two outer CNOTs cancel each other.
- Step 8:The standard Toffoli circuit (Nielsen and Chuang, Fig. 4.9) uses CNOTs, Hadamards and single-qubit phase gates, seven of them or , and CNOTs are necessary for a Toffoli (Shende and Markov 2009). Each decomposed controlled-SWAP is a block of constant depth that still touches the ancilla, so the depth becomes .
∎
The two circuits side by side. The general counts of the proposition, and the counts for three concrete feature maps with the lab points (and , for three features), counted with native , , , CNOT and CSWAP gates and greedy left-packed moments:
| inversion test | SWAP test | |
|---|---|---|
| qubits | ||
| gates | ||
| CNOTs (CSWAP CNOT, CCX, CNOT; -CNOT Toffoli) | ||
| depth | at most | at most ; after decomposition |
| needs the inverse circuit | yes | no |
| estimator of | ||
| product, (, , ) | qubits, gates, CNOTs, depth | qubits, gates, CNOTs, depth |
| ZZ map, reps , (, , ) | qubits, gates, CNOTs, depth | qubits, gates, CNOTs, depth |
| ZZ map, reps , (, , ) | qubits, gates, CNOTs, depth | qubits, gates, CNOTs, depth |
The trade-off is visible in the last rows. The inversion test always wins on width and on entangling gates: it never needs the CNOTs of the controlled-SWAPs, which on hardware dominate the error budget. The SWAP test can win on depth in the native gate count, because it runs the two preparations in parallel instead of in series; for the deep ZZ map () the inversion test is moments deep against . Once the controlled-SWAPs are compiled into CNOTs and single-qubit gates, each of them costs a block of roughly a dozen moments, and the SWAP test loses that advantage unless is large compared with .
The second comparer uses the entangling ZZ feature map with three features and two repetitions. The kernel value is small, , so the SWAP test returns ancilla outcome with probability , barely distinguishable from a fair coin, while the inversion test returns with probability , a rare event whose frequency directly is the kernel. The next section turns this observation into a statement about shots.
Quick check
In which situation can the inversion test not be used to estimate ?
Shot statistics#
The inversion test needs fewer shots than the SWAP test
Let . With shots, the inversion-test estimator and the SWAP-test estimator are unbiased, with with equality only at . For , reaching the same standard deviation requires times as many SWAP-test shots, a ratio that grows like as .
Proof (7 steps)
- Step 1:Each shot independently returns with probability (first theorem), so the count is binomial with mean and variance .
- Step 2:The SWAP test returns ancilla outcome with probability (previous lesson); the affine estimator is unbiased by linearity.
- Step 3:with , and the Bernoulli variance with , .
- Step 4:The difference of the two single-shot variances is , nonnegative on and zero only at . Hence the inversion test is never worse.
- Step 5:Equal standard deviation needs shots proportional to the single-shot variance ; for cancel the common factor .
- Step 6:As the ratio tends to its minimum , and for small kernels the gap explodes: the inversion test's variance vanishes with , whereas the SWAP test's variance stays at its maximum. For a concentrated kernel of size the SWAP test needs about times as many shots.
- Step 7:The lab value: and ; the ratio is .
∎
Quick check
For a kernel value , how many times as many shots does the SWAP test need as the inversion test to reach the same standard deviation?
Depth doubling and noise bias#
Everything so far assumed a perfect device. On hardware every gate is followed by some decoherence, and the inversion test runs two encoding circuits in series, so a qubit experiences twice as many noisy operations as in a single encoding. The measured all-zeros frequency then estimates a noisy probability , and more shots do not remove the difference: the estimator becomes biased. Two exactly solvable noise models show the direction of the bias.
Local depolarizing noise on a product R_X inversion test
- Step 1:Model: after every gate, the depolarizing channel with error probability acts on each qubit the gate touched. The second form follows from for a qubit.
- Step 2:In Bloch coordinates the channel shrinks the Bloch vector by the factor and keeps its direction.
- Step 3:The channel is covariant: gets the factor like , and . So all noise steps on a qubit can be moved past its rotations to the end of the circuit.
- Step 4:All gates are one-qubit gates, so the state stays a product state. Qubit undergoes noisy gates in the inversion test (one per encoding), its two rotations merge into , and maps the Bloch vector of to .
- Step 5:The probability of outcome on a qubit with Bloch vector is , and the qubits are independent.
- Step 6:Each factor is pulled towards by the factor , so is pulled towards ; even identical inputs no longer give . Because every qubit sees twice the gates of one encoding, the contraction is instead of : doubling the depth squares the damage.
- Step 7:The lab circuit under depolarizing noise per gate: the estimate is biased by , larger than the statistical error of shots, so more shots alone cannot fix it.
Result
Global depolarizing noise and its correction from the diagonal
- Step 1:Model: the whole circuit is followed by a global depolarizing channel that keeps the ideal state with probability and replaces it by the maximally mixed state otherwise; decreases with the depth of .
- Step 2:Linearity: the ideal part contributes and the maximally mixed part assigns probability to every outcome.
- Step 3:The bias is negative whenever and positive below: noise pulls every kernel value towards the uninformative constant , the noise-induced concentration of Thanasilp et al. (2024).
- Step 4:Running the inversion test with (ideally ) measures , provided the noise does not depend on the data.
- Step 5:Invert the affine relation; this is the device-noise correction of Hubregtsen et al. (2022). Dividing by multiplies the statistical error by , so the corrected estimate needs about times as many shots.
Result
Verification in code#
The TypeScript cell builds the lab circuit with the engine function inversionTestCircuit, prints its gate list (note the reversed order of the uncompute half), its outcome distribution and the collapse to ; prints the inverse of the ZZ feature map produced by adjointCircuit; checks on random pairs that equals the exact kernel for an encoding and for the ZZ map with two repetitions; reproduces the SWAP-test value ; and recounts the resources of the second comparer.
import { circuitUnitary, mulberry32, runStatevector, matrix } from '@/lib/quantum-simulator';
import { adjointCircuit, angleEncoding, fidelityKernel, inversionTestCircuit, inversionTestProbability, swapTestCircuit, swapTestProbability, zzFeatureMap } from '@/lib/qml';
type Op = { kind: string; gate?: string; targets?: number[]; controls?: number[]; params?: unknown[] };
const fmt = (v: number) => v.toFixed(10);
const show = (op: Op) =>
op.kind !== 'gate' ? op.kind : op.gate + '(' + op.targets!.join(',') + (op.params ? ', ' + Number(op.params[0]).toFixed(4) : '') + ')';
const depth = (ops: Op[]) => {
const last = new Map<number, number>();
let d = 0;
for (const op of ops) {
if (op.kind !== 'gate') continue;
const qs = [...(op.controls ?? []), ...op.targets!];
const level = 1 + Math.max(...qs.map((q) => last.get(q) ?? 0));
qs.forEach((q) => last.set(q, level));
d = Math.max(d, level);
}
return d;
};
const stats = (ops: Op[]) => {
const gates = ops.filter((op) => op.kind === 'gate');
const cnots = gates.filter((op) => op.gate === 'CNOT').length;
const cswaps = gates.filter((op) => op.gate === 'CSWAP').length;
return 'gates ' + gates.length + ', CNOTs after decomposition ' + (cnots + 8 * cswaps) + ', depth ' + depth(gates);
};
const x = [0.3, 1.2];
const xp = [1.0, 0.4];
// (1) The lab circuit: R_X product encoding, V = U(x')^dagger U(x).
const rx = angleEncoding(2, { rotation: 'RX' });
const V = inversionTestCircuit(rx, x, xp);
console.log('V = ' + V.ops.map(show).join('; '));
console.log('P(00), P(01), P(10), P(11) = ' + Array.from(runStatevector(V).probabilities()).map(fmt).join(', '));
console.log("P(00) = " + fmt(inversionTestProbability(rx, x, xp)) + " K(x, x') = " + fmt(fidelityKernel(rx, x, xp)));
const collapsed = circuitUnitary({ version: 1, numQubits: 2, numClbits: 0, ops: [
{ kind: 'gate', gate: 'RX', targets: [0], params: [-0.7] },
{ kind: 'gate', gate: 'RX', targets: [1], params: [0.8] },
] });
console.log('V equals R_X(-0.7) (x) R_X(0.8): ' + (matrix.maxAbsDiff(circuitUnitary(V), collapsed) < 1e-12));
// (2) The ZZ feature map (reps 1): the adjoint is the reversed list with negated angles.
const zz = zzFeatureMap(2, { reps: 1 });
console.log("U(x')^dagger = " + adjointCircuit(zz(xp)).ops.map(show).join('; '));
console.log("ZZ: P(00) = " + fmt(inversionTestProbability(zz, x, xp)) + " K(x, x') = " + fmt(fidelityKernel(zz, x, xp)));
// (3) Agreement on random data for both encodings (3 qubits, ZZ with 2 repetitions).
const rng = mulberry32(41);
for (const [name, map] of [['angle (R_X)', angleEncoding(3, { rotation: 'RX' })], ['ZZ, reps 2', zzFeatureMap(3, { reps: 2 })]] as const) {
let worst = 0;
for (let t = 0; t < 100; t++) {
const a = [0, 1, 2].map(() => 2 * Math.PI * rng());
const b = [0, 1, 2].map(() => 2 * Math.PI * rng());
worst = Math.max(worst, Math.abs(inversionTestProbability(map, a, b) - fidelityKernel(map, a, b)));
}
console.log(name + ': 100 random pairs, max |P(000) - K| < 1e-12: ' + (worst < 1e-12));
}
// (4) The SWAP test on 2n + 1 = 5 qubits estimates the same kernel through P(0) = (1 + K) / 2.
const p0 = swapTestProbability(runStatevector(rx(x)), runStatevector(rx(xp)));
console.log('SWAP test: P(0) = ' + fmt(p0) + ' 2 P(0) - 1 = ' + fmt(2 * p0 - 1));
// (5) Resources for the ZZ map with 3 features and 2 repetitions.
const zz3 = zzFeatureMap(3, { reps: 2 });
const a3 = [0.3, 1.2, 2.0];
const b3 = [1.0, 0.4, 0.5];
console.log('ZZ, 3 features, reps 2: K = ' + fmt(fidelityKernel(zz3, a3, b3)));
console.log(' inversion test (3 qubits): ' + stats(inversionTestCircuit(zz3, a3, b3).ops));
console.log(' SWAP test (7 qubits): ' + stats(swapTestCircuit(3)(zz3(a3), zz3(b3)).ops));Expected output
V = RX(0, 0.3000); RX(1, 1.2000); RX(1, -0.4000); RX(0, -1.0000) P(00), P(01), P(10), P(11) = 0.7486048950, 0.1338161986, 0.0997484596, 0.0178304467 P(00) = 0.7486048950 K(x, x') = 0.7486048950 V equals R_X(-0.7) (x) R_X(0.8): true U(x')^dagger = CNOT(0,1); RZ(1, -11.7427); CNOT(0,1); RZ(1, -0.8000); RZ(0, -2.0000); H(1); H(0) ZZ: P(00) = 0.2754859933 K(x, x') = 0.2754859933 angle (R_X): 100 random pairs, max |P(000) - K| < 1e-12: true ZZ, reps 2: 100 random pairs, max |P(000) - K| < 1e-12: true SWAP test: P(0) = 0.8743024475 2 P(0) - 1 = 0.7486048950 ZZ, 3 features, reps 2: K = 0.0204708258 inversion test (3 qubits): gates 48, CNOTs after decomposition 16, depth 32 SWAP test (7 qubits): gates 53, CNOTs after decomposition 40, depth 19
The NumPy cell rebuilds everything from and matrices: a circuit is a time-ordered list of gates, its unitary the product in reverse order, and its inverse the reversed list of conjugate transposes. It prints the lab distribution against the closed form, the two diagnostic values, the ZZ kernel three ways (inversion test, overlap, and the diagonal formula of the worked inverse), a five-qubit SWAP test, the variance comparison with the ratio , and a density-matrix simulation of the lab circuit under local depolarizing noise against the closed form .
import numpy as np
I2 = np.eye(2, dtype=complex)
H = np.array([[1, 1], [1, -1]], dtype=complex) / np.sqrt(2)
CNOT = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]], dtype=complex)
def rx(t):
c, s = np.cos(t / 2), np.sin(t / 2)
return np.array([[c, -1j * s], [-1j * s, c]])
def rz(t):
return np.diag([np.exp(-0.5j * t), np.exp(0.5j * t)])
def on(gate, q):
# a one-qubit gate on qubit q of two (qubit 0 is the left Kronecker factor)
return np.kron(gate, I2) if q == 0 else np.kron(I2, gate)
def run(gates):
# time-ordered gate list G_1, ..., G_L -> U = G_L ... G_1
U = np.eye(4, dtype=complex)
for G in gates:
U = G @ U
return U
def adjoint(gates):
# reverse the order and replace every gate by its conjugate transpose
return [G.conj().T for G in reversed(gates)]
def rx_map(x):
return [on(rx(x[0]), 0), on(rx(x[1]), 1)]
def zz_map(x):
phi = (np.pi - x[0]) * (np.pi - x[1])
return [on(H, 0), on(H, 1), on(rz(2 * x[0]), 0), on(rz(2 * x[1]), 1), CNOT, on(rz(2 * phi), 1), CNOT]
zero = np.array([1, 0, 0, 0], dtype=complex)
x, xp = np.array([0.3, 1.2]), np.array([1.0, 0.4])
# (1) The lab circuit V = U(x')^dagger U(x) and its four outcome probabilities.
V = run(rx_map(x) + adjoint(rx_map(xp)))
p = np.abs(V @ zero) ** 2
c2, s2 = np.cos((x - xp) / 2) ** 2, np.sin((x - xp) / 2) ** 2
closed = np.array([c2[0] * c2[1], c2[0] * s2[1], s2[0] * c2[1], s2[0] * s2[1]])
print("P(00), P(01), P(10), P(11):", " ".join(f"{v:.10f}" for v in p))
print("product of cos^2 / sin^2: ", " ".join(f"{v:.10f}" for v in closed))
print("V == R_X(-0.7) (x) R_X(0.8):", bool(np.allclose(V, np.kron(rx(-0.7), rx(0.8)), atol=1e-12)))
# (2) The two wrong circuits of the lab diagnostics.
no_dagger = run(rx_map(x) + rx_map(xp))
crossed = run(rx_map(x) + adjoint(rx_map(xp[::-1])))
print(f"forgot the dagger: P(00) = {abs(no_dagger[0, 0]) ** 2:.10f} crossed features: P(00) = {abs(crossed[0, 0]) ** 2:.10f}")
# (3) ZZ feature map (reps 1): inversion test, overlap, and the diagonal middle block.
ux, uxp = run(zz_map(x)), run(zz_map(xp))
Vzz = run(zz_map(x) + adjoint(zz_map(xp)))
overlap = abs(np.vdot(uxp @ zero, ux @ zero)) ** 2
dphi = (np.pi - x[0]) * (np.pi - x[1]) - (np.pi - xp[0]) * (np.pi - xp[1])
z = np.array([1, -1])
theta = (x[0] - xp[0]) * z[:, None] + (x[1] - xp[1]) * z[None, :] + dphi * np.outer(z, z)
diag_form = abs(np.exp(-1j * theta).mean()) ** 2
print(f"ZZ: P(00) = {abs(Vzz[0, 0]) ** 2:.10f} |<phi(x')|phi(x)>|^2 = {overlap:.10f} |mean exp(-i theta)|^2 = {diag_form:.10f}")
print("ZZ: V^dagger V == I:", bool(np.allclose(Vzz.conj().T @ Vzz, np.eye(4), atol=1e-12)), " U(x')^dagger from the reversed list:", bool(np.allclose(run(adjoint(zz_map(xp))), uxp.conj().T, atol=1e-12)))
# (4) SWAP test on 5 qubits for the R_X states: P(ancilla = 0) = (1 + K) / 2.
a, b = run(rx_map(x)) @ zero, run(rx_map(xp)) @ zero
psi = np.kron(np.array([1, 0], dtype=complex), np.kron(a, b)).reshape(2, 4, 4)
psi = np.tensordot(H, psi, axes=(1, 0))
psi[1] = psi[1].T.copy()
psi = np.tensordot(H, psi, axes=(1, 0))
p0 = float(np.sum(np.abs(psi[0]) ** 2))
print(f"SWAP test: P(0) = {p0:.10f} 2 P(0) - 1 = {2 * p0 - 1:.10f}")
# (5) Single-shot variances K(1 - K) and 1 - K^2, and the shot ratio (1 + K) / K.
for K in [0.9, p[0], 0.5, 0.25, 0.1, 2.0 ** -10]:
print(f"K = {K:.6f} inversion {K * (1 - K):.6f} SWAP {1 - K * K:.6f} ratio {(1 + K) / K:9.4f}")
# (6) Local depolarizing noise (p = 0.01) after every gate of the lab circuit, density-matrix simulation.
X = np.array([[0, 1], [1, 0]], dtype=complex)
Y = np.array([[0, -1j], [1j, 0]])
Zm = np.diag([1.0 + 0j, -1.0])
def depolarize(rho, q, pr):
kraus = [np.sqrt(1 - pr) * I2, np.sqrt(pr / 3) * X, np.sqrt(pr / 3) * Y, np.sqrt(pr / 3) * Zm]
return sum(on(k, q) @ rho @ on(k, q).conj().T for k in kraus)
def noisy_p00(gates_with_qubits, pr):
rho = np.outer(zero, zero.conj())
for G, q in gates_with_qubits:
rho = depolarize(G @ rho @ G.conj().T, q, pr)
return rho[0, 0].real
lab = [(on(rx(0.3), 0), 0), (on(rx(1.2), 1), 1), (on(rx(-1.0), 0), 0), (on(rx(-0.4), 1), 1)]
diagonal = [(on(rx(0.3), 0), 0), (on(rx(1.2), 1), 1), (on(rx(-0.3), 0), 0), (on(rx(-1.2), 1), 1)]
eta = (1 - 4 * 0.01 / 3) ** 2
print(f"noisy P(00) = {noisy_p00(lab, 0.01):.10f} prod (1 + eta cos d) / 2 = {np.prod((1 + eta * np.cos(x - xp)) / 2):.10f} noiseless K = {p[0]:.10f}")
print(f"noisy K(x, x) = {noisy_p00(diagonal, 0.01):.10f} ((1 + eta) / 2)^2 = {((1 + eta) / 2) ** 2:.10f}")Expected output
P(00), P(01), P(10), P(11): 0.7486048950 0.1338161986 0.0997484596 0.0178304467 product of cos^2 / sin^2: 0.7486048950 0.1338161986 0.0997484596 0.0178304467 V == R_X(-0.7) (x) R_X(0.8): True forgot the dagger: P(00) = 0.3076221171 crossed features: P(00) = 0.9875602676 ZZ: P(00) = 0.2754859933 |<phi(x')|phi(x)>|^2 = 0.2754859933 |mean exp(-i theta)|^2 = 0.2754859933 ZZ: V^dagger V == I: True U(x')^dagger from the reversed list: True SWAP test: P(0) = 0.8743024475 2 P(0) - 1 = 0.7486048950 K = 0.900000 inversion 0.090000 SWAP 0.190000 ratio 2.1111 K = 0.748605 inversion 0.188196 SWAP 0.439591 ratio 2.3358 K = 0.500000 inversion 0.250000 SWAP 0.750000 ratio 3.0000 K = 0.250000 inversion 0.187500 SWAP 0.937500 ratio 5.0000 K = 0.100000 inversion 0.090000 SWAP 0.990000 ratio 11.0000 K = 0.000977 inversion 0.000976 SWAP 0.999999 ratio 1025.0000 noisy P(00) = 0.7319620910 prod (1 + eta cos d) / 2 = 0.7319620910 noiseless K = 0.7486048950 noisy K(x, x) = 0.9736865264 ((1 + eta) / 2)^2 = 0.9736865264
References
- V. Havlíček, A. D. Córcoles, K. Temme, A. W. Harrow, A. Kandala, J. M. Chow and J. M. Gambetta, Supervised learning with quantum-enhanced feature spaces, Nature 567, 209–212 (2019).doi:10.1038/s41586-019-0980-2
- H. Buhrman, R. Cleve, J. Watrous and R. de Wolf, Quantum fingerprinting, Physical Review Letters 87, 167902 (2001).doi:10.1103/PhysRevLett.87.167902
- M. A. Nielsen and I. L. Chuang, Quantum Computation and Quantum Information, 10th anniversary edition, Cambridge University Press (2010), Section 4.3 and Figure 4.9.doi:10.1017/CBO9780511976667
- V. V. Shende and I. L. Markov, On the CNOT-cost of TOFFOLI gates, Quantum Information and Computation 9, 461–486 (2009).arxiv.org
- S. Thanasilp, S. Wang, M. Cerezo and Z. Holmes, Exponential concentration in quantum kernel methods, Nature Communications 15, 5200 (2024).doi:10.1038/s41467-024-49287-w
- T. Hubregtsen, D. Wierichs, E. Gil-Fuster, P.-J. H. S. Derks, P. K. Faehrmann and J. J. Meyer, Training quantum embedding kernels on near-term quantum computers, Physical Review A 106, 042431 (2022).doi:10.1103/PhysRevA.106.042431
- V. Heyraud, Z. Li, Z. Denis, A. Le Boité and C. Ciuti, Noisy quantum kernel machines, Physical Review A 106, 052421 (2022).doi:10.1103/PhysRevA.106.052421
- S. Wang, E. Fontana, M. Cerezo, K. Sharma, A. Sone, L. Cincio and P. J. Coles, Noise-induced barren plateaus in variational quantum algorithms, Nature Communications 12, 6961 (2021).doi:10.1038/s41467-021-27045-6
Hands-on labs
Build the inversion test of an angle-encoding kernel
1 step · auto-gradedOpen labBuild the compute–uncompute circuit of the two-qubit product encoding for and with gates only, and read the kernel value off the probability of the outcome .