Some checks failed
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 7s
wai-quantum wasmQ / does this change touch it (push) Successful in 10s
wai-quantum energy-landscape jobs / does this change touch it (push) Successful in 28s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Failing after 54s
wai-quantum wasmQ / the reference modules rebuild to their modules of record · linux (push) Successful in 40s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Failing after 1m16s
joule-moq-remote host agent / joule-moq-remote · does this change touch it (push) Has been cancelled
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (push) Has been cancelled
joule-moq-remote host agent / joule-moq-remote, every target (macos) (push) Has been cancelled
joule-moq-room room service / joule-moq-room · does this change touch it (push) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (push) Has been cancelled
joule-moq-web browser client / joule-moq-web · does this change touch it (push) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Has been cancelled
wai-app and Create / wai-app · does this change touch it (push) Has been cancelled
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Has been cancelled
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Has been cancelled
wai-audit collector and player integration / does this change touch it (push) Has been cancelled
wai-audit collector and player integration / collector · linux (push) Has been cancelled
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Has been cancelled
WAI operation catalogue / does this change touch it (push) Has been cancelled
WAI operation catalogue / the catalogue and every door · linux (push) Has been cancelled
wai-fleet service / does this change touch it (push) Has been cancelled
wai-fleet service / service · linux (push) Has been cancelled
wai-fleet service / service · macos (push) Has been cancelled
wai-ledger service / does this change touch it (push) Has been cancelled
wai-ledger service / service · linux (push) Has been cancelled
wai-ledger service / service · macos (push) Has been cancelled
wai-quantum for JavaScript / does this change touch it (push) Has been cancelled
wai-quantum for JavaScript / javascript · linux (push) Has been cancelled
wai-quantum studio and desktop / does this change touch it (push) Has been cancelled
wai-quantum studio and desktop / studio · browser (push) Has been cancelled
wai-quantum studio and desktop / desktop app · macos (push) Has been cancelled
wai-quantum studio and desktop / desktop app · linux (push) Has been cancelled
wai-quantum studio and desktop / desktop app · windows (push) Has been cancelled
wai-sink-android native sink library / does this change touch it (push) Has been cancelled
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Has been cancelled
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Has been cancelled
wai-sink-swift native sink package / does this change touch it (push) Has been cancelled
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Has been cancelled
WAI Studio / does this change touch it (push) Has been cancelled
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Has been cancelled
WAI Studio / Studio in Chromium and Firefox · macos (push) Has been cancelled
WAI Studio / Studio in WebKit · linux (push) Has been cancelled
wai-quantum wasmQ / profile, engines, reference modules, adversarial, vectors · macos (push) Successful in 2m13s
wai-quantum energy-landscape jobs / the module under wasm32-wasip2 (wasmtime) (push) Successful in 2m33s
wai-quantum wasmQ / interpreter and vectors under wasm32-wasip2 (wasmtime) (push) Successful in 2m38s
wai-quantum energy-landscape jobs / the same bits · macos (push) Successful in 4m11s
wai-quantum wasmQ / profile, engines, reference modules, adversarial, vectors · linux (push) Successful in 4m51s
wai-quantum energy-landscape jobs / native against WebAssembly, over many seeds (push) Successful in 6m22s
wai-quantum energy-landscape jobs / the same bits · linux-arm64 (push) Successful in 7m45s
wai-quantum energy-landscape jobs / reader, kernels, answers and the stated result · linux, release (push) Successful in 9m14s
wai-quantum command line / does this change touch it (push) Has been cancelled
wai-quantum command line / command line · linux (push) Has been cancelled
wai-quantum command line / command line · macos (push) Has been cancelled
wai-quantum contract / does this change touch it (push) Has been cancelled
wai-quantum contract / API compatibility · linux (push) Has been cancelled
wai-quantum contract / schemas and the committed tool lists · linux (push) Has been cancelled
wai-quantum contract / the policy is linked, and the deprecations page reads (push) Has been cancelled
wai-quantum docs, course and locales / does this change touch it (push) Has been cancelled
wai-quantum docs, course and locales / every command and snippet in the docs · linux (push) Has been cancelled
wai-quantum docs, course and locales / the course and the command line's languages · linux (push) Has been cancelled
wai-quantum docs, course and locales / the Studio's words in every locale · linux (push) Has been cancelled
wai-quantum editors / does this change touch it (push) Has been cancelled
wai-quantum editors / editors · linux (push) Has been cancelled
wai-quantum editors / editors · macos (push) Has been cancelled
wai-quantum resource estimation / does this change touch it (push) Has been cancelled
wai-quantum resource estimation / estimation and calibration · linux, release (push) Has been cancelled
wai-quantum other formats / does this change touch it (push) Has been cancelled
wai-quantum other formats / readers, writers and the set · linux (push) Has been cancelled
wai-quantum other formats / the set under wasm32-wasip2 (wasmtime) (push) Has been cancelled
wai-quantum OpenQASM reader / does this change touch it (push) Has been cancelled
wai-quantum OpenQASM reader / reader and corpus · linux (push) Has been cancelled
wai-quantum OpenQASM reader / corpus under wasm32-wasip2 (wasmtime) (push) Has been cancelled
wai-quantum pulse and dynamics / does this change touch it (push) Has been cancelled
wai-quantum pulse and dynamics / reader, simulator and pulse jobs · linux, release (push) Has been cancelled
wai-quantum pulse and dynamics / the same bits · linux-arm64 (push) Has been cancelled
wai-quantum pulse and dynamics / the same bits · macos (push) Has been cancelled
wai-quantum pulse and dynamics / reader, simulator and pulse jobs under wasm32-wasip2 (wasmtime) (push) Has been cancelled
wai-quantum for Python / does this change touch it (push) Has been cancelled
wai-quantum for Python / python · linux (push) Has been cancelled
wai-quantum for Python / python · macos (push) Has been cancelled
wai-quantum error correction and mitigation / does this change touch it (push) Has been cancelled
wai-quantum error correction and mitigation / codes, decoders, texts and mitigation · linux, release (push) Has been cancelled
wai-quantum extension points / does this change touch it (push) Has been cancelled
wai-quantum extension points / the registry and the example · linux (push) Has been cancelled
wai-quantum extension points / the registry and the example · linux-arm64 (push) Has been cancelled
wai-quantum extension points / the registry under wasm32-wasip2 (wasmtime) (push) Has been cancelled
wai-quantum service / does this change touch it (push) Has been cancelled
wai-quantum service / service · linux (push) Has been cancelled
wai-quantum service / service · macos (push) Has been cancelled
wai-quantum service / service energy · linux packages (push) Has been cancelled
wai-quantum variational and algorithm library / does this change touch it (push) Has been cancelled
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux, release (push) Has been cancelled
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux-arm64, release (push) Has been cancelled
wai-quantum verdicts and repairs / does this change touch it (push) Has been cancelled
wai-quantum verdicts and repairs / verdicts, repairs and the intent set · linux (push) Has been cancelled
wai-quantum verdicts and repairs / the intent set and the verdict under wasm32-wasip2 (wasmtime) (push) Has been cancelled
wai-quantum views in agent hosts / does this change touch it (push) Has been cancelled
wai-quantum views in agent hosts / views · the page and its engine (push) Has been cancelled
wai-quantum views in agent hosts / views · a scripted host (push) Has been cancelled
wai-quantum-landscape-fpga reference design / does this change touch it (push) Has been cancelled
wai-quantum-landscape-fpga reference design / the member against the model of the logic, and the logic against the model · linux, release (push) Has been cancelled
wai-quantum-landscape-fpga reference design / the board's code on the board's processor's architecture · linux-arm64, release (push) Has been cancelled
Re-landed from PR #659 (branch wai/quantum-wasmq, head 39fdb517a) as one
commit on main, under the land-it model. Five review rounds; the last had
no high or critical finding, and its mediums were fixed on the branch.
A hybrid quantum program runs classical code between its gates. OpenQASM 3
declares such a function with `extern` and leaves its body and linking
outside the language. wasmQ (wai.quantum.wasmq) packs the program and the
WebAssembly that defines its externs into one content-addressed WAI
envelope; a run gives the same result bytes and fuel on every host and
seals the engine's job receipt.
- extensions/quantum-wasmq.md (normative) and quantum-wasmq.wit.
- wai/wai-wasmq: the profile (Lime1, nothing imported, bounded memory,
refusal codes W001-W017); what a run asks of its host, bounded from the
bundle alone before anything runs; fuel defined on the module as written;
a weighted stack; two engines (the pinned wasmtime 50.0.1 and an
interpreter of the crate's own that also runs on wasm32); the envelope,
runner, receipts, transcript replay, reference programs and vectors.
- wai-quantum: engine::wasmq (built with quantum_receipt), the job form
beside its receipts; the estimate verifier answers a request no host
re-runs with a verdict carrying rerun_error, combined here with main's
reaction clock (clock_of).
- wai/quantum-conformance/wasmq: envelopes, refusals and receipts.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
247 lines
12 KiB
Rust
247 lines
12 KiB
Rust
//! The reference modules (extensions/quantum-wasmq.md §8): the engine's qLDPC decoder and
|
|
//! its atom rearrangement planner, built as wasmQ modules of record, give exactly what the
|
|
//! same code gives natively, called directly and in the middle of a circuit, on every engine.
|
|
|
|
use wai_quantum::quantum_atom::{Array, target_block, target_bytes};
|
|
use wai_quantum::quantum_qec::CssCode;
|
|
use wai_wasmq::engine::{Engine, Interpreter};
|
|
use wai_wasmq::envelope::{Run, open, pack};
|
|
use wai_wasmq::interp::Metering;
|
|
use wai_wasmq::reference::{self, checks_prior, target_prior};
|
|
use wai_wasmq::run::{EngineKind, run, shot_seed};
|
|
use wai_wasmq::{abi, meter};
|
|
use wai_quantum::ed25519_dalek::SigningKey;
|
|
|
|
const DECODER: &[u8] = include_bytes!("../../quantum-conformance/wasmq/modules/qldpc_decoder.wasm");
|
|
const PLANNER: &[u8] = include_bytes!("../../quantum-conformance/wasmq/modules/atom_planner.wasm");
|
|
|
|
fn engines(module: &[u8], prepared: &'static [u8]) -> Vec<Box<dyn Engine>> {
|
|
let module: &'static [u8] = Box::leak(module.to_vec().into_boxed_slice());
|
|
#[allow(unused_mut)] // the native engine is added where this build has it
|
|
let mut v: Vec<Box<dyn Engine>> = vec![Box::new(Interpreter::new(module, Metering::Own).unwrap()), Box::new(Interpreter::new(prepared, Metering::Module).unwrap())];
|
|
#[cfg(all(feature = "wasmtime", not(target_arch = "wasm32")))]
|
|
v.push(Box::new(wai_wasmq::engine::Native::new(prepared).unwrap()));
|
|
v
|
|
}
|
|
|
|
fn bits(v: u64, n: usize) -> Vec<bool> {
|
|
(0..n).map(|i| v >> i & 1 == 1).collect()
|
|
}
|
|
|
|
struct Rng(u64);
|
|
impl Rng {
|
|
fn next(&mut self) -> u64 {
|
|
self.0 = self.0.wrapping_add(0x9e37_79b9_7f4a_7c15);
|
|
let mut z = self.0;
|
|
z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
|
|
z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
|
|
z ^ (z >> 31)
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn the_priors_are_the_engines_own_bytes() {
|
|
for code in [CssCode::surface(3), CssCode::surface(5), CssCode::gross()] {
|
|
assert_eq!(checks_prior(code.n, &code.checks), code.check_matrix_bytes());
|
|
}
|
|
assert_eq!(target_prior(8, 8, &target_block(8, 8, 4, 4)), target_bytes(&target_block(8, 8, 4, 4), 8, 8));
|
|
assert_eq!(reference::target_block(8, 8, 4, 4), target_block(8, 8, 4, 4));
|
|
}
|
|
|
|
fn decoder_instance<'a>(e: &'a dyn Engine, code: &CssCode, seed: u64) -> Box<dyn wai_wasmq::engine::Instance + 'a> {
|
|
let mut i = e.instantiate().unwrap();
|
|
i.set_fuel(1 << 40);
|
|
abi::lifecycle(i.as_mut(), "wasmq-seed", &[seed]).unwrap();
|
|
abi::prior(i.as_mut(), 0, &checks_prior(code.n, &code.checks)).unwrap();
|
|
i
|
|
}
|
|
|
|
#[test]
|
|
fn the_decoder_module_decodes_as_the_engine_does_on_every_engine() {
|
|
let prepared: &'static [u8] = Box::leak(meter::prepare(DECODER).unwrap().into_boxed_slice());
|
|
let small = CssCode::surface(3);
|
|
let decl = wai_quantum::qasm::ExternDecl { name: "decode64".into(), args: vec![wai_quantum::qasm::ExternArg::Bit(small.checks.len() as u32)], ret: Some(small.n as u32) };
|
|
let seed = 11;
|
|
// Every error of weight at most two on surface(3).
|
|
let mut errors = vec![vec![]];
|
|
for a in 0..small.n {
|
|
errors.push(vec![a]);
|
|
for b in a + 1..small.n {
|
|
errors.push(vec![a, b]);
|
|
}
|
|
}
|
|
let mut fuels: Vec<Vec<u64>> = Vec::new();
|
|
for e in engines(DECODER, prepared) {
|
|
let mut i = decoder_instance(e.as_ref(), &small, seed);
|
|
let mut f = Vec::new();
|
|
for err in &errors {
|
|
let mut x = vec![false; small.n];
|
|
for &q in err {
|
|
x[q] = true;
|
|
}
|
|
let syn = small.syndrome(&x);
|
|
i.set_fuel(1 << 30);
|
|
let got = abi::call(i.as_mut(), &decl, "decode64", &syn, false).unwrap();
|
|
f.push((1u64 << 30) - i.fuel() as u64);
|
|
assert_eq!(got, wasmq_qldpc_decoder::decode_bits(&small, &syn, seed), "{} on {err:?}", e.name());
|
|
if err.len() <= 1 {
|
|
let residual: Vec<usize> = (0..small.n).filter(|&q| got[q] != x[q]).collect();
|
|
assert!(small.syndrome(&(0..small.n).map(|q| got[q] != x[q]).collect::<Vec<_>>()).iter().all(|b| !b));
|
|
assert!(small.is_trivial(&residual), "a weight-1 error decoded to a logical");
|
|
}
|
|
}
|
|
fuels.push(f);
|
|
}
|
|
assert!(fuels.windows(2).all(|w| w[0] == w[1]), "each call's fuel is the same on every engine");
|
|
|
|
// The gross code through the list form, with random errors of weight up to four.
|
|
let gross = CssCode::gross();
|
|
let decl = wai_quantum::qasm::ExternDecl { name: "decode".into(), args: vec![wai_quantum::qasm::ExternArg::Bit(gross.checks.len() as u32)], ret: Some(gross.n as u32) };
|
|
let mut rng = Rng(5);
|
|
let cases: Vec<Vec<bool>> = (0..12)
|
|
.map(|_| {
|
|
let mut x = vec![false; gross.n];
|
|
for _ in 0..1 + rng.next() % 4 {
|
|
x[(rng.next() % gross.n as u64) as usize] = true;
|
|
}
|
|
gross.syndrome(&x)
|
|
})
|
|
.collect();
|
|
let mut fuels: Vec<Vec<u64>> = Vec::new();
|
|
for e in engines(DECODER, prepared) {
|
|
let mut i = decoder_instance(e.as_ref(), &gross, seed);
|
|
let mut f = Vec::new();
|
|
for syn in &cases {
|
|
i.set_fuel(1 << 34);
|
|
let got = abi::call(i.as_mut(), &decl, "decode", syn, false).unwrap();
|
|
f.push((1u64 << 34) - i.fuel() as u64);
|
|
assert_eq!(got, wasmq_qldpc_decoder::decode_bits(&gross, syn, seed), "{}", e.name());
|
|
}
|
|
fuels.push(f);
|
|
}
|
|
assert!(fuels.windows(2).all(|w| w[0] == w[1]));
|
|
}
|
|
|
|
#[test]
|
|
fn the_planner_module_plans_as_the_engine_does_on_every_engine() {
|
|
let prepared: &'static [u8] = Box::leak(meter::prepare(PLANNER).unwrap().into_boxed_slice());
|
|
for (w, h, tw, th, f) in [(4u32, 4u32, 2u32, 2u32, "plan64"), (5, 5, 3, 3, "plan64"), (9, 9, 5, 5, "plan")] {
|
|
let n = (w * h) as usize;
|
|
let target = target_block(w, h, tw, th);
|
|
let decl = wai_quantum::qasm::ExternDecl { name: f.into(), args: vec![wai_quantum::qasm::ExternArg::Bit(n as u32)], ret: Some(2 * n as u32 + 1) };
|
|
let mut rng = Rng(w as u64);
|
|
let loads: Vec<Vec<bool>> = (0..16).map(|k| Array::load(w, h, 300 + 40 * k, rng.next()).occ).collect();
|
|
let mut fuels: Vec<Vec<u64>> = Vec::new();
|
|
for e in engines(PLANNER, prepared) {
|
|
let mut i = e.instantiate().unwrap();
|
|
i.set_fuel(1 << 40);
|
|
abi::prior(i.as_mut(), 0, &target_prior(w, h, &target)).unwrap();
|
|
let mut fu = Vec::new();
|
|
for occ in &loads {
|
|
i.set_fuel(1 << 34);
|
|
let got = abi::call(i.as_mut(), &decl, f, occ, false).unwrap();
|
|
fu.push((1u64 << 34) - i.fuel() as u64);
|
|
assert_eq!(got, wasmq_atom_planner::plan_bits(w, h, &target, occ), "{} {w}x{h}", e.name());
|
|
// The engine's own check of the plan, on what the module returned.
|
|
let plan = wai_quantum::quantum_atom::solve(&Array { w, h, occ: occ.clone() }, &target);
|
|
assert_eq!(got[2 * n], plan.feasible && wai_quantum::quantum_atom::verify(&Array { w, h, occ: occ.clone() }, &target, &plan));
|
|
}
|
|
fuels.push(fu);
|
|
}
|
|
assert!(fuels.windows(2).all(|w| w[0] == w[1]));
|
|
}
|
|
}
|
|
|
|
fn kinds() -> Vec<EngineKind> {
|
|
#[allow(unused_mut)] // the native engine is added where this build has it
|
|
let mut k = vec![EngineKind::Interpreter, EngineKind::InterpreterPrepared];
|
|
#[cfg(all(feature = "wasmtime", not(target_arch = "wasm32")))]
|
|
k.insert(0, EngineKind::Native);
|
|
k
|
|
}
|
|
|
|
#[test]
|
|
fn a_memory_round_decodes_in_the_middle_of_the_circuit_and_every_shot_ends_in_the_code() {
|
|
let key = SigningKey::from_bytes(&[7; 32]);
|
|
for (code, errors, shots, state) in [(CssCode::surface(3), 1, 48, "shot"), (CssCode::surface(5), 2, 24, "job"), (CssCode::gross(), 3, 6, "shot")] {
|
|
let mut r = Run::new(shots, 1234);
|
|
r.state = state.into();
|
|
let env = pack(&reference::qec_bundle(DECODER, code.n, &code.checks, errors, r)).unwrap();
|
|
let o = open(&env).unwrap();
|
|
let mut bodies = Vec::new();
|
|
for k in kinds() {
|
|
let (body, log) = run(&o, k, &key, true).unwrap();
|
|
let log = log.unwrap();
|
|
assert_eq!(body["result"]["status"], "ok", "{}: {}", code.id, body["result"]);
|
|
// Every call's result is the native decoder's on the same syndrome.
|
|
for c in &log {
|
|
let syn: Vec<bool> = (0..code.checks.len()).map(|i| c.input[i / 8] >> (i % 8) & 1 == 1).collect();
|
|
let seed = if state == "shot" { shot_seed(1234, c.shot) } else { 1234 };
|
|
let want = abi::pack(&wasmq_qldpc_decoder::decode_bits(&code, &syn, seed));
|
|
assert_eq!(c.output, want, "shot {} of {}", c.shot, code.id);
|
|
}
|
|
assert_eq!(log.len() as u64, shots);
|
|
// The record replays: every call's output and fuel again, from its input alone.
|
|
assert!(wai_wasmq::run::replay(&o, &log, k).unwrap().is_empty());
|
|
let mut bad = log.clone();
|
|
bad[0].output[0] ^= 1;
|
|
bad[1].fuel += 1;
|
|
assert_eq!(wai_wasmq::run::replay(&o, &bad, k).unwrap().len(), 2, "this test can fail");
|
|
bodies.push(wai_quantum::engine::receipt::canonical(&body));
|
|
}
|
|
assert!(bodies.windows(2).all(|w| w[0] == w[1]), "{}: the same job bytes on every engine", code.id);
|
|
let body: serde_json::Value = serde_json::from_slice(&bodies[0]).unwrap();
|
|
// Every shot: the second syndrome is clear and the residual is no logical.
|
|
let (n, m) = (code.n, code.checks.len());
|
|
for (key, count) in body["result"]["counts"].as_object().unwrap() {
|
|
let bit = |i: usize| key.as_bytes()[key.len() - 1 - i] == b'1';
|
|
let k = key.len();
|
|
// Bits in declaration order: e*, s, corr, s2, fin; fin are the last n declared.
|
|
let fin: Vec<bool> = (k - n..k).map(bit).collect();
|
|
let s2: Vec<bool> = (k - n - m..k - n).map(bit).collect();
|
|
assert!(s2.iter().all(|b| !b), "{}: the syndrome after correction ({count} shots)", code.id);
|
|
let residual: Vec<usize> = (0..n).filter(|&q| fin[q]).collect();
|
|
assert!(code.syndrome(&fin).iter().all(|b| !b));
|
|
assert!(code.is_trivial(&residual), "{}: a shot ended in a logical error", code.id);
|
|
}
|
|
assert!(wai_wasmq::verify(&body, Some(&o), kinds()[0]).unwrap().ok());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn atoms_are_rearranged_in_the_middle_of_the_circuit_and_fill_the_target() {
|
|
let key = SigningKey::from_bytes(&[7; 32]);
|
|
for (w, h, tw, th, shots) in [(4u32, 4u32, 2u32, 2u32, 64u64), (9, 9, 3, 3, 12)] {
|
|
let env = pack(&reference::atom_bundle(PLANNER, w, h, tw, th, Run::new(shots, 99))).unwrap();
|
|
let o = open(&env).unwrap();
|
|
let target = target_block(w, h, tw, th);
|
|
let n = (w * h) as usize;
|
|
let mut bodies = Vec::new();
|
|
for k in kinds() {
|
|
let (body, log) = run(&o, k, &key, true).unwrap();
|
|
for c in log.unwrap() {
|
|
let occ: Vec<bool> = (0..n).map(|i| c.input[i / 8] >> (i % 8) & 1 == 1).collect();
|
|
assert_eq!(c.output, abi::pack(&wasmq_atom_planner::plan_bits(w, h, &target, &occ)));
|
|
}
|
|
bodies.push(wai_quantum::engine::receipt::canonical(&body));
|
|
}
|
|
assert!(bodies.windows(2).all(|w| w[0] == w[1]));
|
|
let body: serde_json::Value = serde_json::from_slice(&bodies[0]).unwrap();
|
|
let mut feasible = 0;
|
|
for (key, count) in body["result"]["counts"].as_object().unwrap() {
|
|
let bit = |i: usize| key.as_bytes()[key.len() - 1 - i] == b'1';
|
|
let k = key.len();
|
|
// Declared: occ, plan, fin.
|
|
let plan_ok = bit(n + 2 * n);
|
|
let fin: Vec<bool> = (k - n..k).map(bit).collect();
|
|
let occ: Vec<bool> = (0..n).map(bit).collect();
|
|
if plan_ok {
|
|
feasible += count.as_u64().unwrap();
|
|
assert!(target.iter().all(|&t| fin[t]), "a feasible plan left a target site empty");
|
|
assert_eq!(fin.iter().filter(|&&b| b).count(), occ.iter().filter(|&&b| b).count(), "atoms are moved, never made or lost");
|
|
}
|
|
}
|
|
assert!(feasible > 0);
|
|
let _ = bits(0, 0);
|
|
}
|
|
}
|