Some checks failed
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Successful in 3s
no-vanity-metrics / WAI public text names no comparison (pull_request) Successful in 4s
no-vanity-metrics / WAI public text names no company or product (pull_request) Successful in 3s
standards workspaces build + test / eoc-rs (pull_request) Successful in 1m55s
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 3m14s
standards workspaces build + test / jcp-rs (pull_request) Successful in 1m31s
standards workspaces build + test / aac-rs (pull_request) Successful in 1m50s
standards workspaces build + test / proof-rs (pull_request) Successful in 1m13s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 1m20s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 50s
standards workspaces build + test / sandbox-rs (pull_request) Successful in 2m10s
standards workspaces build + test / map-rs (pull_request) Successful in 59s
standards workspaces build + test / mesh-rs (pull_request) Successful in 44s
standards workspaces build + test / smart-byte-rs (pull_request) Successful in 3m38s
standards workspaces build + test / openpay (pull_request) Successful in 3m11s
WAI conformance / cargo-class corpora · linux (pull_request) Successful in 3m56s
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Successful in 13s
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Successful in 5m6s
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Successful in 2m11s
WAI conformance / cross-arch byte-equality · linux (pull_request) Successful in 24s
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Successful in 38s
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Successful in 44s
WAI energy receipts / energy receipts · linux (pull_request) Successful in 1m13s
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Successful in 2m7s
WAI JPEG-AI whole decode (pinned inputs, required) / fetch pinned JPEG-AI inputs → whole decode + pixel hash, required (pull_request) Successful in 57s
WAI neural sink gates / model-free refusals of the neural sink (pull_request) Successful in 1m2s
WAI mbt2018_mean integer decode (regenerated vectors) / regenerate mbt2018_mean integer vectors → Rust decode, required (pull_request) Successful in 3m57s
wai-web wasm32 / wai-web wasm32 build · corpus, menu and writers (pull_request) Successful in 1m44s
standards workspaces build + test / arl-rs (pull_request) Successful in 23m30s
standards workspaces build + test / joule-ui-rs (pull_request) Successful in 28m45s
standards workspaces build + test / jouledesk-rs (pull_request) Successful in 23m46s
standards workspaces build + test / joulehook-rs (pull_request) Successful in 22m26s
standards workspaces build + test / sense-rs (pull_request) Successful in 18m49s
standards workspaces build + test / macOS energy backends (pull_request) Failing after 13m54s
WAI conformance / cargo-class corpora · macos (pull_request) Successful in 25m26s
WAI conformance / cross-arch byte-equality · macos (pull_request) Successful in 1m17s
WAI energy receipts / energy receipts · macos (pull_request) Successful in 12m58s
The byte-exact simulator is fixed-point and dyadic by design. quantum_sv is the general state vector for everything else (arbitrary rotations, sqrt W, fSim, random unitaries), and the ground truth approximate methods are measured against, up to about 30 qubits. - Split real and imaginary arrays; qubit 0 most significant, as in the tensor networks. - Kernels: unrolled one- and two-qubit, general k-qubit, and a diagonal fast path. - Fusion around multi-qubit gates: pending one-qubit gates join the next multi-qubit gate on their qubit, trailing ones the last, and above width 2 adjacent multi-qubit gates merge. Each move only crosses gates on other qubits. - Threads, with no unsafe code: block-aligned slices, and for gates on the top qubits a split at the top target bit, or into four quarters for adjacent pairs. - Every path computes each amplitude through one row sum in one order, so threading never changes a bit. The native-vs-WASI pin caught a path whose sum ran in a different order; the fix is the shared row_dot, and a test now forces 1/2/3/8/32 threads and demands identical states (falsified by reversing one kernel's sum). - Reductions (norm, Pauli expectations, sorted-uniform sampling) are summed in fixed chunks. gates: Gate moves here from quantum_tn (re-exported there), with the standard gates by name: H, X, Y, Z, S, T, sqrt X/Y/W, RX/RY/RZ, phase, CX, CZ, SWAP, iSWAP, CPhase, RZZ, fSim. Checked: - final states of random circuits on 8, 12 and 16 qubits agree with an independent simulator to 2e-16 at fusion widths 0, 2 and 4; - tensor-network amplitudes equal the state vector's to 1e-12 on 18 qubits (tests/tn_vs_sv.rs); - a 26-qubit, depth-20, 770-gate circuit runs in about 9 s at width 2, in double precision. CLI: wai-quantum sv --file CIRCUIT.jsonl [--fuse --top --sample --expect --json]; tn shares its circuit reader. Byte-identical natively and under wasm32-wasip2. Co-Authored-By: Claude Opus 5.5 <[email protected]>
62 lines
2.5 KiB
Rust
62 lines
2.5 KiB
Rust
//! Two independent methods, one answer: an amplitude contracted as a tensor
|
|
//! network equals the state vector's, for every bitstring tried and for a
|
|
//! batch of open outputs.
|
|
#![cfg(all(feature = "quantum_tn", feature = "quantum_sv"))]
|
|
|
|
use wai_quantum::gates::Gate;
|
|
use wai_quantum::quantum_sv::StateVector;
|
|
use wai_quantum::quantum_tn::{contract_plan, find_path, Families, Network, PathOptions};
|
|
|
|
fn circuit(n: u32, depth: u32) -> Vec<Gate> {
|
|
let mut g = Vec::new();
|
|
let mut a = 0.2f64;
|
|
for layer in 0..depth {
|
|
for q in 0..n {
|
|
a += 0.613;
|
|
g.push(match (q * 7 + layer) % 4 {
|
|
0 => Gate::rx(q, a),
|
|
1 => Gate::sqrt_w(q),
|
|
2 => Gate::ry(q, a),
|
|
_ => Gate::sqrt_x(q),
|
|
});
|
|
}
|
|
let mut q = layer % 2;
|
|
while q + 1 < n {
|
|
g.push(Gate::fsim(q, q + 1, 1.2 + 0.1 * q as f64, 0.5));
|
|
q += 2;
|
|
}
|
|
g.push(Gate::cz(0, n - 1));
|
|
}
|
|
g
|
|
}
|
|
|
|
#[test]
|
|
fn tensor_network_amplitudes_equal_the_state_vector() {
|
|
let n = 18;
|
|
let gates = circuit(n, 8);
|
|
let mut sv = StateVector::zero(n).unwrap();
|
|
sv.run(&gates, 2).unwrap();
|
|
let opts = PathOptions { trials: 16, seed: 1, max_size: Some(4096.0), reconfigure: 6, families: Families::Both };
|
|
for x in [0usize, 1, 77_777, 131_071, 262_143] {
|
|
let bits: Vec<u8> = (0..n).map(|q| ((x >> (n - 1 - q)) & 1) as u8).collect();
|
|
let mut net = Network::amplitude(n, &gates, &bits, &[]).unwrap();
|
|
net.simplify();
|
|
let plan = find_path(&net.shape(), &net.dims, &net.open, &opts);
|
|
let t = contract_plan(&net, &plan).unwrap().data[0];
|
|
let s = sv.amplitude(x);
|
|
assert!((t.re - s.re).abs() < 1e-12 && (t.im - s.im).abs() < 1e-12, "x {x}: {t:?} vs {s:?}");
|
|
}
|
|
// A batch: qubits 4 and 11 open, the rest fixed to x = 77 777.
|
|
let x = 77_777usize;
|
|
let bits: Vec<u8> = (0..n).map(|q| ((x >> (n - 1 - q)) & 1) as u8).collect();
|
|
let mut net = Network::amplitude(n, &gates, &bits, &[4, 11]).unwrap();
|
|
net.simplify();
|
|
let plan = find_path(&net.shape(), &net.dims, &net.open, &opts);
|
|
let t = contract_plan(&net, &plan).unwrap();
|
|
for j in 0..4usize {
|
|
let (b4, b11) = ((j >> 1) & 1, j & 1);
|
|
let y = (x & !(1 << (n - 1 - 4)) & !(1 << (n - 1 - 11))) | (b4 << (n - 1 - 4)) | (b11 << (n - 1 - 11));
|
|
let s = sv.amplitude(y);
|
|
assert!((t.data[j].re - s.re).abs() < 1e-12 && (t.data[j].im - s.im).abs() < 1e-12, "batch {j}");
|
|
}
|
|
}
|