Skip to main content

WAI Extension: Quantum Compile Certificates

Mirrored from the canonical text at commit c5e7133e ().

Status: Draft. Defines the certificate of a compile, wai.quantum.compile/1: one record for each compile that names every pass with the digest of the circuit it was given and of the circuit it gave, the layer its check stands on and the distance it adds, so that the whole is one chain from the program’s text to the compiled program’s text; the rules any reader holds that record to without running anything; what a verifier does with a sealed one; and what each synthesis method the passes use guarantees. A job that ran compiled carries the chain in its result. Reference implementation: wai_quantum::engine::compile, engine::certificate and engine::synth; vectors: quantum-conformance/compile/.

Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119/8174.

1. Scope and model

A compile takes an OpenQASM program whose measurements all come at the end and writes it in another gate set (its basis) through an ordered list of named passes. Every pass is checked where it acts before its output is used; a pass whose check does not hold is left out, and the program goes on as it was. The compile’s certificate records all of it.

The claim a certificate makes is one sentence: the output text is the program text, up to a global phase, to within epsilon.bound in the operator norm, and here is each step with how it was checked. It is not a proof object that a small checker replays: it is a chain of digests that fixes which circuits the claim is about, a statement for each step of what kind of check stood behind it, and a compile that gives the same bytes on every host, so that a verifier holding the request can make the certificate again and compare.

A compile does not place a program on a device’s qubits or route it; the exact compile to a device’s own gates and connectivity for a provider’s job is the provider protocol’s (quantum-providers §4), and its program is checked there before it is sent.

2. The request

{"qasm", "epsilon", "level", "basis", "stages", "twirl", "dd", "passes"}, all but qasm optional:

MemberMeaningDefault
qasmthe program
epsilonthe most the output may differ from the program in the operator norm, up to a global phase: a number greater than 0, and at most 0.5 for the basis clifford_t1e-6
level0, 1 or 2: which passes run (§3); above 0, the best on the basis’s objective of this level’s output and every lower level’s (§3.1)1
basisthe gate set the output is written in (below)clifford_t
stagestrue: the result also holds the circuit after each passfalse
twirltrue or {"seed": N}: frame each two-qubit Clifford gate with seeded Paulisoff
dd"xx" or "xy4": a decoupling sequence in each idle windowoff
passesnames of passes the host holds, built in (§3) or its own, run after the level’snone

The bases:

basisThe output’s gatesApproximates
clifford_th x y z s sdg t tdg cx cz swap: every rotation off the multiples of π/4 written as a Clifford+T wordwithin epsilon
standardthe reader’s standard gates at any anglenothing
czone-qubit gates at any angle around cz, the two-qubit gate of the device bases rzsxxcz and prxcznothing
zzone-qubit gates around rzz(θ), 0 ≤ θ ≤ π/2: the zz gate of the device basis gpizz at θ/2π of a turnnothing
xxone-qubit gates around rxx(θ), 0 ≤ θ ≤ π/2: the xx gate of the device basis prxrzxx at θ/2π of a turnnothing

A request MUST be refused, and nothing compiled, when its program measures in the middle, resets after a gate or acts on a measured bit; when it holds more than 200 000 gates; when basis, level, epsilon, twirl or dd is not one of the values above; when it gives target (a device’s name, which a compile does not take); when it names a pass the host does not hold; or when epsilon, shared by the program’s rotations, leaves one of them less than 1e-15. A compile MUST also be refused when a pass writes more than 2 000 000 gates, the most a program is read with: its output would not read back. The pass that passes it is named, and approximate stops as soon as it does.

3. The passes

