wai-quantum 0.4.0: wai.quantum.circuit2 — a correctly rounded phase table, circuit/1 stated exactly, both read by stated rules #207

Merged
dcharlot merged 14 commits from wai-quantum-circuit2 into main 2026-10-10 15:52:03 -04:00
153 changed files with 6759 additions and 668 deletions

View file

@ -62,6 +62,8 @@ on:
- 'wai/extensions/http-delivery.md'
- 'wai/extensions/moq-streaming-format.md'
- 'wai/extensions/jwp-receipts.md'
# The quantum referee requires this extension's Appendix B to state its phase tables.
- 'wai/extensions/quantum-sim.md'
- 'wai/wai-web/**'
# The audio provenance check below reads the corpora above with this tool.
- 'wai/tools/wai_audio_provenance_check.py'
@ -95,6 +97,8 @@ on:
- 'wai/extensions/http-delivery.md'
- 'wai/extensions/moq-streaming-format.md'
- 'wai/extensions/jwp-receipts.md'
# The quantum referee requires this extension's Appendix B to state its phase tables.
- 'wai/extensions/quantum-sim.md'
- 'wai/wai-web/**'
# The audio provenance check below reads the corpora above with this tool.
- 'wai/tools/wai_audio_provenance_check.py'
@ -457,6 +461,94 @@ jobs:
v staged-measure wai_stage_measure ../staged-measure-conformance
v telemetry wai_telemetry ../telemetry-conformance
# wai-quantum and the quantum corpus under wasm32-wasip2, run by wasmtime. On wasm32
# usize is 32 bits, so arithmetic that cannot overflow on a 64-bit host can there: a
# section's offset plus its length, a capacity reserved from a count a file claims, a
# shift by a qubit count. The builds are debug builds, so overflow checks are on and
# such an overflow panics instead of wrapping. Three steps:
# 1. tests/bit_identity.rs, which pins one result of each f64 layer, so the wasm32
# build must give the bits every native leg gives;
# 2. the library's unit tests in the modules that hold the circuit core, its
# container, its JSON reader and its pins (quantum, ijson, receipt_pins,
# quantum_fabric, quantum_source, quantum_channel, quantum_qudit, quantum_receipt),
# each required to have run;
# 3. wai_quantum_vectors verify over all four trees of quantum-conformance/ (both
# capabilities, the reject corpus and the accept corpus), the same check the matrix
# above runs natively.
# One leg: wasm32 is the same machine on every host. Linux, so it does not queue on the
# single macOS runner.
quantum-wasip2:
name: quantum core and corpus under wasm32-wasip2 (wasmtime)
runs-on: linux
timeout-minutes: 60
steps:
- uses: actions/checkout@v5
- name: Install Rust 1.98.0 with the wasm32-wasip2 target
shell: bash
run: |
export PATH="$HOME/.cargo/bin:$PATH"
command -v rustup >/dev/null 2>&1 || \
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal --default-toolchain 1.98.0
rustup toolchain install 1.98.0 --profile minimal
rustup default 1.98.0
rustup target add --toolchain 1.98.0 wasm32-wasip2
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
# The release binary, pinned by version and SHA-256, rather than a build from source.
- name: Install wasmtime 49.0.2
shell: bash
run: |
set -euo pipefail
[ "$(uname -m)" = x86_64 ] || { echo "::error::the pinned wasmtime archive is x86_64; this host is $(uname -m)"; exit 1; }
if ! command -v xz >/dev/null 2>&1; then
SUDO=""; [ "$(id -u)" -ne 0 ] && SUDO="sudo"
$SUDO apt-get update -qq
$SUDO apt-get install -y -qq xz-utils
fi
v=49.0.2
f="wasmtime-v$v-x86_64-linux.tar.xz"
curl --proto '=https' --tlsv1.2 -sSfL -o "$RUNNER_TEMP/$f" \
"https://github.com/bytecodealliance/wasmtime/releases/download/v$v/$f"
echo "a4d6e9e3a5a60f527cf7793d674c48930c80c2e8977995b8a275cad3254b9322 $RUNNER_TEMP/$f" | sha256sum -c -
tar -xJf "$RUNNER_TEMP/$f" -C "$RUNNER_TEMP"
echo "$RUNNER_TEMP/wasmtime-v$v-x86_64-linux" >> "$GITHUB_PATH"
- name: tests/bit_identity.rs under wasmtime
working-directory: wai/wai-quantum
env:
CARGO_TARGET_WASM32_WASIP2_RUNNER: wasmtime
run: cargo test --locked --target wasm32-wasip2 --features full --test bit_identity
# The filters are module paths, so a module that is renamed or loses its tests would
# leave its filter matching nothing and the run passing; the loop fails the step
# unless every module had a test that passed.
- name: The circuit core's unit tests under wasmtime
shell: bash
working-directory: wai/wai-quantum
env:
CARGO_TARGET_WASM32_WASIP2_RUNNER: wasmtime
run: |
set -euo pipefail
mods="quantum ijson receipt_pins quantum_fabric quantum_source quantum_channel quantum_qudit quantum_receipt"
filters=()
for m in $mods; do filters+=("$m::"); done
cargo test --locked --target wasm32-wasip2 --features full --lib -- "${filters[@]}" 2>&1 \
| tee "$RUNNER_TEMP/wasip2-lib.log"
for m in $mods; do
grep -q "^test $m::.* \.\.\. ok$" "$RUNNER_TEMP/wasip2-lib.log" \
|| { echo "::error::no test of $m ran"; exit 1; }
done
- name: wai_quantum_vectors verify under wasmtime
shell: bash
working-directory: wai/wai-rs
run: |
set -euo pipefail
cargo build --locked --target wasm32-wasip2 --no-default-features --features quantum --bin wai_quantum_vectors
wasmtime run --dir ../quantum-conformance::/corpus \
target/wasm32-wasip2/debug/wai_quantum_vectors.wasm verify /corpus
# The generated v2 vocabulary (wai/vocab/v2.*) is checked as a consumer uses it:
# sample manifests, typed and untyped, WAI1 and WAI2, are expanded through the
# JSON-LD context exactly as written on the wire and validated against the SHACL
@ -488,7 +580,7 @@ jobs:
# verdicts required to equal wai_signer_vectors' line for line), and
# int_payload_verify.py (the integer payloads and their refusal fixtures), and
# staged_verify.py (the staged-delivery corpus), and http_verify.py (the HTTP delivery
# corpus).
# corpus), and quantum-conformance/tools/referee.py (both quantum-sim capabilities).
# Each exits non-zero on any failure or any difference, and the step fails with it.
# One platform: what they check is the reading of the text, not the architecture.
independent-verifiers:
@ -587,6 +679,19 @@ jobs:
working-directory: wai
shell: bash
run: python3 staged-measure-conformance/sim_verify.py staged-measure-conformance
# The quantum corpus's second implementation (quantum-sim extension), integers only:
# it derives the circuit/1 phase table by its recurrence and the circuit2 table by an
# interval-certified procedure, and requires both literal tables and their digests,
# and the extension's Appendix B to state the same;
# rebuilds every file of both vector trees byte for byte and recomputes every manifest
# entry with its own reader, simulator, sampler and BLAKE3; refuses every reject file
# with its listed class and by the rule its name states; and requires dyadic_ladder
# to see every ±1 change of every P(k) under both tables. Standard library only, run
# isolated (-I), so no module from the working directory, the environment or the
# user's site-packages is imported.
- name: quantum referee.py
shell: bash
run: python3 -I wai/quantum-conformance/tools/referee.py wai/quantum-conformance
# chain_differential.py signs receipt chains around jwp-receipts §3 step 3 and §6.1
# (two keys, two tracks, both payloads, replays, forks, gaps, the guard and the
# freshness bound), and chain_gap_differential.py genuine chains up to 90 groups

View file

