All checks were successful
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Successful in 12m23s
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Successful in 5s
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 6s
wai-quantum on every processor / emulated · aarch64-unknown-linux-gnu (pull_request) Successful in 1m47s
wai-quantum on every processor / emulated · armv7-unknown-linux-gnueabihf (pull_request) Successful in 2m49s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 6s
WAI conformance / does this change touch it (pull_request) Successful in 7s
WAI energy receipts / does this change touch it (pull_request) Successful in 10s
WAI JPEG-AI whole decode (pinned inputs, required) / does this change touch it (pull_request) Successful in 7s
WAI neural sink gates / does this change touch it (pull_request) Successful in 11s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 1m12s
wai-ops-gpu integer operators on GPUs / does this change touch it (pull_request) Successful in 10s
wai-pack / wai-pack · does this change touch it (pull_request) Successful in 8s
wai-quantum command line / does this change touch it (pull_request) Successful in 8s
wai-quantum dataflow member / does this change touch it (pull_request) Successful in 6s
wai-quantum CUDA member / does this change touch it (pull_request) Successful in 7s
wai-quantum signal processor / does this change touch it (pull_request) Successful in 5s
wai-quantum FPGA member / does this change touch it (pull_request) Successful in 7s
wai-quantum HIP member / does this change touch it (pull_request) Successful in 6s
wai-quantum Metal member / does this change touch it (pull_request) Successful in 5s
wai-quantum neural-processor member / does this change touch it (pull_request) Successful in 6s
wai-quantum npu-cores member / does this change touch it (pull_request) Successful in 7s
wai-quantum on every processor / emulated · loongarch64-unknown-linux-gnu (pull_request) Successful in 3m38s
wai-quantum OpenCL member / does this change touch it (pull_request) Successful in 6s
wai-quantum CUDA member / member · CUDA (jetson-hub) (pull_request) Successful in 27s
wai-quantum-qpu / does this change touch it (pull_request) Successful in 7s
wai-quantum HIP member / member · HIP (framework-128gb) (pull_request) Successful in 20s
wai-quantum service / does this change touch it (pull_request) Successful in 6s
wai-quantum matrix-extension member / does this change touch it (pull_request) Successful in 7s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 6s
wai-quantum tensor-engine member / does this change touch it (pull_request) Successful in 7s
wai-quantum CPU vector units / does this change touch it (pull_request) Successful in 5s
wai-quantum portable tensor program / does this change touch it (pull_request) Successful in 6s
wai-quantum OpenCL member / member · OpenCL GPU and CPU (jetson-hub) (pull_request) Successful in 24s
wai-quantum WebGPU member / does this change touch it (pull_request) Successful in 5s
WAI mbt2018_mean integer decode (regenerated vectors) / does this change touch it (pull_request) Successful in 5s
wai-web wasm32 / does this change touch it (pull_request) Successful in 5s
wai-quantum portable tensor program / tensor program · GPUs (jetson-hub) (pull_request) Successful in 15s
wai-quantum npu-cores member / member · npu-cores, neural processor (framework-128gb silicon) (pull_request) Successful in 1m13s
wai-quantum OpenCL member / member · OpenCL GPU (framework-128gb) (pull_request) Successful in 13s
wai-quantum CPU vector units / member · vector units, avx2 and avx512 (framework-128gb silicon) (pull_request) Successful in 10s
wai-quantum portable tensor program / tensor program · integrated GPU (framework-128gb) (pull_request) Successful in 8s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 1m3s
wai-quantum on every processor / emulated · powerpc64-unknown-linux-gnu (pull_request) Successful in 5m25s
wai-quantum on every processor / emulated · powerpc64le-unknown-linux-gnu (pull_request) Successful in 6m1s
wai-quantum on every processor / emulated · riscv64gc-unknown-linux-gnu (pull_request) Successful in 4m2s
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Successful in 7m37s
wai-quantum on every processor / emulated · s390x-unknown-linux-gnu (pull_request) Successful in 4m8s
wai-quantum on every processor / emulated · sparc64-unknown-linux-gnu (pull_request) Successful in 6m16s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 7s
wai-quantum on every processor / emulated · i686-unknown-linux-gnu (pull_request) Successful in 4m10s
wai-quantum WebGPU member / member · discrete GPU, Vulkan (jetson-hub) (pull_request) Successful in 20m25s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m2s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 27s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 10m17s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 18m12s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 1m24s
wai-ops-gpu integer operators on GPUs / builds · no adapter is not a pass (linux) (pull_request) Successful in 1m45s
wai-pack / wai-pack · linux (pull_request) Successful in 1m20s
wai-quantum command line / command line · linux (pull_request) Successful in 1m7s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 6m57s
wai-quantum CUDA member / member · CUDA absent (linux) (pull_request) Successful in 24s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:b140) (pull_request) Successful in 3m25s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:401e) (pull_request) Successful in 4m35s
wai-quantum FPGA member / member · FPGA simulation absent (linux) (pull_request) Successful in 21s
wai-quantum Metal member / member · Metal absent (linux) (pull_request) Successful in 26s
wai-quantum neural-processor member / member · neural processor absent (linux) (pull_request) Successful in 26s
wai-quantum OpenCL member / member · OpenCL absent (linux) (pull_request) Successful in 21s
wai-quantum-qpu / clients against their contracts (linux) (pull_request) Successful in 20s
wai-quantum service / service · linux (pull_request) Successful in 39s
wai-quantum matrix-extension member / member · matrix extension, emulated (aarch64 Linux) (pull_request) Successful in 19s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 3m23s
wai-quantum signal processor / processor and member · signal processor, emulated (pull_request) Successful in 14m8s
wai-quantum CPU vector units / member · vector unit, rvv 1024-bit (riscv64, emulated) (pull_request) Successful in 19s
wai-quantum CPU vector units / member · vector unit, sve 128-bit (aarch64, emulated) (pull_request) Successful in 28s
wai-quantum CPU vector units / member · vector unit, rvv 128-bit (riscv64, emulated) (pull_request) Successful in 14s
wai-quantum CPU vector units / member · vector unit, sve 2048-bit (aarch64, emulated) (pull_request) Successful in 10s
wai-quantum tensor-engine member / member · tensor engine, the kernel toolchain's simulator (linux) (pull_request) Successful in 8m5s
wai-quantum CPU vector units / member · vector unit, avx2 (x86_64 silicon) (pull_request) Successful in 15s
wai-quantum CPU vector units / member · vector unit, sve 512-bit (aarch64, emulated) (pull_request) Successful in 12s
wai-quantum portable tensor program / tensor program · CPU, mutants, GPU builds (pull_request) Successful in 29s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 3m12s
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Successful in 2m9s
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness · MSRV (pull_request) Successful in 3m13s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 4m18s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 5m22s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 15s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 2m23s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 15m0s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 12s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 26s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 1m36s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 4m35s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 6m54s
wai-pack / wai-pack · linux-arm64 (pull_request) Successful in 1m14s
wai-pack / wai-pack · the floor through a media prober (pull_request) Successful in 24s
wai-pack / wai-pack · dependency licences (pull_request) Successful in 1m18s
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Successful in 25s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 6m16s
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Successful in 23s
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Successful in 19s
wai-pack / wai-pack · independent verifier (Python) (pull_request) Successful in 4m8s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 35m22s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 8m33s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 14m16s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 23s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 54s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 6m14s
wai-ops-gpu integer operators on GPUs / Metal GPU and browser WebGPU (macos) (pull_request) Successful in 3m12s
wai-pack / wai-pack · macos (pull_request) Successful in 1m3s
wai-quantum command line / command line · macos (pull_request) Successful in 28s
wai-quantum dataflow member / member · dataflow device absent (macos) (pull_request) Successful in 14s
wai-quantum FPGA member / member · FPGA datapath, simulated (macos) (pull_request) Successful in 1m13s
wai-quantum Metal member / member · Metal (macos) (pull_request) Successful in 29s
wai-quantum neural-processor member / member · neural processor (macos) (pull_request) Successful in 5m49s
wai-quantum OpenCL member / member · OpenCL GPU (macos) (pull_request) Successful in 29s
wai-quantum service / service · macos (pull_request) Successful in 44s
wai-quantum matrix-extension member / member · matrix extension absent (macos) (pull_request) Successful in 9s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 2m12s
wai-quantum CPU vector units / member · vector unit absent (macos) (pull_request) Successful in 13s
wai-quantum portable tensor program / tensor program · Metal and the arm64 CPU (macos) (pull_request) Successful in 15s
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Successful in 4m26s
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Successful in 1m43s
This carries 0.6.13, which was not published on its own, and 0.6.14. ## 0.6.13 The engine is the microscope and the judge, a local model is a muse that waits to be asked, and the reader is the author. Every figure is the engine's. Nothing changes the reader's program until they apply a change. engine::critique gives a program's measures before it runs: - gates by kind; one-, two- and three-qubit gates; T gates; gates off the Clifford angles; - depth and two-qubit depth, and whether it is a Clifford circuit; - a fidelity at reference error rates, named as a model. It also gives the program's smells, each with its lines and operations: gates that cancel, rotations that merge or do nothing, idle qubits, and qubits never measured. critique::variants rewrites the program's own text with the smells fixed, all of them to a fixed point and each one alone. Each candidate carries its measures and the equivalence verdict; one the check finds different is never offered. engine::equiv compares two programs up to a global phase: - by tableau for Clifford circuits, at any size; - otherwise on every basis state, to 8 qubits; - otherwise on random product states, to 22 qubits, which is evidence, not proof; - otherwise unchecked, with the reason. qasm::parse_lines gives each operation's line, and draw::layout each gate's operation index. engine::shortcuts lists every exact classical route the engine knows, priced on the program, and names the cheapest for each question: - the stabilizer tableau; - the cut-rank sum; - an exact matrix product state, at a bond bounded by the operator Schmidt ranks of the gates crossing each cut. The bound is held by a test against the true Schmidt ranks of random circuits; - the light cone; - a tensor-network contraction, when asked to be thorough; - the state vector. A cheap route proves a design classically easy; none being cheap proves nothing. On the 70-qubit random graph-state circuit the quick check finds the cut-rank sum (widest cut 30) in under 2 s. The thorough one finds widest cut 29 in about 4 minutes. Quantum Studio gains: - the critique, always on under the diagram, with the smells flagged on it, Show and Fix; - the classical cost, on request; - Alternatives: Improve (the engine's rewrites and the model's, each checked) and Explore (the model's different circuits, each measured and compared), with an atlas and Apply; - Predict first, which sets the reader's expected outcome against the run; - an assistant that asks questions first and speaks only when asked, offering (never sending) a hint when allowed. Its new tools are critique_qasm, check_equivalent and classical_shortcuts. wai-web exports the four engine calls. The desktop app answers them natively. wai-quantum-cli 0.1.1 adds critique, equivalent (exit 0/1/2), improve and shortcuts, with four MCP tools. examples/cutrank_qasm gains probs: the exact 2^n·p of given bit strings, with their linear cross-entropy. ## 0.6.14 A deep circuit on a line, contracted qubit by qubit along time, keeps a boundary of only the bonds between two neighbouring qubits: about half the depth for a controlled-Z brickwork. The contraction search rarely found that tree on its own. - Network::amplitude_split_placed builds the same network as amplitude_split, index for index, with each index's place in the circuit: a qubit and a time. - tensor_places, sweep_orders and sweep_path turn the places into the trees that sweep qubit by qubit, or time by time. - find_path_seeded and find_path_restarts_seeded score such trees beside the trials and polish the best of them all alike. A seed that is not a tree of the network is ignored. - The engine's tensor_network method and the thorough shortcut lens take both sweeps as seeds. On the 70-qubit random graph-state circuit, one amplitude's largest intermediate falls from 2^48 to 2^36, and its multiply-adds from 2^56.1 to 2^48.7, in the thorough lens. With 16 trials and no seeds the search finds 2^59. The pinned plans in tests/bit_identity.rs call find_path itself and are unchanged. The job service answers four design checks: POST /v1/critique, /v1/equivalent, /v1/improve and /v1/shortcuts, with the matching MCP tools. They run in its own process within bounds: - each counts against the client's submissions; - at most two run at once, and one that waits ten seconds is refused with a 503; - equivalence work past 4e9 gate amplitudes, and a thorough search, are refused with a 422 naming the local command. The smoke script checks each one. It now follows a job that outlasts /v1/run's wait, as a client does, instead of failing on a loaded host. wai-quantum-cli 0.1.2 carries the faster contraction. Co-Authored-By: Claude Opus 5.5 <[email protected]>
183 lines
15 KiB
Markdown
183 lines
15 KiB
Markdown
# wai-quantum-service
|
||
|
||
The WAI quantum stack as a public job service. Send an OpenQASM program; get back measurement counts, Pauli expectation values or amplitudes. Each result names the method that produced it and how accurate it is, and carries a signature you can check.
|
||
|
||
No account and no key. The public instance is at **https://wai.transaction.science/quantum-jobs/v1**.
|
||
|
||
```sh
|
||
# A Bell pair, 1000 shots.
|
||
curl -s https://wai.transaction.science/quantum-jobs/v1/run \
|
||
-H 'content-type: application/json' \
|
||
-d '{"qasm": "OPENQASM 3.0; qubit[2] q; bit[2] c; h q[0]; cx q[0], q[1]; c = measure q;", "shots": 1000}'
|
||
```
|
||
|
||
## Jobs
|
||
|
||
A job is JSON:
|
||
|
||
| field | meaning |
|
||
|---|---|
|
||
| `qasm` | the program: OpenQASM 3, or OpenQASM 2 (required) |
|
||
| `method` | `auto` (the default) or a method below |
|
||
| `shots` | measurement shots (default 1024 when nothing else is asked for; at most 1,000,000) |
|
||
| `seed` | the sampling seed (default 1); the same job and seed give the same counts |
|
||
| `observables` | Pauli strings such as `"Z0 Z1"`, or `{"pauli": "X3 Y4", "coeff": 0.5}` |
|
||
| `amplitudes` | bit strings, one character per qubit, qubit `n − 1` first |
|
||
| `noise` | `{"depolarizing_1q", "depolarizing_2q", "amplitude_damping", "dephasing", "readout"}`, each a probability |
|
||
| `options` | per method: `threshold`, `max_weight` and `ladder` (pauli), `max_bond` and `cutoff` (mps), `fusion` (statevector), `trajectories`, `memory_gb` |
|
||
|
||
Counts are keyed by the program's classical bits, the highest bit first. With no measurement in the program, every qubit is measured into the bit of its own index.
|
||
|
||
The program may use the standard gates, user `gate` definitions, and the control modifiers `ctrl @`, `ctrl(n) @`, `negctrl @` and `negctrl(n) @` (on `x y z h s sdg t tdg p` and `cx cy cz ch cp ccx ccz`). Measurement and `reset` may come anywhere, and `if` acts on measured bits (`if (c[0]) x q[1];`, `if (c == 3) { … } else { … }`, OpenQASM 2's `if(c==1) x q;`). Loops, `inv @` and `pow @` are refused, each with its line and what to write instead (`src/qasm.rs` lists everything read).
|
||
|
||
## Methods
|
||
|
||
| method | takes | answers | accuracy |
|
||
|---|---|---|---|
|
||
| `exact` | angles that are dyadic multiples of 2π, up to 26 qubits | counts, expectations, amplitudes, a state hash | bit-exact |
|
||
| `statevector` | any circuit, up to 32 qubits | counts, expectations, amplitudes | exact |
|
||
| `statevector_single` | any circuit with gates on at most four qubits, up to 33 qubits, where the host has a GPU | counts, expectations, amplitudes | single |
|
||
| `stabilizer` | Clifford circuits (rotations by whole quarter turns), up to 32768 qubits, optionally with depolarizing, dephasing and readout noise | counts, expectations | exact; with noise, an estimate |
|
||
| `pauli` | any circuit, up to 1024 qubits | expectations | bounded |
|
||
| `mps` | any circuit, up to 4096 qubits, at bond dimension up to 256; best when entanglement stays low | counts, expectations, amplitudes | exact when nothing is truncated, otherwise heuristic |
|
||
| `tensor_network` | any circuit | amplitudes | exact |
|
||
| `cutrank` | a Clifford circuit, then one layer of one-qubit gates at any angles, up to 4096 qubits, as wide as the state's cut-rank allows | counts, amplitudes | exact; single when only a single-precision table fits |
|
||
| `cutrank_single` | as `cutrank`, with the table on the host's GPU, where it has one; only when asked for | counts, amplitudes | single |
|
||
| `density_matrix` | noisy circuits, up to 16 qubits within a job's memory | counts, expectations | exact |
|
||
| `trajectories` | noisy circuits, up to 32 qubits | counts, expectations | estimate |
|
||
|
||
How the methods run:
|
||
|
||
- **statevector** groups consecutive gates into passes over the state. Each pass applies its gates tile by tile, in a buffer that fits a core's cache. The grouping never changes a bit of the result.
|
||
- **cutrank** takes a Clifford circuit followed, on each qubit, by one-qubit gates at any angles (a qubit's gates from its first non-Clifford one on act on that qubit alone).
|
||
- It writes the Clifford part's state as a graph state with local Cliffords, and sums the amplitude one qubit at a time along an order of the qubits, in a table of `2^cut` entries. Here `cut` is the state's cut-rank, its entanglement in bits, across the cut the sum has reached.
|
||
- The planner makes one short search for an order with narrower cuts, enough to bound the job's memory and work. The run searches longer, from several seeds on threads of their own, and keeps the cheapest order that is no wider than the planner's. The cost is set by the widest cut, `max_cut` in the result, not by the number of qubits.
|
||
- Counts are exact samples, drawn qubit by qubit from the table's conditional probabilities.
|
||
- Amplitudes carry the circuit's own global phase. A stabilizer tableau does not fix it, so one amplitude of the Clifford part is tracked exactly, gate by gate, and the summed amplitudes are scaled to agree with it, together with the phase the lowering to Clifford gates drops. A circuit with so many Hadamards that the tracking would take more than about a minute reports `global_phase` as not fixed instead.
|
||
- The table is held in double precision when it fits the job's memory, and in single precision otherwise (accuracy class `single`).
|
||
- **pauli** reports each value with its truncation `bound`. It holds at most as many Pauli terms as the job's memory allows; a sum that would outgrow it raises its threshold until it fits (`threshold_reached`), and the bound covers everything that dropped. Unless `ladder` is `false`, it also reports a `ladder`: the value and bound at up to three thresholds a decade above the one asked for, so you can see the value settle as the threshold drops.
|
||
- **stabilizer**, with noise, samples by Pauli frames against one noiseless outcome of the tableau, 64 shots to a machine word. Its counts have the law of independent noisy shots. Its expectation values are estimates with standard errors, from at least 10,000 shots unless `trajectories` sets the number. Amplitude damping is not a Pauli channel and is refused.
|
||
- **trajectories** treats every shot as an independent noisy trajectory in law. Shots that took the same errors share one state, so the error-free part of a circuit, and the error-free majority of the shots, run once. `histories` in the result counts the distinct error histories that ran.
|
||
|
||
### Programs that measure in the middle
|
||
|
||
A program that measures a qubit and then acts on it, resets a qubit after its first gate, or uses `if` on measured bits runs on `statevector` or `stabilizer`. `auto` picks the stabilizer tableau when every gate is Clifford, and the state vector otherwise.
|
||
|
||
- **Counts** split their shots. The shots enter together, and at each measurement or reset they divide between the outcomes as independent shots would: binomially, in the outcome's probability. Each outcome then runs on in its own copy of the state. Shots that read the same outcomes share one state, and the counts have the law of independent runs.
|
||
- **Expectation values** are exact: the mixture over every branch of non-zero probability, at most 4096 branches. As for any program, they describe the state before the final measurements. A measurement whose qubit nothing touches afterwards, and whose bit no later condition reads, is not made for them.
|
||
- The result's `dynamic` member reports what the walks did:
|
||
- `measurements_and_resets`;
|
||
- `branches_run` and `states_at_once` for the counts;
|
||
- `branches_weighed` for the expectation values.
|
||
|
||
Noise in such a program, and amplitudes of one, are refused, each with its reason. The state vector holds a copy for each branch still running, so it takes one qubit fewer than for a program that measures only at the end.
|
||
|
||
```sh
|
||
# Teleportation: ⟨Z2⟩ = cos 0.7 and ⟨X2⟩ = sin 0.7, exactly.
|
||
curl -s https://wai.transaction.science/quantum-jobs/v1/run -H 'content-type: application/json' -d '{
|
||
"qasm": "OPENQASM 3.0; qubit[3] q; bit[3] c; ry(0.7) q[0]; h q[1]; cx q[1], q[2]; cx q[0], q[1]; h q[0]; c[0] = measure q[0]; c[1] = measure q[1]; if (c[1]) x q[2]; if (c[0]) z q[2]; c[2] = measure q[2];",
|
||
"observables": ["Z2", "X2"], "shots": 1000 }'
|
||
```
|
||
|
||
`auto` picks the first method that takes the job. With noise, it tries `density_matrix`, then `stabilizer`, then `trajectories`. For counts, it tries `stabilizer`, `exact`, `statevector`, `statevector_single`, `cutrank`, then `mps`. For expectations alone, it tries `stabilizer`, `exact`, `statevector`, `statevector_single`, `pauli`, then `mps`. For amplitudes alone, it tries `exact`, `statevector`, `statevector_single`, `cutrank`, `tensor_network`, then `mps`. The job's `why` names the method chosen and the ones that could not take it.
|
||
|
||
The accuracy classes:
|
||
|
||
- **bit-exact**: the same bits on every machine. Amplitudes are held in 30-bit fixed point, and every output is an exact function of them.
|
||
- **exact**: no approximation beyond double-precision rounding.
|
||
- **single**: no approximation beyond single-precision rounding, about 10⁻⁷ relative per gate; sums are taken in double precision.
|
||
- **bounded**: an approximation, with a rigorous bound on the error (`bound`) beside each value.
|
||
- **estimate**: a statistical estimate, with its standard error (`stderr`).
|
||
- **heuristic**: an approximation, reported with the standard estimate of its error but not a bound. A matrix product state that truncated reports its discarded weight and its fidelity estimate, and a `warning` when the estimate is below 0.9.
|
||
|
||
Counts are always seeded samples.
|
||
|
||
## Endpoints
|
||
|
||
| | |
|
||
|---|---|
|
||
| `GET /v1` | the service: its methods, limits, load and receipt key |
|
||
| `POST /v1/run` | submit a job and wait up to 25 s: the finished job, or `202` and the job if it is still running |
|
||
| `POST /v1/jobs` | submit a job: `202` and the job, with its `id` |
|
||
| `GET /v1/jobs/{id}` | the job: its status, the request as submitted, and its result when it is done |
|
||
| `DELETE /v1/jobs/{id}` | cancel a queued or running job |
|
||
| `POST /v1/verify` | `{"request": ..., "result": ...}`: whether the result's receipt seals that request and that result |
|
||
| `POST /v1/critique` | `{"qasm"}`: the program's measures (gates by kind, two-qubit gates, depth, T count, whether it is Clifford, a modelled fidelity) and its smells, each with its lines |
|
||
| `POST /v1/equivalent` | `{"a", "b"}`: whether two programs are the same circuit up to a global phase, and how that was decided |
|
||
| `POST /v1/improve` | `{"qasm"}`: the program with its smells fixed, each candidate with its measures and checked the same circuit |
|
||
| `POST /v1/shortcuts` | `{"qasm"}`: each exact classical route to simulating the program, priced on it, and the cheapest for each question |
|
||
|
||
Every refusal says why: `400` for a program or job that does not read, `422` for one larger than a job may be, `429` past the per-client limits, `503` when the queue is full. `GET /v1` states the limits.
|
||
|
||
The four checks answer at once, in the service's own process. Each counts against the client's submissions, as a job does. At most two run at a time, and a check that waits ten seconds for its turn is refused (`503`). Some checks are refused (`422`) with the command that runs them on your own machine:
|
||
|
||
- an equivalence check that would apply more than 4·10⁹ gate amplitudes;
|
||
- an improvement whose candidates' checks would apply more than that;
|
||
- a thorough search for shortcuts.
|
||
|
||
## Receipts
|
||
|
||
Every finished result carries a `receipt`: an Ed25519 signature, by the key `GET /v1` publishes, over the BLAKE3 digest of the request as submitted and the result as returned. `POST /v1/verify` checks one, and so can any Ed25519 implementation:
|
||
|
||
- digest = BLAKE3(`wai:quantum-service-receipt` ‖ 0x02 ‖ len(R) ‖ R ‖ len(S) ‖ S), each len a big-endian u64;
|
||
- R and S are the RFC 8785 canonical texts (`"canon": "rfc8785"`) of the request and of the result without its `receipt`: keys sorted, no whitespace, every number written as ECMAScript writes the double it reads.
|
||
|
||
So a result verifies after any JSON reader has carried it, a browser's included. Whole numbers in a request must be within ±(2^53 − 1), so that every reader reads them alike. Receipts issued before the canonical form carry no `canon` and still verify (see `src/receipt.rs`).
|
||
|
||
## Energy
|
||
|
||
Every finished result carries `energy`, inside the body the receipt seals: the CPU energy the job's worker process spent, from its start to its exit. The service reads it from the kernel's per-process count (`proc_pid_rusage`, `ri_energy_nj`, on macOS) after the worker exits and before it is reaped. An exited process has left every core, so its count is complete.
|
||
|
||
```json
|
||
"energy": {
|
||
"joules_micro": 2540113,
|
||
"energy_provenance": "OnChipCounter",
|
||
"energy_uncertainty": { "relative_ppm": 1, "window_us": 2603412 },
|
||
"energy_counter_filtering": "Unknown",
|
||
"coverage": "whole",
|
||
"covers": "the CPU energy of the job's worker process, from its start to its exit, with the CPU energy system services billed to it",
|
||
"excludes": ["memory", "the host's idle draw"],
|
||
"cpu_ms": 31680,
|
||
"source": "proc_pid_rusage ri_energy_nj + ri_billed_energy − ri_serviced_energy, read after the worker exited and before it was reaped"
|
||
}
|
||
```
|
||
|
||
The fields follow WAI's energy-measurement extension (§2):
|
||
|
||
- `energy_provenance` is the acquisition class. `OnChipCounter` means the silicon's own accounting, with no calibration behind it.
|
||
- `energy_uncertainty.relative_ppm` declares the part of the uncertainty that can be evaluated: here, the rounding to whole microjoules. It is not the figure's total error, because the counter's own systematic error is not evaluated.
|
||
- `window_us` is the worker's lifetime.
|
||
- `energy_counter_filtering` is `Unknown`, because the platform does not document whether the count is filtered.
|
||
|
||
A `statevector_single` or `cutrank_single` job runs on the GPU, which this counter does not read, so its figure is `partial` and says so in `excludes`. So is a figure that includes CPU energy system services billed to the worker, since such credits land late.
|
||
|
||
Where the service cannot read the count (off macOS), `energy` is `{"unmetered": "<why>"}`. It is never a figure of zero. `wai-quantum-service run FILE` runs a job in its own process and reports no energy.
|
||
|
||
## Running it
|
||
|
||
```sh
|
||
cargo build --release
|
||
WAI_QSVC_ADDR=127.0.0.1:8241 ./target/release/wai-quantum-service serve
|
||
bash smoke.sh http://127.0.0.1:8241
|
||
```
|
||
|
||
Each job runs in a child process of the same binary (`worker`), at a lower scheduling priority than the host's other work, and is watched for its resident memory and its time.
|
||
|
||
These variables set the limits:
|
||
|
||
| variable | default | meaning |
|
||
|---|---|---|
|
||
| `WAI_QSVC_BUDGET_GB` | 96 | memory all running jobs share |
|
||
| `WAI_QSVC_JOB_GB` | 72 | memory one job may take |
|
||
| `WAI_QSVC_WORKERS` | 4 | jobs running at once |
|
||
| `WAI_QSVC_MIN_FREE_PCT` | 15 | share of the host's memory a starting job must leave free |
|
||
| `WAI_QSVC_JOB_SECS` | 900 | the longest a job may run |
|
||
| `WAI_QSVC_CLIENT_ACTIVE` | 3 | queued or running jobs one client may hold |
|
||
| `WAI_QSVC_CLIENT_BURST` | 30 | submissions one client may make per window |
|
||
| `WAI_QSVC_CLIENT_WINDOW_SECS` | 600 | the window |
|
||
| `WAI_QSVC_MAX_QUEUE` | 256 | jobs waiting at once |
|
||
| `WAI_QSVC_RETAIN_SECS` | 86400 | how long results are kept |
|
||
| `WAI_QSVC_TRUSTED_PROXIES` | `127.0.0.1,::1` | peers whose `X-Forwarded-For` names the client |
|
||
| `WAI_QSVC_KEY` | `~/.config/wai-quantum-service/signing.key` | the signing key, created on first start |
|
||
|
||
`wai-quantum-service run job.json` runs one job in the current process and prints its plan and its result.
|