PassWhat it doesThe layer its check stands on (§5)
lowerevery gate in h x y z s sdg t tdg cx cz swap rz, a rz at a multiple of π/4 as the named gates it isexact_arithmetic when every decomposition used is of a gate whose own entries, and its decomposition’s, are in Z[ω]/√2ᵏ (§7.1); else exact_simulation
simplifychecked rewrites: a gate and its inverse cancel, rotations merge, a gate is carried past what it commutes with; each rewrite’s gates held to the gates they replace by a tableau or on every basis state of their qubits, the two unitaries at most 1e-12 apart at one global phase (in the Frobenius norm), so a rewrite moves nothing past the rounding of doublesexact_simulation
phase_foldphase gates on one parity of the path variables merged into one (§7.5)exact_arithmetic when every angle is a multiple of π/4; else exact_simulation
phase_resyntheach region of cx cz swap, Pauli and phase gates written again with the fewest T terms its phase polynomial’s signature allows that the search finds (§7.5)exact_arithmetic
resynth_1qeach run of one-qubit gates written again when that is cheaper (§7.2)exact_arithmetic when every run rewritten was a Clifford+T word; else exact_simulation
resynth_2qeach block on one pair of qubits written with at most three CNOTs when that uses fewer (§7.4)exact_simulation
approximateevery rz off the multiples of π/4 as a Clifford+T word within its share of the budget (§7.3)bounded; exact_arithmetic when there was none to write
native_2qeach block on one pair written around the basis’s own two-qubit gate, at most three of it (§7.4)exact_simulation
twirleach cx, cz and swap between a seeded Pauli and its image through the gatestabilizer
ddthe decoupling sequence in each window where a qubit idles for as many layers as it has pulsesstabilizer

The passes a level runs, in order:

Levelclifford_tstandardcz, zz, xx
0lower, approximatelowerlower, native_2q (each two-qubit gate by its own fixed identity)
1simplify, lower, simplify, phase_fold, lower, approximate, phase_fold, simplify, lowersimplify, lower, simplify, phase_fold, simplifysimplify, lower, simplify, phase_fold, simplify, lower, native_2q, resynth_1q
2simplify, lower, simplify, resynth_2q, lower, resynth_1q, phase_fold, simplify, lower, approximate, resynth_1q, phase_fold, phase_resynth, simplify, lowersimplify, lower, simplify, resynth_2q, lower, phase_fold, resynth_1q, simplifyas level 1

Then the request’s passes, then twirl, then dd. A request’s passes may name a built-in pass too: "passes": ["phase_resynth"] lowers the T count past phase folding at any level and in any basis.

3.1 Each level against the levels below it

A basis’s objective is what its compiles are held to: the output’s counts (§4) compared in this order, fewer first.

BasisObjective
clifford_tt_count, then cnots, then gates
standardcnots, then gates
cz, zz, xxtwo_qubit, then gates

A pass that writes a part of the circuit again (resynth_1q, resynth_2q) keeps the new part only when it is better on the same counts in the same order, with the rotations off the multiples of π/4 weighed before them in clifford_t, since each becomes a word of about 3·log₂(1/ε) T gates.

A pass’s gain can still cost a later pass more: two-qubit blocks written again with fewer CNOTs can leave phase folding fewer T gates to merge. So a compile at level 1 or 2 also compiles the program at each level below it, under the same options (the request’s passes, twirl and dd too), and gives the output that is best on the objective, of those that tie the highest level’s: a level MUST NOT give an output worse on its objective than a lower level gives for the same request. The certificate is the kept compile’s (its passes, its bound and its check of the whole output), under the level asked for, and its guard records the comparison (here of clifford_t_n8_d40, §7.5, at level 2, whose own passes give two T gates more than level 1’s):

"guard": {
  "how": "…",
  "objective": ["t_count", "cnots", "gates"],
  "candidates": [
    { "level": 2, "output": "<64 hex>", "counts": { "t_count": 36, "cnots": 150, "gates": 287 } },
    { "level": 1, "output": "<64 hex>", "counts": { "t_count": 34, "cnots": 156, "gates": 287 } },
    { "level": 0, "output": "<64 hex>", "counts": { "t_count": 72, "cnots": 160, "gates": 374 } }
  ],
  "kept": 1
}

A lower level that refuses the program is a candidate with the reason (refused) and is not kept; a refusal of the level asked for is the compile’s. A compile at level 0 has no guard.

4. The certificate

