plan (PLAN_REVISION 2): Config { tile_bits, run_max, skip_identity } with
PER_GATE (what compile makes) and TILED (tiles of up to 1024 amplitudes, runs
of up to 1024 gates, capped at 2^30 / 2^n, 16 at 26 qubits); Step::Tile
{ first, count, size }; compile_with, schedule, execute_from,
PlannedGate::{new, is_identity}. A tile run is a maximal run of consecutive
gates that act inside a tile: diagonal gates on any target, others with their
target's bit below the tile size. Only exact identities are skipped (circuit/1's
P(19..=32) is 2^30 - 1 and stays). The CPU executor mirrors the tile kernel's
index arithmetic tile by tile; lanes::exact_row is shared with apply_words.
Tests: every configuration (10 of them) equals the native simulator over
random-v1 (300) and fabric-v1 and certifies with the four lanes32 pins; long
random circuits and full-range random words tile exactly as they run gate by
gate; fabric-v1 covers every tile path; malformed programs are refused;
a_rounded_product_is_never_negated runs under every configuration.
wgsl: TILE_SHADER = lanes32.wgsl followed by lanes32_tile.wgsl (entry point
apply_tile, workgroup 256, one workgroup per tile, the tile size, gate range
and grid in a 32-byte uniform run record, gates in a 48-byte read-only storage
record), tile_implementation_id() = wgsl-lanes32-tile/de6fb388454a0144 (pinned),
tile records, tile_grid (x at most 8), TILE_MUTANTS T1 (barrier between gates
removed, detector Race over race_witness), T2 (the report's minimum dropped,
Range) and T3 (tbit < size -> <=, Malformed over malformed_tile_run).
Deviation from the plan's kernel text: no workgroup memory. naga 30.0.1
decorates every array type with ArrayStride and struct members with Offset,
and spirv-val (SPIRV-Tools 2026.4) rejects explicit layouts on Workgroup
variables (VUID-StandaloneSpirv-None-10684); per the plan the kernel was
restructured instead: each workgroup updates its own tile in place in the state
planes, with storageBarrier() between gates. The uniformity argument is
unchanged (one barrier, at the top level of the loop over the run's gates).
The min of the report is taken once per gate so that T2's text occurs once; a
tile outside the state reports bit 2; a record outside the gate buffer reads
as malformed.
Checker: SHADER and TILE_SHADER each under their own rules (entry points and
workgroup sizes, bindings, no workgroup memory, bool/u32 only, literal shifts,
atomics, barrier kind and placement at the top level of the body or of a
top-level for loop with no break, continue or return), translation to MSL,
SPIR-V and HLSL, mutants; lanes32_tile.spv for spirv-val; --tile-shader.
Member: WebGpuMember::tiled() compiles TILE_SHADER, probes it, plans with
TILED and reports the tile implementation; per-gate stays the default and the
fallback. Runs interleave gate and tile dispatches per submission (a second
uniform ring for run records, a storage buffer for the runs' gates), within
SUBMIT_BUDGET. Device tests: g8 kills T1-T3 on the tile member; new g12 runs
2,000 full-range cases tiled vs per-gate vs the CPU, the four pinned
certificates under the tile implementation, forced geometries, the conformance
vectors, five repeated runs, and prints per-gate vs tiled timing. The member
script requires 13 tests and both implementations' certificates and mutants.
Browser: QuantumWebGpu.tiled(); the worker certifies and runs the vectors on
the tile member too; browser_webgpu.mjs requires "tiles certified bit-exact 4
of 4" and fabric/expected.json pins tile_implementation.
CI: checks validate lanes32_tile.spv and package lanes32_tile.wgsl; the
browser job checks the tile pin and greps the tile certificates; the wasip2 job
requires the new tests by name, and its timeout is 90 minutes (the planner test
runs several minutes alone in a debug wasm build).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
117 lines
5.8 KiB
Markdown
117 lines
5.8 KiB
Markdown
# quantum-conformance
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
## Native
|
|
|
|
```sh
|
|
cargo build --release --no-default-features --features quantum --bin wai_quantum_vectors
|
|
./target/release/wai_quantum_vectors verify wai/quantum-conformance
|
|
```
|
|
|
|
## WASI (the edge)
|
|
|
|
Same binary, same source, different architecture:
|
|
|
|
```sh
|
|
cargo build --release --target wasm32-wasip2 --no-default-features --features quantum \
|
|
--bin wai_quantum_vectors
|
|
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] [module file]
|
|
```
|
|
|
|
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.
|
|
|
|
## Browser, on the fabric's WebGPU member
|
|
|
|
```sh
|
|
WAI_QUANTUM_WEBGPU_REQUIRE=1 node wai/quantum-conformance/browser_webgpu.mjs
|
|
```
|
|
|
|
Serves `wai-web/demo` and this directory on 127.0.0.1 and opens
|
|
`quantum_webgpu.html` in Playwright's headless browser, with the `quantum_webgpu`
|
|
bundle built into `wai-web/demo/pkg-webgpu` (`wai-web/demo/README.md`). The gate
|
|
kernel runs on the page's WebGPU adapter, compiled by the browser's own WGSL
|
|
compiler. The page must certify the kernel bit-exact for both gatesets on random-v1
|
|
and fabric-v1 with the digests `fabric/expected.json` pins (the CPU reference's), and
|
|
run every vector of both trees to its statevector hash, on the per-gate implementation
|
|
and again on the tile implementation `fabric/expected.json` names (the browser's
|
|
compiler holds its barrier to WGSL's uniformity rules); refuse every reject file with
|
|
its listed class; and refuse a circuit wider than the member holds. Without
|
|
`WAI_QUANTUM_WEBGPU_REQUIRE=1`, a page offered no adapter is reported and passes. CI
|
|
runs it on macOS (`wai-quantum-webgpu.yml`, job `browser`).
|
|
|
|
## 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 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`.
|