@ -29,7 +29,10 @@ name: WAI energy receipts
# 3. wai-quantum-serve: `cargo test --locked --lib`, native: the verdict
# logic behind POST /verify, for a receipt in either form, and that an
# unmetered receipt's 0 is rendered as the unmetered marker (null), never
# as zero joules.
# as zero joules; and that /run and /receipt build in the gateset the
# request names (circuit2 by default), name its capability, give the
# corpus's GHZ3 hashes in each, and answer 400 for an unknown gateset or
# a circuit with no circuit hash.
#
# It does NOT:
# - check that a newly sealed receipt in a family with an optional label
@ -96,6 +99,9 @@ on:
- 'wai/CHANGELOG.md'
# tests/video_receipt.rs reads the WIV1 refusal fixtures.
- 'wai/int-payload-conformance/**'
# wai_quantum_vectors' tests require the committed quantum corpus to be
# what `gen` writes.
- 'wai/quantum-conformance/**'
- '.github/workflows/wai-energy-receipts.yml'
pull_request:
paths:
@ -107,6 +113,9 @@ on:
- 'wai/CHANGELOG.md'
# tests/video_receipt.rs reads the WIV1 refusal fixtures.
- 'wai/int-payload-conformance/**'
# wai_quantum_vectors' tests require the committed quantum corpus to be
# what `gen` writes.
- 'wai/quantum-conformance/**'
- '.github/workflows/wai-energy-receipts.yml'
jobs:
@ -170,7 +179,7 @@ jobs:
# signer's level beside validity (jwp-receipts §7.1, §7.4). The verdict
# logic is a plain function, tested natively; the wasm32-wasip2 build of
# the component is not part of this workflow.
- name: wai-quantum-serve — POST /verify accepts either form and reports the signer's level
- name: wai-quantum-serve — POST /verify verdicts, and /run and /receipt in the requested gateset
working-directory: wai/wai-quantum-serve
shell: bash
run: cargo test --locked --lib

View file

@ -55,6 +55,8 @@ on:
- 'wai/wai-web/**'
- 'wai/wai-rs/**'
- 'wai/wai-quantum/**'
# quantum::tests and quantum_toolchain::tests read the quantum corpora.
- 'wai/quantum-conformance/**'
- 'wai/neural-conformance/**'
- 'wai/staged-conformance/**'
- 'wai/staged-measure-conformance/**'
@ -67,6 +69,8 @@ on:
- 'wai/wai-web/**'
- 'wai/wai-rs/**'
- 'wai/wai-quantum/**'
# quantum::tests and quantum_toolchain::tests read the quantum corpora.
- 'wai/quantum-conformance/**'
- 'wai/neural-conformance/**'
- 'wai/staged-conformance/**'
- 'wai/staged-measure-conformance/**'
@ -131,7 +135,12 @@ jobs:
# staged-delivery binding's pure half replays the staged corpus and reads a layer's
# header and cost (stage::tests); the measurement binding's pure half evaluates the
# staged-measurement corpus to its goldens and seals a page-recorded session equal
# to the native tool's (measure::tests). The count check turns a test that
# to the native tool's (measure::tests). The quantum sink opens every file of
# both quantum corpora to their manifests' hashes and capability and refuses
# every reject file with its listed class (quantum::tests), and the quantum IDE
# builds its catalog circuits in its gateset to the same manifests, stores no
# parameter on a gate other than P, and shows no hash for an invalid circuit
# (quantum_toolchain::tests). The count check turns a test that
# stopped being compiled into a failure instead of a silent "0 passed".
- name: wai-web native unit tests
shell: bash
@ -139,7 +148,7 @@ jobs:
run: |
set -euo pipefail
cargo test --locked --lib 2>&1 | tee "$RUNNER_TEMP/wai-web-native.log"
grep -q "test result: ok. 24 passed; 0 failed" "$RUNNER_TEMP/wai-web-native.log"
grep -q "test result: ok. 31 passed; 0 failed" "$RUNNER_TEMP/wai-web-native.log"
- name: wasm32 int_synth decode equals the frozen native corpus
shell: bash
working-directory: wai/wai-web

View file

@ -6,6 +6,99 @@ wire format may change and such changes are recorded here.
## v0.4.0 — current
### Quantum circuits: `wai.quantum.circuit2`, and `wai.quantum.circuit` stated exactly
- **A new capability, `wai.quantum.circuit2`** ([quantum-sim](extensions/quantum-sim.md),
SPEC §5). Magic `WQC2`, contract `ext` `wai.quantum.circuit2/1`, numeric
`wai.det.amp64`, gateset `cliffordT+dyadicP.rn`. The container layout, the gate IR and
the arithmetic are those of `wai.quantum.circuit`; the phase table is not. Each
`P(k)` holds the integers nearest to `2^30·cos(2π/2^k)` and `2^30·sin(2π/2^k)`, so its
controlled-phase ladder gives the QFT. The literal table is normative (§3.2, Appendix
B.2, digest `d34cb793…3510`); an exact-integer interval procedure certifies every entry,
informatively. The contract and the measurement are byte-canonical, and the op-log ends
exactly after its last op. Registered in the machine-readable registry and the
vocabularies, with `wai.det.amp64` as an identifier.
- **`wai.quantum.circuit` is frozen, and its table stated for the first time** (§3.1,
Appendix B.1, digest `3fa9805f…8466`). The text gives the exact recurrence — the sine
formula, the truncating halving, the floor square root — and the deviation of every
entry from the ideal phase: from `P(8)` on the imaginary part is too large, by up to
7032 units of `2^−30`, and `P(19..32)` apply no phase. The claim that this table gives the
QFT is withdrawn. Writers SHOULD NOT emit new circuit/1 content.
- **Both capabilities are specified to the bit** (§2–§4): little-endian integers, section
bounds computed without overflow, a repeated known section refused, the contract and
the measurement read as I-JSON (RFC 7493) by rules stated in full: no repeated member
name, no surrogate or noncharacter, no number of magnitude 2^1024 − 2^970 or more, at
most 127 levels deep, and an integer read exactly; the three refusal
classes (malformed, contract, invalid) in the order a reader checks them, the
complex-product composition, the index convention, the gate matrices, the hash layouts
and the shot sampler. `circuit_hash` covers the canonical contract, so it names the
capability and its table; `statevector_hash` does not. §5 states the error per
capability, and a new §8 why circuit2 is a capability of its own and what an older
reader does with it (it refuses `WQC2` at the magic).
- **Newly non-conforming circuit/1 payloads** (quantum-sim §8, SPEC §5): a contract whose
`ext`, `numeric`, `frac` or `gateset` is missing or carries another value; an
`n_qubits` that is not an unsigned integer of at most 255; a known section kind more
than once; section bounds that overflow; a contract or measurement that repeats a
member name within one object, holds a noncharacter, or holds a number of magnitude
2^1024 − 2^970 or more that an earlier build's float parser let through (some builds
also refused numbers just below it, which are now accepted). No file a reference writer
wrote is among them.
- **Corpus.** `quantum-conformance/` keeps its four original vectors and manifest entries
byte for byte and adds qft5_x22, dyadic_ladder and qft8_ones, which see the phase table:
under either table, `dyadic_ladder`'s statevector hash changes with every ±1 change of
any `P(1..32)` component. `v2/` holds the same seven circuits as circuit2; `reject/` at
least one payload for each refusal a payload can carry, with its class; and `accept/`
payloads at the edges of the same rules that a reader must accept, with how each reads.
`tools/referee.py`, integers only, derives both tables, requires Appendix B to state
them, reads every JSON section by the same rules, and rebuilds and checks every file. The
Appendix B tables are rendered from the reference constants by
`wai_quantum_vectors appendix`, and a test fails when the text differs.
### wai-quantum 0.4.0: circuits carry their gateset
- **`Gateset { V1, V2 }`** names the capability a circuit is reconstructed with, and
`Circuit` carries one in a new field. `Circuit::new` and `Circuit::qft` build V2
(`wai.quantum.circuit2`); a circuit read from a container takes the container's, and one
derived from another keeps it. `PHASE_V1` and `PHASE_V2` are literal constants: no
recurrence runs at load. `simulate`, `to_wqc`, `circuit_hash`, receipts, the fabric's
lanes and the toolchain follow the circuit's gateset. `from_wqc` reads both magics,
checks a circuit/1 contract's values and a circuit2 contract's bytes, reads the contract
and the measurement as I-JSON with a strict reader of its own that decides every rule
from the text, the number range on the literal's digits (so neither a build feature nor
a float parser's limits changes a verdict), refuses repeated sections and
wrapping bounds, and no longer sizes an allocation from a claimed op count.
`reject_corpus()` and `accept_corpus()` return the payloads a reader must refuse, each
with its class, and must accept, each with its reading; the corpus's `reject/` and
`accept/` trees are written from them.
- **Every circuit built in code changes its `circuit_hash`**, since the contract names the
capability, and its statevector wherever `H`, `T`, `T†`, `P(3)` or `P(k ≥ 5)` acts on a
nonzero amplitude (`P(1)`, `P(2)` and `P(4)` are the same in both tables). Every
circuit/1 artefact reproduces: the four original vectors, the legacy receipt pins, the
lanes32 certificate corpus and the other pins are unchanged, built in `Gateset::V1`, and
new V2 pins sit beside them.
- **wai-rs** registers `wai.quantum.circuit2`; `quantum_envelope` tags an envelope with the
circuit's capability and refuses one whose capability and magic disagree. The
`wai-quantum` CLI takes `--gateset v1|v2` (default v2) and names the capability in its
JSON; with `--gateset v1` and a phase of `k ≥ 8` it prints the circuit/1 deviation on
standard error. `wai_quantum_meter` seals the capability the file names. The browser
sink reads both magics; the IDE has `set_gateset`, and its `add()` sets the parameter of
every gate but `P` to 0. The serve component, `wai-quantum-serve` 0.5.0, takes
`gateset=v1|v2` on `/run`, `/qasm` and `/receipt`.
- **Migration from 0.3** (a breaking release):
- `Circuit::new` is V2. To reproduce or verify a 0.3 artefact, read its `WQC1` file, or
set `c.gateset = Gateset::V1` on a circuit built in code; a receipt's `gateset_of`
says which gateset a circuit's ops match it under.
- `quantum::phase`, `quantum::inv_sqrt2` and `quantum::CAPABILITY` are removed in favour
of `Gateset::phase`, `Gateset::inv_sqrt2` and `Gateset::capability`.
- `to_wqc`, `circuit_hash` and `quantum_toolchain::circuit_id` return a `Result`; they
fail only on a circuit its gateset does not allow, never on one that has simulated.
- `Circuit` and `QuantumError` are `#[non_exhaustive]`; `QuantumError` gains `Contract`
and `kind()`.
- `quantum_fabric::certify_lanes` and `lanes::random_circuit` take a gateset, with a
kernel and generator id per gateset; the circuit/1 ids are unchanged.
- `validate` refuses a gate with more than 255 controls, and in V2 repeated controls and
a parameter on any gate but `P`. `from_wqc` refuses the payloads quantum-sim §8 lists.
### Integer operators (Draft), and the payload text of two integer codecs
- **A new extension, [integer-operators](extensions/integer-operators.md) (Draft).**