{
  "format": "wai.quantum.compile/1",
  "basis": "clifford_t",
  "level": 0,
  "source": { "hash": "<64 hex>", "qubits": 2, "counts": { "…": "…" } },
  "output": { "hash": "<64 hex>", "counts": { "…": "…" } },
  "epsilon": { "budget": 0.0001, "rotations": 2, "each": 5e-05, "bound": 7.4e-05 },
  "passes": [
    { "pass": "lower", "input": "<64 hex>", "output": "<64 hex>",
      "layer": "exact_simulation", "bound": 0.0,
      "before": { "…": "…" }, "after": { "…": "…" },
      "check": { "how": "…", "verdict": "exact", "checked": 1, "proved": 0, "distance": 5.6e-17 } },
    { "pass": "approximate", "input": "<64 hex>", "output": "<64 hex>",
      "layer": "bounded", "bound": 7.4e-05,
      "before": { "…": "…" }, "after": { "…": "…" },
      "check": { "how": "…", "verdict": "approximate", "rotations": 2, "epsilon_each": 5e-05, "t_count": 76, "distance": 7.4e-05 } }
  ],
  "rotations": [ { "angle": 0.3, "t_count": 38, "distance": 3.8e-05, "k": 20 }, { "…": "…" } ],
  "whole": { "how": "…", "distance": 7.3e-05, "verdict": "approximate", "layer": "exact_simulation" },
  "verdict": "approximate",
  "layer": "exact_simulation",
  "weakest": "bounded",
  "reading": "…"
}

A certificate sealed before certificates carried input, output, layer and bound holds none of them, nor layer and weakest. It is of the earlier form, and is held to its format and its budget alone (§6).

5. Layers

5.1 A pass’s layer

Weakest first:

LayerWhat the engine didWhat that does not show
uncheckednothing: the pass was skipped, or its check did not hold and it was left outthe pass changed nothing: its output is its input
boundedcomputed the output’s operator-norm distance from the input, up to a global phase, from the output itself in fixed point, and rounded it upequality: the two differ by at most the bound
exact_simulationcompared in double precision: dense matrices or every basis state of the qubits a step touches, or a phase polynomial’s sumsa proof: the two are equal to the rounding of doubles
exact_arithmeticestablished an identity in integers: a word multiplied out over Z[ω]/√2ᵏ, a phase polynomial in whole eighths of a turn, or two unitaries proportional entry by entry (§7.1)anything of gates whose angles are not whole eighths of a turn
stabilizercompared stabilizer tableausanything of a circuit that is not Clifford

exact_arithmetic and stabilizer are proofs, and a pass checked by either adds no distance. exact_simulation is a numeric check: the pass’s record says exact, never proof, unless every step of it was also proved (a host’s registered pass proved by a chain of checked rewrites says proof with this layer, since each rewrite’s window is compared on a tableau or on basis states). stabilizer, exact_simulation and unchecked are the layers of those names in a job’s verdict (quantum-providers §8); exact_arithmetic and bounded are a compile’s own.

5.2 The whole compile’s layer

The whole output is held to the whole program by the first of these that decides it, and a compile whose output any of them finds is not the program MUST be refused:

LayerThe checkAsked when
stabilizerboth are Clifford circuits with the same tableauno pass approximated, up to 4096 qubits
exact_arithmeticboth multiplied out over Z[ω]/√2ᵏ and found proportional (§7.1)no pass approximated, every gate of both in the ring, up to 6 qubits and 2²² gate-entry updates
exact_simulationtheir dense unitaries, the distance at most epsilon.bound plus 1e-9 for the rounding of doublesup to 8 qubits
pass_equivalencenone: the passes’ own checks stand, composedotherwise

So a compile that approximates never has a proof’s layer; a wide program that is not Clifford stands on its passes’ checks, and its certificate says so.

6. Holding a certificate to its form, and to its request

6.1 The form

