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]>
290 lines
19 KiB
Shell
290 lines
19 KiB
Shell
#!/usr/bin/env bash
|
|
# smoke.sh BASE_URL: the service's promises, checked over HTTP against a running
|
|
# instance (CI starts one locally; after a deploy, run it against production).
|
|
#
|
|
# bash smoke.sh http://127.0.0.1:8241
|
|
# bash smoke.sh https://<public base>
|
|
#
|
|
# Each check prints one line and the script fails on the first that does not
|
|
# hold. Needs curl and python3.
|
|
set -euo pipefail
|
|
U=${1:?usage: smoke.sh BASE_URL}
|
|
U=${U%/}
|
|
tmp=$(mktemp -d)
|
|
trap 'rm -rf "$tmp"' EXIT
|
|
|
|
post() { curl -sS --max-time 120 -X POST "$U$1" -H 'content-type: application/json' --data-binary "@$2"; }
|
|
py() { python3 -I -c "$@"; }
|
|
# POST /v1/run, then follow a job still queued or running past the service's
|
|
# wait through GET /v1/jobs/{id}, as a client would: on a loaded host a job
|
|
# can outlast the wait without anything being wrong. At most ten minutes.
|
|
run() {
|
|
post /v1/run "$1" > "$2"
|
|
for _ in $(seq 1 120); do
|
|
case "$(py 'import json,sys; print(json.load(open(sys.argv[1])).get("status", ""))' "$2")" in
|
|
queued|running) sleep 5; curl -sS --max-time 30 "$U/v1/jobs/$(py 'import json,sys; print(json.load(open(sys.argv[1]))["id"])' "$2")" > "$2.next" && mv "$2.next" "$2" ;;
|
|
*) return 0 ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# The service describes itself, with its methods and its receipt key.
|
|
curl -sS --max-time 30 "$U/v1" > "$tmp/describe.json"
|
|
py 'import json,sys
|
|
d=json.load(open(sys.argv[1]))
|
|
assert d["service"]=="wai-quantum-service", d
|
|
ms={m["method"] for m in d["methods"]}
|
|
assert {"exact","statevector","stabilizer","pauli","tensor_network","cutrank","density_matrix","trajectories"} <= ms, ms
|
|
assert len(d["receipt_key"])==64
|
|
print("describe: ok,", len(ms), "methods, receipt key", d["receipt_key"][:16]+"…")' "$tmp/describe.json"
|
|
|
|
# A 40-qubit GHZ state: Clifford, so the stabilizer method, and only the two
|
|
# all-equal outcomes.
|
|
py 'import json
|
|
n=40
|
|
q="OPENQASM 3.0;\nqubit[%d] q;\nh q[0];\n" % n + "".join("cx q[%d], q[%d];\n" % (i,i+1) for i in range(n-1))
|
|
print(json.dumps({"qasm": q, "shots": 1000, "seed": 7}))' > "$tmp/ghz.json"
|
|
run "$tmp/ghz.json" "$tmp/ghz.out"
|
|
py 'import json,sys
|
|
d=json.load(open(sys.argv[1])); r=d["result"]
|
|
assert d["status"]=="done" and r["method"]=="stabilizer", d
|
|
c=r["counts"]; assert set(c) <= {"0"*40, "1"*40} and sum(c.values())==1000, c
|
|
assert "receipt" in r
|
|
print("ghz-40: ok,", r["method"], c)' "$tmp/ghz.out"
|
|
|
|
# Its receipt verifies, and a changed result does not.
|
|
py 'import json,sys
|
|
req=json.load(open(sys.argv[1])); res=json.load(open(sys.argv[2]))["result"]
|
|
json.dump({"request": req, "result": res}, open(sys.argv[3],"w"))
|
|
res["counts"]["0"*40] = res["counts"].get("0"*40, 0) + 1
|
|
json.dump({"request": req, "result": res}, open(sys.argv[4],"w"))' "$tmp/ghz.json" "$tmp/ghz.out" "$tmp/v.json" "$tmp/t.json"
|
|
post /v1/verify "$tmp/v.json" | py 'import json,sys; d=json.load(sys.stdin); assert d["valid"] is True, d; print("receipt: verifies")'
|
|
post /v1/verify "$tmp/t.json" | py 'import json,sys; d=json.load(sys.stdin); assert d["valid"] is False, d; print("receipt: a changed result does not verify")'
|
|
|
|
# The job carries its request as submitted, so whoever holds only the id can
|
|
# check the receipt: verify from the service's answer alone.
|
|
py 'import json,sys
|
|
req=json.load(open(sys.argv[1])); job=json.load(open(sys.argv[2]))
|
|
assert job["request"]==req, job.get("request")
|
|
json.dump({"request": job["request"], "result": job["result"]}, open(sys.argv[3],"w"))' "$tmp/ghz.json" "$tmp/ghz.out" "$tmp/vj.json"
|
|
post /v1/verify "$tmp/vj.json" | py 'import json,sys; d=json.load(sys.stdin); assert d["valid"] is True, d; print("receipt: verifies from the job alone")'
|
|
|
|
# The job's energy: a counter figure with its class and declared uncertainty,
|
|
# or why it is unmetered, never zero. SMOKE_EXPECT_ENERGY=1 (a macOS host)
|
|
# requires the figure. A changed figure breaks the receipt: it is sealed.
|
|
export SMOKE_EXPECT_ENERGY="${SMOKE_EXPECT_ENERGY:-0}"
|
|
py 'import json,os,sys
|
|
e=json.load(open(sys.argv[1]))["result"]["energy"]
|
|
if "joules_micro" in e:
|
|
uj=e["joules_micro"]; u=e["energy_uncertainty"]
|
|
assert uj > 0 and e["energy_provenance"] == "OnChipCounter", e
|
|
assert u["relative_ppm"] > 0 and u["window_us"] > 0 and uj * u["relative_ppm"] >= 288676, e
|
|
assert e["energy_counter_filtering"] in ("Unknown", "Off", "On") and e["coverage"] in ("whole", "partial"), e
|
|
print("energy: %.6f J of CPU, %s, %s" % (uj / 1e6, e["coverage"], e["energy_provenance"]))
|
|
else:
|
|
assert os.environ["SMOKE_EXPECT_ENERGY"] != "1", e
|
|
assert e["unmetered"], e
|
|
print("energy: unmetered,", e["unmetered"])' "$tmp/ghz.out"
|
|
py 'import json,sys
|
|
d=json.load(open(sys.argv[1]))
|
|
e=d["result"]["energy"]
|
|
if "joules_micro" in e: e["joules_micro"] += 1
|
|
else: e["unmetered"] += "."
|
|
json.dump(d, open(sys.argv[2],"w"))' "$tmp/vj.json" "$tmp/ve.json"
|
|
post /v1/verify "$tmp/ve.json" | py 'import json,sys; d=json.load(sys.stdin); assert d["valid"] is False, d; print("energy: a changed figure does not verify")'
|
|
|
|
# As a browser sends it back: whole doubles without a fraction, keys reversed.
|
|
py 'import json,sys
|
|
def js(v):
|
|
if isinstance(v, float) and v.is_integer(): return int(v)
|
|
if isinstance(v, dict): return {k: js(v[k]) for k in reversed(list(v))}
|
|
if isinstance(v, list): return [js(x) for x in v]
|
|
return v
|
|
v=json.load(open(sys.argv[1])); json.dump(js(v), open(sys.argv[2],"w"))' "$tmp/vj.json" "$tmp/vjs.json"
|
|
post /v1/verify "$tmp/vjs.json" | py 'import json,sys; d=json.load(sys.stdin); assert d["valid"] is True, d; print("receipt: verifies after a browser-style round trip")'
|
|
|
|
# Continuous angles on a small circuit: the dense state vector, and the
|
|
# probabilities sum to the shots.
|
|
py 'import json; print(json.dumps({"qasm": "qubit[3] q; rx(0.3) q[0]; ry(1.2) q[1]; cx q[0], q[2]; crz(0.7) q[1], q[2];", "shots": 500, "observables": ["Z0", "Z1 Z2"]}))' > "$tmp/rot.json"
|
|
run "$tmp/rot.json" "$tmp/rot.out"
|
|
py 'import json,sys,math
|
|
d=json.load(open(sys.argv[1])); r=d["result"]
|
|
assert d["status"]=="done" and r["method"]=="statevector", d
|
|
assert sum(r["counts"].values())==500
|
|
z0=r["expectations"][0]["value"]; assert abs(z0-math.cos(0.3))<1e-12, z0
|
|
print("rotations: ok, <Z0> =", z0)' "$tmp/rot.out"
|
|
|
|
# A 100-qubit circuit's expectation values: sparse Pauli dynamics, each value
|
|
# with its bound.
|
|
py 'import json
|
|
n=100
|
|
q="qubit[%d] q;\n" % n + "".join("rx(0.3) q[%d];\n" % i for i in range(n)) + "".join("cx q[%d], q[%d];\n" % (i,i+1) for i in range(n-1))
|
|
print(json.dumps({"qasm": q, "observables": ["Z0", "Z50 Z51"]}))' > "$tmp/wide.json"
|
|
run "$tmp/wide.json" "$tmp/wide.out"
|
|
py 'import json,sys,math
|
|
d=json.load(open(sys.argv[1])); r=d["result"]
|
|
assert d["status"]=="done" and r["method"]=="pauli", d
|
|
e=r["expectations"]; assert all("bound" in x for x in e), e
|
|
assert abs(e[0]["value"]-math.cos(0.3)) <= e[0]["bound"]+1e-9, e
|
|
print("pauli-100: ok,", [(x["observable"], round(x["value"],6), x["bound"]) for x in e])' "$tmp/wide.out"
|
|
|
|
# The pauli answer carries its threshold ladder, and the smaller threshold
|
|
# never drops more.
|
|
py 'import json,sys
|
|
d=json.load(open(sys.argv[1])); e=d["result"]["expectations"][0]
|
|
l=e["ladder"]; b=[x["bound"] for x in l]
|
|
assert len(l)>=2 and l[-1]["value"]==e["value"] and all(y<=x+1e-12 for x,y in zip(b,b[1:])), e
|
|
print("pauli ladder: ok,", [(x["threshold"], round(x["value"],6)) for x in l])' "$tmp/wide.out"
|
|
|
|
# Noisy shots: branching trajectories, every shot counted, and shots that
|
|
# share their errors sharing a state.
|
|
py 'import json
|
|
n=14
|
|
q="qubit[%d] q;\nbit[%d] c;\n" % (n,n) + "".join("ry(0.4) q[%d];\n" % i for i in range(n)) + "".join("cz q[%d], q[%d];\n" % (i,i+1) for i in range(n-1)) + "c = measure q;\n"
|
|
print(json.dumps({"qasm": q, "method": "trajectories", "shots": 2000, "noise": {"depolarizing_1q": 0.0005, "depolarizing_2q": 0.002, "readout": 0.01}}))' > "$tmp/noisy.json"
|
|
run "$tmp/noisy.json" "$tmp/noisy.out"
|
|
py 'import json,sys
|
|
d=json.load(open(sys.argv[1])); assert d.get("status")=="done", d; r=d["result"]
|
|
assert r["method"]=="trajectories", d
|
|
assert sum(r["counts"].values())==2000, r
|
|
h=r["accuracy"]["histories"]; assert 1 <= h < 2000, r["accuracy"]
|
|
print("noisy-14: ok,", r["method"], h, "histories for 2000 shots")' "$tmp/noisy.out"
|
|
|
|
# A wide noisy Clifford circuit: Pauli frames on the stabilizer tableau.
|
|
py 'import json
|
|
n=500
|
|
q="qubit[%d] q;\n" % n + "h q[0];\n" + "".join("cx q[%d], q[%d];\n" % (i,i+1) for i in range(n-1))
|
|
print(json.dumps({"qasm": q, "shots": 1000, "noise": {"depolarizing_2q": 0.0005, "readout": 0.001}, "observables": ["Z0 Z499"]}))' > "$tmp/nghz.json"
|
|
run "$tmp/nghz.json" "$tmp/nghz.out"
|
|
py 'import json,sys
|
|
d=json.load(open(sys.argv[1])); assert d.get("status")=="done", d; r=d["result"]
|
|
assert r["method"]=="stabilizer" and r["accuracy"]["class"]=="estimate", d
|
|
assert sum(r["counts"].values())==1000, r
|
|
e=r["expectations"][0]; assert 0.5 < e["value"] < 1.0 and e["stderr"] > 0, e
|
|
print("noisy-ghz-500: ok,", r["method"], "<Z0 Z499> =", round(e["value"],4), "±", round(e["stderr"],4))' "$tmp/nghz.out"
|
|
|
|
# The single-precision state vector on the GPU, where the service has one,
|
|
# against the double-precision one.
|
|
if py 'import json,sys; d=json.load(open(sys.argv[1])); sys.exit(0 if any(m["method"]=="statevector_single" and m.get("available") for m in d["methods"]) else 1)' "$tmp/describe.json"; then
|
|
py 'import json; print(json.dumps({"qasm": "qubit[12] q; h q; rx(0.3) q[0]; cx q[0], q[11]; crz(0.7) q[3], q[9]; ry(1.1) q[5];", "observables": ["Z0 Z11", "X5"], "method": "statevector_single"}))' > "$tmp/gpu.json"
|
|
py 'import json,sys; d=json.load(open(sys.argv[1])); d["method"]="statevector"; json.dump(d, open(sys.argv[2],"w"))' "$tmp/gpu.json" "$tmp/cpu.json"
|
|
run "$tmp/gpu.json" "$tmp/gpu.out"
|
|
run "$tmp/cpu.json" "$tmp/cpu.out"
|
|
py 'import json,sys
|
|
g=json.load(open(sys.argv[1])); c=json.load(open(sys.argv[2])); assert g.get("status")=="done" and c.get("status")=="done", (g, c)
|
|
gv=[e["value"] for e in g["result"]["expectations"]]; cv=[e["value"] for e in c["result"]["expectations"]]
|
|
assert g["result"]["accuracy"]["class"]=="single" and all(abs(a-b)<1e-5 for a,b in zip(gv,cv)), (gv, cv)
|
|
e=g["result"]["energy"]
|
|
# The counter reads the CPU only, so a GPU job never claims a whole figure.
|
|
assert "joules_micro" not in e or (e["coverage"]=="partial" and "GPU" in e["excludes"][0]), e
|
|
print("gpu: ok,", g["result"]["accuracy"]["device"], gv, "energy", e.get("coverage", "unmetered"))' "$tmp/gpu.out" "$tmp/cpu.out"
|
|
else
|
|
echo "gpu: this instance has none"
|
|
fi
|
|
|
|
# What a program finds first: the index, the examples, the OpenAPI document.
|
|
curl -sS --max-time 30 -H 'accept: application/json' "$U/" > "$tmp/index.json"
|
|
py 'import json,sys; d=json.load(open(sys.argv[1])); assert d["mcp"].endswith("/mcp") and d["openapi"].endswith("/v1/openapi.json"), d; print("index: ok,", d["mcp"])' "$tmp/index.json"
|
|
curl -sS --max-time 30 "$U/v1/examples" > "$tmp/examples.json"
|
|
curl -sS --max-time 30 "$U/v1/openapi.json" > "$tmp/openapi.json"
|
|
py 'import json,sys
|
|
e=json.load(open(sys.argv[1]))["examples"]; o=json.load(open(sys.argv[2]))
|
|
assert len(e)>=5 and all("job" in x and "qasm" in x["job"] for x in e), e
|
|
assert o["openapi"].startswith("3.1") and "/v1/run" in o["paths"] and "/mcp" in o["paths"], list(o["paths"])
|
|
print("examples and openapi: ok,", len(e), "examples,", len(o["paths"]), "paths")' "$tmp/examples.json" "$tmp/openapi.json"
|
|
|
|
# An agent over the Model Context Protocol: initialize, list the tools, run
|
|
# the first example, and check its receipt.
|
|
mcp() { curl -sS --max-time 120 -X POST "$U/mcp" -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' --data-binary "$1"; }
|
|
mcp '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"1"}}}' > "$tmp/mcp-init.json"
|
|
code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 30 -X POST "$U/mcp" -H 'content-type: application/json' --data-binary '{"jsonrpc":"2.0","method":"notifications/initialized"}')
|
|
mcp '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' > "$tmp/mcp-tools.json"
|
|
py 'import json,sys
|
|
i=json.load(open(sys.argv[1]))["result"]; t=json.load(open(sys.argv[2]))["result"]["tools"]
|
|
assert i["protocolVersion"]=="2025-06-18" and "tools" in i["capabilities"], i
|
|
names={x["name"] for x in t}; assert {"run_quantum_circuit","get_quantum_job","verify_quantum_receipt","quantum_service_info","quantum_circuit_examples","critique_qasm","check_equivalent","improve_qasm","classical_shortcuts"} <= names, names
|
|
assert sys.argv[3]=="202", sys.argv[3]
|
|
print("mcp: ok, initialized,", len(t), "tools")' "$tmp/mcp-init.json" "$tmp/mcp-tools.json" "$code"
|
|
py 'import json,sys
|
|
job=json.load(open(sys.argv[1]))["examples"][0]["job"]
|
|
print(json.dumps({"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"run_quantum_circuit","arguments":job}}))' "$tmp/examples.json" > "$tmp/mcp-call.json"
|
|
mcp "@$tmp/mcp-call.json" > "$tmp/mcp-run.json"
|
|
py 'import json,sys
|
|
r=json.load(open(sys.argv[1]))["result"]; job=r["structuredContent"]; text=r["content"][0]["text"]
|
|
assert not r["isError"] and job["status"]=="done" and "counts" in job["result"], r
|
|
assert "method:" in text and "counts" in text, text
|
|
req=json.load(open(sys.argv[2]))["examples"][0]["job"]
|
|
print(json.dumps({"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"verify_quantum_receipt","arguments":{"request":req,"result":job["result"]}}}))' "$tmp/mcp-run.json" "$tmp/examples.json" > "$tmp/mcp-verify.json"
|
|
curl -sS --max-time 60 -X POST "$U/mcp" -H 'content-type: application/json' --data-binary "@$tmp/mcp-verify.json" > "$tmp/mcp-verified.json"
|
|
py 'import json,sys
|
|
v=json.load(open(sys.argv[1]))["result"]; assert v["structuredContent"]["valid"] is True, v
|
|
print("mcp run + verify: ok,", json.load(open(sys.argv[2]))["result"]["content"][0]["text"].splitlines()[1])' "$tmp/mcp-verified.json" "$tmp/mcp-run.json"
|
|
|
|
# Grover's search on five qubits as the IDE writes it: its oracle and its
|
|
# diffusion are each a Z under four controls. Four rounds find the item.
|
|
py 'import json
|
|
n, marked = 5, 0b10110
|
|
def mcz(): return "ctrl(4) @ z q[0],q[1],q[2],q[3],q[4];\n"
|
|
q = "OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[5] q;\n" + "".join("h q[%d];\n" % i for i in range(n))
|
|
for _ in range(4):
|
|
flips = "".join("x q[%d];\n" % i for i in range(n) if not marked >> i & 1)
|
|
q += flips + mcz() + flips
|
|
q += "".join("h q[%d];\nx q[%d];\n" % (i, i) for i in range(n)) + mcz() + "".join("x q[%d];\nh q[%d];\n" % (i, i) for i in range(n))
|
|
print(json.dumps({"qasm": q, "shots": 1000}))' > "$tmp/grover.json"
|
|
run "$tmp/grover.json" "$tmp/grover.out"
|
|
py 'import json,sys
|
|
d=json.load(open(sys.argv[1])); r=d["result"]
|
|
hits=r["counts"].get("10110", 0)
|
|
assert d["status"]=="done" and hits > 980, d
|
|
print("grover-5 (ctrl modifiers): ok,", r["method"], hits, "of 1000 on the marked item")' "$tmp/grover.out"
|
|
|
|
# A program that measures in the middle and acts on what it read: teleportation
|
|
# delivers ry(0.7)|0⟩ to q[2], so ⟨Z2⟩ = cos 0.7 and ⟨X2⟩ = sin 0.7 exactly.
|
|
py 'import json; print(json.dumps({"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": 2000}))' > "$tmp/tele.json"
|
|
run "$tmp/tele.json" "$tmp/tele.out"
|
|
py 'import json,math,sys
|
|
d=json.load(open(sys.argv[1])); r=d["result"]; e=[x["value"] for x in r["expectations"]]
|
|
assert d["status"]=="done" and abs(e[0]-math.cos(0.7))<1e-12 and abs(e[1]-math.sin(0.7))<1e-12, d
|
|
assert r["dynamic"]["branches_weighed"]==4 and sum(r["counts"].values())==2000, r
|
|
print("teleport (mid-circuit measurement, if): ok,", r["method"], e)' "$tmp/tele.out"
|
|
|
|
# A Clifford circuit on 60 qubits, then T and H on each: past the state
|
|
# vector, and not Clifford, so auto samples it exactly by cut-rank. Its graph
|
|
# (a ring with chords of length 5) keeps every cut narrow.
|
|
py 'import json
|
|
n=60; q="OPENQASM 3.0; qubit[%d] q; bit[%d] c; h q;" % (n, n)
|
|
q+="".join(" cz q[%d], q[%d]; cz q[%d], q[%d];" % (i, (i+1)%n, i, (i+5)%n) for i in range(n))
|
|
q+="".join(" t q[%d]; h q[%d];" % (i, i) for i in range(n)) + " c = measure q;"
|
|
print(json.dumps({"qasm": q, "shots": 100, "seed": 3}))' > "$tmp/cut.json"
|
|
run "$tmp/cut.json" "$tmp/cut.out"
|
|
py 'import json,sys
|
|
d=json.load(open(sys.argv[1])); r=d["result"]
|
|
assert d["status"]=="done" and r["method"]=="cutrank" and sum(r["counts"].values())==100, d
|
|
assert r["accuracy"]["class"]=="exact" and r["accuracy"]["max_cut"]<=12, r["accuracy"]
|
|
print("cutrank (60 qubits, Clifford then T and H): ok, max cut", r["accuracy"]["max_cut"], "bits,", r["distinct_outcomes"], "distinct outcomes")' "$tmp/cut.out"
|
|
|
|
# A refusal says why.
|
|
py 'import json; print(json.dumps({"qasm": "qubit[1] q; bit c; c = measure q; while (c) { x q; c = measure q; }"}))' > "$tmp/bad.json"
|
|
code=$(curl -sS -o "$tmp/bad.out" -w '%{http_code}' -X POST "$U/v1/jobs" -H 'content-type: application/json' --data-binary "@$tmp/bad.json")
|
|
[ "$code" = 400 ] || { echo "a bad program got HTTP $code"; exit 1; }
|
|
py 'import json,sys; d=json.load(open(sys.argv[1])); assert "not supported" in d["error"], d; print("refusal: ok,", d["error"])' "$tmp/bad.out"
|
|
|
|
# The design checks answer at once: a critique, an improvement checked the same
|
|
# circuit, the equivalence check, the classical shortcuts, and a thorough search
|
|
# sent to the command line.
|
|
py 'import json; print(json.dumps({"qasm": "OPENQASM 3.0;\nqubit[2] q;\nh q[0];\nh q[0];\ncx q[0], q[1];\n"}))' > "$tmp/design.json"
|
|
post /v1/critique "$tmp/design.json" > "$tmp/critique.out"
|
|
py 'import json,sys; d=json.load(open(sys.argv[1])); assert d["ok"] and d["gates"]==3 and d["smells"][0]["kind"]=="cancels" and d["smells"][0]["lines"]==[3,4], d; print("critique: ok,", d["smells"][0]["message"])' "$tmp/critique.out"
|
|
post /v1/improve "$tmp/design.json" > "$tmp/improve.out"
|
|
py 'import json,sys; c=json.load(open(sys.argv[1]))["candidates"][0]; assert c["measures"]["gates"]==1 and c["equivalence"]["verdict"]=="equivalent", c; print("improve: ok,", c["equivalence"]["how"])' "$tmp/improve.out"
|
|
py 'import json; print(json.dumps({"a": "OPENQASM 3.0;\nqubit[2] q;\nh q[0];\nh q[0];\ncx q[0], q[1];\n", "b": "OPENQASM 3.0;\nqubit[2] q;\ncx q[0], q[1];\n"}))' > "$tmp/pair.json"
|
|
post /v1/equivalent "$tmp/pair.json" > "$tmp/equivalent.out"
|
|
py 'import json,sys; d=json.load(open(sys.argv[1])); assert d["verdict"]=="equivalent" and d["how"]=="tableau", d; print("equivalent: ok, by tableau")' "$tmp/equivalent.out"
|
|
post /v1/shortcuts "$tmp/design.json" > "$tmp/shortcuts.out"
|
|
py 'import json,sys; d=json.load(open(sys.argv[1])); assert d["summary"].startswith("Classically easy at any width"), d; print("shortcuts: ok,", d["summary"][:40] + "…")' "$tmp/shortcuts.out"
|
|
py 'import json; print(json.dumps({"qasm": "qubit[1] q;", "thorough": True}))' > "$tmp/thorough.json"
|
|
code=$(curl -sS -o "$tmp/thorough.out" -w '%{http_code}' -X POST "$U/v1/shortcuts" -H 'content-type: application/json' --data-binary "@$tmp/thorough.json")
|
|
[ "$code" = 422 ] || { echo "a thorough search got HTTP $code"; exit 1; }
|
|
py 'import json,sys; d=json.load(open(sys.argv[1])); assert "wai-quantum shortcuts --thorough" in d["error"], d; print("thorough: ok, sent to the command line")' "$tmp/thorough.out"
|
|
|
|
echo "smoke: every check held at $U"
|