View file

@ -154,14 +154,19 @@ pure Rust with no host bindings, **one source builds for native and
`wasm32-wasip2` and produces byte-identical results** — the same circuit
reconstructs to the same statevector hash on a laptop or at the edge.
Only `wai.quantum.circuit` is a registered payload capability, and
`wai.quantum.calibration` and `wai.quantum.job` are registered records; the other
names below are module labels ([`REGISTRY.md`](REGISTRY.md) lists the receipt
labels no revision registers).
`wai.quantum.circuit2` and `wai.quantum.circuit` are the registered payload
capabilities, and `wai.quantum.calibration` and `wai.quantum.job` are registered
records; the other names below are module labels ([`REGISTRY.md`](REGISTRY.md)
lists the receipt labels no revision registers). The two circuit capabilities
share the container and the gates and differ in the phase table: circuit2's holds
the integers nearest to each phase and is the default for new content, and
`wai.quantum.circuit` is frozen so that every file, hash and receipt made with it
reproduces ([quantum-sim](extensions/quantum-sim.md) §8).
| Module | What it does | Conformance |
|---|---|---|
| `wai.quantum.circuit` | byte-exact statevector simulation (dyadic Clifford+T+P(k)) | statevector-equivalence |
| `wai.quantum.circuit2` | byte-exact statevector simulation (dyadic Clifford+T+P(k)), with the correctly rounded phase table | statevector-equivalence |
| `wai.quantum.circuit` | the same, with the frozen phase table existing content was made with | statevector-equivalence |
| `wai.quantum.toolchain` | four backends (statevector / stabilizer / tensor-network MPS / sparse-Pauli), algorithm library, OpenQASM 3.0 in-and-out, **QIR export + ingest**, Bloch + entanglement analysis | statevector-equivalence |
| `wai.quantum.compile` | Clifford routing + stabilizer-tableau equivalence proof | signed equivalence certificate |
| `wai.quantum.cal.*` | calibration, filter-function robust control, DD noise spectroscopy | reproducible + receipt |
@ -189,8 +194,13 @@ cargo build --release --no-default-features \
./target/release/wai-quantum qir qft -n 4 | \\
./target/release/wai-quantum run --qir # and read it back
./target/release/wai-quantum receipt ghz -n 3 | ./target/release/wai-quantum verify
./target/release/wai-quantum run qft -n 5 --gateset v1 # the frozen wai.quantum.circuit
```
Circuits are `wai.quantum.circuit2` unless `--gateset v1` asks for
`wai.quantum.circuit`, which reproduces the circuit and statevector hashes
earlier releases gave.
### Same source, at the edge
```bash
@ -222,6 +232,7 @@ wasmtime serve -S cli=y --addr 127.0.0.1:8231 \
GET /health GET /algorithms
GET /run?algo=ghz&n=5&top=8 POST /run (body = OpenQASM 3.0)
GET /qasm?algo=bell GET /receipt?algo=ghz&n=3[&shots=&seed=]
(/run, /qasm and /receipt also take &gateset=v1|v2)
POST /verify (body = receipt JSON; 200 valid / 409 invalid / 400 unparseable)
```

View file

@ -49,8 +49,9 @@ either; staged-delivery §4 processes it.
Two further tables hold strings that look like capabilities and are not:
- **identifiers** name a part of a capability's definition (`wai.det.fixed64`, the
fixed-point floor; `wai.world.sim.*`, the simulation steps of the feed and avatar
capabilities);
fixed-point floor; `wai.det.amp64`, the complex amplitude arithmetic of
`wai.quantum.circuit2`; `wai.world.sim.*`, the simulation steps of the feed and
avatar capabilities);
- **unregistered labels** are strings the reference implementation uses as labels
that no revision registers, each with the reason.
@ -211,6 +212,7 @@ and a role are fixed once registered.
| `wai.prior.set` | payload | registered | binary | standalone | royalty-free | standard-defined | — | §5 Prior artifacts, general tensors and derivation operations |
| `wai.quantum.calibration` | record | registered | — | — | — | — | — | §5 Interactive, temporal & computed content |
| `wai.quantum.circuit` | payload | registered | binary | standalone | royalty-free | standard-defined | — | §5 Interactive, temporal & computed content |
| `wai.quantum.circuit2` | payload | registered | binary | standalone | royalty-free | standard-defined | — | §5 Interactive, temporal & computed content |
| `wai.quantum.job` | record | registered | — | — | — | — | — | §5 Interactive, temporal & computed content |
| `wai.semantic.clip` | payload | registered | image | standalone | royalty-free | behavioral | — | §5 Neural capabilities |
| `wai.semantic.perco2` | payload | registered | image | standalone | non-commercial | behavioral | — | §5 Neural capabilities |
@ -250,7 +252,8 @@ and a role are fixed once registered.
| identifier (not a capability) | meaning | in |
|---|---|---|
| `wai.det.fixed64` | the fixed-point arithmetic floor the deterministic *-equivalence criteria are computed in | §5 Interactive, temporal & computed content |
| `wai.det.amp64` | the complex fixed-point arithmetic of wai.quantum.circuit2: re and im each an i64 at scale 2^frac, products exact then rounded half up, sums exact (quantum-sim §2.1, §3.0) | §5 Interactive, temporal & computed content |
| `wai.det.fixed64` | the fixed-point arithmetic floor the deterministic *-equivalence criteria are computed in (Q32.32, interactive-worlds §6.2); inside a wai.quantum.circuit contract it names the quantum-sim §3.0 arithmetic at frac 30, products rounded half up | §5 Interactive, temporal & computed content |
| `wai.world.sim.feed0` | the identity simulation step of wai.feed.state | §5 Interactive, temporal & computed content |
| `wai.world.sim.skeletal0` | the skeletal-pose simulation step of wai.avatar.pose | §5 Interactive, temporal & computed content |

View file

@ -522,9 +522,9 @@ fidelity tier, a replicate class and a role. A derivation or record string is no
capability and is not dispatchable (§4): step 3 does not take an envelope's
`capability` that names one, and step 5 may still take a usable fallback. A row of the tables below that
registers a record says what the record attests, not a payload format. Named
sub-identifiers this section uses — `wai.det.fixed64`, `wai.world.sim.feed0`,
`wai.world.sim.skeletal0` — name parts of a capability's definition and are
not capabilities.
sub-identifiers this section uses — `wai.det.fixed64`, `wai.det.amp64`,
`wai.world.sim.feed0`, `wai.world.sim.skeletal0` — name parts of a capability's
definition and are not capabilities.
### Mandatory floor
@ -729,7 +729,27 @@ standard. See the linked extension for each.
| `wai.film.linear` | WFLM container (sealed world + camera track + frame schedule) | film-equivalence · [linear-film](extensions/linear-film.md) |
| `wai.film.reel` | WREL container (sealed world + a sequence of shots = camera track + schedule each) | reel-equivalence (film-equivalence with cuts) · [linear-film](extensions/linear-film.md) |
| `wai.ternary.tt` | WQTT container (balanced-ternary MPS cores — packed trits + integer per-column scales) | a **quantum-inspired** (tensor-network) transform ported from the ternary/MPS fabric with ONE change: the per-column scale is an **integer**, so the whole decode is `i64`/`i128` and the reconstruction is byte-identical on every machine — **reconstruction-equivalence** (a portable recon hash), receiptable. Scope: a **provenance** transform, measured at 13.3 dB SNR for 3.8× with six residual layers (`Lossy` tier; the extension's §5). Encoder-side float SVD only · [ternary-tt](extensions/ternary-tt.md) |
| `wai.quantum.circuit` | WQC container (gate op-log — Clifford+T + dyadic phase) | the wire carries a **circuit** (kilobytes, linear in gate count), the sink CLASSICALLY simulates it in a fixed-point **complex** floor (`Amp` = i64 re/im), and the reconstructed `2^n`-amplitude statevector is byte-identical on every machine — **statevector-equivalence** (a portable statevector hash); measurement is sampled by the pinned `splitmix64` so a shot histogram at a pinned `(seed, shots)` converges too (**shot-histogram-equivalence**). The dyadic phase ladder gives the **QFT** ("quantum FFT"), transported as a circuit and reconstructed byte-exact. No quantum hardware — NISQ noise breaks the determinism the standard rests on; this makes a quantum *computation* transportable + receiptable, with **no** speedup claimed · [quantum-sim](extensions/quantum-sim.md) |
| `wai.quantum.circuit` | WQC container (gate op-log — Clifford+T + dyadic phase) | the wire carries a **circuit** (kilobytes, linear in gate count), the sink CLASSICALLY simulates it in a fixed-point **complex** floor (`Amp` = i64 re/im), and the reconstructed `2^n`-amplitude statevector is byte-identical on every machine — **statevector-equivalence** (a portable statevector hash); measurement is sampled by the pinned `splitmix64` so a shot histogram at a pinned `(seed, shots)` converges too (**shot-histogram-equivalence**). The dyadic phase ladder transports the **QFT** ("quantum FFT") as a circuit, reconstructed byte-exact; the phase table is frozen as existing content was made with it, so `P(k)` deviates from the ideal phase for k ≥ 8 and applies none for k ≥ 19, and new content uses `wai.quantum.circuit2`. No quantum hardware — NISQ noise breaks the determinism the standard rests on; this makes a quantum *computation* transportable + receiptable, with **no** speedup claimed · [quantum-sim](extensions/quantum-sim.md) |
| `wai.quantum.circuit2` | WQC container under magic `WQC2` (the same gate op-log) | the successor of `wai.quantum.circuit`, with the same statevector- and shot-histogram-equivalence: a correctly rounded phase table (each component of every `P(k)` within half a unit of 2^30·e^{2πi/2^k}), so the dyadic phase ladder gives the **QFT**; a byte-canonical contract; an op-log that ends exactly after its last op. A new capability, not a change to the old one, because a registered capability's payload format is fixed (§8): a reader that predates it rejects a `WQC2` payload at the magic · [quantum-sim](extensions/quantum-sim.md) |
The contract of a `wai.quantum.circuit2` payload names its arithmetic
`wai.det.amp64`: complex amplitudes as `i64` pairs at scale `2^frac`, each
product exact and then rounded half up, each sum exact. Inside a
`wai.quantum.circuit` contract, `wai.det.fixed64` names that same arithmetic at
frac 30. [quantum-sim](extensions/quantum-sim.md) §2.1 defines both.
*Payloads the quantum-sim reader rules make non-conforming* (their envelopes still
parse). [quantum-sim](extensions/quantum-sim.md) §2 and §2.1 state reader rules that
enforce the registration of `wai.quantum.circuit` as it was made (§8). A sink refuses,
when it decodes it, a `wai.quantum.circuit` payload whose contract does not carry
the registered `ext`, `numeric`, `frac` and `gateset`, a `wai.quantum.circuit2`
contract among them; whose `n_qubits` is not an unsigned integer of at most 255;
that carries a known section kind more than once; that has a section whose
bounds overflow; or whose contract or measurement repeats a member name within one
object, holds a noncharacter, or holds a number of magnitude 2^1024 − 2^970 or more
that an earlier reader's float parser let through. No payload a reference writer
wrote is among them;
[quantum-sim](extensions/quantum-sim.md) §8 lists them with the rules.
And the verify half — a signed, energy-accounted lineage for opaque
captured content WAI does **not** reconstruct (content-addressing +

View file

@ -5,20 +5,39 @@
> 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**). Reference impl: the `quantum` feature of
> `wai-rs` (`crate::quantum`); corpus: `quantum-conformance/`; capability
> `wai.quantum.circuit`.
> **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` module of the `wai-quantum` crate, which `wai-rs` re-exports as
> `wai::quantum` under its `quantum` feature; corpus: `quantum-conformance/`.
Keywords **MUST**, **MUST NOT**, **SHOULD**, **MAY** are RFC 2119/8174.
## 1. Scope and model
A `wai.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 the `wai.det.fixed64` 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*.
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
@ -41,38 +60,141 @@ 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"`; `wai.quantum.circuit` is authoritative. Its replicate
class is `StandardDefined` (WAI's own deterministic floor), its fidelity tier
`Lossless` (the simulation analog — the reconstruction is byte-exact).
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`)
```
"WQC1" | u16 n_sections | section table (u8 kind, u32 off, u32 len) | sections
magic | u16 n_sections | n_sections × (u8 kind, u32 off, u32 len) | sections
```
`off` is relative to the start of the sections blob (immediately after the
table). Unknown section kinds MUST be ignored (forward-compatible).
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) | REQUIRED |
| `0x02` | gate op-log | REQUIRED |
| `0x03` | measurement (canonical JSON) | OPTIONAL |
| `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
```json
{ "ext": "wai.quantum.circuit/1", "n_qubits": 3,
"numeric": "wai.det.fixed64", "frac": 30, "gateset": "cliffordT+dyadicP" }
```
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:
`frac` is the amplitude fixed-point scale (`FRAC`, 30 in v1). `gateset`
names the reconstruction's gate algebra (§3).
- 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
`n_ops u32`, then per op:
`u32 n_ops`, then per op:
```
u8 opcode | u8 n_ctrl | u8 target | u16 param | n_ctrl × u8 control
@ -80,7 +202,7 @@ 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)` (0 otherwise). Opcodes:
`k` for `P(k)`. Opcodes:
| opcode | gate | | opcode | gate |
|---|---|---|---|---|
@ -91,71 +213,246 @@ The op is a **controlled-1-qubit gate**: the base gate `opcode` is applied to
| 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`. A target MUST be `< n_qubits`; a control
MUST be `< n_qubits` and `≠ target`; `P(k)` MUST have `1 ≤ k ≤ 32`.
`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": 13034510, "shots": 100000, "basis": "computational" }
{"seed":12648430,"shots":100000,"basis":"computational"}
```
Pins a computational-basis sampling for shot-histogram-equivalence (§4).
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
The state is `2^n` amplitudes, `amps[|0…0⟩] = 1`, all others `0` at start. Each
op applies its base gate's 2×2 fixed-point matrix `M` to the amplitude pair
`(i, i∨2^target)` for every `i` with the target bit clear **and** all control
bits set:
### 3.0 Arithmetic, for both capabilities
```
a0' = M00·a0 + M01·a1 a1' = M10·a0 + M11·a1
```
An implementer needs all of this, with the phase table of §3.1 or §3.2, to
reproduce a statevector.
Complex products use a pinned round-half-up fixed-point multiply
(`(a·b + 2^(FRAC−1)) >> FRAC`, `i128` intermediate). The one irrational the
Clifford+T set needs — `1/√2` — and the dyadic phases `e^{2πi/2^k}` are built
by an **integer half-angle recurrence** seeded at `(cos π/2, sin π/2) = (0, 1)`
(`cos(θ/2)=√((1+cosθ)/2)`, integer `isqrt`), so **no float ever runs**.
`gateset = "cliffordT+dyadicP"` is universal (Clifford+T is dense in
`SU(2^n)`); the dyadic phase ladder gives the **QFT** ("quantum FFT"), which is
transported as a circuit (`H` + controlled-`P(k)` + swaps) and reconstructs
byte-exact.
- **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 `wai.quantum.circuit`, a conforming sink MUST reconstruct the
> identical fixed-point statevector, hence the identical BLAKE3 — on every
> machine, no tolerance parameter.
> 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"
|| n_qubits || frac_le || canonical amps)
‖ u8 n_qubits ‖ u32le frac
‖ per amplitude, in index order: i64le re ‖ i64le im)
circuit_hash = BLAKE3("wai:quantum-circuit\x01"
|| contract_bytes || oplog_bytes)
‖ canonical contract (§2.1) of the capability for n_qubits
‖ canonical op-log)
```
`circuit_hash` is the frame-independent identity of the circuit; each sink's
`statevector_hash` is the verifiable result.
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 with the pinned `splitmix64` PRNG seeded by `seed`
(walking the un-normalized `|amp|²` prefix sums — no divide), producing an
identical per-basis-state count vector, hence:
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"
|| n_qubits || seed_le || shots_le || counts_le)
‖ 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:
@ -163,22 +460,48 @@ 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 — each gate carries a bounded
rounding error (`≈ 2^−FRAC` per op, accumulating roughly linearly). 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 per-gate error bound is the contract, not
a hidden claim.
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 and
reconstructs a 32-amplitude state; a 26-qubit circuit 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.
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.
@ -192,7 +515,7 @@ is trusted the way it honestly can be.**
| field | what it is | how it is trusted |
|---|---|---|
| `circuit_hash` | identity — the `WQC` circuit's hash | re-checkable |
| `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** |
@ -209,6 +532,9 @@ 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.
@ -220,6 +546,15 @@ Two verification depths:
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: on a host that exposes its SoC's power interface to
@ -238,9 +573,11 @@ measured figure the meter writes a measurement report (energy-measurement §6).
verified with `Labelled::verify` / `Labelled::verify_reconstruction`. The
`wai-quantum verify` CLI and the HTTP handler's `POST /verify` accept a receipt
in either form (`quantum_energy::MaybeLabelled`) and restate its class. A receipt
sealed without a label keeps its legacy bytes and its figure is unlabelled. A
representative run on the reference QFT-5 vector: **≈43 µJ measured per
reconstruction, `work_amp_updates = 672`** (21 ops × 2⁵), sealed and self-verified.
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: **≈43 µJ
measured 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*
@ -261,7 +598,55 @@ stochastic. Such a prior is `NeuralFloat`/`Behavioral`: it MUST NOT back
`wai.semantic.*` conforms by a CLIP-similarity threshold. Naming the metric now
fixes the axis before that capability is ever registered.
## Appendix
## 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.
## 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
@ -271,3 +656,94 @@ 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 -->

View file

@ -1,12 +1,22 @@
# quantum-conformance
Statevector-equivalence for the `wai.quantum.circuit` extension: given the same
`WQC` circuit, a conforming sink MUST reconstruct the identical fixed-point
statevector — **hash equality, no tolerance**.
Statevector-equivalence for both capabilities of the quantum-sim extension
(`../extensions/quantum-sim.md`): given the same `WQC` circuit, a conforming sink
MUST reconstruct the identical fixed-point statevector — **hash equality, no
tolerance**.
**Provenance.** Generated here by `wai_quantum_vectors` from circuits authored in code. No media.
`vectors/*.wqc` plus `expected_hashes.json` are the pinned corpus. They are the
Four trees, each a pinned corpus:
| tree | capability | what |
|---|---|---|
| `vectors/` + `expected_hashes.json` | `wai.quantum.circuit` (`WQC1`) | bell, ghz3, qft3 and qft5, frozen as they were first written, then qft5_x22, dyadic_ladder and qft8_ones |
| `v2/vectors/` + `v2/expected_hashes.json` | `wai.quantum.circuit2` (`WQC2`) | the same seven circuits; each entry names its `capability` |
| `reject/` + `reject/reject.json` | both | payloads a conforming reader refuses, each with the class it is refused as: `malformed`, `contract` or `invalid` (extension §2) |
| `accept/` + `accept/accept.json` | both | payloads a conforming reader accepts, at the edges of the same rules, each with how it reads: capability, `n_qubits`, op count, circuit hash and measurement (extension §2) |
An entry with no `capability` is a `wai.quantum.circuit` vector. The trees are the
one reference all three surfaces are checked against, rather than being checked
against each other.
@ -28,19 +38,61 @@ wasmtime run --dir wai/quantum-conformance::/corpus \
target/wasm32-wasip2/release/wai_quantum_vectors.wasm verify /corpus
```
CI runs this leg as a debug build, so integer overflow panics instead of wrapping
(`wai-conformance.yml`, job `quantum-wasip2`, which also runs the crate's
`bit_identity` tests and the circuit core's unit tests under `wasmtime`).
## Browser
```sh
node wai/quantum-conformance/browser_verify.mjs [path/to/quantum-ml/pkg]
node wai/quantum-conformance/browser_verify.mjs [path/to/quantum-ml/pkg] [module file]
```
Drives the deployed wasm-bindgen bundle in headless Chromium. Note that
`statevector_hash_hex()` is empty until `run()` is called — the circuit is built
eagerly, the state is not.
Drives the deployed wasm-bindgen bundle in headless Chromium: the sink opens every
file of both vector trees to its manifest entry, refuses every reject file with
its listed class and reads every accept file as listed (the two 255-qubit accept
files only to the `simulate` stage: the sink simulates on construction, so they
are checked to be read, not compared), and the IDE builds its catalog circuits in each gateset to the
matching manifest. It is run by hand, before the website deploys a bundle. Note that
the IDE's `statevector_hash_hex()` is empty until `run()` is called — the circuit is
built eagerly, the state is not.
## Referee
```sh
python3 -I wai/quantum-conformance/tools/referee.py wai/quantum-conformance
```
A second implementation of the extension in Python, integers only, sharing no code
with the Rust reference. It derives both phase tables (circuit/1 by its recurrence,
circuit2 by an interval-certified procedure) and requires their literal values and
digests, and the extension's Appendix B to state the same; rebuilds every vector
file byte for byte and recomputes every manifest entry; refuses every reject file
with its listed class and by the rule its name states; accepts every accept file
and reads it as listed; and requires
`dyadic_ladder` to change its statevector hash under every ±1 change of every
phase-table entry, in both tables. CI runs it on Linux (`wai-conformance.yml`,
job `independent-verifiers`).
## Scope
The corpus covers the **byte-exact dyadic core**, where hash equality is the right
bar. The floating-point layers (`quantum_source`, `quantum_channel`) are held to
The corpus pins the container, the reader's refusals, the fixed-point arithmetic
and both phase tables, where hash equality is the right bar. What it covers, and
where it stops:
- **Every phase-table entry.** Under either table, a change of ±1 to either
component of any `P(1..32)`, with `H` following `re P(3)`, changes
`dyadic_ladder`'s statevector hash; the referee checks this on every run. A
change of ±1 to `H` alone changes the hash of every vector that applies `H`.
- **The four original vectors see no `P(k)`.** They run the QFT from
`|0…0⟩`, where every controlled phase acts on zero amplitudes, so no change to a
`P(k)` entry moves their hashes except through `H`, which follows `re P(3)`; the
three vectors after them are there for that.
- **One control at most.** No vector applies a gate with more than one control.
Such gates appear in the reject tree, and in the accept tree as circuit/1's
repeated control.
- **One measurement.** The shot sampler is pinned by bell's measurement alone.
The floating-point layers (`quantum_source`, `quantum_channel`) are held to
exact IEEE-754 bits by unit tests instead, since they have no `WQC` circuit to
pin — see `entropy_is_bit_identical_across_architectures`.

View file

@ -0,0 +1,177 @@
{
"v1_members_reordered.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": null
},
"v1_whitespace.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": null
},
"v1_further_members.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": null
},
"v1_escapes_and_characters.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": null
},
"v1_depth_127.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": null
},
"v1_numbers_largest_finite.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": null
},
"v1_numbers_long_literals.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": null
},
"v1_numbers_toward_zero.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": null
},
"v1_n_qubits_255.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 255,
"n_ops": 2,
"circuit_hash": "eaa87747d510e6d6cff04212fbcecf37aa22fa6fed8fe716ea3110092e6045e0",
"measure": null
},
"v1_measure_lax.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": {
"seed": 1,
"shots": 10
}
},
"v1_measure_missing_shots.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": {
"seed": 1,
"shots": 0
}
},
"v1_measure_u64_max.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": {
"seed": 18446744073709551615,
"shots": 18446744073709551615
}
},
"v1_measure_not_u64.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": {
"seed": 0,
"shots": 0
}
},
"v1_measure_other_types.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": {
"seed": 0,
"shots": 0
}
},
"v1_measure_not_object.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": {
"seed": 0,
"shots": 0
}
},
"v1_oplog_trailing_bytes.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": null
},
"v1_param_on_h.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "2eed24488205bf419b886feed0947cc63a21813f62f3a7a697b5785adcc72b08",
"measure": null
},
"v1_repeated_control.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "3aaa7132a1cc0f068c8f009f4e8d6137a825f6d22c2e5a32255a4a38c547755b",
"measure": null
},
"v1_unknown_sections.wqc": {
"capability": "wai.quantum.circuit",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "894d9a9582b19f27b8d08d06938357237fc00f7f30bf4bfc2be0c04fa5e47a4e",
"measure": null
},
"v2_unknown_sections.wqc": {
"capability": "wai.quantum.circuit2",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "6f6199943059fc4d90554d7c33f1ac69723603f5128962a6e3cac9c765484d2b",
"measure": null
},
"v2_n_qubits_255.wqc": {
"capability": "wai.quantum.circuit2",
"n_qubits": 255,
"n_ops": 2,
"circuit_hash": "225f13952c14c6375adf7cc85080b1dd34af8f5378e1dac737517e0212d74c32",
"measure": null
},
"v2_measure_u64_max.wqc": {
"capability": "wai.quantum.circuit2",
"n_qubits": 2,
"n_ops": 2,
"circuit_hash": "6f6199943059fc4d90554d7c33f1ac69723603f5128962a6e3cac9c765484d2b",
"measure": {
"seed": 18446744073709551615,
"shots": 18446744073709551615
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,14 +1,30 @@
// Browser leg of statevector-equivalence.
// Browser leg of statevector-equivalence, for both capabilities.
//
// The native and `wasm32-wasip2` legs are checked by `wai_quantum_vectors verify`.
// This checks the third surface the extension claims — a browser — against the
// same pinned corpus, so all three are held to one reference rather than to each
// other.
// This checks the third surface the extension claims, a browser, against the same
// pinned corpus, so all three are held to one reference rather than to each other.
// It is a manual tool: run it on the bundle before the website deploys it.
//
// node browser_verify.mjs [path/to/quantum-ml/pkg]
// node browser_verify.mjs [path/to/quantum-ml/pkg] [module file]
//
// Needs Playwright with its bundled Chromium. `statevector_hash_hex()` is empty
// until `run()` is called: the circuit is built eagerly, the state is not.
// In headless Chromium, with the wasm-bindgen bundle (module file
// `wai_quantum_ml.js` by default):
//
// - QuantumSink opens every file of `vectors/` (wai.quantum.circuit) and
// `v2/vectors/` (wai.quantum.circuit2) to its manifest entry: the capability (an
// entry of the circuit/1 manifest names none), n_qubits, n_ops, the circuit and
// statevector hashes, and the histogram hash where the entry pins a measurement.
// - QuantumSink refuses every file `reject/reject.json` lists, and its error names
// the listed class in parentheses: `<stage> (<class>): <reason>`.
// - QuantumSink reads every file `accept/accept.json` lists as listed: capability,
// n_qubits, n_ops, circuit hash and measurement. A file too wide to simulate
// (n_qubits 255) is read and then refused at the `simulate` stage, never at
// `WQC parse`.
// - QuantumIde.load_algorithm builds bell, ghz and qft in its default gateset to
// `v2/expected_hashes.json`, and after `set_gateset(1)` to the circuit/1 manifest.
//
// Needs Playwright with its bundled Chromium. `statevector_hash_hex()` of the IDE is
// empty until `run()` is called: the circuit is built eagerly, the state is not.
import http from "node:http";
import fs from "node:fs";
import path from "node:path";
@ -18,19 +34,85 @@ import { createRequire } from "node:module";
const HERE = path.dirname(fileURLToPath(import.meta.url));
const PKG = process.argv[2] ||
"/Users/dcharlot/data-share/vibe-coding/wai-transaction-science-web/public/quantum-ml/pkg";
const MODULE = process.argv[3] || "wai_quantum_ml.js";
const PLAYWRIGHT_HOST = process.env.PLAYWRIGHT_HOST ||
"/Users/dcharlot/data-share/vibe-coding/joulesperbit/";
const { chromium } = createRequire(PLAYWRIGHT_HOST)("playwright");
const EXPECTED = JSON.parse(fs.readFileSync(path.join(HERE, "expected_hashes.json"), "utf8"));
// vector name -> how the catalog builds that circuit
const CASES = [
["bell.wqc", "bell", 2, 0],
["ghz3.wqc", "ghz", 3, 0],
["qft3.wqc", "qft", 3, 0],
["qft5.wqc", "qft", 5, 0],
const readJson = (p) => JSON.parse(fs.readFileSync(p, "utf8"));
const bytesOf = (p) => Array.from(fs.readFileSync(p));
// The two vector trees. An entry of the circuit/1 manifest names no capability.
const TREES = [
{ prefix: "", dir: HERE, capability: "wai.quantum.circuit" },
{ prefix: "v2/", dir: path.join(HERE, "v2"), capability: null },
];
const MANIFEST = Object.fromEntries(TREES.map((t) => [t.prefix, readJson(path.join(t.dir, "expected_hashes.json"))]));
// Every vector file, with what the sink must report for it.
const SINK = [];
for (const t of TREES) {
for (const [file, e] of Object.entries(MANIFEST[t.prefix])) {
SINK.push({
label: t.prefix + file,
bytes: bytesOf(path.join(t.dir, "vectors", file)),
want: {
capability: e.capability || t.capability,
n_qubits: e.n_qubits,
n_ops: e.n_ops,
circuit: e.circuit_hash,
statevector: e.statevector_hash,
histogram: e.measure ? e.measure.histogram_hash : null,
},
});
}
}
// Every reject file, with the class it must be refused as.
const REJECT_DIR = path.join(HERE, "reject");
const REJECT = Object.entries(readJson(path.join(REJECT_DIR, "reject.json"))).map(([file, kind]) => ({
label: "reject/" + file,
bytes: bytesOf(path.join(REJECT_DIR, file)),
kind,
}));
// Every accept file, with its reading. seed and shots are u64, beyond what a JSON
// number keeps exactly in JS, so they are compared as decimal strings.
const ACCEPT_DIR = path.join(HERE, "accept");
const acceptText = fs.readFileSync(path.join(ACCEPT_DIR, "accept.json"), "utf8")
.replace(/"(seed|shots)": (\d+)/g, '"$1": "$2"');
const ACCEPT = Object.entries(JSON.parse(acceptText)).map(([file, e]) => ({
label: "accept/" + file,
bytes: bytesOf(path.join(ACCEPT_DIR, file)),
want: {
capability: e.capability,
n_qubits: e.n_qubits,
n_ops: e.n_ops,
circuit: e.circuit_hash,
measure: e.measure ? `${e.measure.seed} ${e.measure.shots}` : null,
},
}));
// The IDE's catalog: vector file -> (algorithm id, qubits), in each gateset against
// its manifest. Gateset 2 (circuit2) is the IDE's default; 1 is set explicitly.
const CATALOG = [
["bell.wqc", "bell", 2],
["ghz3.wqc", "ghz", 3],
["qft3.wqc", "qft", 3],
["qft5.wqc", "qft", 5],
];
const IDE = [];
for (const [gateset, prefix, capability] of [[2, "v2/", "wai.quantum.circuit2"], [1, "", "wai.quantum.circuit"]]) {
for (const [file, id, n] of CATALOG) {
const e = MANIFEST[prefix][file];
IDE.push({
label: `QuantumIde ${id}(${n}) in gateset ${gateset} = ${prefix}${file}`,
id, n, gateset,
want: { gateset, capability, circuit: e.circuit_hash, statevector: e.statevector_hash },
});
}
}
const MIME = { ".js": "text/javascript", ".wasm": "application/wasm", ".html": "text/html" };
const PORT = Number(process.env.PORT || 8794);
@ -46,12 +128,17 @@ const server = http.createServer((req, res) => {
fs.createReadStream(f).pipe(res);
});
// Compare the fields of `want` with `got`; the names of those that differ.
function differ(want, got) {
return Object.keys(want).filter((k) => got[k] !== want[k]);
}
let browser;
process.on("unhandledRejection", (e) => { console.error("UNHANDLED:", e); process.exitCode = 1; });
try {
if (!fs.existsSync(path.join(PKG, "wai_quantum_ml.js"))) {
console.error(`no bundle at ${PKG} — pass the pkg directory as argv[1]`);
if (!fs.existsSync(path.join(PKG, MODULE))) {
console.error(`no ${MODULE} at ${PKG}; pass the pkg directory (and the module file) as arguments`);
process.exit(2);
}
await new Promise((r) => server.listen(PORT, "127.0.0.1", r));
@ -64,37 +151,126 @@ try {
// but networkidle still stalls behind them on some hosts.
await page.goto(`http://127.0.0.1:${PORT}/`, { waitUntil: "domcontentloaded", timeout: 30000 });
const got = await page.evaluate(async ({ cases, port }) => {
const mod = await import(`http://127.0.0.1:${port}/wai_quantum_ml.js`);
const got = await page.evaluate(async ({ sink, reject, accept, ide, port, module }) => {
const mod = await import(`http://127.0.0.1:${port}/${module}`);
await mod.default();
const out = {};
for (const [name, id, n, param] of cases) {
const ide = new mod.QuantumIde(n);
const ok = ide.load_algorithm(id, n, param);
if (ok) ide.run(); // the state is not computed until this
out[name] = ok
? { circuit: ide.circuit_hash_hex(), statevector: ide.statevector_hash_hex() }
: { error: "load_algorithm returned false" };
ide.free();
const message = (e) => String((e && e.message) || e);
const out = { sink: {}, reject: {}, accept: {}, ide: {} };
for (const c of sink) {
try {
const s = new mod.QuantumSink(new Uint8Array(c.bytes));
out.sink[c.label] = {
capability: s.capability(),
n_qubits: s.n_qubits(),
n_ops: s.n_ops(),
circuit: s.circuit_hash_hex(),
statevector: s.statevector_hash_hex(),
histogram: s.histogram_hash_hex() ?? null,
};
s.free();
} catch (e) {
out.sink[c.label] = { error: message(e) };
}
}
for (const c of reject) {
try {
new mod.QuantumSink(new Uint8Array(c.bytes)).free();
out.reject[c.label] = { accepted: true };
} catch (e) {
out.reject[c.label] = { error: message(e) };
}
}
for (const c of accept) {
try {
const s = new mod.QuantumSink(new Uint8Array(c.bytes));
out.accept[c.label] = {
capability: s.capability(),
n_qubits: s.n_qubits(),
n_ops: s.n_ops(),
circuit: s.circuit_hash_hex(),
measure: s.has_measure() ? `${s.seed()} ${s.shots()}` : null,
};
s.free();
} catch (e) {
out.accept[c.label] = { error: message(e) };
}
}
for (const c of ide) {
const q = new mod.QuantumIde(c.n);
try {
if (c.gateset !== 2 && !q.set_gateset(c.gateset)) {
out.ide[c.label] = { error: `set_gateset(${c.gateset}) returned false` };
continue;
}
if (!q.load_algorithm(c.id, c.n, 0)) {
out.ide[c.label] = { error: "load_algorithm returned false" };
continue;
}
q.run(); // the state is not computed until this
out.ide[c.label] = {
gateset: q.gateset(),
capability: q.capability(),
circuit: q.circuit_hash_hex(),
statevector: q.statevector_hash_hex(),
};
} catch (e) {
out.ide[c.label] = { error: message(e) };
} finally {
q.free();
}
}
return out;
}, { cases: CASES, port: PORT });
}, { sink: SINK, reject: REJECT, accept: ACCEPT, ide: IDE, port: PORT, module: MODULE });
let fail = 0;
for (const [name] of CASES) {
const e = EXPECTED[name], g = got[name];
if (g.circuit === e.circuit_hash && g.statevector === e.statevector_hash) {
console.log(`PASS ${name}`);
} else {
const report = (label, problem) => {
if (problem) {
fail++;
console.log(`FAIL ${name}`);
console.log(` circuit browser=${g.circuit}\n corpus =${e.circuit_hash}`);
console.log(` statevector browser=${g.statevector}\n corpus =${e.statevector_hash}`);
console.log(`FAIL ${label}: ${problem}`);
} else {
console.log(`PASS ${label}`);
}
};
for (const c of SINK) {
const g = got.sink[c.label];
if (g.error) {
report(c.label, `refused: ${g.error}`);
continue;
}
const bad = differ(c.want, g);
report(c.label, bad.length ? bad.map((k) => `${k} browser=${g[k]} corpus=${c.want[k]}`).join("; ") : null);
}
console.log(errs.length ? `console errors: ${errs.length}` : "console errors: 0");
for (const c of REJECT) {
const g = got.reject[c.label];
if (g.accepted) {
report(c.label, `accepted; it must be refused as ${c.kind}`);
continue;
}
const m = /^[^()]+ \(([a-z-]+)\): /.exec(g.error);
report(`${c.label} refused as ${c.kind}`, m && m[1] === c.kind ? null : `refused as: ${g.error}`);
}
for (const c of ACCEPT) {
const g = got.accept[c.label];
if (g.error) {
const wide = c.want.n_qubits === 255 && /^simulate \(/.test(g.error);
report(wide ? `${c.label} read; too wide to simulate` : c.label, wide ? null : `refused: ${g.error}`);
continue;
}
const bad = differ(c.want, g);
report(c.label, bad.length ? bad.map((k) => `${k} browser=${g[k]} corpus=${c.want[k]}`).join("; ") : null);
}
for (const c of IDE) {
const g = got.ide[c.label];
if (g.error) {
report(c.label, g.error);
continue;
}
const bad = differ(c.want, g);
report(c.label, bad.length ? bad.map((k) => `${k} browser=${g[k]} corpus=${c.want[k]}`).join("; ") : null);
}
console.log(errs.length ? `console errors: ${errs.length}\n ${errs.join("\n ")}` : "console errors: 0");
if (fail === 0 && errs.length === 0) {
console.log("all vectors pass: statevector-equivalence holds in the browser");
console.log("all checks pass: statevector-equivalence holds in the browser for both capabilities, every reject file is refused as listed, and every accept file reads as listed");
}
process.exitCode = fail || errs.length ? 1 : 0;
} catch (e) {

View file

@ -27,5 +27,23 @@
"n_ops": 21,
"circuit_hash": "f36a9af99a251cae6f42144b2be3c57523f15e1e2ab3492cf15cac709fc048be",
"statevector_hash": "c268d77f2ddf84fecb028e80ce989123912870f04e5b9a1e3d885c9ce235c27d"
},
"qft5_x22.wqc": {
"n_qubits": 5,
"n_ops": 24,
"circuit_hash": "40c847fe9f85b6d79d245b6e65420197e6bbedb9c0b1ab77baaf1cfe077ff4f5",
"statevector_hash": "95a2d2fd41f6a13c19562729a4b553ee12db6adfaa361b5061c16d801354d0cd"
},
"dyadic_ladder.wqc": {
"n_qubits": 2,
"n_ops": 72,
"circuit_hash": "2fa5b02c952dcaf55ab4cfd2ea5b3fae999ac912a32a4e06dd2b6ee96bb58d4f",
"statevector_hash": "9754af24edd026601297a0f3334eb7171174978841a2938c9b372db942a3851d"
},
"qft8_ones.wqc": {
"n_qubits": 8,
"n_ops": 56,
"circuit_hash": "5ca94d3a960b8ec65a1eb802699f1ed8e20f00e7fbd9297849f0c60047404a1a",
"statevector_hash": "fd683498744552e9e2e8657a2bdc244e4f03d4ee4dd292c9705ba38b19fb709c"
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,68 @@
{
"magic_wqc3.wqc": "malformed",
"v1_ext_other.wqc": "contract",
"v1_numeric_other.wqc": "contract",
"v1_frac_31.wqc": "contract",
"v1_frac_float.wqc": "contract",
"v1_gateset_rn.wqc": "contract",
"v1_contract2_in_wqc1.wqc": "contract",
"v1_fields_missing.wqc": "contract",
"v1_contract_not_object.wqc": "contract",
"v1_n_qubits_256.wqc": "malformed",
"v1_n_qubits_258.wqc": "malformed",
"v1_contract_twice.wqc": "malformed",
"v1_oplog_twice.wqc": "malformed",
"v1_contract_duplicate_member.wqc": "contract",
"v1_contract_lone_surrogate.wqc": "contract",
"v1_contract_too_deep.wqc": "contract",
"v1_n_qubits_minus0.wqc": "malformed",
"v1_contract_lone_low_surrogate.wqc": "contract",
"v1_contract_noncharacter.wqc": "contract",
"v1_contract_raw_noncharacter.wqc": "contract",
"v1_contract_integer_rounds_to_infinity.wqc": "contract",
"v1_contract_number_rounds_to_infinity.wqc": "contract",
"v1_contract_long_literal.wqc": "contract",
"v1_contract_bom.wqc": "contract",
"v1_contract_nan.wqc": "contract",
"v1_contract_control_character.wqc": "contract",
"v1_measure_duplicate_member.wqc": "malformed",
"v1_contract_not_utf8.wqc": "contract",
"v1_contract_number_out_of_range.wqc": "contract",
"v1_n_qubits_fraction.wqc": "malformed",
"v1_n_qubits_missing.wqc": "malformed",
"v1_measure_not_json.wqc": "malformed",
"short_payload.wqc": "malformed",
"table_past_end.wqc": "malformed",
"section_past_end.wqc": "malformed",
"unknown_section_past_end.wqc": "malformed",
"no_contract.wqc": "malformed",
"no_oplog.wqc": "malformed",
"v1_oplog_short.wqc": "malformed",
"v1_op_truncated_controls.wqc": "malformed",
"v1_opcode_10.wqc": "malformed",
"v1_target_out_of_range.wqc": "invalid",
"v1_control_out_of_range.wqc": "invalid",
"v1_control_is_target.wqc": "invalid",
"v1_phase_0.wqc": "invalid",
"v1_phase_33.wqc": "invalid",
"v1_n_ops_u32max.wqc": "malformed",
"v1_offset_wrap.wqc": "malformed",
"v2_contract_whitespace.wqc": "contract",
"v2_contract_key_order.wqc": "contract",
"v2_contract_extra_member.wqc": "contract",
"v2_contract1_in_wqc2.wqc": "contract",
"v2_n_qubits_256.wqc": "malformed",
"v2_contract_not_object.wqc": "contract",
"v2_n_qubits_rounds_to_infinity.wqc": "contract",
"v2_n_qubits_largest_finite.wqc": "malformed",
"v2_phase_0.wqc": "invalid",
"v2_measure_twice.wqc": "malformed",
"v2_measure_seed_signed.wqc": "malformed",
"v2_duplicate_controls.wqc": "invalid",
"v2_param_on_h.wqc": "invalid",
"v2_oplog_trailing_byte.wqc": "malformed",
"v2_opcode_10.wqc": "malformed",
"v2_measure_spaced.wqc": "malformed",
"v2_measure_no_shots.wqc": "malformed",
"v2_measure_basis_x.wqc": "malformed"
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more