These hold of every certificate of the chained form (one whose passes carry input or layer), and a reader can check each without running anything. A certificate that breaks one MUST NOT be accepted.

  1. format is wai.quantum.compile/1.
  2. Every digest is 64 lower-case hex digits.
  3. The digests chain: the first pass’s input is source.hash, each pass’s input is the output of the pass before it, and the last pass’s output is output.hash.
  4. Every layer is one of §5.1’s, and every bound is a finite number that is not negative.
  5. A pass whose layer is unchecked, exact_arithmetic or stabilizer has bound 0, and one whose layer is unchecked has output equal to input.
  6. A pass’s layer is one its check’s verdict gives: rejected and skipped give unchecked; approximate gives bounded; exact gives exact_simulation; proof gives exact_arithmetic, stabilizer or (a registered pass) exact_simulation.
  7. epsilon.bound is the sum of the passes’ bound, in order, in double precision, and is at most epsilon.budget.
  8. verdict and weakest are what the passes conclude (§4).
  9. layer is one of §5.2’s and is whole.layer; it is not stabilizer or exact_arithmetic when verdict is approximate.
  10. whole.distance, where there is one, is at most epsilon.bound plus 1e-9.
  11. Where it holds guard: the guard’s objective is its basis’s (§3.1); its candidates are level and each level below it, highest first, each with an output digest and a whole number for each count of the objective and nothing else, or with refused, the first never refused; kept is the level of a candidate not refused whose output is output.hash and whose counts are output.counts’; and no candidate not refused has fewer counts, compared in the objective’s order, nor the same counts at a higher level than kept. A certificate sealed before the guard has none, and is not held to this rule.

A certificate of the earlier form is held to rule 1 and to epsilon.bound ≤ epsilon.budget. In §6.2 it is held to its output’s digest and to the check of the whole output, and to nothing that depends on the engine that wrote it (its program’s digest, the names of its options): it is never answered differs for not being reproduced.

6.2 A sealed compile

A compile is returned as {"request", "result"}, the result holding qasm (the compiled program), certificate, options, with stages when asked, the engine that made it and its schema, sealed by a receipt in the form every job’s takes (quantum-providers §8). A verifier checks the receipt first; when it holds, it looks at the compile again and reports what it finds under compile:

{ "again": "reproduced", "form": "chained", "layer": "exact_simulation",
  "weakest": "bounded", "passes": 2, "differences": [], "why": "…" }

It MUST answer differs, and the job is then not valid though its seal holds, when any of these is so (differences names each):

Otherwise its answer is:

A verifier compiles a request again only when its program holds at most 50 000 gates and at most 2 000 rotations off the multiples of π/4 once lowered (each is a synthesis); past that it does not, and says so in why.

6.3 A job that ran compiled

A job whose request holds compile runs its program compiled, and its result’s compiled holds, beside the summary (basis, level, budget, distance, the bound, verdict, counts and certificate, the BLAKE3 of the certificate’s RFC 8785 canonical JSON), the certificate’s chain:

"chain": { "source": "<64 hex>", "output": "<64 hex>",
           "layer": "exact_simulation", "weakest": "bounded",
           "passes": [ { "pass": "lower", "input": "<64 hex>", "output": "<64 hex>",
                         "layer": "exact_simulation", "bound": 0.0 }, { "…": "…" } ] }

The chain is held to rules 2 to 5 and 7 of §6.1 (with compiled.distance as the bound and compiled.epsilon as the budget), to weakest, and to a layer of §5.2. A verifier then reads the request again, which compiles its program: reproduced when that gives this compiled byte for byte; differs when the chain breaks a rule, the request asks for no compile, or the verifier’s own engine gives another; otherwise host_statement.

7. What each method guarantees

7.1 Exact arithmetic

A gate whose angles are whole eighths of a turn has a matrix with entries in D[ω] = Z[ω][1/√2], ω = e^{iπ/4}: the Paulis, h s sdg t tdg sx sxdg, the rotations and u at multiples of π/4 (each up to a global phase), cx cy cz ch swap iswap, cp at multiples of π/4, crx cry crz at multiples of π/2 (under a control the rotation’s own phase counts, and its half angle must be a whole eighth), rxx ryy rzz at multiples of π/4, ccx ccz cswap. A circuit of such gates on up to 6 qubits is multiplied out as one matrix of elements of Z[ω] over a common power of √2, with integers of any size and no rounding. Two such unitaries are equal up to a global phase exactly when they are proportional: Aᵢ·Bₚ = Bᵢ·Aₚ for every entry i, for one entry p where B is not zero.

