open-standards/wai/extensions/quantum-sim.md
Transaction Science a7464244c5 WAI Quantum: wasmQ envelopes and qudit jobs in Python, npm, the Studio and the desktop app
- Python: qudit, qudit_check, wasmq (an envelope's bytes, a path or an example's name),
  wasmq_verify (with the envelope, run again byte for byte) and wasmq_examples, the
  extension module running an envelope on wai-wasmq's own interpreter (no compiler in the
  wheel); Service.wasmq and Service.qudit run them on a service. Tests: both kinds run and
  verified here, a qudit run equal to `wai-quantum qudit run`'s bits and a wasmQ/1 job equal
  to `wai-quantum run`'s byte for byte, and both run on a service built from this checkout.
- npm (wai-web, quantum_engine): QuantumEngine.qudit and QuantumEngine.wasmq (the
  interpreter, the only engine on wasm32), engine_qudit_check, engine_wasmq_verify,
  engine_wasmq_examples and engine_wasmq_example. The smoke test runs every example in Node,
  each sealed, held to its form and run again, a fault sealed and W013 refused.
- Quantum Studio: the "Qudits" and "wasmQ" panes (closed until opened), in the browser and
  in the desktop app (its qudit, qudit_check, wasmq, wasmq_verify and wasmq_examples
  commands): the qudit counts by digits, amplitudes as integers, bounds, the seal checked
  and the request run again; an example envelope or a .wai file opened there, its outcome,
  calls, fuel, counts and energy, its seal and form checked and the envelope run again; a
  refusal with its code. The browser e2e drives each.
- quantum-wasmq §11.9 and quantum-sim §9.10 name every surface.

