A third review upheld six findings. - std's f64 parse stops adding exponent digits once the exponent reaches 0x10000, so a literal whose exponent offsets about 655,000 zeros was judged wrong both ways: exactly 1 refused, 10^309 accepted. The Rust reader now decides the range rule on the digits, as the referee does: the significant digits and the decimal exponent, with saturating exponent arithmetic, against the 309 digits of 2^1024 − 2^970. The limit is one constant, RANGE_LIMIT, and a test derives it in decimal from 2^1024 and 2^970 and checks it against std's parse where that parse is exact. - The referee passed a zero-padded exponent of over 4300 digits to int(), which Python refuses; it now converts only the significant exponent digits. - quantum-sim §8, the CHANGELOG and SPEC §5 now list both directions of the range change: numbers at or above the limit that earlier builds let through are refused, numbers below it that some builds refused are accepted. §2 says the rule is decided on the digits, at any length. - The corpus README and the wasip2 job comment were stale. The corpus holds both long literals and the padded exponent: an accept file (exactly 1 and exactly 10, written long) and a reject file (10^309). Co-Authored-By: Claude Opus 5.5 <[email protected]>
98 lines
4.8 KiB
Markdown
98 lines
4.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.
|
|
|
|
## 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`.
|