Guarantee: a proof, the same bits on every host, of the circuit as the engine reads it: an angle within 10⁻¹² eighths of a whole eighth of a turn is read as that eighth, here as everywhere in the engine. Limits: 6 qubits, 2²² gate-entry updates for the pair, and no gate outside the ring; past any of them nothing is concluded and the next check is asked.

A gate in the ring may lower to gates outside it (a controlled phase at an odd eighth lowers through sixteenths of a turn): that decomposition is compared in doubles, and lower’s layer is then exact_simulation.

7.2 One-qubit synthesis

7.3 A rotation in Clifford+T

rz(θ) at an angle off the multiples of π/4 is written as a Clifford+T word by the published grid-problem method: for the denominator exponent k = 0, 1, 2, …, the elements u of Z[ω] with u/√2ᵏ in the part of the unit disk within ε of the rotation and with its conjugate in the unit disk are enumerated as a two-dimensional grid problem; for each, t†t = 2ᵏ − |u|² is solved in Z[ω] by factoring; the first k with a solution gives the operator, and of the operators found at that k the one whose word has the fewest T gates is taken, then the nearest. All of it is integer and fixed-point arithmetic (320 fractional bits).

Guarantee. The word is Clifford+T exactly; it multiplies back, in the ring, to the operator found; and its distance to rz(θ), up to a global phase, is computed again from the word itself in fixed point and rounded up. That recomputed distance is the pass’s bound and each rotation’s distance, and it is at most the rotation’s share of the budget, or the compile is refused. The same angle and ε give the same word on every host.

What is not guaranteed. The word is not proved the shortest. At each k at most 64 candidates have their norm equation tried, and a candidate whose factoring passes 2¹⁴ steps is passed over; a shorter word behind such a candidate is missed. Measured: against every Clifford+T operator of at most 11 T gates, the word’s T count is the optimum in 21 of 24 cases and one more in 3; over 1 192 angles and precisions from 10⁻¹ to 10⁻¹³ it is never more than a reference implementation’s of the same method. The count is close to 3·log₂(1/ε).

Measured. The T count of the word for rz(θ) against ε (the engine’s test the_t_count_against_epsilon_is_the_table_the_specification_gives pins every entry and its k; every word’s distance, recomputed from the word, is within its ε). Each synthesis took under a tenth of a second, measured on one core of an arm64 host in a release build.

θ \ ε10⁻²10⁻³10⁻⁴10⁻⁵10⁻⁶10⁻⁷10⁻⁸10⁻⁹10⁻¹⁰
π/7202735515672788998
11429384861718089100
0.123172935475672808797
3·log₂(1/ε)19.929.939.949.859.869.879.789.799.7

The rotations vectors (§9) pin five of these words, and the second implementation (§9) multiplies each pinned word out again in integers and computes its distance in 90-digit decimals: every pinned distance is the word’s own, rounded up, and within its ε.

7.4 Two-qubit synthesis

Any two-qubit unitary is (A₁⊗A₂)·exp(i(a·XX + b·YY + c·ZZ))·(B₁⊗B₂) up to a phase (the KAK decomposition), with a, b, c reduced to (−π/4, π/4].

A block is also written gate by gate through fixed identities (cx as h·cz·h; cz as one rzz(π/2) or rxx(π/2) with quarter turns undone), and that is kept where it spends no more two-qubit gates.

Guarantee and accuracy class. The decomposition is numeric: a fixed-order Jacobi eigen-solver using only + − × ÷ √ and the crate’s own trigonometric functions, in doubles. It is deterministic, the same bits on every host, but it is not exact arithmetic. Every block written is compared with the block it replaces on their 4×4 matrices and kept only within 1e-9; the measured distances add to the pass’s bound. The layer is exact_simulation, the verdict exact, never proof. A job that runs such an output does not gain the bit-exact class from it: the bit-exact method takes dyadic angles only.