Tested on the build hosts: wai-web for wasm32-unknown-unknown and the npm smoke test in Node
26 (macOS arm64); the Python package's wheel (maturin 1.15.0), clippy -D warnings and pytest
(95 passed, the widgets' node test skipped there) on Linux x86_64; the Studio's browser e2e
(macOS arm64, STUDIO_SKIP_SERVICE=1), every qudit and wasmQ check passing.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 23:18:39 -05:00

1068 lines
55 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# WAI Extension: Quantum-Circuit Simulation
> Status: Draft. A quantum computation shipped as **instructions**, not
> outcomes: the wire carries a compact gate op-log (a `WQC` container),
> the sink **classically simulates** it in a fixed-point complex floor,
> and the reconstructed statevector hashes identically on every machine.
> Conformance is **statevector-equivalence** (and, for measured circuits,
> **shot-histogram-equivalence**). Two capabilities share the container
> layout, the gate IR and the arithmetic: `wai.quantum.circuit2` (magic
> `WQC2`), for new content, and `wai.quantum.circuit` (magic `WQC1`), frozen
> so that existing content reproduces bit for bit. Reference impl: the
> `quantum` feature of `wai-quantum` (`wai_quantum::quantum`), which `wai-rs`
> forwards and re-exports as `wai::quantum`; corpus: `quantum-conformance/`.
Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119/8174.
## 1. Scope and model
A quantum-circuit object is a **quantum circuit**: a qubit count and an ordered
list of gates. The sink reconstructs the resulting quantum state by simulating
the circuit from `|0…0⟩` in a fixed-point complex floor — every amplitude is a
complex fixed-point number (`re, im` as `i64` at scale `2^FRAC`), every gate an
integer matrix–vector update with a pinned rounding rule. It is lever 3
(instructions-at-the-sink) applied to computation: the wire carries the
*circuit*, the sink reconstructs the *state*.
Two capabilities carry such an object. They differ only in the magic, the
contract (§2.1), the phase table the gates read (§3.1, §3.2) and how strictly a
reader holds the container (§2):
| capability | magic | contract `ext` | phase table | for |
|---|---|---|---|---|
| `wai.quantum.circuit2` | `WQC2` | `wai.quantum.circuit2/1` | correctly rounded (§3.2) | new content |
| `wai.quantum.circuit` | `WQC1` | `wai.quantum.circuit/1` | frozen (§3.1) | existing content, which reproduces bit for bit |
Below, **circuit2** and **circuit/1** name the two. Writers SHOULD NOT emit new
circuit/1 content: its phase table deviates from the ideal phases for `k ≥ 8` and
applies none for `k ≥ 19` (§3.1). A sink that reconstructs circuit/1 content
reads it exactly as this text states, so that the content keeps its hashes and
its receipts keep verifying. §8 says why the correction is a capability of its
own.
The design rule that governs the whole extension: **WAI's value is
determinism** — byte-identical reconstruction, "conformance is a hash." Real
quantum **hardware** is the enemy of that: NISQ noise and stochastic
measurement are not reproducible across devices. So this extension does
**not** use, require, or emulate a QPU, and delivers **no** quantum speedup.
It makes a quantum *computation* a transportable, deterministic, receiptable
object — nothing more, and it says so plainly.
In scope: the container, the gate IR, the deterministic reconstruct
contract, the **statevector-equivalence** and **shot-histogram-equivalence**
conformance criteria, the quantum-information-theoretic fidelity metric, and
the receipt profile. §9 states registers of qudits (2, 3, 4 or 6 levels) in the same
floor, run as a job of the engine rather than carried in a container.
Out of scope: quantum hardware or any device backend; a compression codec
for arbitrary media (this is not one); variational-quantum-circuit /
"quantum AI" **priors** whose measurement is stochastic — those are at best a
float/behavioral capability that can never back `intent=replicate`, so they
do not belong in this exact-reconstruction extension (§7).
Relationship to the core spec: mirrors worlds / score / film. The
reconstruct runs in the deterministic floor; `media` takes the informational
value `"quantum"`; the envelope's capability names which of the two applies.
Both capabilities have the replicate class `StandardDefined` (WAI's own
deterministic floor) and the fidelity tier `Lossless` (the simulation analog —
the reconstruction is byte-exact).
## 2. Container (`WQC`)
```
magic | u16 n_sections | n_sections × (u8 kind, u32 off, u32 len) | sections
```
The magic names the capability: `WQC1` is circuit/1 and `WQC2` is circuit2. The
layout is otherwise identical. All integers in the container are little-endian.
The sections blob starts immediately after the table, at byte
`6 + 9·n_sections`, and `off` is relative to it: a section occupies the bytes
from `blob + off` to `blob + off + len`. A reader computes these bounds without
overflow (in arithmetic wider than 32 bits, or with checked operations) and
refuses a table or a section, of any kind, that runs past the end of the payload.
| kind | section | required |
|---|---|---|
| `0x01` | contract (canonical JSON, §2.1) | REQUIRED |
| `0x02` | gate op-log (§2.2) | REQUIRED |
| `0x03` | measurement (canonical JSON, §2.3) | OPTIONAL |
Unknown section kinds MUST be ignored (forward-compatible). A known kind that
appears more than once MUST be refused: two readers could otherwise read
different sections of one payload. The reference writer emits the contract, the
op-log and the measurement, if any, in that order and contiguous from offset 0,
and no other section.
**JSON in a section.** The contract and the measurement are I-JSON texts
([RFC 7493](https://www.rfc-editor.org/rfc/rfc7493)), and a reader decides each
of these rules from the section's bytes:
- The section is UTF-8 and holds one JSON value
([RFC 8259](https://www.rfc-editor.org/rfc/rfc8259)), with only space, tab,
line feed and carriage return around its tokens. A byte-order mark is not
whitespace.
- No object names a member twice. Names are compared after their escapes are
decoded, so `"a"` and `"\u0061"` are the same name.
- No name or string holds a surrogate code point or a noncharacter (U+FDD0 to
U+FDEF, and the last two code points of every plane), written raw or as an
escape. An escaped surrogate pair stands for the one character it encodes.
- No number has a magnitude of 2^1024 − 2^970 or more. These are exactly the
numbers that round to an infinite IEEE 754 double, rounding to nearest with
ties to even. A reader decides the rule exactly, on the literal's digits: its
significant digits and its decimal exponent against the 309 digits of
2^1024 − 2^970, however many digits or zeros the literal is written with. A
float parser decides it only where it rounds correctly at every length and
every exponent. A number that rounds to zero is in range.
- Arrays and objects nest at most 127 deep, the outermost counted as the first.
RFC 7493 also asks a sender to keep a number within a double's precision and an
integer within ±(2^53 − 1). A reader here does not hold what it receives to that:
it reads an integer exactly, so `seed` and `shots` (§2.3) span the whole `u64`
range. Where a rule asks for an *unsigned JSON integer*, it means a number
written with no sign, fraction or exponent, whose value is in the range the rule
names: `-0`, `2.0` and `2e0` are not one.
A section that breaks one of these rules is a contract refusal for the contract
and a malformed one for the measurement. A section that breaks several is
refused with that class whichever of them a reader meets first; readers may name
different rules for it, and only the class is specified.
A reader refuses a payload that breaks a rule of this section or of §2.1–§2.3.
It checks in this order and refuses with the class of the first rule broken:
1. The payload is at least 6 bytes and starts with `WQC1` or `WQC2`; else
**malformed**.
2. The section table and every section, of a known kind or not, lie within the
payload; no known kind repeats; the contract and the op-log are present.
Else **malformed**.
3. The contract (§2.1); else **contract**, except that an `n_qubits` that is
not an unsigned integer of at most 255 is **malformed**.
4. The op-log parses (§2.2); else **malformed**.
5. The circuit keeps the rules of its capability (§2.2); else **invalid**.
6. The measurement, if present (§2.3); else **malformed**.
The corpus's `reject/` tree holds at least one payload for each refusal of this
section and of §2.1–§2.3 that a payload can carry, and `reject.json` names each
one's class. The two limits it cannot carry bind a writer instead: the wire
counts a gate's controls in a `u8` and a circuit's ops in a `u32`. Its `accept/`
tree holds payloads at the edges of the same rules that a reader MUST accept,
and `accept.json` gives how each one reads: its capability, `n_qubits`, op count,
`circuit_hash` and measurement.
### 2.1 Contract
The canonical contract bytes, used for writing and for `circuit_hash` (§4.1),
have no whitespace and these members in this order. `N` is `n_qubits` in
decimal, `0` to `255`, with no sign, leading zero, fraction or exponent:
- circuit/1:
`{"ext":"wai.quantum.circuit/1","n_qubits":N,"numeric":"wai.det.fixed64","frac":30,"gateset":"cliffordT+dyadicP"}`
- circuit2:
`{"ext":"wai.quantum.circuit2/1","n_qubits":N,"numeric":"wai.det.amp64","frac":30,"gateset":"cliffordT+dyadicP.rn"}`
A writer writes the canonical contract of its capability.
`ext` is `<capability>/<contract revision>`: `wai.quantum.circuit2/1` is revision
1 of the circuit2 capability, not a version "2.1". `frac` is the amplitude
fixed-point scale (`FRAC`, 30 in both). `gateset` names the reconstruction's gate
algebra (§3); circuit2's string differs from circuit/1's because its constants
differ. `numeric` names the arithmetic:
- `wai.det.amp64`: complex amplitudes, `re` and `im` each an `i64` at scale
`2^frac`. A product of two components is computed exactly and rounded as
`(a·b + 2^(frac−1)) >> frac`, with an arithmetic shift (round half up); sums
are exact (§3.0).
- `wai.det.fixed64`, inside a circuit/1 contract, means the same: the §3.0
arithmetic at frac 30, with products rounded half up. Those bytes are inside
every circuit/1 `circuit_hash`, so they stay. It does not mean the Q32.32
floor, with products rounded toward −∞, that
[interactive-worlds](interactive-worlds.md) §6.2 names `wai.det.fixed64`.
Reading a circuit/1 contract. The section MUST be an I-JSON object (§2), else
contract.
Its `ext`, `numeric` and `gateset` MUST be the strings of the template above and
its `frac` the JSON integer `30` (`30.0` is not); a member that is missing or
carries another value is a contract refusal, so a circuit2 contract in a `WQC1`
container is refused. Then `n_qubits` MUST be an unsigned JSON integer of at most
255, else malformed. Member order, whitespace and further members are free;
`circuit_hash` covers the canonical bytes, not the received ones (§4.1).
Reading a circuit2 contract. The section MUST be an I-JSON object (§2), else contract,
whose `n_qubits` is an unsigned JSON integer of at most 255, else malformed. Its
bytes MUST then equal the canonical circuit2 contract for that `n_qubits`, else
contract: no whitespace, no other member order and no further member, and a
circuit/1 contract in a `WQC2` container is refused.
### 2.2 Gate op-log
`u32 n_ops`, then per op:
```
u8 opcode | u8 n_ctrl | u8 target | u16 param | n_ctrl × u8 control
```
The op is a **controlled-1-qubit gate**: the base gate `opcode` is applied to
`target` iff every qubit in `control` is set. `param` carries the dyadic index
`k` for `P(k)`. Opcodes:
| opcode | gate | | opcode | gate |
|---|---|---|---|---|
| 0 | `I` | | 5 | `S` |
| 1 | `X` | | 6 | `S†` |
| 2 | `Y` | | 7 | `T` |
| 3 | `Z` | | 8 | `T†` |
| 4 | `H` | | 9 | `P(k) = diag(1, e^{2πi/2^k})` |
`CX`/`CZ`/`CP(k)` are these with `n_ctrl = 1`; `CCX` (Toffoli) with
`n_ctrl = 2`; `SWAP` is three `CX`.
Parsing, in both capabilities: every op lies within the section and its opcode is
at most 9, else malformed. In circuit2 the section MUST end exactly after the
`n_ops`-th op, else malformed; in circuit/1 bytes after it are ignored and are
not part of the circuit. `n_ops` is the payload's claim: every op takes at least
5 bytes, so a section of `len` bytes holds at most `⌊(len − 4)/5⌋` ops, and a
reader reserves no more than that.
The rules of the circuit, refused as invalid:
- in both capabilities, a target is `< n_qubits`; a control is `< n_qubits` and
`≠ target`; a gate has at most 255 controls (the wire counts them in a `u8`,
so this binds a writer); `P(k)` has `1 ≤ k ≤ 32`; a circuit has at most
`2^32 − 1` ops;
- in circuit2 also, a gate's controls are pairwise distinct, so there are at
most 254, and `param` is 0 for opcodes 0–8.
circuit/1 keeps the rules it had: a repeated control is the same condition
twice, and opcodes 0–8 ignore `param`.
### 2.3 Measurement (optional)
```json
{"seed":12648430,"shots":100000,"basis":"computational"}
```
Pins a computational-basis sampling for shot-histogram-equivalence (§4.2); the
example is the corpus's bell measurement.
`seed` and `shots` are unsigned 64-bit integers.
- circuit2: the section MUST be exactly
`{"seed":S,"shots":N,"basis":"computational"}`, with `S` and `N` in decimal
with no sign, leading zero, fraction, exponent or whitespace; else malformed.
- circuit/1: the section MUST be I-JSON (§2), else malformed. A `seed` or `shots` that
is missing or is not an unsigned integer in the `u64` range reads as 0, and
`basis` is not read. The reference writer writes the circuit2 form.
## 3. Reconstruct contract
### 3.0 Arithmetic, for both capabilities
An implementer needs all of this, with the phase table of §3.1 or §3.2, to
reproduce a statevector.
- **Amplitude.** `(re, im)`, each an `i64` at scale `2^30`; `2^30` is 1. A unit
below means `2^−30`.
- **Product.** `fx(a, b) = (a·b + 2^29) >> 30`, with `a·b` exact (signed 128-bit
arithmetic holds it) and `>>` an arithmetic shift, that is floor division by
`2^30`.
- **Complex product.** `(a·b).re = fx(a.re, b.re) − fx(a.im, b.im)` and
`(a·b).im = fx(a.re, b.im) + fx(a.im, b.re)`. Each product is rounded
separately; the sums are exact.
- **Initial state.** `2^n` amplitudes, `amps[0] = (2^30, 0)` and every other
`(0, 0)`. Qubit `q` is bit `q` of the basis index, qubit 0 the least
significant.
- **A gate** (base, controls `C`, target `t`, param), for every index `i` with
bit `t` clear and every bit of `C` set, with `j = i | 2^t`, sets
```
a_i' = m00·a_i + m01·a_j a_j' = m10·a_i + m11·a_j
```
from the values before the gate, each product a complex product and each sum
exact. Gates apply in op-log order.
- **Matrices.** With `P(k)` the capability's phase table (§3.1 or §3.2),
`h = re P(3)`, `1 = (2^30, 0)` and `i = (0, 2^30)`:
| opcode | gate | `m00` | `m01` | `m10` | `m11` |
|---|---|---|---|---|---|
| 0 | `I` | `1` | `0` | `0` | `1` |
| 1 | `X` | `0` | `1` | `1` | `0` |
| 2 | `Y` | `0` | `−i` | `i` | `0` |
| 3 | `Z` | `1` | `0` | `0` | `−1` |
| 4 | `H` | `(h, 0)` | `(h, 0)` | `(h, 0)` | `(−h, 0)` |
| 5 | `S` | `1` | `0` | `0` | `i` |
| 6 | `S†` | `1` | `0` | `0` | `−i` |
| 7 | `T` | `1` | `0` | `0` | `P(3)` |
| 8 | `T†` | `1` | `0` | `0` | `conj P(3)` |
| 9 | `P(k)` | `1` | `0` | `0` | `P(k)` |
- The capability selects the table and nothing else, and only `H`, `T`, `T†`
and `P(k)` read it.
- `fx(±2^30, x) = ±x` and `fx(0, x) = 0` exactly, so a product with a matrix
entry of `0`, `±1` or `±i` is exact. An implementation may skip such products
(a diagonal gate need touch only `a_j`) without changing a bit.
The canonical reconstructed quantity is the amplitude vector serialized as
`re_le(i64) ‖ im_le(i64)` per amplitude, in index order.
`cliffordT+dyadicP` and `cliffordT+dyadicP.rn` are universal (Clifford+T is
dense in `SU(2^n)`). In circuit2, `P(k)` gives the controlled-phase ladder of
the QFT ("quantum FFT"), transported as a circuit (`H` + controlled-`P(k)` +
swaps) and reconstructed byte-exact; the circuit/1 table does not (§3.1). No float runs on the decode: the phase tables are
integer constants.
### 3.1 The circuit/1 phase table (frozen)
`P1(1) = (−2^30, 0)` and `P1(2) = (0, 2^30)`. For `k = 3..32`, with
`c = re P1(k−1)`:
```
re P1(k) = isqrt(⌊(2^30 + c) / 2⌋ · 2^30)
im P1(k) = isqrt(⌊(2^30 − c) / 2⌋ · 2^30)
```
`isqrt` is the floor square root. Both halves are non-negative, so truncating
division and floor division agree. `H` uses `h = re P1(3) = 759250124`, `T` is
`P1(3)` and `T†` is `conj P1(3)`.
The table is the one every circuit/1 file, hash and receipt was made with, and it
is kept bit for bit. Its literal values (Appendix B.1) are normative by equality,
and so is its digest, BLAKE3 over `i64le(re) ‖ i64le(im)` for `k = 1..32`
(512 bytes, no domain prefix):
`3fa9805ff96feb819a1cf371fedcd3b5228f93eddf933d0edcf401cbf8c28466`.
Its floors compound. The stored values deviate from `2^30·e^{2πi/2^k}`, in units:
- `re P1(k)` is low by up to 1.3 units for every `k ≥ 3`;
- `im P1(k)` is within 2.2 units for `k ≤ 7`, then too large: +9.52 (`k = 8`),
+21.1 (9), +49.0 (10), +90.5 (11), +124.3 (12), +224.4 (13), +112.2 (14),
+1355.6 (15), +677.3 (16), +5283.2 (17, about 10% of the angle) and +7032.1
(18, about 27%);
- `im P1(19..32) = 0`: these entries apply no phase at all, a deviation of the
whole angle, from −12868 units at `k = 19` to −1.57 at `k = 32`.
A QFT on `n` qubits uses `P(2..n)`, so in circuit/1 a QFT on 8 or more qubits
applies phases that are off by more than 9 units, and one on 19 or more applies
none for its smallest rotations.
### 3.2 The circuit2 phase table
`P2(1) = (−2^30, 0)` and `P2(2) = (0, 2^30)`, both exact. For `k = 3..32`:
```
P2(k) = ( ⌊2^30·cos(2π/2^k) + ½⌋ , ⌊2^30·sin(2π/2^k) + ½⌋ )
```
the integers nearest to the ideal values. For `k ≥ 3` every ideal value is
irrational, so none is a half-integer and the nearest integer is unique. The
closest any ideal value comes to a half-integer is 0.00456 unit, at `im P2(22)`,
so any computation of the ideal values accurate to better than that rounds to the
same table. `H` uses `h = re P2(3) = 759250125`, `T` is `P2(3)` and `T†` is
`conj P2(3)`; `re P2(3) = im P2(3)`.
The literal values (Appendix B.2) are normative by equality, and an
implementation carries them as constants; it need not compute them. Their digest,
computed as for circuit/1, is
`d34cb793715348e7c92db027c0bc3dddb6008f5730470bafaed978ea7fb23510`.
**The circuit2 table gives the QFT**: every rotation `P(2..32)` of the
controlled-phase ladder is within half a unit per component of its ideal value.
§5 states what that leaves of the error.
*Derivation (informative).* An exact-integer procedure certifies the table with no
floating point. At scale `2^62` it keeps an enclosure
`c_lo ≤ 2^62·cos(2π/2^k) ≤ c_hi` and `s_lo ≤ 2^62·sin(2π/2^k) ≤ s_hi`, starting
from `(cos, sin)(π/2) = (0, 1)`, which is exact, and halves the angle with
`cos(θ/2) = √((1 + cos θ)/2)` and `sin(θ/2) = sin θ / (2 cos(θ/2))`, which has no
cancellation, rounding every bound outward:
```
S = 2^62
ceil_isqrt(x) = r if r·r = x, else r + 1, where r = isqrt(x)
R(x) = (x + 2^31) >> 32 -- scale 2^62 to 2^30, half up
(c_lo, c_hi, s_lo, s_hi) = (0, 0, S, S)
for k in 3..=32:
c_lo' = isqrt(((S + c_lo)·S) >> 1)
c_hi' = ceil_isqrt(⌈(S + c_hi)·S / 2⌉)
s_lo' = ⌊s_lo·S / (2·c_hi')⌋
s_hi' = ⌈s_hi·S / (2·c_lo')⌉
require R(c_lo') = R(c_hi') = re P2(k)
require R(s_lo') = R(s_hi') = im P2(k)
require |(x mod 2^32) − 2^31| > 2^20 for x in {c_lo', c_hi', s_lo', s_hi'}
(c_lo, c_hi, s_lo, s_hi) = (c_lo', c_hi', s_lo', s_hi')
```
Every step keeps a true enclosure, and when both ends of an enclosure round to
the same integer, that integer is the correctly rounded value. Every product
fits 125 bits, every enclosure is at most 3 units of `2^−62` wide, and no end
comes within 19,590,902 units of `2^−62` of a tie. The reference implementation
runs this procedure as a test, and the corpus referee runs it independently.
## 4. Conformance
### 4.1 statevector-equivalence
> Given the same circuit under the same capability, a conforming sink MUST
> reconstruct the identical fixed-point statevector, hence the identical
> BLAKE3 — on every machine, no tolerance parameter.
```
statevector_hash = BLAKE3("wai:quantum-statevector\x01"
‖ u8 n_qubits ‖ u32le frac
‖ per amplitude, in index order: i64le re ‖ i64le im)
circuit_hash = BLAKE3("wai:quantum-circuit\x01"
‖ canonical contract (§2.1) of the capability for n_qubits
‖ canonical op-log)
```
The canonical op-log is the §2.2 encoding of the circuit's ops: `u32le n_ops`,
then each op, and nothing after. For circuit2 the canonical contract and op-log
are the bytes received, since the reader requires them. For circuit/1 the
contract is the re-rendered template, however the received one was formatted,
and bytes after the last op are not part of the op-log.
`circuit_hash` is the identity of the circuit, and its contract names the
capability, so it binds the capability and its phase table: the same ops under
circuit/1 and circuit2 have different circuit hashes. `statevector_hash` hashes
the amplitudes alone and names no capability: the two capabilities give the same
statevector, and so the same hash, for a circuit in which no gate that reads the
table acts on a nonzero amplitude (one of `X` gates only, say). A run is
therefore identified by its `circuit_hash`, and each sink's `statevector_hash`
is the verifiable result.
### 4.2 shot-histogram-equivalence (measured circuits)
For a circuit with a §2.3 measurement, a conforming sink MUST sample the
computational-basis outcome as follows, producing an identical per-basis-state
count vector:
- The weight of basis state `i` is `w_i = re_i² + im_i²`, exact; `W` is their
sum, and `cum_i` the sum of `w_0..w_i`. The weights are not normalised.
- `splitmix64` with state `s`, starting at `seed`, all arithmetic mod `2^64`:
`s ← s + 0x9E3779B97F4A7C15`; `z ← s`;
`z ← (z ⊕ (z >> 30))·0xBF58476D1CE4E5B9`;
`z ← (z ⊕ (z >> 27))·0x94D049BB133111EB`; the draw is `z ⊕ (z >> 31)`.
- Each of the `shots` shots draws `x`, takes `r = x mod W`, and counts the first
basis state `i` with `cum_i > r`. If `W` is 0, every count is 0.
```
histogram_hash = BLAKE3("wai:quantum-histogram\x01"
‖ u8 n_qubits ‖ u64le seed ‖ u64le shots
‖ per basis state, in index order: u64le count)
```
`seed`, `shots` and every count are `u64le`; `n_qubits` is a `u8` prefix. The
histogram depends only on the statevector and the measurement, so it names no
capability either.
## 5. Fidelity and size (honest)
Two honesties the format states rather than implies:
1. **The reconstruction is exact; the model it reconstructs is an
approximation.** The statevector is byte-identical across sinks
(statevector-equivalence), but it is a *fixed-point* approximation of the
ideal complex-amplitude unitary evolution. This is the same call as
`wai.video.int_motion`: byte-exact reconstruction of a defined-lossy quantity.
The tier is therefore `Lossless` in the *simulation* sense (like world
replay), and the error bound is part of the contract, not a hidden claim.
Per capability:
- **circuit2.** Every table constant is within ½ unit of its ideal value,
which §3.2 proves, and every product within ½ unit of the exact product.
One gate applied to a pair of amplitudes whose squared moduli sum to at
most 1 therefore lands within 2 units per component of the ideal gate
applied to the same pair: each component takes at most two rounded
products, ½ unit each, and the constants' error of ½ unit each meets
components whose squares sum to at most 1, which gives `1 + √2/2 ≈ 1.71`.
The worst measured on random normalised pairs is under 1.5 units. Errors
accumulate roughly linearly in the number of gates. Some table entries have
a modulus slightly above 1, by at most 0.3603 unit (`||P2(k)|² − 1|` is at
most 0.73 unit), so a long run of one phase drifts the norm upward, at the
order of the product rounding: `P2(19)` applied `2^18` times to `|1⟩`, a
half turn, ends at modulus 1.0000189 and within `10^−5` rad of the half
turn. The resolution of `2^−30` is a floor no rounding removes:
`P2(26..32)` carry imaginary parts of 101 down to 2, so `P2(32)` is correct
to the nearest unit (ideal 1.5708, stored 2) and 27% off in relative angle.
A finer resolution needs a new capability.
- **circuit/1.** The same arithmetic with the constants of §3.1, which are
off by up to 12868 units, and `P1(19..32)` apply no phase. The bound above
does not hold: one `P1(k)` errs by as much as its constant does. `P1(19)`
applied `2^18` times to `|1⟩` ends at exactly `(1073479680, 0)`: each step
loses a unit and none rotates.
A QFT on `n` qubits needs `P(2..n)`, so a 26-qubit QFT needs `P(19..26)` and
is circuit2-only.
2. **The state is exponential; the circuit is not.** A statevector is
`2^n` amplitudes × 16 bytes — the reconstruction is heavy and grows
exponentially. The *transportable* object is the circuit op-log, which is
linear in gate count (the reference corpus's QFT-5 circuit is 261 bytes as
circuit/1 and 263 as circuit2, and reconstructs a 32-amplitude state; a
26-qubit QFT is still a few kilobytes and reconstructs ~1 GiB). The win is
exactly WAI's thesis — the wire carries instructions, the sink
reconstructs — and it is *why* the receipt matters: because reconstruction
cost is exponential, an energy-metered, byte-exact, signed record of the
computation is a genuinely novel artifact.
This extension is a way to make a quantum computation portable and verifiable.
It is not a media codec and it is not a route to quantum advantage.
## 6. Receipt (JWP profile)
The receipt (`wai-quantum/src/quantum_receipt.rs`, feature `quantum_receipt`,
which `wai-rs` forwards under the same name) is the artifact this whole extension
exists to make possible. Its
design principle: **separate the two halves of the reconstruction's cost so each
is trusted the way it honestly can be.**
| field | what it is | how it is trusted |
|---|---|---|
| `circuit_hash` | identity — the `WQC` circuit's hash, which names its capability | re-checkable |
| `statevector_hash` | the byte-exact reconstruction result | **re-checkable** (re-simulate) |
| `measurement` | optional `{seed, shots, histogram_hash}` | re-checkable |
| `work_amp_updates` | `n_ops · 2^n` — the exponential reconstruction cost | **verified by recomputation** |
| `joules_micro` | measured marginal CPU energy the sink spent; `null` beside `energy_unmetered`, the reason, for a run nobody measured ([quantum-ops](quantum-ops.md) §3.5), and in a receipt sealed before that form, `0`, the unmetered marker, read as unmetered (legacy), never as zero joules | **attested by signature** |
| `energy_provenance` and its evidence (optional; [energy-measurement](energy-measurement.md) §2.8) | how `joules_micro` was acquired | **attested by signature**, not re-measurable |
`work_amp_updates` is *portable-exact*: anyone recomputes it from `(n_ops,
n_qubits)` and it grows exponentially in qubits, so a sink cannot inflate or
deflate the stated cost. `joules_micro` is *measured-attested*: only the signer
can vouch for what its own silicon drew, and the same holds for the class that
labels it and for the values of any report about it (energy-measurement §6). One Ed25519 signature,
verified strictly by the rule every quantum receipt is ([quantum-providers](quantum-providers.md)
§8.2 *The signature, strictly*), covers all of it
over a Merkle root of the leaf hashes (`circuit`, `statevector`, `[histogram]`) —
the worlds / provenance / film receipt shape reused, `parent_receipt_hash`
chaining a derivation exactly as they do.
The receipt format is the same for both capabilities. A receipt names its
capability through `circuit_hash`, whose contract names it (§4.1).
Two verification depths:
- `verify()` — Merkle root recomputes, `work == n_ops · 2^n`, signature valid by that rule.
- `verify_reconstruction(circuit)` — the strong, portable check: **independently
re-simulate the circuit** and confirm it reproduces the receipt's
`circuit_hash`, `statevector_hash`, shape, and histogram, *then* that the
receipt verifies. A receipt claiming a statevector the circuit does not
reconstruct to is rejected on any machine. (The measured `joules_micro` stays
attested-only — re-simulation checks the *result and cost*, never the signer's
energy draw.)
`verify_reconstruction` re-simulates the circuit under its own capability: the
circuit as decoded from its container, whose magic names it. A receipt sealed
under one capability therefore does not verify against the same ops under the
other. A receipt sealed before circuit2 existed (by `wai-quantum` 0.3.x) is a
circuit/1 receipt: re-verify it with its `WQC1` file, or with the circuit built
in circuit/1 (`Gateset::V1`). The reference's `gateset_of` reports under which
capability a circuit's ops match a receipt's `circuit_hash`; it explains a failed
reconstruction and decides nothing.
`to_json()` / `from_json()` give the portable, sorted-key JSON an out-of-band
verifier reads. `wai_quantum_meter <circuit.wqc> [receipt.json]` fills the
energy honestly: it samples the CPU power the open-source `macmon` reader
reports (no elevated privileges), brackets a reconstruction burst against an idle
baseline, and writes the marginal microjoules — never a fabricated number; where
no reader is present, or the reported power does not move in both brackets
([energy-measurement](energy-measurement.md) §3.1), or the §4 ratio cannot
support a figure, it emits an UNMETERED receipt in the unmetered form
([quantum-ops](quantum-ops.md) §3.5: `joules_micro` `null` beside `energy_unmetered`, the
meter's reason, inside the signature), never a figure of zero joules, with the exact work
intact. A receipt sealed before that form carries the unmetered marker `0`
([energy-measurement](energy-measurement.md) §2) and is read as unmetered (legacy).
`POST /verify` renders either as `"joules_micro": null` with `"unmetered"` saying why. Beside a
figure the meter writes a measurement report (energy-measurement §6). A figure is sealed with its acquisition class as a
`quantum_energy::Labelled` receipt ([energy-measurement](energy-measurement.md)
§2.8): `ModelBased`, inside the signature, because the samples are a power the
reader reports from a channel it selects, not a counter the meter reads and shows
live ([energy-measurement](energy-measurement.md) §3.1). It is
verified with `Labelled::verify` / `Labelled::verify_reconstruction`. The
`wai-quantum verify` CLI and the HTTP handler's `POST /verify` accept a receipt
in any form (`quantum_energy::MaybeLabelled`) and restate its class. A receipt
sealed without a label keeps its legacy bytes and its figure is unlabelled. The
meter decodes the circuit from its container, so the receipt binds the capability
the file names. A representative run on the reference QFT-5 vector, at a revision
that labelled the same reported power `OnChipCounter`: **≈43 µJ per
reconstruction, `work_amp_updates = 672`** (21 ops × 2⁵), sealed and
self-verified.
Because a quantum computation carries no speedup here, this is exactly the value
the standard adds: an energy-accounted, byte-exact, signed record whose *result*
and *cost* anyone can re-check, and whose *energy* the signer attests.
## 7. Quantum information theory as the conformance metric
The exact path above conforms by **byte identity**, so state fidelity is
`1` by construction — but the reference exposes the
quantum-information-theoretic metric explicitly, `fidelity_fx(a, b) =
|⟨a|b⟩|²` in the fixed-point floor (`0` for orthogonal states, `≈ ONE` for
equal). It serves two roles: a **diagnostic** here (how close an *approximate*
or float simulation lands to the byte-exact reference), and the **conformance
metric** for the future path this extension deliberately excludes — a
variational-quantum-circuit / "quantum AI" prior whose measurement is
stochastic. Such a prior is `NeuralFloat`/`Behavioral`: it MUST NOT back
`intent=replicate`, and would conform by a declared fidelity floor, exactly as
`wai.semantic.*` conforms by a CLIP-similarity threshold. Naming the metric now
fixes the axis before that capability is ever registered.
## 8. Versions
**Why circuit2 is a capability of its own.** The circuit/1 table comes from a
recurrence whose floors compound (§3.1). Correcting it under the same string
would change the payload format of a registered capability, which SPEC §8
forbids: once a capability string is registered, its payload format is fixed
forever, and a later change never widens an existing string. It would also
change the reconstruction, the `circuit_hash` and every receipt of the content
made with it. So the corrected table is a new capability, `wai.quantum.circuit2`,
with a magic of its own, and circuit/1 stays as it was.
**What a reader that predates circuit2 does.** It requires the magic `WQC1`, so
it refuses a `WQC2` payload at the magic, before it reads anything else. It does
not advertise `wai.quantum.circuit2`, so an envelope that names that capability
is inert to it (SPEC §4). It recomputes `circuit_hash` with the circuit/1
contract, so a circuit2 receipt does not verify there. Each of these fails
closed: no older reader reconstructs circuit2 content with the circuit/1 table.
**Payloads this revision makes non-conforming.** This revision states reader
rules for circuit/1 that enforce its registration as it was made (SPEC §8): the
contract's values (§2.1), the range of `n_qubits`, sections within the payload,
and one section of each known kind (§2). Earlier reference readers accepted
payloads that break them, and a reader of this revision refuses:
- a `WQC1` contract whose `ext`, `numeric`, `frac` or `gateset` is missing or
carries another value, a circuit2 contract among them;
- an `n_qubits` that is not an unsigned integer of at most 255 (an earlier
reader read 258 as 2);
- a known section kind that appears more than once (an earlier reader kept the
last);
- a section whose bounds overflow (an earlier reader could wrap on a 32-bit
target);
- a contract or measurement that repeats a member name within one object (an
earlier reader kept the last), or that holds a noncharacter in a name or a
string;
- a contract or measurement holding a number of magnitude 2^1024 − 2^970 or
more that an earlier reader accepted. Earlier readers left the range to their
float parser, so depending on how they were built they accepted some such
numbers, and refused some numbers below the limit that a reader of this
revision accepts.
The other rules of §2 refuse what earlier reference readers refused.
No file written by any reference version is affected: every reference writer
wrote the canonical contract, one section of each kind, and sections within the
payload. The reference implementation adds circuit2 in `wai-quantum` 0.4.0, where
a circuit built in code is circuit2 unless it is built as circuit/1.
## 9. Qudits
A register of **qudits** generalises the qubit: each of its `n` digits has `d`
levels. The Pauli group becomes the Weyl–Heisenberg group (the shift `X` and
the clock `Z`), the Hadamard becomes the Fourier transform over `Z_d`, and
`CNOT` becomes addition modulo `d`. This section states a register's
arithmetic, its constants, what each gate adds to the error, its measurement,
and the job that runs it (`wai.quantum.qudit/1`). It adds no capability: no
container carries a register, nothing in §2 to §8 changes, and a sink that
reads `WQC` needs none of it. Reference implementation: `quantum_qudit` (the
library) and `engine::qudit` (the job) in `wai-quantum`, and `wai-quantum
qudit`; corpus: `quantum-conformance/qudit/`.
The rule of §1 holds here: the same integers on every machine, every constant a
stated number, and the error a stated bound.
### 9.1 The register
- **Dimensions.** `d` is 2, 3, 4 or 6: the dimensions whose roots of unity
have degree at most two over the rationals (`φ(d) ≤ 2`), so that every
coordinate of a root is `0`, `±1`, `±1/2` or `±√3/2` (§9.2). Every other
dimension is refused; none is given roots from a float or a series. (8 and 12
would take the same construction, their coordinates `±√2/2` and `±√3/2`, and
are not built.)
- **Amplitudes.** `d^n` amplitudes, each as in §3.0: `(re, im)`, `i64` at
scale `2^30`. Qudit `q` is digit `q` of the base-`d` index, qudit 0 the least
significant. The initial state has `amps[0] = (2^30, 0)` and every other
`(0, 0)`.
- **Fibres.** For a gate on qudit `q`, a fibre is the `d` amplitudes at
indices `i₀ + j·d^q` for `j = 0 … d − 1`, where `i₀` has digit `q` equal to 0;
amplitude `j` of the fibre is the one at level `j`.
At `d = 2` the register is circuit2's state vector, and its gates are circuit2's
(§9.3).
### 9.2 The constants
**The roots.** `ω_d^k = e^{2πik/d}` is `12k/d` twelfths of a turn, whose
coordinates are:
| twelfths | 0 | 2 | 3 | 4 | 6 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|
| `(cos, sin)` | `(1, 0)` | `(1/2, √3/2)` | `(0, 1)` | `(−1/2, √3/2)` | `(−1, 0)` | `(−1/2, −√3/2)` | `(0, −1)` | `(1/2, −√3/2)` |
Each coordinate is `s·√(p/q)` for a sign `s` and whole `p`, `q`: `1` is
`√(1/1)`, `1/2` is `√(1/4)` and `√3/2` is `√(3/4)`. The Fourier gate's entry
`ω_d^m/√d` has the coordinates `s·√(p/(q·d))`.
**The fixed point of `s·√(p/q)`** is `s·c`, with
```
f = ⌊√⌊p·2^60 / q⌋⌋ (= ⌊2^30·√(p/q)⌋)
c = f + 1 when 4·p·2^60 ≥ (2f + 1)²·q, else f
```
in whole numbers: `c` is the nearest whole number to `2^30·√(p/q)`, and every
machine finds the same one. It is **exact** (the fixed point holds the number
itself) when `c²·q = p·2^60`: so `0`, `±1` and `±1/2` are exact. Every other
constant is irrational, so it is **correctly rounded**: within half a unit
(`2^−31`) of its number, and never a tie. These are all of them:
| constant | `p/q` | at `2^30` | the number at `2^30` | error, units |
|---|---|---|---|---|
| `√3/2` | 3/4 | 929887697 | 929887696.6898 | +0.3102 |
| `1/√2` | 1/2 | 759250125 | 759250124.9940 | +0.0060 |
| `1/√3` | 1/3 | 619925131 | 619925131.1266 | −0.1266 |
| `1/(2√3)` | 1/12 | 309962566 | 309962565.5633 | +0.4367 |
| `1/√6` | 1/6 | 438353264 | 438353264.0476 | −0.0476 |
| `1/(2√6)` | 1/24 | 219176632 | 219176632.0238 | −0.0238 |
| `√2/4` | 1/8 | 379625062 | 379625062.4970 | −0.4970 |
So: every root of `d = 2` (`±1`) and `d = 4` (`±1`, `±i`) is exact, as are the
real parts of the roots of `d = 3` and `d = 6`; their imaginary parts are
`±929887697`. `F_4`'s entries (`±1/2`, `±i/2`) are exact. `F_2`'s are
`±759250125`, which is circuit2's `re P(3)`. `F_3`'s are `619925131` and
`(−309962566, ±536870912)`; `F_6`'s are `±438353264` and
`(±219176632, ±379625062)`. A first version of the reference took `√3/2` and
`1/√3` as floors (929887696 and 619925130, the second a floor of a floor and
1.13 units low) and called them exact; this text replaces it.
**The constants' digest** of `d` is BLAKE3 over `"wai:qudit-constants\x01" ‖
u8 d`, then `ω_d^k` for `k = 0 … d − 1`, then the Fourier entries `ω_d^m/√d`
for `m = 0 … d − 1`, each as `i64le re ‖ i64le im`:
| `d` | constants' digest |
|---|---|
| 2 | `fa5e6bc7fe53b14b4e5917caeb9b8028ae316c7f619bdd5c292565c9360b9dbf` |
| 3 | `2f4a3854c397f95e152396701355baab1c14f1ba5a735c0d34378fd71b571d72` |
| 4 | `0bc240d517a49c6052b02e972d0592f8b21b342c782f8770f845cc88e61045a3` |
| 6 | `15f24f2b6546ea838e9360b122e4172c4574097c6fabc61cea0980c920596715` |
### 9.3 The gates and their arithmetic
Products and sums are §3.0's: each real product `fx(a, b)` rounded half up,
each complex product four of them, every sum exact. A gate reads the amplitudes
as they were before it.
| gate | takes | does |
|---|---|---|
| `shift` | `power` `a`, `0 ≤ a < d` | in every fibre, the amplitude at level `j` moves to level `(j + a) mod d` |
| `clock` | `power` `b`, `0 ≤ b < d` | in every fibre, the amplitude at level `j` is multiplied by `ω^{b·j}` |
| `phase` | `powers` `k₀ … k_{d−1}`, each `0 ≤ k_j < d` | in every fibre, the amplitude at level `j` is multiplied by `ω^{k_j}` |
| `fourier` | `power` `p`, `0 ≤ p ≤ 3` | `p = 0`: nothing. `p = 2`: in every fibre, the amplitude at level `j` moves to level `(−j) mod d`. `p = 1`: in every fibre, `a'_k = Σ_j F_{kj}·a_j` with `F_{kj}` the Fourier entry of `m = jk mod d`. `p = 3`: the same with `m = (−jk) mod d`, `F†` |
| `csum` | qudits `c ≠ t`, `power` `a`, `0 ≤ a < d` | the amplitude at an index whose digits `c` and `t` are `x` and `y` moves to the index whose digit `t` is `(y + a·x) mod d`, the others unchanged |
`F²` is the reflection, applied as the permutation it is; applying `F` twice
gives the reflection within its bound, not exactly. A multiplication by `ω^0 =
(2^30, 0)` leaves an amplitude as it was, so a gate whose every entry is 1 (a
power of 0, or every `k_j = 0`) changes nothing, and an implementation may skip
it.
At `d = 2`, `fourier` is circuit2's `H` (its entries are `(±h, 0)` with `h = re
P(3)`, and the sum is §3.0's `m00·a_i + m01·a_j`), `shift` is `X`, `clock` is
`Z` and `csum` is `CNOT`: a program of them gives circuit2's amplitudes on any
state, bit for bit. At `d = 4`, `F` is the two-qubit Fourier transform (`H` on
the high qubit, a controlled `P(2)` from the low one, `H` on the low one, a
swap), and the two give the same integers on every basis state. At `d = 6`, `F`
is `F_2 ⊗ F_3` under the Chinese-remainder relabelling of the levels (`n = (3n₁
+ 2n₂) mod 6` in, `k ≡ k₁ (mod 2)` and `k ≡ k₂ (mod 3)` out), exactly in the
constants' own numbers.
### 9.4 What a gate adds to the error
A register's amplitudes are the same integers everywhere, and differ from the
ideal state by what the arithmetic rounds. Of each gate, two numbers:
- `r`, the most rounded products in one coordinate of one output amplitude. A
product with a coordinate `0` or `±1` is exact (§3.0); every other is
rounded, by at most half a unit. For `clock` and `phase`, `r` is the most, over
their entries, of the coordinates of an entry that are neither `0` nor `±1`;
for `fourier` with `p = 1` or `3`, the most, over the output levels `k`, of
that count summed over `j`; for a permutation, 0.
- `κ`, a bound on the operator norm of the gate's matrix as held less the
ideal one, in units: each irrational coordinate is off by at most half a unit.
For `clock` and `phase`, `κ = ½·√m`, `m` the most irrational coordinates of
any entry; for `fourier` with `p = 1` or `3`, `κ = ½·√m`, `m` the irrational
coordinates of all `d²` entries (a Frobenius bound); for a permutation, 0.
| `d` | `F`, `F†`: `r` | `F`, `F†`: `κ` | `clock`, `phase` with a root other than `±1` | otherwise |
|---|---|---|---|---|
| 2 | 2 | 1 | | 0, 0 |
| 3 | 5 | 1.5 | `r = 2`, `κ = ½` | 0, 0 |
| 4 | 4 | 0 | | 0, 0 |
| 6 | 10 | `½·√52 ≈ 3.606` | `r = 2`, `κ = ½` | 0, 0 |
`shift`, `csum`, `F²` and the identity add nothing, and so does a `clock` or
`phase` whose roots are all `±1` or `±i` (every one at `d = 2` and `d = 4`;
`clock` with `b = 3` at `d = 6`). A program of such gates is the ideal state
exactly.
**The state's bound.** On `N = d^n` amplitudes, from `E = 0`, each gate in turn
sets
```
E ← E·(1 + κ·2^−30) + κ + (r/2)·√(2N)
```
in units of `2^−30`, and the final `E` bounds the 2-norm distance between the
computed state and the ideal one: the ideal unitary carries the error so far
unchanged, the matrix as held adds `κ` times the state's norm (at most
`1 + E·2^−30`), and each of the `2N` coordinates takes at most `r` roundings of
half a unit. It is computed in IEEE-754 binary64, every operation rounded to
nearest, in this order: `√(2N)` once; then `((E·(1 + κ·2^−30)) + κ) + ((0.5·r)
·√(2N))` for each gate, `κ` itself `0.5·√m`. So it is the same double on every
machine. On random programs of every gate, on 1 to 3 qudits of every dimension
and random states, the largest distance measured is 0.79 of the bound.
**The outcomes' bound.** With `e = E·2^−30`, the law the counts are drawn from
(§9.5) is within total variation `2e(2 + e)` of the ideal outcome distribution
while `2e + e² < 1/17`; past that the bound is 1, and says nothing. In doubles,
`e = E/2^30`, the test is `(2·e) + (e·e) < 1/17` (the double nearest `1/17`),
and the bound `(2·e)·(2 + e)`. The
computed weights' law is within `e(2 + e)` of the ideal one, since
`Σ|p̃ᵢ − pᵢ| ≤ |1 − S| + e(2 + e)` with `S = ‖ã‖² ∈ [(1 − e)², (1 + e)²]`.
Reducing a 64-bit draw modulo the weights' sum `W` adds at most
`min(R, W − R)/2^64 ≤ |S − 1| ≤ 2e + e²`, where `R = 2^64 mod W`, while
`|S − 1| < 1/17` keeps `⌊2^64/W⌋` at 15 or 16.
### 9.5 Measurement
Every qudit is read at the end, in the computational basis, as §4.2 reads a
qubit register: the weight of basis state `i` is `wᵢ = reᵢ² + imᵢ²`, exact, `W`
their sum and `cumᵢ` the sum of `w₀ … wᵢ`; `splitmix64` from `seed` gives one
`x` a shot, `r = x mod W`, and the shot's outcome is the first `i` with `cumᵢ >
r`. With `shots` 0, or `W` 0, nothing is drawn. An implementation may sort the
draws and walk the weights once: each shot's outcome is the same.
An outcome is written as the qudits' digits, the highest-numbered qudit first
(qudit 0 is the last character), each digit `0` to `d − 1`. `counts` lists the
outcomes drawn, the most frequent first and then by their text, at most 65536
of them; `distinct_outcomes` is how many there were, and `omitted_shots` the
shots of those not listed.
### 9.6 The state's digest
```
state_blake3 = BLAKE3("wai:qudit-state\x01" ‖ u8 d ‖ u8 n
‖ per amplitude, in index order: i64le re ‖ i64le im)
```
and `norm2` is `⌊Σ (reᵢ² + imᵢ²) / 2^30⌋`, which stays near `2^30`.
### 9.7 The job: `wai.quantum.qudit/1`
A request is a JSON object:
| member | | |
|---|---|---|
| `d` | required | 2, 3, 4 or 6 |
| `qudits` | required | a whole number, at least 1 |
| `gates` | required | a list, each `{"gate", "qudits"}` and a `power` (`shift`, `clock`, `fourier`, `csum`; 1 when left out) or `powers` (`phase`, required): `qudits` holds one qudit, or for `csum` two different ones, the control then the target |
| `shots` | optional | a whole number; 1024 when left out |
| `seed` | optional | a whole number from 0 to `2^53 − 1`; 1 when left out |
| `amplitudes` | optional | a list of outcomes, each `n` digits as §9.5 writes them |
A whole number is a JSON number with no fractional part from 0 to `2^53 − 1`,
read by its value (`1`, `1.0` and `1e0` are one). A request is checked in this
order, and the first rule that fails is the refusal (the
job layer's codes, `wai-quantum/docs/job-refusals.md`):
1. the request is an object, with no member but these (`J090`);
2. `d` is a whole number (`J090`), and 2, 3, 4 or 6 (`J091`);
3. `qudits` is a whole number of at least 1 (`J090`), and `d^qudits` is at most
`2^24` (`J092`);
4. `gates` is a list (`J090`) of at most 65536 (`J092`), and each gate in turn
reads: its `gate` one of the five, no member its gate does not take, its
`qudits` in the register, a `csum`'s two different, each power in its range
and `phase` with exactly `d` powers (`J090`);
5. `shots` is a whole number (`J090`) of at most 10^6 (`J092`);
6. `seed` is a whole number from 0 to `2^53 − 1` (`J090`);
7. `amplitudes` is a list (`J090`) of at most 64 (`J092`), each `n` digits
below `d` (`J090`);
8. the work is at most `2^32` (`J092`).
**The work** is what the job touches: each gate's (`N` for a permutation or a
`clock` or `phase`; `N·d` for `fourier` with `p = 1` or `3`; nothing for a gate
that changes nothing: a power of 0, or a `phase` of `ω^0` at every level), and
`2N + shots` for the draws and the digest.
**The answer** to a run holds, in this order: `answer` (`"run"`), `d`,
`qudits`, `gates` (how many), `shots`, `seed`, `counts`, `distinct_outcomes`
and `omitted_shots` (§9.5), `outcomes` (a sentence: how an outcome is
written), `amplitudes` when the request asks (each by its digits, `{"re",
"im"}`, the integers at `2^−30`), `state` (`blake3`, `amplitudes` (that is,
`N`) and `norm2`, §9.6), `constants` (`blake3`, §9.2), `work`, and `accuracy`:
`class` `bit-exact`, `bound` (`E·2^−30`), `bound_units` (`E`), `outcomes` (the
outcomes' bound) and a `note`. A host names the engine and the schema
(`engine`, `schema`: `wai.quantum.qudit/1`, `wai-quantum/schemas/qudit.v1.json`),
writes its word on the run's energy in `energy` (a reading, or `unmetered` with
the reason; never 0 for unmetered), and seals the request and the result as
every job is sealed ([quantum-providers.md §8.2](quantum-providers.md), the
receipt `wai.quantum.receipt/2`), so `wai-quantum verify` checks it as any
job's. **Checking one** (`wai-quantum qudit check`) verifies the receipt, runs
the request again and holds every member of the result but `receipt`,
`energy` and `engine` to the one given; it is verified when the signature holds
and nothing differs.
### 9.8 The ceiling, measured
A register holds at most `2^24` amplitudes: 24 qubits, 15 qutrits, 12 ququarts,
or 9 qudits of six levels. Its state is 256 MiB of amplitudes, which a 32-bit
host holds as one allocation. A job does at most `2^32` units of work, about a
minute of the largest register's Fourier gates on wasm32. Measured on the
reference build host (an arm64 workstation of 32 cores, shared) on 2026-11-10
by `engine::qudit`'s `measure_the_ceiling`, a release build natively and the
same test compiled to `wasm32-wasip2` and run by wasmtime 50.0.1 on the same
host:
| | native (aarch64), two runs | wasm32-wasip2 |
|---|---|---|
| a Fourier gate, per amplitude touched | 1.95–2.77 ns | 9.6–11.5 ns |
| a `clock`, per amplitude | 1.91–3.06 ns | 11.4–11.7 ns |
| a `shift` or `csum`, per amplitude | under 2 ns | under 5 ns |
| the largest job (127 Fourier gates on 24 qubits, work `2^32`) | 9.6 s and 10.1 s | 49.9 s |
| memory at its end | 277 MiB resident | 275 MiB linear memory |
A gate's time is the difference between a job of four of them and a job of none,
so the cheapest gates' figures are within the noise of a shared host (one run
gave a negative time for a `shift` at `d = 4`). The figures are for scale; the
limits are the contract, and they are the same on every host.
### 9.9 Conformance
`quantum-conformance/qudit/vectors.json` holds each dimension's constants (its
roots and Fourier entries at `2^30`, and their digest), 29 vectors (every gate
and power on every dimension, from one qudit to 14 qubits, each with the answer
a conforming host gives, every member of §9.7's answer but those a host adds),
and 35 requests a conforming host refuses, each with its code. A column of each
Fourier gate is among the vectors, every entry times an amplitude of exactly 1,
so a change of one unit to any constant changes some vector's state. Every
vector's answer is the same bytes on arm64 macOS, x86_64 Linux and
wasm32-wasip2 (CI, `wai-quantum-qudit.yml`), and
`quantum-conformance/tools/qudit_referee.py` recomputes all of it from this
section alone, in Python, in whole numbers and doubles, and moves every
constant by one unit to see a vector's state move.
### 9.10 What is not here
- **No noise and no measurement in the middle.** Every qudit is read once, at
the end.
- **No other dimension**, and no mixed register (a qubit beside a qutrit).
- **No energy reading but the job service's.** Every surface runs a qudit job and
checks one: the command line (`wai-quantum qudit run`, `check`), both MCP servers
(`run_qudit`), the job service (`POST /v1/qudit`, run as a job in a worker), the
Python package (`qudit`, `qudit_check`), the npm package (`QuantumEngine.qudit`,
`engine_qudit_check`), the Studio and the desktop app. The job service writes
its worker's reading in `energy`, or the unmetered form with the reason; every
other host writes the unmetered form with its reason.
- **No device.** Nothing here has run on a three-level machine. A register is
the ideal circuit's state, computed exactly as stated; it says nothing of how
a device's levels would behave.
## Appendix A — One floor, one more kind of state
statevector-equivalence is replay-equivalence with the world state replaced by
a quantum amplitude vector, and the deterministic floor extended from real
fixed-point (`Fx`) to complex fixed-point (`Amp`). The same discipline that
makes a world replay, a mix sum, an actuator buzz, a film frame and a Gaussian
cloud reconstruct now makes a quantum state reconstruct — one floor, one more
cargo class, one verification. The state is heavy and the model approximate;
the *reconstruction* of it is exact and auditable, and that — not a quantum
speedup WAI does not claim — is the honest thing the standard adds.
## Appendix B — The phase tables
`P(k)` as `(re, im)` at scale `2^30`, for `k = 1..32`, with each table's digest:
BLAKE3 over `i64le(re) ‖ i64le(im)` for `k = 1..32`, 512 bytes, no domain prefix.
The tables and digests below are rendered from the reference implementation's
constants (`PHASE_V1`, `PHASE_V2`) by `wai_quantum_vectors appendix`, and a test
fails when this text differs from what the constants render. B.1 is circuit/1's
table (§3.1) and B.2 is circuit2's (§3.2).
<!-- generated: wai_quantum_vectors appendix; do not edit by hand -->
### B.1 `wai.quantum.circuit`
| k | re P(k) | im P(k) |
|---:|---:|---:|
| 1 | -1073741824 | 0 |
| 2 | 0 | 1073741824 |
| 3 | 759250124 | 759250124 |
| 4 | 992008094 | 410903207 |
| 5 | 1053110175 | 209476638 |
| 6 | 1068571463 | 105245102 |
| 7 | 1072448454 | 52686012 |
| 8 | 1073418432 | 26350953 |
| 9 | 1073660972 | 13176485 |
| 10 | 1073721610 | 6588405 |
| 11 | 1073736770 | 3294284 |
| 12 | 1073740560 | 1647223 |
| 13 | 1073741507 | 823774 |
| 14 | 1073741744 | 411887 |
| 15 | 1073741803 | 207243 |
| 16 | 1073741818 | 103621 |
| 17 | 1073741822 | 56755 |
| 18 | 1073741823 | 32768 |
| 19 | 1073741823 | 0 |
| 20 | 1073741823 | 0 |
| 21 | 1073741823 | 0 |
| 22 | 1073741823 | 0 |
| 23 | 1073741823 | 0 |
| 24 | 1073741823 | 0 |
| 25 | 1073741823 | 0 |
| 26 | 1073741823 | 0 |
| 27 | 1073741823 | 0 |
| 28 | 1073741823 | 0 |
| 29 | 1073741823 | 0 |
| 30 | 1073741823 | 0 |
| 31 | 1073741823 | 0 |
| 32 | 1073741823 | 0 |
Digest: `3fa9805ff96feb819a1cf371fedcd3b5228f93eddf933d0edcf401cbf8c28466`
### B.2 `wai.quantum.circuit2`
| k | re P(k) | im P(k) |
|---:|---:|---:|
| 1 | -1073741824 | 0 |
| 2 | 0 | 1073741824 |
| 3 | 759250125 | 759250125 |
| 4 | 992008094 | 410903207 |
| 5 | 1053110176 | 209476638 |
| 6 | 1068571464 | 105245103 |
| 7 | 1072448455 | 52686014 |
| 8 | 1073418433 | 26350943 |
| 9 | 1073660973 | 13176464 |
| 10 | 1073721611 | 6588356 |
| 11 | 1073736771 | 3294193 |
| 12 | 1073740561 | 1647099 |
| 13 | 1073741508 | 823550 |
| 14 | 1073741745 | 411775 |
| 15 | 1073741804 | 205887 |
| 16 | 1073741819 | 102944 |
| 17 | 1073741823 | 51472 |
| 18 | 1073741824 | 25736 |
| 19 | 1073741824 | 12868 |
| 20 | 1073741824 | 6434 |
| 21 | 1073741824 | 3217 |
| 22 | 1073741824 | 1608 |
| 23 | 1073741824 | 804 |
| 24 | 1073741824 | 402 |
| 25 | 1073741824 | 201 |
| 26 | 1073741824 | 101 |
| 27 | 1073741824 | 50 |
| 28 | 1073741824 | 25 |
| 29 | 1073741824 | 13 |
| 30 | 1073741824 | 6 |
| 31 | 1073741824 | 3 |
| 32 | 1073741824 | 2 |
Digest: `d34cb793715348e7c92db027c0bc3dddb6008f5730470bafaed978ea7fb23510`
<!-- end generated -->