open-standards/wai/quantum-cross-simulator/tools/corpus.py
Transaction Science c16cb20861
Some checks failed
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 6s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (pull_request) Successful in 6s
WAI conformance / does this change touch it (pull_request) Successful in 6s
WAI energy receipts / does this change touch it (pull_request) Successful in 8s
WAI examples / WAI examples · does this change touch them (pull_request) Successful in 5s
wai-quantum command line / does this change touch it (pull_request) Successful in 5s
wai-quantum contract / 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 dataflow member / does this change touch it (pull_request) Successful in 6s
wai-audit collector and player integration / does this change touch it (pull_request) Successful in 38s
WAI operation catalogue / does this change touch it (pull_request) Successful in 30s
wai-quantum docs, course and locales / does this change touch it (pull_request) Successful in 6s
wai-quantum editors / does this change touch it (pull_request) Successful in 7s
wai-quantum signal processor / does this change touch it (pull_request) Successful in 8s
wai-quantum FPGA member / does this change touch it (pull_request) Successful in 8s
wai-quantum HIP member / does this change touch it (pull_request) Successful in 9s
wai-quantum for JavaScript / does this change touch it (pull_request) Successful in 10s
wai-quantum OpenQASM reader / 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 npu-cores member / does this change touch it (pull_request) Successful in 6s
wai-quantum neural-processor member / does this change touch it (pull_request) Successful in 6s
wai-quantum OpenCL member / does this change touch it (pull_request) Successful in 6s
wai-quantum resource estimation / does this change touch it (pull_request) Successful in 43s
wai-quantum other formats / does this change touch it (pull_request) Successful in 42s
wai-quantum on every processor / emulated · aarch64-unknown-linux-gnu (pull_request) Failing after 48s
wai-quantum pulse and dynamics / does this change touch it (pull_request) Successful in 5s
wai-quantum for Python / does this change touch it (pull_request) Successful in 6s
wai-quantum error correction and mitigation / does this change touch it (pull_request) Successful in 6s
wai-quantum-qpu / does this change touch it (pull_request) Successful in 6s
wai-quantum extension points / does this change touch it (pull_request) Successful in 6s
wai-quantum on every processor / emulated · loongarch64-unknown-linux-gnu (pull_request) Failing after 2m1s
wai-quantum service / does this change touch it (pull_request) Successful in 5s
wai-quantum on every processor / emulated · i686-unknown-linux-gnu (pull_request) Failing after 1m11s
WAI conformance / fast integer kernels, every x86_64 kernel set (AVX-512 silicon) (pull_request) Successful in 2m54s
wai-quantum matrix-extension member / does this change touch it (pull_request) Successful in 10s
wai-quantum tensor-engine member / does this change touch it (pull_request) Successful in 9s
wai-quantum studio and desktop / does this change touch it (pull_request) Successful in 11s
wai-quantum portable tensor program / does this change touch it (pull_request) Successful in 11s
wai-quantum variational and algorithm library / does this change touch it (pull_request) Successful in 6s
wai-quantum on every processor / emulated · s390x-unknown-linux-gnu (pull_request) Failing after 1m49s
wai-quantum CPU vector units / does this change touch it (pull_request) Successful in 5s
wai-quantum verdicts and repairs / does this change touch it (pull_request) Successful in 6s
wai-quantum views in agent hosts / does this change touch it (pull_request) Successful in 5s
wai-quantum WebGPU member / does this change touch it (pull_request) Successful in 5s
wai-sink-android native sink library / does this change touch it (pull_request) Successful in 6s
wai-sink-swift native sink package / does this change touch it (pull_request) Successful in 6s
WAI Studio / does this change touch it (pull_request) Successful in 8s
wai-web reach builds / wai-web reach · does this change touch it (pull_request) Successful in 6s
wai-web wasm32 / does this change touch it (pull_request) Successful in 8s
wai-quantum HIP member / member · HIP (framework-128gb) (pull_request) Successful in 58s
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 23s
wai-quantum portable tensor program / tensor program · integrated GPU (framework-128gb) (pull_request) Successful in 12s
wai-quantum CPU vector units / member · vector units, avx2 and avx512 (framework-128gb silicon) (pull_request) Successful in 17s
wai-quantum on every processor / emulated · powerpc64le-unknown-linux-gnu (pull_request) Failing after 5m30s
wai-quantum on every processor / emulated · powerpc64-unknown-linux-gnu (pull_request) Successful in 6m17s
wai-quantum on every processor / emulated · armv7-unknown-linux-gnueabihf (pull_request) Successful in 8m54s
wai-quantum on every processor / emulated · riscv64gc-unknown-linux-gnu (pull_request) Successful in 12m57s
wai-quantum WebGPU member / member · integrated GPU, Vulkan (framework-128gb) (pull_request) Successful in 8m5s
wai-quantum on every processor / emulated · sparc64-unknown-linux-gnu (pull_request) Successful in 21m43s
wai-quantum WebGPU member / member · DX12 and Vulkan (cbio-windows) (pull_request) Successful in 12m47s
wai-quantum CUDA member / member · CUDA (thor) (pull_request) Successful in 3m36s
wai-quantum OpenCL member / member · OpenCL GPU and CPU (thor) (pull_request) Successful in 2m34s
wai-quantum WebGPU member / member · GPU, Vulkan (thor) (pull_request) Successful in 25m6s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 56s
WAI conformance / codec wrappers · fuzz smoke, text decode limits, C entry points, provenance, the semantic path (pull_request) Successful in 2m25s
wai-quantum command line / command line · macos (pull_request) Failing after 1m7s
wai-quantum dataflow member / member · dataflow device absent (macos) (pull_request) Successful in 16s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 7m16s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (pull_request) Successful in 1m37s
wai-quantum editors / editors · macos (pull_request) Successful in 1m28s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 12m29s
wai-quantum contract / the policy is linked, and the deprecations page reads (pull_request) Successful in 12s
wai-quantum Metal member / member · Metal (macos) (pull_request) Successful in 1m5s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 56s
wai-quantum OpenCL member / member · OpenCL GPU (macos) (pull_request) Successful in 36s
wai-quantum FPGA member / member · FPGA datapath, simulated (macos) (pull_request) Successful in 1m41s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (pull_request) Failing after 4m19s
wai-quantum pulse and dynamics / the same bits · macos (pull_request) Successful in 1m12s
WAI conformance / faces from keypoints under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m27s
wai-audit collector and player integration / collector · linux (pull_request) Successful in 1m23s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (pull_request) Successful in 3m41s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:401e) (pull_request) Successful in 4m7s
wai-quantum command line / command line · linux (pull_request) Failing after 3m29s
wai-quantum dataflow member / member · dataflow device, simulated (pci 1e52:b140) (pull_request) Successful in 4m43s
wai-quantum neural-processor member / member · neural processor (macos) (pull_request) Successful in 4m55s
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 3m55s
wai-quantum contract / API compatibility · linux (pull_request) Failing after 4m26s
wai-quantum CUDA member / member · CUDA absent (linux) (pull_request) Successful in 3m2s
WAI conformance / cargo-class corpora · macos (pull_request) Failing after 18m11s
wai-quantum-qpu / credentials in the keychain (macos) (pull_request) Successful in 3m42s
WAI operation catalogue / the catalogue and every door · linux (pull_request) Successful in 7m58s
wai-quantum for Python / python · macos (pull_request) Successful in 4m48s
wai-quantum matrix-extension member / member · matrix extension absent (macos) (pull_request) Successful in 30s
wai-quantum editors / editors · linux (pull_request) Successful in 2m32s
wai-quantum FPGA member / member · FPGA simulation absent (linux) (pull_request) Successful in 47s
wai-quantum contract / schemas and the committed tool lists · linux (pull_request) Failing after 4m35s
wai-quantum docs, course and locales / the course and the command line's languages · linux (pull_request) Successful in 3m54s
wai-quantum OpenQASM reader / corpus under wasm32-wasip2 (wasmtime) (pull_request) Successful in 2m59s
wai-quantum Metal member / member · Metal absent (linux) (pull_request) Successful in 3m8s
wai-quantum OpenCL member / member · OpenCL absent (linux) (pull_request) Successful in 2m50s
wai-quantum other formats / the set under wasm32-wasip2 (wasmtime) (pull_request) Successful in 4m39s
wai-quantum pulse and dynamics / reader, simulator and pulse jobs under wasm32-wasip2 (wasmtime) (pull_request) Successful in 1m59s
wai-quantum docs, course and locales / the Studio's words in every locale · linux (pull_request) Successful in 1m9s
wai-quantum neural-processor member / member · neural processor absent (linux) (pull_request) Successful in 3m43s
wai-quantum resource estimation / estimation and calibration · linux, release (pull_request) Successful in 4m17s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 22m1s
wai-quantum OpenQASM reader / reader and corpus · linux (pull_request) Successful in 4m41s
wai-quantum for JavaScript / javascript · linux (pull_request) Successful in 4m53s
wai-quantum CPU vector units / member · vector unit absent (macos) (pull_request) Successful in 43s
wai-quantum service / service · macos (pull_request) Failing after 4m58s
wai-quantum portable tensor program / tensor program · Metal and the arm64 CPU (macos) (pull_request) Successful in 50s
wai-quantum studio and desktop / desktop app · macos (pull_request) Successful in 5m49s
wai-quantum other formats / readers, writers and the set · linux (pull_request) Successful in 5m54s
wai-quantum for Python / python · linux (pull_request) Successful in 5m10s
wai-quantum matrix-extension member / member · matrix extension, emulated (aarch64 Linux) (pull_request) Failing after 4m14s
wai-quantum WebGPU member / member · browser WebGPU (macos) (pull_request) Successful in 4m29s
wai-quantum studio and desktop / desktop app · windows (pull_request) Successful in 10m4s
wai-quantum extension points / the registry under wasm32-wasip2 (wasmtime) (pull_request) Successful in 3m37s
wai-quantum WebGPU member / member · Metal (macos) (pull_request) Successful in 5m11s
wai-quantum extension points / the registry and the example · linux (pull_request) Successful in 5m3s
wai-quantum-qpu / clients against their contracts (linux) (pull_request) Successful in 3m9s
wai-quantum CPU vector units / member · vector unit, rvv 1024-bit (riscv64, emulated) (pull_request) Successful in 1m28s
wai-quantum error correction and mitigation / codes, decoders, texts and mitigation · linux, release (pull_request) Successful in 6m5s
wai-quantum signal processor / processor and member · signal processor, emulated (pull_request) Failing after 12m19s
wai-quantum CPU vector units / member · vector unit, sve 128-bit (aarch64, emulated) (pull_request) Successful in 3m41s
wai-quantum portable tensor program / tensor program · CPU, mutants, GPU builds (pull_request) Successful in 5m20s
wai-quantum service / service · linux (pull_request) Failing after 6m17s
wai-quantum CPU vector units / member · vector unit, sve 2048-bit (aarch64, emulated) (pull_request) Successful in 3m13s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (pull_request) Successful in 19m17s
wai-quantum CPU vector units / member · vector unit, rvv 128-bit (riscv64, emulated) (pull_request) Failing after 3m54s
wai-quantum CPU vector units / member · vector unit, avx2 (x86_64 silicon) (pull_request) Successful in 41s
wai-quantum CPU vector units / member · vector unit, sve 512-bit (aarch64, emulated) (pull_request) Failing after 1m1s
wai-quantum verdicts and repairs / the intent set and the verdict under wasm32-wasip2 (wasmtime) (pull_request) Successful in 1m57s
wai-quantum studio and desktop / desktop app · linux (pull_request) Successful in 7m49s
wai-quantum studio and desktop / studio · browser (pull_request) Successful in 5m47s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 19m30s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (pull_request) Successful in 9m13s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Successful in 2m51s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux, release (pull_request) Successful in 9m37s
wai-quantum views in agent hosts / views · the page and its engine (pull_request) Successful in 4m27s
wai-quantum tensor-engine member / member · tensor engine, the kernel toolchain's simulator (linux) (pull_request) Successful in 11m26s
wai-quantum views in agent hosts / views · a scripted host (pull_request) Successful in 5m13s
wai-web reach builds / wai-web reach builds · this tree's wai-web, every rung on its engine line (pull_request) Successful in 5m12s
wai-web reach builds / wai-web reach builds · the package of record, every output as recorded (pull_request) Successful in 4m15s
wai-quantum WebGPU member / shader checks · browser build · wasip2 inertness (pull_request) Successful in 5m6s
wai-quantum pulse and dynamics / reader, simulator and pulse jobs · linux, release (pull_request) Successful in 5m23s
wai-quantum verdicts and repairs / verdicts, repairs and the intent set · linux (pull_request) Successful in 7m41s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 29m7s
wai-quantum WebGPU member / member · software Vulkan (linux) (pull_request) Successful in 9m13s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 8m59s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (pull_request) Successful in 16m58s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 17m28s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 15m32s
WAI conformance / cargo-class corpora · linux (pull_request) Failing after 59m54s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 2m29s
wai-quantum CUDA member / member · CUDA (jetson-hub) (pull_request) Successful in 1m45s
wai-quantum OpenCL member / member · OpenCL GPU and CPU (jetson-hub) (pull_request) Successful in 39s
wai-quantum service / service energy · linux packages (pull_request) Successful in 1m36s
wai-quantum portable tensor program / tensor program · GPUs (jetson-hub) (pull_request) Successful in 24s
wai-quantum WebGPU member / member · GPU, Vulkan (jetson-hub) (pull_request) Successful in 22m23s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 1m6s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 5m20s
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Successful in 15s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 46s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 2m46s
WAI conformance / each feature of the independent verifiers' steps compiles alone (pull_request) Successful in 17m54s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 25m59s
wai-quantum HIP member / member · HIP absent (linux-arm64) (pull_request) Successful in 1m27s
wai-quantum npu-cores member / member · npu-cores absent (linux-arm64) (pull_request) Successful in 41s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 8m10s
wai-quantum pulse and dynamics / the same bits · linux-arm64 (pull_request) Successful in 2m6s
wai-quantum tensor-engine member / member · tensor engine absent (linux-arm64) (pull_request) Successful in 32s
wai-quantum extension points / the registry and the example · linux-arm64 (pull_request) Successful in 3m20s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux-arm64, release (pull_request) Successful in 2m29s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (pull_request) Successful in 4m32s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 31m52s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 1h37m18s
Merge the corpus branch's results and page, with this branch's comparison and timings
The comparison rerun on this branch's engine (commit d4282f680; each file
names its trees):