7.5 T-count reduction

Three passes lower the T count, and all are proofs when the circuit is Clifford+T:

phase_resynth runs at level 2 of clifford_t, after the last phase_fold, and in any basis and level when a request names it in passes.

Where the whole circuit is Clifford+T on up to 6 qubits, the whole output is also proved the whole program in exact arithmetic (§5.2), whatever the passes did.

Measured. The T count of Clifford+T programs: as written (each gate lowered as lower writes it), the output of level 1, the output of level 2’s own passes and of level 2 (the best of that and the levels below it, §3.1), and the T gates phase_resynth removed in level 2’s passes; then the CNOTs of the outputs of levels 1 and 2. The first four are of the cross-simulator’s corpus (quantum-cross-simulator/corpus/qasm/), the rest of quantum-conformance/compile/benchmarks/. The engine’s test the_t_count_reductions_are_the_table_the_specification_gives pins every entry; no compile approximates a rotation, and each within six qubits is proved the program in exact arithmetic.

ProgramQubitsAs writtenLevel 1Level 2’s passesLevel 2phase_resynthCNOTs, level 1CNOTs, level 2
clifford_t_n4_d2041911111103431
clifford_t_n8_d40872343634 (level 1’s)0156156
clifford_t_n12_d4012964646460232230
grover_n332828282802424
ccz_triples_n442887711613
ccz_line_n662814131311831
cccz_ancilla_n552115151501616
toffoli_chain_n773523232302626
adder_n884224242404343

What it shows: phase folding takes most of what there is to take, and phase_resynth finds more where several Toffolis share variables inside one region (ccz_triples_n4: 4·Σ xᵢxⱼxₖ over the four triples is seven T gates, not eight; ccz_line_n6, at 13 more CNOTs). On the random circuits, the Toffoli chain and the adder no region phase folding leaves takes fewer by the search (where its terms span six variables or fewer, none can); what more there is needs the Hadamards between regions taken out of the way, which no pass here does. On clifford_t_n8_d40 level 2’s own passes write two-qubit blocks again with six fewer CNOTs and no more T gates, but phase folding, after them, then has two T gates fewer to merge: 36 against level 1’s 34. Each block is better on the objective where it is written; the loss shows only in the whole, so the guard (§3.1) keeps level 1’s output, and level 2 is never worse than level 1. Running phase folding before resynth_2q gives 34 T gates and 150 CNOTs here, but more T gates on five of the corpus’s rotation-heavy programs (dyadic_n6_k20, gate_c2ry, gate_c2rz, rotations_wide_n20, tn_shallow_n26, from 2 to 28 more) and fewer on two (rotations_n6, rotations_counts_n6, 12 fewer), so the order stays as it is.

8. Determinism

A compile is the same bytes on every host: the synthesis of rotations is integer and fixed-point arithmetic; the numeric decompositions use only + − × ÷ √ and the crate’s own trigonometric functions, with fixed-order eigen-solvers; no output depends on a map’s order, a clock or a thread. That is what lets a verifier compile again and compare (§6.2). The conformance vectors pin the digest of each certificate; they are held on macOS arm64, Linux x86-64, Linux arm64 and wasm32.

9. Conformance

quantum-conformance/compile/vectors.json holds:

quantum-conformance/compile/benchmarks/ holds the Clifford+T programs of §7.5’s table that are not the cross-simulator’s.

quantum-conformance/tools/compile_form.py is a second implementation of §6.1 and of §7.3’s guarantee, in Python, from this text alone. It holds the set’s pinned certificates to the eleven rules (certificate.json, of the forged vectors’ first request, and guarded.json, a level-2 compile’s with its guard) and makes the forged vectors’ edits to the certificate of their request: each must break the rule its vector names, and a vector that names none must leave the form holding. And it multiplies each rotations vector’s word out over Z[ω]/√2ᵏ in integers: the word must be Clifford+T with the T count pinned, unitary, and no farther from its rotation, computed in 90-digit decimals, than its pinned distance, which must be that distance rounded up and within ε.

10. What it leaves out