- macOS arm64 (M3 Ultra): 1743 pass, 0 fail; 11 known, 10 refused as
  listed, 12 not run, 12 recorded.
- Linux x86_64 (Ryzen AI Max+ 395): 1738 pass, 0 fail; 11 known, 10
  refused as listed, 14 not run, 12 recorded.
- The colour code, a correlated error and a general Pauli channel match the
  other engine mechanism by mechanism, and their rates; a Pauli channel with
  no independent form is refused, as listed. The bit-exact method meets its
  bound against OpenQASM's state with the phase its result states, on every
  circuit. The 30-qubit QFT at max_bond 256 runs, exact.

Timings on both hosts, and before-after-macos-arm64.json: the same harness
on the corpus branch's build, then this branch's, on the M3 Ultra.

The page says what the results now state, and the hand-written Pauli
channel's reason is corrected: the other engine does give its model (only
the reason text changed after the runs, so the tools and corpus trees they name differ
from this commit's by that description).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 09:14:43 -05:00

635 lines
37 KiB
Python

#!/usr/bin/env python3
"""The corpus: every circuit, its parameters, why it is here and what it must give.
Standard library only. Every circuit comes out of this file the same on every machine: random
circuits draw from SHA-256 in counter mode, not from a library's generator, and angles are
written exactly (see `exact.parse_angle`). `corpus/manifest.json` pins each circuit's digest, so
a change to any circuit shows as a change to the manifest.
A step is a gate {"g": name, "q": [qubits], "a": [angles]}, or {"measure": q, "bit": c},
{"reset": q}, or {"if": [c, v], "then": [gates]}. Gate names are those of OpenQASM 3's standard
library, and `exact.prims` says what each means.
An entry's `expect` says what it is held to:
exact_state the integer state vector (exact.py) of the circuit
known_state a state stated in closed form, which exact.py also reproduces
distribution the exact distribution of its classical bits (exact.py walks every branch)
stabilizer the stabilizer group, from the integer tableau (exact.py) and every engine
amplitudes chosen amplitudes in closed form, for circuits too wide for any state vector
pairwise no exact reference at this width: the engines against each other
expectation an expectation value under noise, in closed form
qec a noisy Clifford circuit's detector error model and detection rates
"""
import functools
import hashlib
import json
import os
import sys
from fractions import Fraction
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import exact # noqa: E402
class Stream:
"""Integers from SHA-256 in counter mode: the same on every machine and every version."""
def __init__(self, label):
self.label = label.encode()
self.counter = 0
self.pool = b""
def _more(self):
self.pool += hashlib.sha256(self.label + b"/" + str(self.counter).encode()).digest()
self.counter += 1
def below(self, n):
"""Uniform in 0..n-1, by rejection."""
bits = max(n - 1, 1).bit_length()
size = (bits + 7) // 8
mask = (1 << bits) - 1
while True:
while len(self.pool) < size:
self._more()
v = int.from_bytes(self.pool[:size], "big") & mask
self.pool = self.pool[size:]
if v < n:
return v
def choice(self, xs):
return xs[self.below(len(xs))]
def g(name, *qubits, a=None):
s = {"g": name, "q": list(qubits)}
if a:
s["a"] = list(a)
return s
def t(m, k):
"""m/2^k of a full turn."""
return "t:%d/%d" % (m, k)
# ------------------------------------------------------------------ programs as text
def qasm_angle(a):
kind, v = exact.parse_angle(a)
if kind == "r":
return a[2:]
f = v * 2
n, d = f.numerator, f.denominator
if n == 0:
return "0"
sign = "-" if n < 0 else ""
n = abs(n)
if n == 1 and d == 1:
return sign + "pi"
if d == 1:
return "%spi*%d" % (sign, n)
if n == 1:
return "%spi/%d" % (sign, d)
return "%spi*%d/%d" % (sign, n, d)
# The standard library's names, and the modifiers for the rest.
_PLAIN = {"id", "x", "y", "z", "h", "s", "sdg", "t", "tdg", "sx", "p", "rz", "rx", "ry", "cx", "cy", "cz", "ch", "cp", "crx", "cry", "crz", "cu", "swap", "cswap", "ccx"}
_DEFS = {
"rzz": "gate rzz(theta) a, b { cx a, b; rz(theta) b; cx a, b; }",
"rxx": "gate rxx(theta) a, b { h a; h b; cx a, b; rz(theta) b; cx a, b; h a; h b; }",
"ryy": "gate ryy(theta) a, b { rx(pi/2) a; rx(pi/2) b; cx a, b; rz(theta) b; cx a, b; rx(-pi/2) a; rx(-pi/2) b; }",
}
def _gate_text(s):
name, qs, args = s["g"], s["q"], s.get("a", [])
params = "(" + ", ".join(qasm_angle(x) for x in args) + ")" if args else ""
q = ", ".join("q[%d]" % x for x in qs)
if name in _PLAIN or name in _DEFS:
return "%s%s %s;" % (name, params, q)
if name == "u":
return "U%s %s;" % (params, q)
if name == "sxdg":
return "inv @ sx %s;" % q
if name == "gphase":
if qs:
return "ctrl(%d) @ gphase%s %s;" % (len(qs), params, q)
return "gphase%s;" % params
if name == "negcx":
return "negctrl @ x %s;" % q
form = exact.controlled_form(name)
if form:
base, k = form
return "ctrl(%d) @ %s%s %s;" % (k, base, params, q)
raise ValueError("no text for gate %s" % name)
def qasm_of(entry):
"""The entry's program as OpenQASM 3: the text the engine reads and the text published."""
out = ["OPENQASM 3.0;", 'include "stdgates.inc";']
names = set()
for s in entry["steps"]:
for x in s.get("then", [s]):
if "g" in x:
names.add(x["g"])
for name in sorted(names):
if name in _DEFS:
out.append(_DEFS[name])
out.append("qubit[%d] q;" % entry["n"])
if entry.get("bits"):
out.append("bit[%d] c;" % entry["bits"])
for s in entry["steps"]:
if "g" in s:
out.append(_gate_text(s))
elif "measure" in s:
out.append("c[%d] = measure q[%d];" % (s["bit"], s["measure"]))
elif "reset" in s:
out.append("reset q[%d];" % s["reset"])
elif "if" in s:
body = " ".join(_gate_text(x) for x in s["then"])
out.append("if (c[%d] == %d) { %s }" % (s["if"][0], s["if"][1], body))
return "\n".join(out) + "\n"
# ------------------------------------------------------------------ circuit builders
def qft_steps(n):
"""The QFT with qubit 0 the lowest bit of the index: |x> to 2^(-n/2) Σ e^{2πi xy/2^n} |y>."""
steps = []
for j in range(n - 1, -1, -1):
steps.append(g("h", j))
for k in range(j - 1, -1, -1):
steps.append(g("cp", k, j, a=[t(1, j - k + 1)]))
for i in range(n // 2):
steps.append(g("swap", i, n - 1 - i))
return steps
def inverse_steps(steps):
out = []
dag = {"h": "h", "x": "x", "y": "y", "z": "z", "s": "sdg", "sdg": "s", "t": "tdg", "tdg": "t", "cx": "cx", "cy": "cy", "cz": "cz", "swap": "swap", "sx": "sxdg", "sxdg": "sx", "ccx": "ccx"}
for s in reversed(steps):
name = s["g"]
if name in dag:
out.append({"g": dag[name], "q": s["q"]})
elif name in ("p", "rz", "rx", "ry", "cp", "crz", "crx", "cry", "rzz", "rxx", "ryy"):
out.append({"g": name, "q": s["q"], "a": [exact._neg(s["a"][0])]})
else:
raise ValueError("no inverse for %s" % name)
return out
def basis_prep(n, x):
return [g("x", q) for q in range(n) if (x >> q) & 1]
def grover_steps(n, marked, iterations):
steps = [g("h", q) for q in range(n)]
all_q = list(range(n))
cz = "c%dz" % (n - 1) if n > 3 else {2: "cz", 3: "ccz"}.get(n, "z")
for _ in range(iterations):
flip = [g("x", q) for q in range(n) if not (marked >> q) & 1]
steps += flip + [{"g": cz, "q": all_q}] + flip
steps += [g("h", q) for q in range(n)] + [g("x", q) for q in range(n)]
steps += [{"g": cz, "q": all_q}]
steps += [g("x", q) for q in range(n)] + [g("h", q) for q in range(n)]
return steps
def qpe_steps(bits, phase_turns):
"""Phase estimation of the eigenvalue e^{2πi φ} of p(2πφ) on qubit `bits`, prepared in |1>.
Counting qubits 0..bits-1; the outcome y estimates φ = y/2^bits, read as an integer."""
num, den = phase_turns
steps = [g("x", bits)] + [g("h", q) for q in range(bits)]
for j in range(bits):
# 2^j applications of the unitary, as one controlled phase.
m = (num * (1 << j)) % den
angle = "q:%d/%d" % (m, den) if den & (den - 1) else t(m, den.bit_length() - 1)
steps.append(g("cp", j, bits, a=[angle]))
steps += inverse_steps_qft(bits)
return steps
def inverse_steps_qft(n):
return inverse_steps(qft_steps(n))
def random_clifford_t(n, depth, seed, gateset=("h", "s", "t", "sdg", "tdg", "x")):
r = Stream("clifford_t/%d/%d/%d" % (n, depth, seed))
steps = []
for _ in range(depth):
for q in range(n):
if r.below(3):
steps.append(g(r.choice(gateset), q))
order = list(range(n))
for i in range(n - 1, 0, -1):
j = r.below(i + 1)
order[i], order[j] = order[j], order[i]
for i in range(0, n - 1, 2):
steps.append(g(r.choice(("cx", "cz")), order[i], order[i + 1]))
return steps
def random_clifford(n, depth, seed):
return random_clifford_t(n, depth, seed, gateset=("h", "s", "sdg", "x", "y", "z", "sx"))
def random_dyadic(n, depth, seed, k):
r = Stream("dyadic/%d/%d/%d/%d" % (n, depth, seed, k))
steps = []
for layer in range(depth):
for q in range(n):
steps.append(g(r.choice(("rx", "ry", "rz")), q, a=[t(r.below(1 << k), k)]))
for q in range(layer % 2, n - 1, 2):
steps.append(g("cz", q, q + 1))
return steps
def random_rotations(n, depth, seed):
"""U gates whose angles are decimal radians, no dyadic among them, on a brickwork of cx."""
r = Stream("rotations/%d/%d/%d" % (n, depth, seed))
def angle():
return "r:%d.%017d" % (r.below(3), r.below(10**17))
steps = []
for layer in range(depth):
for q in range(n):
steps.append(g("u", q, a=[angle(), angle(), angle()]))
for q in range(layer % 2, n - 1, 2):
steps.append(g("cx", q, q + 1))
return steps
def ghz_steps(n):
return [g("h", 0)] + [g("cx", q, q + 1) for q in range(n - 1)]
def distinct_product(n):
"""A product state whose every amplitude differs: any exchange of qubits shows."""
steps = []
for q in range(n):
steps.append(g("ry", q, a=[t(1, q + 4)]))
steps.append(g("rz", q, a=[t(3, q + 6)]))
return steps
def measure_all(n):
return [{"measure": q, "bit": q} for q in range(n)]
# ------------------------------------------------------------------ the entries
def entries():
out = []
def add(id_, family, params, reason, n, steps, expect, tier="full", bits=0, engines=None, shots=0, **extra):
e = {"id": id_, "family": family, "params": params, "reason": reason, "n": n, "bits": bits, "steps": steps, "expect": expect, "tier": tier, "shots": shots}
if engines:
e["engines"] = engines
e.update(extra)
out.append(e)
# Bit order.
add("bit_order_x_low", "bit_order", {"n": 5}, "An X on qubit 0 must read as index 1, the first thing that differs between engines' conventions.", 5, [g("x", 0)], "exact_state", tier="ci")
add("bit_order_x_high", "bit_order", {"n": 5}, "The other end of the same convention: an X on the highest qubit is index 16.", 5, [g("x", 4)], "exact_state")
add("bit_order_product", "bit_order", {"n": 6}, "Every amplitude differs, so any exchange of two qubits changes the state.", 6, distinct_product(6), "exact_state", tier="ci")
add("bit_order_control", "bit_order", {"n": 4}, "A cx from qubit 0 to qubit 3: the control and target must not swap roles.", 4, [g("x", 0), g("cx", 0, 3)], "exact_state")
add("bit_order_named_bits", "bit_order", {"n": 2}, "Classical bits named out of order: qubit 1 into bit 0. The counts must follow the bits, not the qubits.", 2, [g("x", 1), {"measure": 1, "bit": 0}, {"measure": 0, "bit": 1}], "distribution", bits=2, shots=4000, tier="ci")
add("empty_register", "bit_order", {"n": 3}, "A program of no gates: the state is |000>.", 3, [], "exact_state")
add("one_qubit", "bit_order", {"n": 1}, "The smallest register.", 1, [g("h", 0)], "exact_state")
add("top_index_n20", "bit_order", {"n": 20}, "An index at bit 19: index arithmetic past 16 bits, with no entanglement to hide it.", 20, [g("x", 19), g("h", 18)], "pairwise", tier="ci")
# GHZ.
for n in (2, 3, 5, 8, 12):
add("ghz_n%d" % n, "ghz", {"n": n}, "Known answer: two amplitudes of 1/sqrt(2), every other zero. It exposes any leakage out of those two.", n, ghz_steps(n), "known_state", tier="ci" if n == 3 else "full")
add("ghz_counts_n8", "ghz", {"n": 8}, "Sampling: only the two outcomes may appear, equally often.", 8, ghz_steps(8) + measure_all(8), "distribution", bits=8, shots=100000)
# QFT.
for n, x in ((3, 5), (5, 19), (8, 173), (12, 2741), (14, 10923)):
add("qft_n%d_x%d" % (n, x), "qft", {"n": n, "x": x}, "Closed form e^{2πi xy/2^n}/2^(n/2), and every controlled phase up to 2π/2^n: the rotations a fixed-point table holds least well.", n, basis_prep(n, x) + qft_steps(n), "known_state", tier="ci" if n == 5 else "full", qft_x=x)
add("qft_superposed_n10", "qft", {"n": 10, "seed": 11}, "A QFT over a random Clifford+T state: its phases act on every amplitude, where from a basis state most cancel.", 10, random_clifford_t(10, 4, 11) + qft_steps(10), "exact_state")
add("qft_counts_n8", "qft", {"n": 8, "x": 173}, "Sampling a uniform distribution of 256 outcomes.", 8, basis_prep(8, 173) + qft_steps(8) + measure_all(8), "distribution", bits=8, shots=200000)
add("qft_wide_n20", "qft", {"n": 20, "x": 699051}, "Past any integer reference here: engines against each other, and chosen amplitudes against the closed form.", 20, basis_prep(20, 699051) + qft_steps(20), "pairwise", qft_x=699051)
# Grover.
for n, marked, it in ((3, 5, 2), (5, 19, 4), (8, 173, 12), (10, 683, 25)):
add("grover_n%d" % n, "grover", {"n": n, "marked": marked, "iterations": it}, "Closed form: the marked state's probability is sin²((2k+1)θ) with sin θ = 2^(-n/2). Multi-controlled gates, and interference that rounding drains.", n, grover_steps(n, marked, it), "exact_state", tier="ci" if n == 3 else "full", grover=[marked, it])
add("grover_counts_n5", "grover", {"n": 5, "marked": 19, "iterations": 4}, "Sampling a peaked distribution.", 5, grover_steps(5, 19, 4) + measure_all(5), "distribution", bits=5, shots=100000)
# Phase estimation.
for bits, m in ((4, 5), (8, 173), (12, 2741)):
add("qpe_t%d_m%d" % (bits, m), "qpe", {"bits": bits, "phase": "%d/2^%d" % (m, bits)}, "A phase of exactly m/2^t: the outcome is m with probability 1, so every other amplitude must cancel to zero.", bits + 1, qpe_steps(bits, (m, 1 << bits)), "exact_state", tier="ci" if bits == 4 else "full", qpe=[m, bits])
for bits in (6, 10):
add("qpe_t%d_third" % bits, "qpe", {"bits": bits, "phase": "1/3"}, "A phase that is no dyadic: the outcome's law is the closed form sin²(π2^t δ)/(2^(2t) sin²(πδ)), and the bit-exact method must refuse it rather than round it.", bits + 1, qpe_steps(bits, (1, 3)), "exact_state", qpe_third=bits)
# Random circuits.
for n, depth, seed in ((4, 20, 1), (8, 40, 2), (12, 40, 3)):
add("clifford_t_n%d_d%d" % (n, depth), "random_clifford_t", {"n": n, "depth": depth, "seed": seed}, "Universal, in the gates the bit-exact method holds as table constants.", n, random_clifford_t(n, depth, seed), "exact_state", tier="ci" if n == 4 else "full")
for n, depth, seed, k in ((6, 20, 4, 16), (10, 30, 5, 32)):
add("dyadic_n%d_k%d" % (n, depth), "random_dyadic", {"n": n, "depth": depth, "seed": seed, "k": k}, "Rotations by m/2^k of a turn: each is many table phases in fixed point, so its error is largest here.", n, random_dyadic(n, depth, seed, k), "exact_state", tier="ci" if n == 6 else "full")
for n, depth, seed in ((6, 20, 6), (10, 30, 7), (12, 40, 8)):
add("rotations_n%d" % n, "random_rotations", {"n": n, "depth": depth, "seed": seed}, "Arbitrary decimal angles: double-precision engines only, and the bit-exact method must refuse.", n, random_rotations(n, depth, seed), "exact_state", tier="ci" if n == 6 else "full")
add("rotations_counts_n6", "random_rotations", {"n": 6, "depth": 20, "seed": 6}, "Sampling a distribution with no structure.", 6, random_rotations(6, 20, 6) + measure_all(6), "distribution", bits=6, shots=200000)
add("rotations_wide_n20", "random_rotations", {"n": 20, "depth": 10, "seed": 9}, "No integer reference at this width: engines against each other, with fusion and threads in play.", 20, random_rotations(20, 10, 9), "pairwise")
# Mirror circuits: known answer, any width.
for n, depth, seed in ((10, 40, 21), (16, 30, 22), (20, 20, 23)):
forward = random_dyadic(n, depth, seed, 16)
add("mirror_n%d" % n, "mirror", {"n": n, "depth": depth, "seed": seed}, "U then its inverse: the state is |0…0> exactly, at a width no integer reference reaches, and what remains is the engine's accumulated rounding.", n, forward + inverse_steps(forward), "mirror", tier="ci" if n == 10 else "full")
# Small angles.
for k in (8, 16, 24, 26, 28, 30, 32):
add("small_angle_k%d" % k, "small_angle", {"k": k}, "h, p(2π/2^k), h: P(1) = sin²(π/2^k). Within the phase table, and at its resolution floor as k nears 32.", 1, [g("h", 0), g("p", 0, a=[t(1, k)]), g("h", 0)], "exact_state", tier="ci" if k == 32 else "full", probe=1)
for k in (33, 40, 47, 48, 52, 60):
add("below_grid_k%d" % k, "small_angle", {"k": k}, "An angle below the table's last entry: the bit-exact method refuses it, or reads it as nothing when it is within its reader's tolerance of 0. Whether each engine holds the phase or drops it is recorded beside its distance.", 1, [g("h", 0), g("p", 0, a=[t(1, k)]), g("h", 0)], "exact_state", tier="ci" if k == 47 else "full", probe=1)
add("tiny_radians", "small_angle", {"radians": "1e-12"}, "A small decimal angle, not on any dyadic grid.", 1, [g("h", 0), g("rz", 0, a=["r:1e-12"]), g("h", 0)], "exact_state", probe=1)
add("controlled_small_angle_k30", "small_angle", {"k": 30}, "The same phase under a control.", 2, [g("h", 0), g("h", 1), g("cp", 0, 1, a=[t(1, 30)])], "exact_state", probe=2)
# The phase is the result here, so these two are held to the state with its phase (`strict`),
# not modulo one: a phase dropped, doubled or misread as a whole turn shows.
add("repeated_phase_k19", "small_angle", {"k": 19, "count": 262144}, "p(2π/2^19) applied 2^18 times to |1> is a half turn, -|1>. The extension's section 5 states what fixed point leaves of it: modulus 1.0000189, within 1e-5 rad of the half turn.", 1, [g("x", 0)] + [g("p", 0, a=[t(1, 19)])] * 262144, "exact_state", phase_is_result=True, extension_figure=True, engines=["wai.exact", "wai.statevector", "aer.statevector", "ddsim.statevector", "qsim.statevector"])
add("repeated_phase_k19_quarter", "small_angle", {"k": 19, "count": 131072}, "p(2π/2^19) applied 2^17 times to |1> is a quarter turn, i|1>: the half turn is its own negative, and this one is not, so a phase applied with the wrong sign shows.", 1, [g("x", 0)] + [g("p", 0, a=[t(1, 19)])] * 131072, "exact_state", phase_is_result=True, engines=["wai.exact", "wai.statevector", "aer.statevector", "ddsim.statevector", "qsim.statevector"])
add("h_squared_chain", "small_angle", {"count": 4096}, "2048 pairs of H on a superposition: the identity, where fixed point's rounding of 1/sqrt(2) adds up.", 1, [g("h", 0)] * 4096, "exact_state", engines=["wai.exact", "wai.statevector", "aer.statevector", "ddsim.statevector", "qsim.statevector", "quimb.dense"])
# Gate conventions: every gate of the library on a state that shows what it does.
gate_cases = [
("id", 1, []), ("x", 1, []), ("y", 1, []), ("z", 1, []), ("h", 1, []), ("s", 1, []), ("sdg", 1, []), ("t", 1, []), ("tdg", 1, []), ("sx", 1, []), ("sxdg", 1, []),
("p", 1, [t(3, 7)]), ("rz", 1, [t(3, 7)]), ("rx", 1, [t(3, 7)]), ("ry", 1, [t(3, 7)]), ("u", 1, [t(3, 7), t(5, 8), t(7, 9)]),
("cx", 2, []), ("cy", 2, []), ("cz", 2, []), ("ch", 2, []), ("csx", 2, []), ("swap", 2, []),
("cp", 2, [t(3, 7)]), ("crx", 2, [t(3, 7)]), ("cry", 2, [t(3, 7)]), ("crz", 2, [t(3, 7)]), ("cu", 2, [t(3, 7), t(5, 8), t(7, 9), t(1, 5)]),
("rzz", 2, [t(3, 7)]), ("rxx", 2, [t(3, 7)]), ("ryy", 2, [t(3, 7)]), ("negcx", 2, []),
("ccx", 3, []), ("ccz", 3, []), ("cswap", 3, []), ("c2p", 3, [t(3, 7)]), ("c2rz", 3, [t(3, 7)]), ("c2ry", 3, [t(3, 7)]), ("c3x", 4, []), ("c3z", 4, []),
]
for name, arity, args in gate_cases:
qs = list(range(arity))
add("gate_%s" % name, "gate_conventions", {"gate": name}, "What this gate means, from OpenQASM 3's standard library, applied to a state with no symmetry; engines that define it otherwise show here.", arity, distinct_product(arity) + [{"g": name, "q": qs, **({"a": args} if args else {})}], "exact_state", tier="ci" if name in ("sx", "rz", "cu", "c2rz", "negcx") else "full")
for name, args in (("rz", [t(1, 0)]), ("rx", [t(1, 0)]), ("ry", [t(1, 0)]), ("p", [t(1, 0)]), ("rz", [t(2, 0)]), ("u", [t(1, 0), t(0, 0), t(0, 0)])):
add("full_turn_%s_%s" % (name, args[0].replace(":", "").replace("/", "_")), "gate_conventions", {"gate": name, "angle": args[0]}, "A rotation by whole turns: the identity up to a sign, and the sign is the convention. Engines that lower it through a phase gate lose the sign; a global phase changes no outcome, and under a control it would.", 1, distinct_product(1) + [{"g": name, "q": [0], "a": args}], "exact_state")
add("gate_gphase_controlled", "gate_conventions", {"gate": "ctrl @ gphase"}, "A global phase under a control is a relative phase, so no engine may drop it.", 2, distinct_product(2) + [g("gphase", 0, a=[t(3, 7)])], "exact_state")
add("controlled_rz_full_turn", "gate_conventions", {"gate": "crz", "angle": "1 turn"}, "crz by a full turn is diag(1, 1, -1, -1): the sign rz loses globally is here relative.", 2, [g("h", 0), g("h", 1), g("crz", 0, 1, a=[t(1, 0)])], "exact_state", tier="ci")
# Measurement in the middle, reset and feedback.
alpha = t(1, 5)
add("teleport", "dynamic", {"angle": alpha}, "Teleportation: Bell measurement, then corrections on classical bits. Qubit 2 must end as qubit 0 began, whatever the outcomes.", 3, [g("ry", 0, a=[alpha]), g("h", 1), g("cx", 1, 2), g("cx", 0, 1), g("h", 0), {"measure": 0, "bit": 0}, {"measure": 1, "bit": 1}, {"if": [1, 1], "then": [g("x", 2)]}, {"if": [0, 1], "then": [g("z", 2)]}, {"measure": 2, "bit": 2}], "distribution", bits=3, shots=200000, tier="ci")
add("reset_after_superposition", "dynamic", {}, "A reset of a qubit in superposition leaves |0> whatever it read, and leaves its Bell partner mixed.", 2, [g("h", 0), g("cx", 0, 1), {"reset": 0}, {"measure": 0, "bit": 0}, {"measure": 1, "bit": 1}], "distribution", bits=2, shots=100000, tier="ci")
add("measure_twice", "dynamic", {}, "A second measurement in the same basis repeats the first: 00 and 11 only.", 1, [g("h", 0), {"measure": 0, "bit": 0}, {"measure": 0, "bit": 1}], "distribution", bits=2, shots=100000)
add("feedback_flip", "dynamic", {}, "Flip a measured 1 back: the second reading is always 0.", 1, [g("h", 0), {"measure": 0, "bit": 0}, {"if": [0, 1], "then": [g("x", 0)]}, {"measure": 0, "bit": 1}], "distribution", bits=2, shots=100000)
add("ghz_by_fusion", "dynamic", {}, "A GHZ state made from two Bell pairs by a parity measurement and a correction: Clifford, with feedback, so a stabilizer engine must also get it.", 4, [g("h", 0), g("cx", 0, 1), g("h", 2), g("cx", 2, 3), g("cx", 1, 2), {"measure": 2, "bit": 0}, {"if": [0, 1], "then": [g("x", 3)]}, {"measure": 0, "bit": 1}, {"measure": 1, "bit": 2}, {"measure": 3, "bit": 3}], "distribution", bits=4, shots=100000)
add("repeat_until_success", "dynamic", {"rounds": 3}, "Three rounds of a non-Clifford trial on a second qubit, which is measured and then flipped back to |0> by an x conditioned on what was read (no reset instruction): the branches weigh differently, and the law is exact.", 2, _rus_steps(3), "distribution", bits=4, shots=200000)
# Stabilizer circuits at width.
for n in (100, 1000, 5000):
add("clifford_ghz_n%d" % n, "clifford_large", {"n": n}, "A GHZ state across the whole register: sparse generators, past any state vector.", n, ghz_steps(n), "stabilizer", tier="ci" if n == 100 else "full")
for n in (65, 1000, 5000):
add("clifford_cluster_n%d" % n, "clifford_large", {"n": n}, "A line cluster state: every generator X Z neighbours, with its signs flipped by a layer of Z.", n, [g("h", q) for q in range(n)] + [g("cz", q, q + 1) for q in range(n - 1)] + [g("z", q) for q in range(0, n, 3)], "stabilizer")
for n, depth, seed in ((63, 12, 31), (64, 12, 32), (65, 12, 33), (127, 12, 34), (128, 12, 35), (129, 12, 36), (1000, 30, 37), (2000, 20, 38)):
add("clifford_random_n%d" % n, "clifford_large", {"n": n, "depth": depth, "seed": seed}, "Random Clifford layers, with widths on and either side of a machine word: packing bugs live at those edges.", n, random_clifford(n, depth, seed), "stabilizer", tier="ci" if n == 65 else "full")
add("clifford_random_n10_as_state", "clifford_large", {"n": 10, "depth": 30, "seed": 39}, "A Clifford circuit small enough for a state vector: the two formalisms must describe one state.", 10, random_clifford(10, 30, 39), "exact_state")
add("clifford_counts_n40", "clifford_large", {"n": 40, "depth": 8, "seed": 40}, "Sampling past the provider receipt's 22-qubit comparison: outcomes must lie in the affine space the stabilizers fix.", 40, random_clifford(40, 8, 40) + measure_all(40), "stabilizer_counts", bits=40, shots=20000, tier="ci")
# Noise, in closed form.
for p, k in (("0.01", 20), ("0.1", 7)):
add("noise_depol1_x_chain_p%s_k%d" % (p.replace(".", "_"), k), "noise", {"channel": "depolarizing_1q", "p": p, "gates": k}, "k X gates, each followed by a depolarizing channel: <Z> = (-1)^k (1 - 4p/3)^k exactly.", 1, [g("x", 0)] * k, "expectation", noise={"depolarizing_1q": float(p)}, observable="Z0", closed=["depol1", p, k], tier="ci" if k == 7 else "full")
add("noise_depol2_cx_chain", "noise", {"channel": "depolarizing_2q", "p": "0.02", "gates": 9}, "k cx gates, each followed by a two-qubit depolarizing channel: <Z Z> = (1 - 16p/15)^k exactly.", 2, [g("cx", 0, 1)] * 9, "expectation", noise={"depolarizing_2q": 0.02}, observable="Z0 Z1", closed=["depol2", "0.02", 9])
# Wide circuits, by methods that reach past a state vector.
for n in (30, 50, 100):
add("mps_ghz_n%d" % n, "wide_mps", {"n": n}, "Bond dimension 2 at any width: the amplitudes of the two outcomes, in closed form.", n, ghz_steps(n), "amplitudes", wide_kind="ghz", tier="ci" if n == 30 else "full")
for n, x in ((30, 715827883), (40, 366503875925)):
add("mps_qft_n%d" % n, "wide_mps", {"n": n, "x": x}, "The QFT of a basis state is a product state, reached through modest entanglement. Chosen amplitudes in closed form.", n, basis_prep(n, x) + qft_steps(n), "amplitudes", wide_kind="qft", qft_x=x)
# The bond asked for is not the bond reached: at 256, past what an estimate at that bond admits.
add("mps_qft_n30_bond256", "wide_mps", {"n": 30, "x": 715827883, "max_bond": 256}, "The 30-qubit QFT at a bond far above what it reaches: a job naming the method runs under a meter of the bond it holds, and stays exact.", 30, basis_prep(30, 715827883) + qft_steps(30), "amplitudes", wide_kind="qft", qft_x=715827883, max_bond=256, only_engines=["wai.mps"])
add("tn_shallow_n26", "wide_tn", {"n": 26, "depth": 5, "seed": 41}, "A shallow rotation brickwork: amplitudes by contraction, against matrix product states and a state vector.", 26, random_rotations(26, 5, 41), "wide_pairwise")
add("tn_mirror_n40", "wide_tn", {"n": 40, "depth": 3, "seed": 42}, "A shallow mirror circuit, too wide for a state vector here: the amplitude of |0…0> is exactly 1.", 40, random_dyadic(40, 3, 42, 16) + inverse_steps(random_dyadic(40, 3, 42, 16)), "wide_mirror", tier="ci")
return out
def _rus_steps(rounds):
steps = []
for r in range(rounds):
steps += [g("h", 1), g("t", 1), g("cx", 0, 1), g("h", 1), g("t", 1), {"measure": 1, "bit": r}, {"if": [r, 1], "then": [g("x", 1)]}, g("h", 0), g("t", 0)]
steps.append({"measure": 0, "bit": rounds})
return steps
# ------------------------------------------------------------------ what the bit-exact method must do
# The bit-exact method's reader (wai-quantum/src/qasm.rs, `dyadic`) takes an angle as 2πm/2^k for
# the smallest k ≤ 32 within 10^-14 of a turn, and refuses one it cannot (`[Q500]`). This is that
# rule applied to the corpus's angles as written, exactly: each angle is "exact" (m/2^k, k ≤ 32),
# "moved" (within the tolerance of such an angle, not on it) or "refused". A gate whose lowering
# halves an angle (crz, crx, cry, cu) or takes it under modifiers is given angles of k ≤ 30 here,
# which the corpus checks, so that the rule on the written angle is the rule on every angle the
# lowering reaches.
READER_TOLERANCE = Fraction(1, 10**14)
GRID = 32
HALVING = {"crz", "crx", "cry", "cu", "c2p", "c2rz", "c2ry", "gphase"}
def _turns(a):
kind, v = exact.parse_angle(a)
if kind == "t":
return v
return v / (2 * Fraction(exact._PI, 1 << (exact.PREC + exact.GUARD)))
@functools.lru_cache(maxsize=None)
def reader_angle(a):
"""("exact" | "moved" | "refused", how far the reader moves it, in turns)."""
t = _turns(a) % 1
for k in range(GRID + 1):
x = t * (1 << k)
m = round(x)
if abs(x - m) <= READER_TOLERANCE * (1 << k):
return ("exact" if x == m else "moved", abs(x - m) / (1 << k))
return ("refused", None)
def reader_class(e):
"""What the bit-exact method must do with an entry: ("exact", 0), ("moved", the sum of how
far its angles move, in turns) or ("refused", 0)."""
moved = Fraction(0)
worst = "exact"
for s in e["steps"]:
for x in s.get("then", [s]):
for a in x.get("a", []):
kind, by = reader_angle(a)
if kind == "refused":
return ("refused", 0)
if kind == "moved":
worst = "moved"
moved += by
if x["g"] in HALVING and kind == "exact" and exact.parse_angle(a)[0] == "t" and int(a[2:].partition("/")[2]) > GRID - 2:
raise ValueError("%s: %s at %s halves past the grid; the rule above would not hold" % (e["id"], x["g"], a))
return (worst, moved)
# Refusals by the engine under test that a run accepts, each with the words it must give. Any
# other refusal, crash or time-out of the engine under test fails the run. "must": the engine
# must refuse (accepting fails the run); "may": a refusal with these words is recorded as one,
# and an answer is checked like any other.
QEC_REFUSALS = [
{"entry": "qec_refused_channel_with_no_independent_form", "engine": "wai.qec", "must": "refuse", "text": "no form as independent", "reason": "a Pauli channel no independent flips can give is refused, never approximated"},
{"entry": "qec_refused_random_detector", "engine": "wai.qec", "must": "refuse", "text": "is not deterministic", "reason": "a detector that is random without noise is no detector"},
]
def expected_refusals():
"""QEC_REFUSALS, and every entry the bit-exact method must refuse by the reader's rule."""
out = []
for e in entries():
runs_exact = e["expect"] in ("exact_state", "known_state", "mirror") and "wai.exact" in e.get("engines", ["wai.exact"])
if runs_exact and reader_class(e)[0] == "refused":
out.append({"entry": e["id"], "engine": "wai.exact", "must": "refuse", "text": "[Q500]", "reason": "an angle no grid of 2^32 holds within 10^-14 of a turn"})
return out + QEC_REFUSALS
# ------------------------------------------------------------------ the error-correction circuits
def qec_entries():
"""The noisy Clifford circuits: id, family, what generates it, why it is here, its tier."""
out = []
def add(id_, code, d, r, p, reason, tier="full"):
out.append({"id": id_, "family": "qec", "code": code, "distance": d, "rounds": r, "p": p, "reason": reason, "tier": tier, "expect": "qec"})
for d in (3, 5, 7, 9, 11, 15):
add("surface_z_d%d" % d, "surface_code:rotated_memory_z", d, d, 0.001, "The rotated surface-code memory experiment in Z: the circuit decoders are measured on. The model must match mechanism by mechanism, and every detector's rate must follow it.", tier="ci" if d == 3 else "full")
for d in (3, 5, 7):
add("surface_x_d%d" % d, "surface_code:rotated_memory_x", d, d, 0.001, "The same in the X basis: resets and measurements in X.")
for d in (3, 5):
add("unrotated_z_d%d" % d, "surface_code:unrotated_memory_z", d, d, 0.002, "The unrotated layout: another gate order, and detectors with other coordinates.")
for d in (3, 9, 25):
add("repetition_d%d" % d, "repetition_code:memory", d, d, 0.005, "A line of data qubits: the simplest model, with long detector chains at d = 25.")
add("surface_z_d5_noiseless", "surface_code:rotated_memory_z", 5, 5, 0.0, "No noise at all: every detector and the observable are silent on every shot, and the model is empty.", tier="ci")
add("color_d3", "color_code:memory_xyz", 3, 3, 0.002, "A colour code, whose syndrome cycle turns the axes with C_XYZ gates: the model must match mechanism by mechanism, and every detector's rate must follow it.")
return out
HAND_WRITTEN_QEC = {
"qec_inverted_and_tagged": ("A measurement target inverted, which flips its value and no detection event, and a tag on noise.", """\
R 0 1
X_ERROR[leak](0.01) 0
CX 0 1
M !0 1
DETECTOR rec[-1] rec[-2]
OBSERVABLE_INCLUDE(0) rec[-1]
"""),
"qec_measure_flip_noise": ("Measurement flip noise in both bases, and a reset in X.", """\
R 0
RX 1
M(0.02) 0
MX(0.03) 1
DETECTOR rec[-2]
DETECTOR rec[-1]
"""),
"qec_depolarize_merge": ("Two channels whose mechanisms have the same symptoms merge by the XOR rule, p1 + p2 - 2 p1 p2.", """\
R 0 1
DEPOLARIZE1(0.01) 0
X_ERROR(0.02) 0
DEPOLARIZE2(0.03) 0 1
M 0 1
DETECTOR rec[-2]
DETECTOR rec[-1]
"""),
"qec_pauli_observable": ("An observable on Pauli targets rather than measurement records.", """\
R 0 1 2
H 0
CX 0 1 1 2
Z_ERROR(0.01) 1
OBSERVABLE_INCLUDE(0) X0 X1 X2
"""),
"qec_correlated": ("A correlated error, with a Y among its targets: one mechanism with every symptom, and the targets flipping together.", """\
R 0 1 2
E(0.01) X0 Y1
E(0.02) X2
M 0 1 2
DETECTOR rec[-3]
DETECTOR rec[-2]
DETECTOR rec[-1]
"""),
"qec_pauli_channel": ("A general Pauli channel: exclusive outcomes, written as independent flips at the rates that give the same law. The model must match mechanism by mechanism, and every detector's rate must follow it.", """\
R 0
RX 1
PAULI_CHANNEL_1(0.01, 0.02, 0.03) 0 1
M 0
MX 1
DETECTOR rec[-2]
DETECTOR rec[-1]
"""),
"qec_refused_channel_with_no_independent_form": ("A Pauli channel whose exclusive outcomes no independent flips can give (Z's rate would be below zero): it must be refused with its line, never approximated in silence.", """\
R 0
PAULI_CHANNEL_1(0.1, 0.1, 0) 0
M 0
DETECTOR rec[-1]
"""),
"qec_refused_random_detector": ("A detector that is random without noise is no detector: it must be refused.", """\
RX 0
M 0
DETECTOR rec[-1]
"""),
}
def manifest_entry(e, text):
return {
"id": e["id"],
"family": e["family"],
"params": e.get("params", {"distance": e.get("distance"), "rounds": e.get("rounds"), "p": e.get("p"), "code": e.get("code")}),
"reason": e["reason"],
"expect": e["expect"],
"tier": e["tier"],
"qubits": e.get("n"),
"gates": sum(1 for s in e.get("steps", []) if "g" in s) if "steps" in e else None,
"sha256": hashlib.sha256(text.encode()).hexdigest(),
}
def build(tier=None):
"""Every circuit entry in the tier (or all), with its text."""
es = entries()
if tier == "ci":
es = [e for e in es if e["tier"] == "ci"]
for e in es:
e["qasm"] = qasm_of(e)
return es
COMMIT_LIMIT = 16 * 1024 # a program up to this many bytes is committed as a file
def main():
root = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "corpus")
os.makedirs(os.path.join(root, "qasm"), exist_ok=True)
rows = []
for e in build():
rows.append(manifest_entry(e, e["qasm"]))
if len(e["qasm"]) <= COMMIT_LIMIT:
with open(os.path.join(root, "qasm", e["id"] + ".qasm"), "w") as f:
f.write(e["qasm"])
with open(os.path.join(root, "qec-hand-written.json"), "w") as f:
json.dump({k: {"reason": v[0], "text": v[1]} for k, v in HAND_WRITTEN_QEC.items()}, f, indent=1)
f.write("\n")
# The error-correction circuits are the pinned reference generator's, committed as text
# (corpus/qec/); a run checks that the generator still writes them.
for e in qec_entries():
text = open(os.path.join(root, "qec", e["id"] + ".circuit")).read()
rows.append({"id": e["id"], "family": "qec", "params": {"code": e["code"], "distance": e["distance"], "rounds": e["rounds"], "p": e["p"]}, "reason": e["reason"], "expect": "qec", "tier": e["tier"], "sha256": hashlib.sha256(text.encode()).hexdigest()})
with open(os.path.join(root, "expected-refusals.json"), "w") as f:
json.dump({"about": "Refusals by the engine under test that a run accepts, each with the words it must give; tools/corpus.py writes this file from the reader's rule and its list, and a run checks it against them. Any other refusal, crash or time-out of the engine under test fails the run. must: refuse (accepting fails the run) or may (a refusal with these words is recorded as one).", "refusals": expected_refusals()}, f, indent=1, ensure_ascii=False)
f.write("\n")
with open(os.path.join(root, "manifest.json"), "w") as f:
json.dump({"about": "Every circuit of the corpus: parameters, reason, what it is held to, and the SHA-256 of its OpenQASM text. tools/corpus.py writes this file; the run fails if the generator no longer gives these bytes.", "circuits": rows}, f, indent=1, ensure_ascii=False)
f.write("\n")
print("%d circuits" % len(rows))
if __name__ == "__main__":
main()