use crate::quantum::{Circuit, FRAC, Gateset, MAX_QUBITS, ONE, QuantumError, StateVector};
use crate::quantum_energy::{EnergyClass, Uncertainty, check_label};
use crate::quantum_ops::content_hash;
use core::future::Future;
use core::pin::Pin;
use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
use serde_json::{Map, Value, json};
pub use crate::quantum_ops::CAP_QUANTUM_FABRIC;
pub const KERNEL_CIRCUIT_APPLY: &str = "wai.quantum.circuit/apply";
pub const KERNEL_CIRCUIT2_APPLY: &str = "wai.quantum.circuit2/apply";
pub const REFERENCE: &str = "reference";
pub const GENERATOR_RANDOM_CIRCUITS: &str = "wai.quantum.circuit/random-v1";
pub const GENERATOR_RANDOM_CIRCUITS2: &str = "wai.quantum.circuit2/random-v1";
pub const fn apply_kernel(gs: Gateset) -> &'static str {
match gs {
Gateset::V1 => KERNEL_CIRCUIT_APPLY,
Gateset::V2 => KERNEL_CIRCUIT2_APPLY,
}
}
pub const fn random_generator(gs: Gateset) -> &'static str {
match gs {
Gateset::V1 => GENERATOR_RANDOM_CIRCUITS,
Gateset::V2 => GENERATOR_RANDOM_CIRCUITS2,
}
}
pub const GENERATOR_FABRIC: &str = "wai.quantum.circuit/fabric-v1";
pub const GENERATOR_FABRIC2: &str = "wai.quantum.circuit2/fabric-v1";
pub const fn fabric_generator(gs: Gateset) -> &'static str {
match gs {
Gateset::V1 => GENERATOR_FABRIC,
Gateset::V2 => GENERATOR_FABRIC2,
}
}
const DOMAIN_FABRIC: &[u8] = b"wai:quantum-fabric\x01";
const DOMAIN_FABRIC_ID: &[u8] = b"wai:quantum-fabric-id\x01";
const DOMAIN_CERT: &[u8] = b"wai:quantum-fabric-certificate\x01";
const DOMAIN_CORPUS: &[u8] = b"wai:quantum-fabric-corpus\x01";
fn put(o: &mut Vec<u8>, bytes: &[u8]) {
o.extend_from_slice(&(bytes.len() as u64).to_be_bytes());
o.extend_from_slice(bytes);
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum FabricClass {
Cpu,
CpuMatrix,
Gpu,
Npu,
Tensor,
Dataflow,
Fpga,
Qpu,
AnalogIsing,
}
impl FabricClass {
pub const ALL: [FabricClass; 9] =
[FabricClass::Cpu, FabricClass::CpuMatrix, FabricClass::Gpu, FabricClass::Npu, FabricClass::Tensor, FabricClass::Dataflow, FabricClass::Fpga, FabricClass::Qpu, FabricClass::AnalogIsing];
pub fn label(self) -> &'static str {
match self {
FabricClass::Cpu => "cpu",
FabricClass::CpuMatrix => "cpu-matrix",
FabricClass::Gpu => "gpu",
FabricClass::Npu => "npu",
FabricClass::Tensor => "tensor",
FabricClass::Dataflow => "dataflow",
FabricClass::Fpga => "fpga",
FabricClass::Qpu => "qpu",
FabricClass::AnalogIsing => "analog-ising",
}
}
pub fn from_label(s: &str) -> Option<FabricClass> {
FabricClass::ALL.into_iter().find(|c| c.label() == s)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Presence {
Detected,
Reachable,
Declared,
}
impl Presence {
pub fn label(self) -> &'static str {
match self {
Presence::Detected => "detected",
Presence::Reachable => "reachable",
Presence::Declared => "declared",
}
}
pub fn from_label(s: &str) -> Option<Presence> {
[Presence::Detected, Presence::Reachable, Presence::Declared].into_iter().find(|p| p.label() == s)
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Parity {
BitExact,
Within { max_ulp: u64, max_abs: f64 },
Statistical { fidelity: f64, shots: u64 },
Uncertified,
}
impl Parity {
pub fn meets(&self, required: &Parity) -> bool {
match (self, required) {
(Parity::Uncertified, _) | (_, Parity::Uncertified) => false,
(Parity::BitExact, _) => true,
(Parity::Within { max_ulp, max_abs }, Parity::Within { max_ulp: u, max_abs: a }) => max_ulp <= u && max_abs <= a,
(Parity::Statistical { fidelity, shots }, Parity::Statistical { fidelity: f, shots: s }) => fidelity >= f && shots >= s,
_ => false,
}
}
fn worst(self, other: Parity) -> Parity {
match (self, other) {
(Parity::Uncertified, _) | (_, Parity::Uncertified) => Parity::Uncertified,
(Parity::BitExact, p) | (p, Parity::BitExact) => p,
(Parity::Within { max_ulp: u1, max_abs: a1 }, Parity::Within { max_ulp: u2, max_abs: a2 }) => Parity::Within { max_ulp: u1.max(u2), max_abs: a1.max(a2) },
(Parity::Statistical { fidelity: f1, shots: s1 }, Parity::Statistical { fidelity: f2, shots: s2 }) => Parity::Statistical { fidelity: f1.min(f2), shots: s1.min(s2) },
_ => Parity::Uncertified,
}
}
fn write_signed(&self, o: &mut Vec<u8>) {
match *self {
Parity::Uncertified => o.push(0),
Parity::BitExact => o.push(1),
Parity::Within { max_ulp, max_abs } => {
o.push(2);
o.extend_from_slice(&max_ulp.to_be_bytes());
o.extend_from_slice(&max_abs.to_bits().to_be_bytes());
}
Parity::Statistical { fidelity, shots } => {
o.push(3);
o.extend_from_slice(&fidelity.to_bits().to_be_bytes());
o.extend_from_slice(&shots.to_be_bytes());
}
}
}
fn to_json(self) -> Value {
match self {
Parity::Uncertified => json!({"tier": "uncertified"}),
Parity::BitExact => json!({"tier": "bit-exact"}),
Parity::Within { max_ulp, max_abs } => json!({"tier": "within", "max_ulp": max_ulp, "max_abs_bits": format!("{:016x}", max_abs.to_bits())}),
Parity::Statistical { fidelity, shots } => json!({"tier": "statistical", "fidelity_bits": format!("{:016x}", fidelity.to_bits()), "shots": shots}),
}
}
fn from_json(v: &Value) -> Option<Parity> {
let bits = |k: &str| v.get(k)?.as_str().filter(|s| s.len() == 16).and_then(|s| u64::from_str_radix(s, 16).ok()).map(f64::from_bits);
Some(match v.get("tier")?.as_str()? {
"uncertified" => Parity::Uncertified,
"bit-exact" => Parity::BitExact,
"within" => Parity::Within { max_ulp: v.get("max_ulp")?.as_u64()?, max_abs: bits("max_abs_bits")? },
"statistical" => Parity::Statistical { fidelity: bits("fidelity_bits")?, shots: v.get("shots")?.as_u64()? },
_ => return None,
})
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct KernelEntry {
pub kernel: String,
pub implementation: String,
pub certificate: Certificate,
pub energy: Option<(u64, EnergyClass)>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Member {
pub id: String,
pub class: FabricClass,
pub presence: Presence,
pub kernels: Vec<KernelEntry>,
pub detail: String,
}
fn vector_units() -> (Vec<&'static str>, &'static str) {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
let mut v = Vec::new();
if std::is_x86_feature_detected!("sse4.2") {
v.push("sse4.2");
}
if std::is_x86_feature_detected!("avx2") {
v.push("avx2");
}
if std::is_x86_feature_detected!("avx512f") {
v.push("avx512f");
}
(v, "asked of the CPU")
}
#[cfg(target_arch = "aarch64")]
{
let mut v = Vec::new();
if std::arch::is_aarch64_feature_detected!("neon") {
v.push("neon");
}
if std::arch::is_aarch64_feature_detected!("sve") {
v.push("sve");
}
(v, "asked of the CPU")
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")))]
{
let mut v = Vec::new();
if cfg!(target_feature = "simd128") {
v.push("simd128");
}
if cfg!(all(target_arch = "arm", target_feature = "neon")) {
v.push("neon");
}
if cfg!(all(any(target_arch = "riscv32", target_arch = "riscv64"), target_feature = "v")) {
v.push("v");
}
(v, "compiled for, of simd128, neon, v")
}
}
pub fn detect_local() -> Member {
let arch = std::env::consts::ARCH;
let (units, how) = vector_units();
let threads = if cfg!(target_arch = "wasm32") { 1 } else { std::thread::available_parallelism().map_or(1, |n| n.get()) };
let units = if units.is_empty() { "none found".to_string() } else { units.join(", ") };
let id = format!("local/cpu-{arch}");
let reference = |kernel: &str| KernelEntry { kernel: kernel.into(), implementation: REFERENCE.into(), certificate: Certificate::reference(kernel, &id), energy: None };
Member {
kernels: Gateset::ALL.into_iter().map(|gs| reference(apply_kernel(gs))).collect(),
id,
class: FabricClass::Cpu,
presence: Presence::Detected,
detail: format!("{arch}; vector units ({how}): {units}; threads: {threads}"),
}
}
fn certified_for(member: &Member, entry: &KernelEntry, kernel: &str) -> bool {
let c = &entry.certificate;
let own = c.kernel == kernel && c.implementation == entry.implementation && c.member == member.id;
let earned = c.cases > 0 || (entry.implementation == REFERENCE && member.class == FabricClass::Cpu);
entry.kernel == kernel && own && earned
}
pub fn place<'a>(members: &'a [Member], kernel: &str, required: &Parity) -> Option<(&'a Member, &'a KernelEntry)> {
ranked(members, kernel, required).first().map(|&(i, j)| (&members[i], &members[i].kernels[j]))
}
pub fn place_for<'a>(members: &'a [Member], kernel: &str, required: &Parity, predict_pj: impl Fn(&Member, &KernelEntry) -> Option<u64>) -> Option<(&'a Member, &'a KernelEntry)> {
ranked_for(members, kernel, required, &predict_pj).first().map(|&(i, j)| (&members[i], &members[i].kernels[j]))
}
fn ranked(members: &[Member], kernel: &str, required: &Parity) -> Vec<(usize, usize)> {
let mut order: Vec<(usize, usize)> = Vec::new();
for (i, m) in members.iter().enumerate().filter(|(_, m)| m.presence == Presence::Detected) {
for (j, k) in m.kernels.iter().enumerate() {
if certified_for(m, k, kernel) && k.certificate.parity.meets(required) {
order.push((i, j));
}
}
}
let key = |&(i, j): &(usize, usize)| {
let (m, k) = (&members[i], &members[i].kernels[j]);
(k.certificate.provenance.rank(), k.energy.is_none(), k.energy.as_ref().map_or(0, |e| e.0), m.id.as_str(), k.implementation != REFERENCE, k.implementation.as_str())
};
order.sort_by(|a, b| key(a).cmp(&key(b)));
order
}
fn ranked_evenly(members: &[Member], kernel: &str, required: &Parity) -> Vec<(usize, usize)> {
let mut order = ranked(members, kernel, required);
let figured = order.iter().filter(|&&(i, j)| members[i].kernels[j].energy.is_some()).count();
if figured != 0 && figured != order.len() {
let key = |&(i, j): &(usize, usize)| {
let (m, k) = (&members[i], &members[i].kernels[j]);
(k.certificate.provenance.rank(), m.id.as_str(), k.implementation != REFERENCE, k.implementation.as_str())
};
order.sort_by(|a, b| key(a).cmp(&key(b)));
}
order
}
fn ranked_for(members: &[Member], kernel: &str, required: &Parity, predict_pj: &dyn Fn(&Member, &KernelEntry) -> Option<u64>) -> Vec<(usize, usize)> {
let order = ranked_evenly(members, kernel, required);
let predicted: Option<Vec<u64>> = order.iter().map(|&(i, j)| predict_pj(&members[i], &members[i].kernels[j])).collect();
match predicted {
Some(pj) => {
let mut by_energy: Vec<(u64, (usize, usize))> = pj.into_iter().zip(order).collect();
by_energy.sort_by_key(|&(pj, (i, j))| (members[i].kernels[j].certificate.provenance.rank(), pj));
by_energy.into_iter().map(|(_, at)| at).collect()
}
None => order,
}
}
pub fn pair_updates(c: &Circuit) -> u64 {
if c.n_qubits == 0 {
return 0;
}
let per_gate = 1u64.checked_shl(u32::from(c.n_qubits) - 1).unwrap_or(u64::MAX);
(c.ops.len() as u64).saturating_mul(per_gate)
}
pub trait RunMeter {
fn start(&mut self) -> Result<(), String>;
fn stop(&mut self) -> Result<Option<(u64, EnergyClass)>, String>;
}
impl<M: RunMeter + ?Sized> RunMeter for &mut M {
fn start(&mut self) -> Result<(), String> {
(**self).start()
}
fn stop(&mut self) -> Result<Option<(u64, EnergyClass)>, String> {
(**self).stop()
}
}
pub(crate) struct Unmetered;
impl RunMeter for Unmetered {
fn start(&mut self) -> Result<(), String> {
Ok(())
}
fn stop(&mut self) -> Result<Option<(u64, EnergyClass)>, String> {
Ok(None)
}
}
fn accepted(reading: Result<Option<(u64, EnergyClass)>, String>) -> (u64, Option<EnergyClass>) {
match reading {
Ok(Some((joules_micro, class))) if check_label(joules_micro, &class).is_ok() => (joules_micro, Some(class)),
_ => (0, None),
}
}
pub(crate) struct Window<'m, M: RunMeter + ?Sized> {
meter: &'m mut M,
tried: bool,
open: bool,
}
impl<'m, M: RunMeter + ?Sized> Window<'m, M> {
pub(crate) fn new(meter: &'m mut M) -> Self {
Window { meter, tried: false, open: false }
}
pub(crate) fn open(&mut self) {
if !self.tried {
self.tried = true;
self.open = self.meter.start().is_ok();
}
}
pub(crate) fn close(mut self) -> (u64, Option<EnergyClass>) {
if !self.open {
return (0, None);
}
self.open = false;
accepted(self.meter.stop())
}
}
impl<M: RunMeter + ?Sized> Drop for Window<'_, M> {
fn drop(&mut self) {
if self.open {
let _ = self.meter.stop();
}
}
}
#[derive(Clone, Debug, Default)]
pub struct EnergyCalibration {
joules_micro: u64,
ops: u64,
runs: u64,
class: Option<EnergyClass>,
spoiled: bool,
}
impl EnergyCalibration {
pub fn new() -> EnergyCalibration {
EnergyCalibration::default()
}
pub fn add(&mut self, ops: u64, joules_micro: u64, class: Option<&EnergyClass>) {
if self.spoiled {
return;
}
let Some(class) = class.filter(|c| check_label(joules_micro, c).is_ok()) else {
self.spoiled = true;
return;
};
let merged = match &self.class {
None => Some(class.clone()),
Some(seen) => one_class(seen, class),
};
match (merged, self.joules_micro.checked_add(joules_micro), self.ops.checked_add(ops)) {
(Some(c), Some(j), Some(o)) => {
self.class = Some(c);
self.joules_micro = j;
self.ops = o;
self.runs += 1;
}
_ => self.spoiled = true,
}
}
pub fn runs(&self) -> u64 {
self.runs
}
pub fn finish(&self) -> Option<(u64, EnergyClass)> {
if self.spoiled || self.ops == 0 {
return None;
}
let class = self.class.clone()?;
let nanojoules = u128::from(self.joules_micro) * 1000;
let ops = u128::from(self.ops);
let figure = u64::try_from(nanojoules.div_ceil(ops)).ok()?;
let rounding = if nanojoules % ops == 0 { 0 } else { 1_000_000u64.div_ceil(figure) };
let widen = |u: Uncertainty| Some(Uncertainty { relative_ppm: u32::try_from(u64::from(u.relative_ppm) + rounding).ok()?, ..u });
let class = match class {
EnergyClass::OnChipCounter { uncertainty, filtering } => EnergyClass::OnChipCounter { uncertainty: widen(uncertainty)?, filtering },
EnergyClass::CalibratedInstrument { uncertainty, calibration_ref } => EnergyClass::CalibratedInstrument { uncertainty: widen(uncertainty)?, calibration_ref },
other => other,
};
Some((figure, class))
}
}
fn one_class(a: &EnergyClass, b: &EnergyClass) -> Option<EnergyClass> {
let wider = |u: &Uncertainty, v: &Uncertainty| Uncertainty { relative_ppm: u.relative_ppm.max(v.relative_ppm), window_us: u.window_us.saturating_add(v.window_us) };
match (a, b) {
(EnergyClass::ModelBased, EnergyClass::ModelBased) => Some(EnergyClass::ModelBased),
(EnergyClass::Estimator, EnergyClass::Estimator) => Some(EnergyClass::Estimator),
(EnergyClass::OnChipCounter { uncertainty: u, filtering: f }, EnergyClass::OnChipCounter { uncertainty: v, filtering: g }) if f == g => {
Some(EnergyClass::OnChipCounter { uncertainty: wider(u, v), filtering: *f })
}
(EnergyClass::CalibratedInstrument { uncertainty: u, calibration_ref: r }, EnergyClass::CalibratedInstrument { uncertainty: v, calibration_ref: s }) if r == s => {
Some(EnergyClass::CalibratedInstrument { uncertainty: wider(u, v), calibration_ref: r.clone() })
}
_ => None,
}
}
pub fn detect_local_metered(corpus: Corpus, meter: &mut dyn RunMeter) -> Member {
let mut local = detect_local();
for entry in &mut local.kernels {
let Some(gs) = Gateset::ALL.into_iter().find(|&gs| apply_kernel(gs) == entry.kernel) else { continue };
let mut calibration = EnergyCalibration::new();
for c in corpus.circuits(gs) {
let mut window = Window::new(&mut *meter);
window.open();
let ran = std::hint::black_box(c.simulate_from(0));
let (joules_micro, class) = window.close();
let class = if ran.is_ok() { class } else { None };
calibration.add(pair_updates(&c), joules_micro, class.as_ref());
}
entry.energy = calibration.finish();
}
local
}
#[derive(Clone, Debug, PartialEq)]
pub enum Output {
Bits(Vec<u64>),
Fixed { values: Vec<i64>, frac: u32 },
Float(Vec<f64>),
}
impl Output {
fn bytes(&self) -> Vec<u8> {
let mut o = Vec::new();
match self {
Output::Bits(v) => {
o.push(1);
o.extend_from_slice(&(v.len() as u64).to_le_bytes());
v.iter().for_each(|x| o.extend_from_slice(&x.to_le_bytes()));
}
Output::Fixed { values, frac } => {
o.push(2);
o.extend_from_slice(&(values.len() as u64).to_le_bytes());
o.extend_from_slice(&frac.to_le_bytes());
values.iter().for_each(|x| o.extend_from_slice(&x.to_le_bytes()));
}
Output::Float(v) => {
o.push(3);
o.extend_from_slice(&(v.len() as u64).to_le_bytes());
v.iter().for_each(|x| o.extend_from_slice(&x.to_bits().to_le_bytes()));
}
}
o
}
}
fn ordered(x: f64) -> i128 {
let b = x.to_bits() as i64;
if b < 0 { i64::MIN as i128 - b as i128 } else { b as i128 }
}
pub fn compare(reference: &Output, member: &Output) -> Parity {
match (reference, member) {
(Output::Bits(r), Output::Bits(m)) => {
if r == m { Parity::BitExact } else { Parity::Uncertified }
}
(Output::Fixed { values: r, frac: fr }, Output::Fixed { values: m, frac: fm }) => {
if fr != fm || r.len() != m.len() || *fr >= 64 {
return Parity::Uncertified;
}
if r == m {
return Parity::BitExact;
}
let ulp = r.iter().zip(m).map(|(a, b)| (*a as i128 - *b as i128).unsigned_abs()).max().unwrap_or(0);
let Ok(ulp) = u64::try_from(ulp) else { return Parity::Uncertified };
Parity::Within { max_ulp: ulp, max_abs: ulp as f64 * 2f64.powi(-(*fr as i32)) }
}
(Output::Float(r), Output::Float(m)) => {
if r.len() != m.len() || r.iter().chain(m).any(|x| !x.is_finite()) {
return Parity::Uncertified;
}
if r.iter().zip(m).all(|(a, b)| a.to_bits() == b.to_bits()) {
return Parity::BitExact;
}
let (mut ulp, mut abs) = (0u128, 0f64);
for (a, b) in r.iter().zip(m) {
ulp = ulp.max((ordered(*a) - ordered(*b)).unsigned_abs());
abs = abs.max((a - b).abs());
}
match u64::try_from(ulp) {
Ok(u) => Parity::Within { max_ulp: u, max_abs: abs },
Err(_) => Parity::Uncertified,
}
}
_ => Parity::Uncertified,
}
}
pub fn statistical(reference: &[f64], counts: &[u64]) -> Parity {
let total: f64 = reference.iter().sum();
let shots = counts.iter().try_fold(0u64, |acc, &c| acc.checked_add(c));
let Some(shots) = shots else { return Parity::Uncertified };
if reference.len() != counts.len() || shots == 0 || !total.is_finite() || total <= 0.0 || reference.iter().any(|p| !p.is_finite() || *p < 0.0) {
return Parity::Uncertified;
}
let overlap: f64 = reference.iter().zip(counts).map(|(p, &c)| (p / total * c as f64 / shots as f64).sqrt()).sum();
Parity::Statistical { fidelity: (overlap * overlap).min(1.0), shots }
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub enum Provenance {
#[default]
Silicon,
Emulator(String),
Simulator(String),
}
impl Provenance {
pub fn label(&self) -> String {
match self {
Provenance::Silicon => "silicon".into(),
Provenance::Emulator(n) => format!("emulator:{n}"),
Provenance::Simulator(n) => format!("simulator:{n}"),
}
}
fn rank(&self) -> u8 {
match self {
Provenance::Silicon => 0,
Provenance::Emulator(_) => 1,
Provenance::Simulator(_) => 2,
}
}
fn write(&self, o: &mut Vec<u8>) {
match self {
Provenance::Silicon => {}
Provenance::Emulator(n) => {
o.push(1);
put(o, n.as_bytes());
}
Provenance::Simulator(n) => {
o.push(2);
put(o, n.as_bytes());
}
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Certificate {
pub kernel: String,
pub implementation: String,
pub member: String,
pub generator: String,
pub parity: Parity,
pub cases: u64,
pub corpus: [u8; 32],
pub provenance: Provenance,
}
impl Certificate {
pub fn reference(kernel: &str, member: &str) -> Certificate {
Certificate {
kernel: kernel.into(),
implementation: REFERENCE.into(),
member: member.into(),
generator: "definition".into(),
parity: Parity::BitExact,
cases: 0,
corpus: [0; 32],
provenance: Provenance::Silicon,
}
}
pub fn with_provenance(self, provenance: Provenance) -> Certificate {
Certificate { provenance, ..self }
}
pub fn hash(&self) -> [u8; 32] {
let mut o = DOMAIN_CERT.to_vec();
for s in [&self.kernel, &self.implementation, &self.member, &self.generator] {
put(&mut o, s.as_bytes());
}
self.parity.write_signed(&mut o);
o.extend_from_slice(&self.cases.to_be_bytes());
o.extend_from_slice(&self.corpus);
self.provenance.write(&mut o);
content_hash(&o)
}
}
#[derive(Clone, Debug)]
pub struct Certification {
hasher: blake3::Hasher,
parity: Option<Parity>,
cases: u64,
}
impl Certification {
pub fn new() -> Certification {
let mut hasher = blake3::Hasher::new();
hasher.update(DOMAIN_CORPUS);
Certification { hasher, parity: None, cases: 0 }
}
pub fn add(&mut self, input: &[u8], reference: &Output, member: &Output) {
let (r, m) = (reference.bytes(), member.bytes());
for bytes in [input, r.as_slice(), m.as_slice()] {
self.hasher.update(&(bytes.len() as u64).to_le_bytes());
self.hasher.update(bytes);
}
let p = compare(reference, member);
self.parity = Some(self.parity.map_or(p, |q| q.worst(p)));
self.cases += 1;
}
pub fn cases(&self) -> u64 {
self.cases
}
pub fn finish(self, kernel: &str, implementation: &str, member: &str, generator: &str) -> Certificate {
Certificate {
kernel: kernel.into(),
implementation: implementation.into(),
member: member.into(),
generator: generator.into(),
parity: self.parity.unwrap_or(Parity::Uncertified),
cases: self.cases,
corpus: *self.hasher.finalize().as_bytes(),
provenance: Provenance::Silicon,
}
}
}
impl Default for Certification {
fn default() -> Self {
Self::new()
}
}
pub fn certify(kernel: &str, implementation: &str, member: &str, generator: &str, cases: impl IntoIterator<Item = (Vec<u8>, Output, Output)>) -> Certificate {
let mut c = Certification::new();
for (input, reference, out) in cases {
c.add(&input, &reference, &out);
}
c.finish(kernel, implementation, member, generator)
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Corpus {
Random { seed: u64, cases: usize },
Fabric { seed: u64, cases: usize, wide: usize },
}
pub const FABRIC_DEFAULT: Corpus = Corpus::Fabric { seed: 7, cases: 200, wide: 24 };
impl Corpus {
pub fn generator(&self, gs: Gateset) -> String {
match *self {
Corpus::Random { seed, cases } => format!("{} seed={seed} cases={cases}", random_generator(gs)),
Corpus::Fabric { seed, cases, wide } => format!("{} seed={seed} cases={cases} wide={wide}", fabric_generator(gs)),
}
}
pub fn name(&self) -> &'static str {
match self {
Corpus::Random { .. } => "random-v1",
Corpus::Fabric { .. } => "fabric-v1",
}
}
pub fn circuits(&self, gs: Gateset) -> Vec<Circuit> {
let (seed, cases, wide) = match *self {
Corpus::Random { seed, cases } => (seed, cases, 0),
Corpus::Fabric { seed, cases, wide } => (seed, cases, wide),
};
let mut s = seed;
let mut v: Vec<Circuit> = (0..cases).map(|_| lanes::random_circuit(&mut s, gs)).collect();
v.extend((0..wide).map(|_| lanes::random_wide_circuit(&mut s, gs)));
v
}
}
pub fn certify_lanes(gs: Gateset, member: &str, circuits: usize, seed: u64) -> Certificate {
lanes::certify_corpus(gs, member, Corpus::Random { seed, cases: circuits })
}
pub fn certify_sampling(kernel: &str, implementation: &str, member: &str, generator: &str, cases: impl IntoIterator<Item = (Vec<u8>, Vec<f64>, Vec<u64>)>) -> Certificate {
let mut h = blake3::Hasher::new();
h.update(DOMAIN_CORPUS);
let mut parity: Option<Parity> = None;
let mut n = 0u64;
for (input, weights, counts) in cases {
for bytes in [input, Output::Float(weights.clone()).bytes(), Output::Bits(counts.clone()).bytes()] {
h.update(&(bytes.len() as u64).to_le_bytes());
h.update(&bytes);
}
let p = statistical(&weights, &counts);
parity = Some(parity.map_or(p, |q| q.worst(p)));
n += 1;
}
Certificate {
kernel: kernel.into(),
implementation: implementation.into(),
member: member.into(),
generator: generator.into(),
parity: parity.unwrap_or(Parity::Uncertified),
cases: n,
corpus: *h.finalize().as_bytes(),
provenance: Provenance::Silicon,
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct FabricReceipt {
pub result_hash: [u8; 32],
pub kernel: String,
pub implementation: String,
pub member_id: String,
pub class: FabricClass,
pub presence: Presence,
pub parity: Parity,
pub certificate_hash: [u8; 32],
pub joules_micro: u64,
pub energy_class: Option<EnergyClass>,
pub signer_pubkey: [u8; 32],
pub signer_id: String,
pub sig: [u8; 64],
}
impl FabricReceipt {
fn signing_payload(&self) -> Vec<u8> {
let mut o = DOMAIN_FABRIC.to_vec();
o.extend_from_slice(&self.result_hash);
for s in [&self.kernel, &self.implementation, &self.member_id] {
put(&mut o, s.as_bytes());
}
put(&mut o, self.class.label().as_bytes());
put(&mut o, self.presence.label().as_bytes());
self.parity.write_signed(&mut o);
o.extend_from_slice(&self.certificate_hash);
o.extend_from_slice(&self.joules_micro.to_be_bytes());
match &self.energy_class {
None => o.push(0),
Some(c) => c.write_signed(&mut o),
}
o.extend_from_slice(&self.signer_pubkey);
put(&mut o, self.signer_id.as_bytes());
o
}
pub fn seal(signer: &SigningKey, signer_id: impl Into<String>, result_hash: [u8; 32], member: &Member, entry: &KernelEntry, joules_micro: u64, energy_class: Option<EnergyClass>) -> FabricReceipt {
let mut r = FabricReceipt {
result_hash,
kernel: entry.kernel.clone(),
implementation: entry.implementation.clone(),
member_id: member.id.clone(),
class: member.class,
presence: member.presence,
parity: entry.certificate.parity,
certificate_hash: entry.certificate.hash(),
joules_micro,
energy_class,
signer_pubkey: signer.verifying_key().to_bytes(),
signer_id: signer_id.into(),
sig: [0; 64],
};
r.sig = signer.sign(&r.signing_payload()).to_bytes();
r
}
pub fn verify(&self) -> bool {
if self.parity == Parity::Uncertified {
return false;
}
let labelled = match &self.energy_class {
None => self.joules_micro == 0,
Some(c) => check_label(self.joules_micro, c).is_ok(),
};
if !labelled {
return false;
}
let Ok(k) = VerifyingKey::from_bytes(&self.signer_pubkey) else {
return false;
};
k.verify(&self.signing_payload(), &Signature::from_bytes(&self.sig)).is_ok()
}
pub fn certificate_matches(&self, certificate: &Certificate) -> bool {
certificate.hash() == self.certificate_hash
&& certificate.parity == self.parity
&& certificate.kernel == self.kernel
&& certificate.implementation == self.implementation
&& certificate.member == self.member_id
}
pub fn receipt_hash(&self) -> [u8; 32] {
let mut h = blake3::Hasher::new();
h.update(DOMAIN_FABRIC_ID);
h.update(&self.signing_payload());
h.update(&self.sig);
*h.finalize().as_bytes()
}
pub fn to_json(&self) -> String {
let hex = |b: &[u8]| b.iter().map(|x| format!("{x:02x}")).collect::<String>();
let mut m = Map::new();
m.insert("capability".into(), json!(CAP_QUANTUM_FABRIC));
m.insert("result_hash".into(), json!(hex(&self.result_hash)));
m.insert("kernel".into(), json!(self.kernel));
m.insert("implementation".into(), json!(self.implementation));
m.insert("member_id".into(), json!(self.member_id));
m.insert("class".into(), json!(self.class.label()));
m.insert("presence".into(), json!(self.presence.label()));
m.insert("parity".into(), self.parity.to_json());
m.insert("certificate_hash".into(), json!(hex(&self.certificate_hash)));
m.insert("joules_micro".into(), json!(self.joules_micro));
if let Some(c) = &self.energy_class {
let mut e = Map::new();
for (k, v) in c.json_fields() {
e.insert(k.into(), v);
}
m.insert("energy_class".into(), Value::Object(e));
}
m.insert("signer_pubkey".into(), json!(hex(&self.signer_pubkey)));
m.insert("signer_id".into(), json!(self.signer_id));
m.insert("sig".into(), json!(hex(&self.sig)));
Value::Object(m).to_string()
}
pub fn from_json(s: &str) -> Option<FabricReceipt> {
let v: Value = serde_json::from_str(s).ok()?;
if v.get("capability")?.as_str()? != CAP_QUANTUM_FABRIC {
return None;
}
fn unhex<const N: usize>(s: &str) -> Option<[u8; N]> {
if s.len() != 2 * N || !s.bytes().all(|b| b.is_ascii_hexdigit()) {
return None;
}
let mut out = [0u8; N];
for (i, c) in s.as_bytes().chunks(2).enumerate() {
out[i] = u8::from_str_radix(std::str::from_utf8(c).ok()?, 16).ok()?;
}
Some(out)
}
let st = |k: &str| v.get(k).and_then(Value::as_str);
let energy_class = match v.get("energy_class") {
None => None,
Some(e) => Some(EnergyClass::from_json_object(e.as_object()?).ok()??),
};
Some(FabricReceipt {
result_hash: unhex(st("result_hash")?)?,
kernel: st("kernel")?.into(),
implementation: st("implementation")?.into(),
member_id: st("member_id")?.into(),
class: FabricClass::from_label(st("class")?)?,
presence: Presence::from_label(st("presence")?)?,
parity: Parity::from_json(v.get("parity")?)?,
certificate_hash: unhex(st("certificate_hash")?)?,
joules_micro: v.get("joules_micro")?.as_u64()?,
energy_class,
signer_pubkey: unhex(st("signer_pubkey")?)?,
signer_id: st("signer_id")?.into(),
sig: unhex(st("sig")?)?,
})
}
}
#[derive(Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum MemberError {
TooWide { n_qubits: u8, max: u8 },
OutOfRange { gate: u32 },
Memory(String),
Timeout,
Device(String),
Circuit(QuantumError),
Other(String),
}
impl MemberError {
pub fn falls_back(&self) -> bool {
matches!(self, MemberError::TooWide { .. } | MemberError::OutOfRange { .. } | MemberError::Memory(_) | MemberError::Timeout | MemberError::Device(_))
}
}
impl std::fmt::Display for MemberError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MemberError::TooWide { n_qubits, max } => write!(f, "{n_qubits} qubits; the member holds at most {max}"),
MemberError::OutOfRange { gate } => write!(f, "the result of op {gate} leaves the member's range"),
MemberError::Memory(e) => write!(f, "out of memory: {e}"),
MemberError::Timeout => write!(f, "a wait on the member passed its time limit"),
MemberError::Device(e) => write!(f, "device: {e}"),
MemberError::Circuit(e) => write!(f, "{e}"),
MemberError::Other(e) => write!(f, "{e}"),
}
}
}
impl std::error::Error for MemberError {}
pub type RunFuture<'r> = Pin<Box<dyn Future<Output = Result<(StateVector, u64, Option<EnergyClass>), MemberError>> + 'r>>;
pub trait Runner {
fn member_id(&self) -> String;
fn run<'r>(&'r self, implementation: &'r str, c: &'r Circuit, start: usize, meter: &'r mut dyn RunMeter) -> RunFuture<'r>;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct CpuReference;
impl<R: Runner + ?Sized> Runner for &R {
fn member_id(&self) -> String {
(**self).member_id()
}
fn run<'r>(&'r self, implementation: &'r str, c: &'r Circuit, start: usize, meter: &'r mut dyn RunMeter) -> RunFuture<'r> {
(**self).run(implementation, c, start, meter)
}
}
impl Runner for CpuReference {
fn member_id(&self) -> String {
detect_local().id
}
fn run<'r>(&'r self, implementation: &'r str, c: &'r Circuit, start: usize, meter: &'r mut dyn RunMeter) -> RunFuture<'r> {
Box::pin(async move {
if implementation != REFERENCE {
return Err(MemberError::Other(format!("the CPU reference does not run implementation {implementation:?}")));
}
let mut window = Window::new(meter);
window.open();
let state = c.simulate_from(start).map_err(MemberError::Circuit)?;
let (joules_micro, class) = window.close();
Ok((state, joules_micro, class))
})
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Refused {
pub member_id: String,
pub implementation: String,
pub error: MemberError,
}
#[derive(Debug)]
pub struct FabricRun {
pub state: StateVector,
pub receipt: FabricReceipt,
pub refusals: Vec<Refused>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct FabricError {
pub refusals: Vec<Refused>,
}
impl std::fmt::Display for FabricError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.refusals.is_empty() {
return write!(f, "no member offers a certified kernel that meets the requirement");
}
write!(f, "no member produced the result:")?;
for r in &self.refusals {
write!(f, " {} ({}): {};", r.member_id, r.implementation, r.error)?;
}
Ok(())
}
}
impl std::error::Error for FabricError {}
pub fn ready<F: Future>(future: F) -> Option<F::Output> {
let mut future = core::pin::pin!(future);
match future.as_mut().poll(&mut core::task::Context::from_waker(core::task::Waker::noop())) {
core::task::Poll::Ready(output) => Some(output),
core::task::Poll::Pending => None,
}
}
type Model<'a> = Box<dyn Fn(&Member, &KernelEntry, &Circuit) -> Option<u64> + 'a>;
#[derive(Default)]
pub struct Fabric<'a> {
members: Vec<Member>,
runners: Vec<(Box<dyn Runner + 'a>, Option<Box<dyn RunMeter + 'a>>)>,
model: Option<Model<'a>>,
}
impl<'a> Fabric<'a> {
pub fn new() -> Fabric<'a> {
Fabric::default()
}
pub fn add(&mut self, member: Member, runner: impl Runner + 'a) -> &mut Self {
self.members.push(member);
self.runners.push((Box::new(runner), None));
self
}
pub fn add_metered(&mut self, member: Member, runner: impl Runner + 'a, meter: impl RunMeter + 'a) -> &mut Self {
self.members.push(member);
self.runners.push((Box::new(runner), Some(Box::new(meter))));
self
}
pub fn set_model(&mut self, model: impl Fn(&Member, &KernelEntry, &Circuit) -> Option<u64> + 'a) -> &mut Self {
self.model = Some(Box::new(model));
self
}
pub fn members(&self) -> &[Member] {
&self.members
}
fn ranked(&self, c: &Circuit, required: &Parity) -> Vec<(usize, usize)> {
let kernel = apply_kernel(c.gateset);
match &self.model {
Some(model) => ranked_for(&self.members, kernel, required, &|m: &Member, k: &KernelEntry| model(m, k, c)),
None => ranked_evenly(&self.members, kernel, required),
}
}
pub fn order(&self, c: &Circuit, required: &Parity) -> Vec<(&Member, &KernelEntry)> {
self.ranked(c, required).into_iter().map(|(i, j)| (&self.members[i], &self.members[i].kernels[j])).collect()
}
pub async fn run(&mut self, c: &Circuit, start: usize, required: &Parity, signer: &SigningKey, signer_id: &str) -> Result<FabricRun, FabricError> {
let mut refusals = Vec::new();
for (i, j) in self.ranked(c, required) {
let member = &self.members[i];
let entry = &member.kernels[j];
let (runner, meter) = &mut self.runners[i];
let runner_is = runner.member_id();
if runner_is != member.id {
let error = MemberError::Other(format!("member {} is paired with a runner that is member {runner_is}", member.id));
refusals.push(Refused { member_id: member.id.clone(), implementation: entry.implementation.clone(), error });
break;
}
let mut unmetered = Unmetered;
let meter: &mut dyn RunMeter = match meter {
Some(m) => m.as_mut(),
None => &mut unmetered,
};
match runner.run(&entry.implementation, c, start, meter).await {
Ok((state, joules_micro, class)) => {
let (joules_micro, class) = accepted(Ok(class.map(|cl| (joules_micro, cl))));
let receipt = FabricReceipt::seal(signer, signer_id, state.statevector_hash(), member, entry, joules_micro, class);
return Ok(FabricRun { state, receipt, refusals });
}
Err(error) => {
let stop = !error.falls_back();
refusals.push(Refused { member_id: member.id.clone(), implementation: entry.implementation.clone(), error });
if stop {
break;
}
}
}
}
Err(FabricError { refusals })
}
}
pub mod lanes {
use super::{Certificate, Certification, Circuit, Corpus, FRAC, MAX_QUBITS, Output, QuantumError, apply_kernel, plan};
use crate::quantum::{BaseGate, Gate, Gateset, ONE};
pub fn mul_wide(a: i32, b: i32) -> (u32, u32) {
let negative = (a < 0) != (b < 0);
let (x, y) = (a.unsigned_abs(), b.unsigned_abs());
let (x1, x0) = (x >> 16, x & 0xffff);
let (y1, y0) = (y >> 16, y & 0xffff);
let p00 = x0.wrapping_mul(y0);
let p01 = x0.wrapping_mul(y1);
let p10 = x1.wrapping_mul(y0);
let p11 = x1.wrapping_mul(y1);
let mid = p01.wrapping_add(p10);
let mid_carry = u32::from(mid < p01);
let lo = p00.wrapping_add(mid << 16);
let lo_carry = u32::from(lo < p00);
let hi = p11.wrapping_add(mid >> 16).wrapping_add(mid_carry << 16).wrapping_add(lo_carry);
if negative {
let lo_n = (!lo).wrapping_add(1);
let hi_n = (!hi).wrapping_add(u32::from(lo_n == 0));
(hi_n, lo_n)
} else {
(hi, lo)
}
}
pub fn fxmul(a: i32, b: i32) -> i32 {
let (hi, lo) = mul_wide(a, b);
let lo2 = lo.wrapping_add(1 << 29);
let hi2 = hi.wrapping_add(u32::from(lo2 < lo));
((lo2 >> 30) | (hi2 << 2)) as i32
}
pub type Lane = [i32; 2];
fn cmul(a: Lane, b: Lane) -> Lane {
[fxmul(a[0], b[0]).wrapping_sub(fxmul(a[1], b[1])), fxmul(a[0], b[1]).wrapping_add(fxmul(a[1], b[0]))]
}
fn cadd(a: Lane, b: Lane) -> Lane {
[a[0].wrapping_add(b[0]), a[1].wrapping_add(b[1])]
}
fn matrix(g: &Gate, gs: Gateset) -> [[Lane; 2]; 2] {
let m = g.base.matrix(g.param, gs);
let l = |a: crate::quantum::Amp| [a.re as i32, a.im as i32];
[[l(m[0][0]), l(m[0][1])], [l(m[1][0]), l(m[1][1])]]
}
pub fn apply(amps: &mut [Lane], target: u8, ctrl_mask: usize, m: [[Lane; 2]; 2]) {
let tbit = 1usize << target;
for i in 0..amps.len() {
if i & tbit == 0 && i & ctrl_mask == ctrl_mask {
let j = i | tbit;
let (a0, a1) = (amps[i], amps[j]);
amps[i] = cadd(cmul(m[0][0], a0), cmul(m[0][1], a1));
amps[j] = cadd(cmul(m[1][0], a0), cmul(m[1][1], a1));
}
}
}
pub fn simulate(c: &Circuit) -> Result<Vec<Lane>, QuantumError> {
c.validate()?;
if c.n_qubits > MAX_QUBITS {
return Err(QuantumError::TooManyQubits(c.n_qubits));
}
let mut amps = vec![[0i32; 2]; 1usize << c.n_qubits];
amps[0] = [ONE as i32, 0];
for g in &c.ops {
let mask = g.controls.iter().fold(0usize, |acc, &q| acc | (1usize << q));
apply(&mut amps, g.target, mask, matrix(g, c.gateset));
}
Ok(amps)
}
fn next(s: &mut u64) -> u64 {
*s = s.wrapping_add(0x9E37_79B9_7F4A_7C15);
let mut z = *s;
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
z ^ (z >> 31)
}
pub fn random_circuit(s: &mut u64, gs: Gateset) -> Circuit {
let n = 2 + (next(s) % 9) as u8;
random_ops(s, gs, n)
}
pub fn random_wide_circuit(s: &mut u64, gs: Gateset) -> Circuit {
let n = 11 + (next(s) % 7) as u8;
random_ops(s, gs, n)
}
fn random_ops(s: &mut u64, gs: Gateset, n: u8) -> Circuit {
let mut c = Circuit::with_gateset(n, gs);
let bases = [BaseGate::I, BaseGate::X, BaseGate::Y, BaseGate::Z, BaseGate::H, BaseGate::S, BaseGate::Sdg, BaseGate::T, BaseGate::Tdg, BaseGate::P];
for _ in 0..(10 + next(s) % 50) {
let base = bases[(next(s) % bases.len() as u64) as usize];
let target = (next(s) % n as u64) as u8;
let mut controls = Vec::new();
for _ in 0..(next(s) % 4) {
let q = (next(s) % n as u64) as u8;
if q != target && !controls.contains(&q) {
controls.push(q);
}
}
let param = if base == BaseGate::P { 1 + (next(s) % 32) as u16 } else { 0 };
c.ops.push(Gate { base, controls, target, param });
}
c
}
pub fn circuit_bytes(c: &Circuit) -> Vec<u8> {
let mut o = vec![c.n_qubits];
for g in &c.ops {
o.push(g.base.opcode());
o.push(g.target);
o.extend_from_slice(&g.param.to_le_bytes());
o.extend_from_slice(&(g.controls.len() as u64).to_le_bytes());
o.extend_from_slice(&g.controls);
}
o
}
pub fn output(lanes: &[Lane]) -> Output {
Output::Fixed { values: lanes.iter().flat_map(|a| [i64::from(a[0]), i64::from(a[1])]).collect(), frac: FRAC }
}
pub fn reference_output(c: &Circuit) -> Result<Output, QuantumError> {
let native = c.simulate_from(0)?;
Ok(Output::Fixed { values: native.amps.iter().flat_map(|a| [a.re, a.im]).collect(), frac: FRAC })
}
pub fn certify_corpus(gs: Gateset, member: &str, corpus: Corpus) -> Certificate {
let mut cert = Certification::new();
for c in corpus.circuits(gs) {
let reference = reference_output(&c).expect("corpus circuits are valid");
let port = output(&simulate(&c).expect("corpus circuits are valid"));
cert.add(&circuit_bytes(&c), &reference, &port);
}
cert.finish(apply_kernel(gs), "lanes32", member, &corpus.generator(gs))
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct GateWords {
pub m: [u32; 8],
pub tbit: u32,
pub ctrl: u32,
}
pub fn gate_words(g: &Gate, gs: Gateset) -> GateWords {
let m = g.base.matrix(g.param, gs);
let w = |a: crate::quantum::Amp| [a.re as i32 as u32, a.im as i32 as u32];
let ([a, b], [c, d], [e, f], [h, k]) = (w(m[0][0]), w(m[0][1]), w(m[1][0]), w(m[1][1]));
GateWords { m: [a, b, c, d, e, f, h, k], tbit: 1 << g.target, ctrl: g.controls.iter().fold(0, |acc, &q| acc | 1 << q) }
}
fn fx_exact(a: i32, b: i32) -> i64 {
(i64::from(a) * i64::from(b) + (1 << 29)) >> 30
}
pub fn fxmul_wide(a: i32, b: i32) -> (u32, u32) {
let v = fx_exact(a, b);
((v >> 32) as u32, v as u32)
}
pub const PROBE_EDGES: [i32; 22] = [
0,
1,
-1,
2,
-2,
1 << 29,
-(1 << 29),
(1 << 30) - 1,
-((1 << 30) - 1),
1 << 30,
-(1 << 30),
46341,
-46341,
3 << 29,
-(3 << 29),
65535,
-65535,
65536,
-65536,
i32::MAX,
i32::MIN,
i32::MIN + 1,
];
#[doc(hidden)]
pub fn probe_pairs(random: usize, seed: u64) -> Vec<(i32, i32)> {
let edges = PROBE_EDGES;
let mut pairs: Vec<(i32, i32)> = edges.iter().flat_map(|&a| edges.iter().map(move |&b| (a, b))).collect();
let mut s = seed;
pairs.extend((0..random).map(|_| (next(&mut s) as i32, next(&mut s) as i32)));
pairs
}
#[doc(hidden)]
pub fn first_mismatch(pairs: &[(i32, i32)], out: &[((u32, u32), (u32, u32))]) -> Option<(i32, i32)> {
if pairs.len() != out.len() {
return pairs.first().copied().or(Some((0, 0)));
}
pairs.iter().zip(out).find(|((a, b), o)| **o != (mul_wide(*a, *b), fxmul_wide(*a, *b))).map(|(p, _)| *p)
}
pub fn apply_words(amps: &mut [Lane], w: &GateWords) -> Option<bool> {
let len = amps.len();
if len < 2 || !len.is_power_of_two() {
return None;
}
let (tbit, ctrl) = (w.tbit as usize, w.ctrl as usize);
if tbit == 0 || !tbit.is_power_of_two() || tbit > len / 2 || ctrl & tbit != 0 || ctrl & !(len - 1) != 0 {
return None;
}
let mut fits = true;
for i in 0..len {
if i & tbit == 0 && i & ctrl == ctrl {
let j = i | tbit;
let (a0, a1) = (amps[i], amps[j]);
let (o0, o1) = (exact_row(w, 0, a0, a1), exact_row(w, 1, a0, a1));
fits &= o0.iter().chain(&o1).all(|v| i32::try_from(*v).is_ok());
amps[i] = [o0[0] as i32, o0[1] as i32];
amps[j] = [o1[0] as i32, o1[1] as i32];
}
}
Some(fits)
}
pub(super) fn exact_row(w: &GateWords, r: usize, a0: Lane, a1: Lane) -> [i64; 2] {
let e = |k: usize| w.m[k] as i32;
let (mr, mi, nr, ni) = (e(4 * r), e(4 * r + 1), e(4 * r + 2), e(4 * r + 3));
[
fx_exact(mr, a0[0]) - fx_exact(mi, a0[1]) + fx_exact(nr, a1[0]) - fx_exact(ni, a1[1]),
fx_exact(mr, a0[1]) + fx_exact(mi, a0[0]) + fx_exact(nr, a1[1]) + fx_exact(ni, a1[0]),
]
}
pub fn run_words(state: &[Lane], gates: &[GateWords]) -> Option<plan::LaneRun> {
let mut amps = state.to_vec();
let mut out_of_range = None;
for (k, w) in gates.iter().enumerate() {
if !apply_words(&mut amps, w)? && out_of_range.is_none() {
out_of_range = Some(k as u32);
}
}
Some(plan::LaneRun { amps, out_of_range })
}
pub fn simulate_checked(c: &Circuit, start: usize) -> Result<plan::LaneRun, QuantumError> {
Ok(plan::execute(&plan::compile(c, start)?))
}
fn ceil_sqrt(x: u128) -> u128 {
let r = x.isqrt();
if r * r < x { r + 1 } else { r }
}
pub(super) fn table_excess(gs: Gateset) -> u128 {
const S: u128 = 1 << 60;
let excess = |sq: u128| ceil_sqrt(sq * S).saturating_sub(S);
let sq = |re: i64, im: i64| (re.unsigned_abs() as u128).pow(2) + (im.unsigned_abs() as u128).pow(2);
let h = gs.inv_sqrt2();
gs.table()[1..].iter().map(|p| excess(sq(p.re, p.im))).chain([excess(2 * sq(h, 0))]).max().unwrap_or(0)
}
pub fn horizon(n_qubits: u8, gs: Gateset) -> u64 {
const S: u128 = 1 << 60;
if n_qubits >= 58 {
return 0;
}
let e = ceil_sqrt(1u128 << (63 + u32::from(n_qubits)));
((S - 1) / (e + 2 * table_excess(gs))) as u64
}
}
pub mod cuda;
pub mod fpga;
pub mod opencl;
pub mod plan;
pub mod sampling;
#[cfg(feature = "quantum_sv")]
pub mod sv64;
pub mod vqpu;
pub mod wgsl;
const _: () = assert!(ONE <= i32::MAX as i64);
#[cfg(test)]
mod tests {
use super::*;
use crate::quantum::{BaseGate, Gate, Gateset, fxmul};
use crate::quantum_energy::{CounterFiltering, Uncertainty};
#[test]
fn provenance_leaves_a_silicon_certificates_hash_as_it_was() {
let c = Certificate {
kernel: KERNEL_CIRCUIT2_APPLY.into(),
implementation: "impl".into(),
member: "local/x".into(),
generator: "g".into(),
parity: Parity::BitExact,
cases: 3,
corpus: [9; 32],
provenance: Provenance::Silicon,
};
let mut o = DOMAIN_CERT.to_vec();
for s in [&c.kernel, &c.implementation, &c.member, &c.generator] {
put(&mut o, s.as_bytes());
}
c.parity.write_signed(&mut o);
o.extend_from_slice(&c.cases.to_be_bytes());
o.extend_from_slice(&c.corpus);
assert_eq!(c.hash(), content_hash(&o), "the pre-provenance encoding");
let emulated = c.clone().with_provenance(Provenance::Emulator("qemu-user 8.2".into()));
let simulated = c.clone().with_provenance(Provenance::Simulator("qemu-user 8.2".into()));
assert_ne!(emulated.hash(), c.hash());
assert_ne!(simulated.hash(), c.hash());
assert_ne!(emulated.hash(), simulated.hash());
assert_ne!(emulated.hash(), c.clone().with_provenance(Provenance::Emulator("qemu-user 8.3".into())).hash());
assert_eq!(Certificate::reference("k", "m").provenance, Provenance::Silicon);
assert_eq!(Provenance::default(), Provenance::Silicon);
assert_eq!((Provenance::Silicon.rank(), emulated.provenance.rank(), simulated.provenance.rank()), (0, 1, 2));
}
fn next(s: &mut u64) -> u64 {
*s = s.wrapping_add(0x9E37_79B9_7F4A_7C15);
let mut z = *s;
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_lane_multiply_is_the_native_one() {
let one = ONE as i32;
let edges = [0, 1, -1, 2, -2, one, -one, one - 1, -(one - 1), one / 2, -(one / 2), i32::MIN / 2, 46341, -46341];
let mut cases: Vec<(i32, i32)> = edges.iter().flat_map(|&a| edges.iter().map(move |&b| (a, b))).collect();
let mut s = 11u64;
for _ in 0..200_000 {
let a = (next(&mut s) % (2 * ONE as u64 + 1)) as i64 - ONE;
let b = (next(&mut s) % (2 * ONE as u64 + 1)) as i64 - ONE;
cases.push((a as i32, b as i32));
}
for (a, b) in cases {
assert_eq!(lanes::fxmul(a, b) as i64, fxmul(a as i64, b as i64), "{a} × {b}");
}
let wide = [0, 1, -1, i32::MAX, i32::MIN, i32::MIN + 1, one, -one, 65535, -65536];
let mut all: Vec<(i32, i32)> = wide.iter().flat_map(|&a| wide.iter().map(move |&b| (a, b))).collect();
for _ in 0..200_000 {
all.push((next(&mut s) as i32, next(&mut s) as i32));
}
for (a, b) in all {
let (hi, lo) = lanes::mul_wide(a, b);
assert_eq!(((hi as u64) << 32 | lo as u64) as i64, a as i64 * b as i64, "{a} × {b} wide");
}
let (a, b) = (1 << 30, i32::MAX); assert_eq!(lanes::fxmul(a, b) as i64, fxmul(a as i64, b as i64));
let (a, b) = (2_147_450_880, 1_073_758_208); assert_eq!(a as i64 * b as i64, (1i64 << 61) - (1 << 29));
assert_ne!(lanes::fxmul(a, b) as i64, fxmul(a as i64, b as i64));
}
#[test]
fn the_lane_simulator_is_the_native_one() {
for gs in Gateset::ALL {
let cert = certify_lanes(gs, "local/test", 300, 7);
assert_eq!(cert.parity, Parity::BitExact, "{cert:?}");
assert_eq!(cert.cases, 300);
assert_eq!(cert.generator, format!("{} seed=7 cases=300", random_generator(gs)));
assert_eq!(certify_lanes(gs, "local/test", 300, 7).hash(), cert.hash());
assert_ne!(certify_lanes(gs, "local/test", 300, 8).corpus, cert.corpus);
let mut s = 7u64;
let spread = (0..300).filter(|_| lanes::simulate(&lanes::random_circuit(&mut s, gs)).unwrap().iter().filter(|a| a[0] != 0 || a[1] != 0).count() >= 4).count();
assert!(spread >= 100, "{gs:?}: {spread} of 300 circuits spread over four amplitudes or more");
}
}
fn hex(b: &[u8]) -> String {
b.iter().map(|x| format!("{x:02x}")).collect()
}
#[test]
fn the_lanes32_corpus_of_each_gateset_is_pinned() {
let v1 = certify_lanes(Gateset::V1, "local/test", 200, 7);
assert_eq!(v1.parity, Parity::BitExact, "{v1:?}");
assert_eq!(hex(&v1.corpus), "d18454c639acfd9c7b66450f4ded1aac4ab46cc10a7bedbcf4958a96e204fb36");
let v2 = certify_lanes(Gateset::V2, "local/test", 200, 7);
assert_eq!(v2.parity, Parity::BitExact, "{v2:?}");
assert_eq!(hex(&v2.corpus), "3dbde276c1095bf827faec71d5980e050f8a55a5ba7d97cd3bbdaec3f43a13b2");
}
#[test]
fn a_v2_certificate_is_its_own() {
let v1 = certify_lanes(Gateset::V1, "local/test", 40, 7);
let v2 = certify_lanes(Gateset::V2, "local/test", 40, 7);
assert_eq!((v1.kernel.as_str(), v2.kernel.as_str()), (KERNEL_CIRCUIT_APPLY, KERNEL_CIRCUIT2_APPLY));
assert_eq!(v1.generator, format!("{GENERATOR_RANDOM_CIRCUITS} seed=7 cases=40"));
assert_eq!(v2.generator, format!("{GENERATOR_RANDOM_CIRCUITS2} seed=7 cases=40"));
assert_eq!(v2.parity, Parity::BitExact, "{v2:?}");
let (mut a, mut b) = (7u64, 7u64);
for _ in 0..40 {
let (x, y) = (lanes::random_circuit(&mut a, Gateset::V1), lanes::random_circuit(&mut b, Gateset::V2));
assert_eq!((x.n_qubits, &x.ops), (y.n_qubits, &y.ops));
assert_eq!((x.gateset, y.gateset), (Gateset::V1, Gateset::V2));
y.validate().unwrap();
}
assert_ne!(v1.corpus, v2.corpus);
assert_ne!(v1.hash(), v2.hash());
let mut member = detect_local();
member.id = "local/test".into();
let filed = |kernel: &str, cert: &Certificate| KernelEntry { kernel: kernel.into(), implementation: "lanes32".into(), certificate: cert.clone(), energy: Some((1, EnergyClass::ModelBased)) };
for (gs, cert) in [(Gateset::V1, &v1), (Gateset::V2, &v2)] {
let other = Gateset::ALL.into_iter().find(|&o| o != gs).unwrap();
let mut m = member.clone();
m.kernels = vec![filed(apply_kernel(gs), cert)];
assert_eq!(place(std::slice::from_ref(&m), apply_kernel(gs), &Parity::BitExact).unwrap().1.implementation, "lanes32");
m.kernels = vec![filed(apply_kernel(other), cert)];
assert!(place(std::slice::from_ref(&m), apply_kernel(other), &Parity::BitExact).is_none(), "a {gs:?} certificate served {}", apply_kernel(other));
assert!(place(std::slice::from_ref(&m), apply_kernel(gs), &Parity::BitExact).is_none());
}
}
pub(super) fn refused_circuits() -> Vec<Circuit> {
let gate = |base, controls: Vec<u8>, target, param| Gate { base, controls, target, param };
let bad = [
(1, vec![gate(BaseGate::H, vec![], 0, 0), gate(BaseGate::P, vec![], 0, 0)]),
(1, vec![gate(BaseGate::P, vec![], 0, 33)]),
(1, vec![gate(BaseGate::X, vec![], 3, 0)]),
(2, vec![gate(BaseGate::X, vec![0], 0, 0)]),
(2, vec![gate(BaseGate::X, vec![5], 1, 0)]),
];
Gateset::ALL.into_iter().flat_map(|gateset| bad.clone().into_iter().map(move |(n_qubits, ops)| Circuit { n_qubits, ops, gateset })).collect()
}
#[test]
fn the_lane_simulator_refuses_what_the_native_one_refuses() {
for c in refused_circuits() {
let native = c.simulate_from(0).unwrap_err();
assert_eq!(lanes::simulate(&c).unwrap_err(), native);
assert_eq!(lanes::simulate_checked(&c, 0).unwrap_err(), native);
}
assert!(matches!(lanes::simulate(&Circuit::new(MAX_QUBITS + 1)), Err(QuantumError::TooManyQubits(_))));
assert!(matches!(lanes::simulate_checked(&Circuit::new(MAX_QUBITS + 1), 0), Err(QuantumError::TooManyQubits(_))));
}
#[test]
fn parity_is_compared_not_asserted() {
let fx = |v: Vec<i64>| Output::Fixed { values: v, frac: 30 };
assert_eq!(compare(&fx(vec![5, -7]), &fx(vec![5, -7])), Parity::BitExact);
assert_eq!(compare(&fx(vec![5, -7]), &fx(vec![5, -6])), Parity::Within { max_ulp: 1, max_abs: 1.0 / (1u64 << 30) as f64 });
assert_eq!(compare(&fx(vec![5]), &Output::Fixed { values: vec![5], frac: 29 }), Parity::Uncertified);
assert_eq!(compare(&Output::Fixed { values: vec![1], frac: 64 }, &Output::Fixed { values: vec![2], frac: 64 }), Parity::Uncertified);
let one_up = f64::from_bits(1.0f64.to_bits() + 1);
assert_eq!(compare(&Output::Float(vec![1.0, -0.5]), &Output::Float(vec![1.0, -0.5])), Parity::BitExact);
assert_eq!(compare(&Output::Float(vec![1.0]), &Output::Float(vec![one_up])), Parity::Within { max_ulp: 1, max_abs: one_up - 1.0 });
assert_eq!(compare(&Output::Float(vec![1.0]), &Output::Float(vec![f64::NAN])), Parity::Uncertified);
assert_eq!(compare(&Output::Float(vec![f64::INFINITY]), &Output::Float(vec![f64::MAX])), Parity::Uncertified);
assert_eq!(compare(&Output::Bits(vec![3]), &Output::Bits(vec![1])), Parity::Uncertified);
let tiny = f64::from_bits(1);
assert_eq!(compare(&Output::Float(vec![tiny]), &Output::Float(vec![-tiny])), Parity::Within { max_ulp: 2, max_abs: 2.0 * tiny });
let c = certify("k", "port", "m", "g", vec![(vec![], fx(vec![1]), fx(vec![1])), (vec![], fx(vec![1]), fx(vec![3]))]);
assert_eq!(c.parity, Parity::Within { max_ulp: 2, max_abs: 2.0 / (1u64 << 30) as f64 });
assert_eq!(certify("k", "port", "m", "g", Vec::new()).parity, Parity::Uncertified);
assert_eq!(compare(&Output::Float(vec![f64::NAN]), &Output::Float(vec![f64::NAN])), Parity::Uncertified);
assert_eq!(compare(&Output::Float(vec![f64::INFINITY]), &Output::Float(vec![f64::INFINITY])), Parity::Uncertified);
let x = |controls: Vec<u8>| Gate { base: BaseGate::X, controls, target: 1, param: 0 };
let a = Circuit { n_qubits: 2, ops: vec![x(vec![0; 1280])], gateset: Gateset::V2 };
let mut b = Circuit { n_qubits: 2, ops: vec![x(vec![])], gateset: Gateset::V2 };
b.ops.extend((0..256).map(|_| Gate { base: BaseGate::I, controls: vec![], target: 0, param: 0 }));
assert_ne!(lanes::circuit_bytes(&a), lanes::circuit_bytes(&b));
let a = certify("k", "port", "m", "g", vec![(vec![], fx(vec![1, 2]), fx(vec![3]))]);
let b = certify("k", "port", "m", "g", vec![(vec![], fx(vec![1]), fx(vec![2, 3]))]);
assert_ne!(a.corpus, b.corpus);
}
#[test]
fn a_sampling_device_is_held_to_a_distribution() {
let Parity::Statistical { fidelity, shots } = statistical(&[0.5, 0.5], &[500, 500]) else { panic!() };
assert!((fidelity - 1.0).abs() < 1e-12 && shots == 1000);
let Parity::Statistical { fidelity, .. } = statistical(&[1.0, 0.0], &[500, 500]) else { panic!() };
assert!((fidelity - 0.5).abs() < 1e-12);
assert_eq!(statistical(&[2.0, 2.0], &[500, 500]), statistical(&[0.5, 0.5], &[500, 500]));
let Parity::Statistical { fidelity, .. } = statistical(&[1e12, 1e12], &[1, 1]) else { panic!() };
assert!(fidelity <= 1.0);
for bad in [statistical(&[0.0, 0.0], &[1, 1]), statistical(&[-0.5, 1.5], &[1, 1]), statistical(&[f64::NAN, 1.0], &[1, 1]), statistical(&[1.0], &[1, 1]), statistical(&[1.0, 1.0], &[0, 0]), statistical(&[1.0, 1.0], &[u64::MAX, 1])] {
assert_eq!(bad, Parity::Uncertified);
}
}
#[test]
fn a_sampling_device_is_certified_by_its_counts() {
let case = |counts: Vec<u64>| (vec![1u8], vec![0.5, 0.5], counts);
let good = certify_sampling("k", "native", "remote/qpu", "g", vec![case(vec![500, 500]), case(vec![480, 520])]);
let Parity::Statistical { fidelity, shots } = good.parity else { panic!("{good:?}") };
assert!(fidelity > 0.999 && fidelity < 1.0 && shots == 1000, "{fidelity} {shots}");
assert_eq!(good.cases, 2);
let worse = certify_sampling("k", "native", "remote/qpu", "g", vec![case(vec![500, 500]), case(vec![900, 100])]);
let Parity::Statistical { fidelity: f2, .. } = worse.parity else { panic!() };
assert!(f2 < fidelity);
assert_ne!(good.corpus, worse.corpus);
assert_eq!(certify_sampling("k", "native", "remote/qpu", "g", Vec::new()).parity, Parity::Uncertified);
assert_eq!(certify_sampling("k", "native", "remote/qpu", "g", vec![case(vec![500, 500]), (vec![], vec![0.0, 0.0], vec![1, 1])]).parity, Parity::Uncertified);
}
#[test]
fn requirements_are_met_in_order() {
let within = |u, a| Parity::Within { max_ulp: u, max_abs: a };
assert!(Parity::BitExact.meets(&Parity::BitExact));
assert!(Parity::BitExact.meets(&within(0, 0.0)));
assert!(Parity::BitExact.meets(&Parity::Statistical { fidelity: 1.0, shots: u64::MAX }));
assert!(!within(1, 1e-9).meets(&Parity::BitExact));
assert!(within(1, 1e-9).meets(&within(4, 1e-6)));
assert!(!within(8, 1e-9).meets(&within(4, 1e-6)));
assert!(!within(0, 0.0).meets(&Parity::Statistical { fidelity: 0.0, shots: 0 }));
assert!(!within(u64::MAX, 1e9).meets(&Parity::Statistical { fidelity: 0.99, shots: 1000 }));
let s = Parity::Statistical { fidelity: 0.995, shots: 10_000 };
assert!(s.meets(&Parity::Statistical { fidelity: 0.99, shots: 1000 }));
assert!(!s.meets(&Parity::Statistical { fidelity: 0.999, shots: 1000 }));
assert!(!s.meets(&within(1_000_000, 1.0)));
assert!(!Parity::Uncertified.meets(&Parity::Statistical { fidelity: 0.0, shots: 0 }));
assert!(!Parity::BitExact.meets(&Parity::Uncertified));
}
fn entry(member: &str, implementation: &str, parity: Parity, nj: Option<u64>) -> KernelEntry {
KernelEntry {
kernel: KERNEL_CIRCUIT_APPLY.into(),
implementation: implementation.into(),
certificate: Certificate { kernel: KERNEL_CIRCUIT_APPLY.into(), implementation: implementation.into(), member: member.into(), generator: "g".into(), parity, cases: 1, corpus: [1; 32], provenance: Provenance::Silicon },
energy: nj.map(|e| (e, EnergyClass::ModelBased)),
}
}
fn member(id: &str, class: FabricClass, presence: Presence, kernels: Vec<KernelEntry>) -> Member {
Member { id: id.into(), class, presence, kernels, detail: String::new() }
}
#[test]
fn placement_serves_the_cheapest_certified_kernel() {
let members = vec![
member("local/cpu", FabricClass::Cpu, Presence::Detected, vec![entry("local/cpu", REFERENCE, Parity::BitExact, Some(900))]),
member("local/gpu", FabricClass::Gpu, Presence::Detected, vec![entry("local/gpu", "lanes32", Parity::BitExact, Some(40)), entry("local/gpu", "f32", Parity::Within { max_ulp: 3, max_abs: 1e-7 }, Some(10))]),
member("local/npu", FabricClass::Npu, Presence::Detected, vec![entry("local/npu", "bf16", Parity::Uncertified, Some(1))]),
member("remote/qpu", FabricClass::Qpu, Presence::Reachable, vec![entry("remote/qpu", "native", Parity::Statistical { fidelity: 0.99, shots: 4000 }, Some(0))]),
];
let (m, k) = place(&members, KERNEL_CIRCUIT_APPLY, &Parity::BitExact).unwrap();
assert_eq!((m.id.as_str(), k.implementation.as_str()), ("local/gpu", "lanes32"));
let (m, k) = place(&members, KERNEL_CIRCUIT_APPLY, &Parity::Within { max_ulp: 4, max_abs: 1e-6 }).unwrap();
assert_eq!((m.id.as_str(), k.implementation.as_str()), ("local/gpu", "f32"));
let (_, k) = place(&members, KERNEL_CIRCUIT_APPLY, &Parity::Statistical { fidelity: 0.9, shots: 100 }).unwrap();
assert_eq!(k.implementation, "lanes32");
assert!(place(&members[2..], KERNEL_CIRCUIT_APPLY, &Parity::Statistical { fidelity: 0.9, shots: 100 }).is_none());
let known = vec![member("b", FabricClass::Cpu, Presence::Detected, vec![entry("b", "p", Parity::BitExact, Some(u64::MAX))]), member("a", FabricClass::Cpu, Presence::Detected, vec![entry("a", "p", Parity::BitExact, None)])];
assert_eq!(place(&known, KERNEL_CIRCUIT_APPLY, &Parity::BitExact).unwrap().0.id, "b");
let tie = vec![member("b", FabricClass::Cpu, Presence::Detected, vec![entry("b", REFERENCE, Parity::BitExact, None)]), member("a", FabricClass::Cpu, Presence::Detected, vec![entry("a", REFERENCE, Parity::BitExact, None)])];
assert_eq!(place(&tie, KERNEL_CIRCUIT_APPLY, &Parity::BitExact).unwrap().0.id, "a");
let mut local = detect_local();
assert_eq!(local.presence, Presence::Detected);
let id = local.id.clone();
local.kernels.push(KernelEntry { kernel: KERNEL_CIRCUIT_APPLY.into(), implementation: "lanes32".into(), certificate: certify_lanes(Gateset::V1, &id, 5, 1), energy: None });
assert_eq!(place(std::slice::from_ref(&local), KERNEL_CIRCUIT_APPLY, &Parity::BitExact).unwrap().1.implementation, REFERENCE);
}
#[test]
fn placement_relies_only_on_a_certificate_of_its_own() {
let ok = entry("local/gpu", "lanes32", Parity::BitExact, Some(1));
let only = |k: KernelEntry, class| place(&[member("local/gpu", class, Presence::Detected, vec![k])], KERNEL_CIRCUIT_APPLY, &Parity::BitExact).is_some();
assert!(only(ok.clone(), FabricClass::Gpu));
let mut k = ok.clone();
k.certificate.kernel = "wai.quantum.other".into();
assert!(!only(k, FabricClass::Gpu));
let mut k = ok.clone();
k.certificate.implementation = "f32".into();
assert!(!only(k, FabricClass::Gpu));
let mut k = ok.clone();
k.certificate.member = "local/cpu".into();
assert!(!only(k, FabricClass::Gpu));
let mut k = ok.clone();
k.certificate.cases = 0;
assert!(!only(k, FabricClass::Gpu));
let reference = KernelEntry { kernel: KERNEL_CIRCUIT_APPLY.into(), implementation: REFERENCE.into(), certificate: Certificate::reference(KERNEL_CIRCUIT_APPLY, "local/gpu"), energy: None };
assert!(!only(reference.clone(), FabricClass::Gpu));
assert!(only(reference, FabricClass::Cpu));
}
#[test]
fn receipts_verify_and_refuse() {
let signer = SigningKey::from_bytes(&[7u8; 32]);
let mut member = detect_local();
let cert = certify_lanes(Gateset::V1, &member.id, 20, 3);
member.kernels.push(KernelEntry { kernel: KERNEL_CIRCUIT_APPLY.into(), implementation: "lanes32".into(), certificate: cert.clone(), energy: None });
let entry = member.kernels.last().unwrap().clone();
let counter = EnergyClass::OnChipCounter { uncertainty: Uncertainty { relative_ppm: 50_000, window_us: 1_000 }, filtering: CounterFiltering::Off };
for (joules, class) in [(1234, Some(counter.clone())), (0, None)] {
let r = FabricReceipt::seal(&signer, "fabric-test", [9; 32], &member, &entry, joules, class);
assert!(r.verify());
assert!(r.certificate_matches(&cert));
assert!(!r.certificate_matches(&certify_lanes(Gateset::V1, &member.id, 20, 4)));
assert!(!r.certificate_matches(&certify_lanes(Gateset::V1, "local/other", 20, 3)));
assert!(!r.certificate_matches(&certify_lanes(Gateset::V2, &member.id, 20, 3)));
let back = FabricReceipt::from_json(&r.to_json()).unwrap();
assert_eq!(back, r);
assert!(back.verify());
}
let r = FabricReceipt::seal(&signer, "fabric-test", [9; 32], &member, &entry, 1234, Some(counter.clone()));
let mut t = r.clone();
t.joules_micro += 1;
assert!(!t.verify());
let mut t = r.clone();
t.member_id = "local/gpu".into();
assert!(!t.verify());
let mut t = r.clone();
t.parity = Parity::Within { max_ulp: 1, max_abs: 1e-9 };
assert!(!t.verify());
let mut t = r.clone();
t.energy_class = Some(EnergyClass::ModelBased);
assert!(!t.verify());
let modelled = FabricReceipt::seal(&signer, "fabric-test", [9; 32], &member, &entry, 1234, Some(EnergyClass::ModelBased));
let payload = modelled.signing_payload();
let at = payload.len() - 32 - 8 - "fabric-test".len() - 1;
assert_eq!(payload[at], 2);
assert_eq!(payload[at - 8..at], 1234u64.to_be_bytes());
let unmetered = FabricReceipt::seal(&signer, "fabric-test", [9; 32], &member, &entry, 0, None).signing_payload();
assert_eq!(unmetered[unmetered.len() - 32 - 8 - "fabric-test".len() - 1], 0);
let mut t = r.clone();
t.kernel = format!("{}\0{}", t.kernel, t.implementation);
t.implementation = String::new();
assert!(!t.verify());
assert!(!FabricReceipt::seal(&signer, "fabric-test", [9; 32], &member, &entry, 1234, None).verify());
assert!(!FabricReceipt::seal(&signer, "fabric-test", [9; 32], &member, &entry, 0, Some(EnergyClass::ModelBased)).verify());
let mut bad = entry.clone();
bad.certificate.parity = Parity::Uncertified;
assert!(!FabricReceipt::seal(&signer, "fabric-test", [9; 32], &member, &bad, 0, None).verify());
for junk in ["", "{}", "[1]", &r.to_json().replace("\"sig\":\"", "\"sig\":\"zz")] {
assert!(FabricReceipt::from_json(junk).is_none());
}
}
#[test]
fn detection_says_how_it_learned() {
let local = detect_local();
assert_eq!(local.class, FabricClass::Cpu);
assert!(local.detail.contains("asked of the CPU") || local.detail.contains("compiled for"), "{}", local.detail);
let kernels: Vec<&str> = local.kernels.iter().map(|k| k.kernel.as_str()).collect();
assert_eq!(kernels, [KERNEL_CIRCUIT_APPLY, KERNEL_CIRCUIT2_APPLY]);
for k in &local.kernels {
assert_eq!((k.certificate.member.as_str(), k.certificate.kernel.as_str(), k.implementation.as_str()), (local.id.as_str(), k.kernel.as_str(), REFERENCE));
}
for gs in Gateset::ALL {
let (_, k) = place(std::slice::from_ref(&local), apply_kernel(gs), &Parity::BitExact).unwrap();
assert_eq!((k.kernel.as_str(), k.implementation.as_str()), (apply_kernel(gs), REFERENCE));
}
}
fn widened(lanes: &[lanes::Lane]) -> Vec<[i64; 2]> {
lanes.iter().map(|a| [i64::from(a[0]), i64::from(a[1])]).collect()
}
fn native(c: &Circuit, start: usize) -> Vec<[i64; 2]> {
c.simulate_from(start).unwrap().amps.iter().map(|a| [a.re, a.im]).collect()
}
#[test]
fn certification_is_certify() {
let mut s = 7u64;
let cases: Vec<(Vec<u8>, Output, Output)> = (0..50)
.map(|_| {
let c = lanes::random_circuit(&mut s, Gateset::V1);
(lanes::circuit_bytes(&c), lanes::reference_output(&c).unwrap(), lanes::output(&lanes::simulate(&c).unwrap()))
})
.collect();
let mut off = cases.clone();
let Output::Fixed { values, .. } = &mut off[17].2 else { panic!() };
values[0] += 1;
for (corpus, parity) in [(cases, Parity::BitExact), (off, Parity::Within { max_ulp: 1, max_abs: 1.0 / (1u64 << 30) as f64 }), (Vec::new(), Parity::Uncertified)] {
let whole = certify("k", "port", "m", "g", corpus.clone());
let mut one = Certification::new();
for (input, reference, member) in &corpus {
one.add(input, reference, member);
}
assert_eq!(one.cases(), corpus.len() as u64);
let one = one.finish("k", "port", "m", "g");
assert_eq!(one, whole);
assert_eq!((one.parity, one.cases), (parity, corpus.len() as u64));
}
let empty = Certification::default().finish("k", "port", "m", "g");
assert_eq!((empty.parity, empty.cases), (Parity::Uncertified, 0));
assert_eq!(empty, certify("k", "port", "m", "g", Vec::new()));
}
#[test]
fn fxmul_wide_is_the_exact_product() {
let mut pairs: Vec<(i32, i32)> = lanes::PROBE_EDGES.iter().flat_map(|&a| lanes::PROBE_EDGES.iter().map(move |&b| (a, b))).collect();
let mut s = 11u64;
for _ in 0..400_000 {
pairs.push((next(&mut s) as i32, next(&mut s) as i32));
}
for (a, b) in pairs {
let (hi, lo) = lanes::fxmul_wide(a, b);
let exact = (i128::from(a) * i128::from(b) + (1 << 29)) >> 30;
assert_eq!(i128::from(((u64::from(hi) << 32) | u64::from(lo)) as i64), exact, "{a} × {b}");
assert_eq!(lo, lanes::fxmul(a, b) as u32, "{a} × {b}");
}
let mut edges = lanes::PROBE_EDGES.to_vec();
edges.sort();
edges.dedup();
assert_eq!(edges.len(), lanes::PROBE_EDGES.len());
}
#[test]
fn apply_words_is_apply() {
let fx = |a: i32, b: i32| (i128::from(a) * i128::from(b) + (1 << 29)) >> 30;
let mut s = 13u64;
let (mut inside, mut outside) = (0, 0);
for case in 0..2000 {
let n = 1 + (next(&mut s) % 10) as u8;
let len = 1usize << n;
let mode = case % 3;
let value = |s: &mut u64, shift: u32| -> i32 {
if mode == 0 && next(s).is_multiple_of(4) { lanes::PROBE_EDGES[(next(s) % 22) as usize] } else { (next(s) as i32) >> shift }
};
let (entry_shift, state_shift) = [(0, 0), (1, 3), (1, 1)][mode];
let entries: [i32; 8] = std::array::from_fn(|_| value(&mut s, entry_shift));
let state: Vec<lanes::Lane> = (0..len).map(|_| [value(&mut s, state_shift), value(&mut s, state_shift)]).collect();
let target = (next(&mut s) % u64::from(n)) as u8;
let tbit = 1usize << target;
let ctrl = if next(&mut s).is_multiple_of(2) { 0 } else { (next(&mut s) as usize) & (len - 1) & !tbit };
let m = [[[entries[0], entries[1]], [entries[2], entries[3]]], [[entries[4], entries[5]], [entries[6], entries[7]]]];
let w = lanes::GateWords { m: entries.map(|e| e as u32), tbit: tbit as u32, ctrl: ctrl as u32 };
let (mut a, mut b) = (state.clone(), state.clone());
let fits = lanes::apply_words(&mut a, &w).unwrap();
lanes::apply(&mut b, target, ctrl, m);
assert_eq!(a, b, "case {case}");
let mut want = true;
for i in (0..len).filter(|i| i & tbit == 0 && i & ctrl == ctrl) {
let (a0, a1) = (state[i], state[i | tbit]);
for [p, q] in m {
let re = fx(p[0], a0[0]) - fx(p[1], a0[1]) + fx(q[0], a1[0]) - fx(q[1], a1[1]);
let im = fx(p[0], a0[1]) + fx(p[1], a0[0]) + fx(q[0], a1[1]) + fx(q[1], a1[0]);
want &= i32::try_from(re).is_ok() && i32::try_from(im).is_ok();
}
}
assert_eq!(fits, want, "case {case}");
if fits { inside += 1 } else { outside += 1 }
}
assert!(inside >= 100 && outside >= 100, "{inside} inside, {outside} outside");
}
#[test]
fn malformed_words_are_refused() {
let mut s = 5u64;
let state: Vec<lanes::Lane> = (0..8).map(|_| [next(&mut s) as i32, next(&mut s) as i32]).collect();
let good = lanes::GateWords { m: [ONE as u32, 0, 0, 0, 0, 0, ONE as u32, 0], tbit: 2, ctrl: 1 };
let mut a = state.clone();
assert_eq!(lanes::apply_words(&mut a, &good), Some(true));
assert_eq!(a, state);
for (tbit, ctrl) in [(0, 0), (3, 0), (8, 0), (2, 2), (2, 3), (1, 8), (4, 9)] {
let mut a = state.clone();
assert_eq!(lanes::apply_words(&mut a, &lanes::GateWords { tbit, ctrl, ..good }), None, "tbit {tbit} ctrl {ctrl}");
assert_eq!(a, state);
}
for len in [0, 1, 3, 6] {
let mut a = vec![[1, 2]; len];
assert_eq!(lanes::apply_words(&mut a, &lanes::GateWords { tbit: 1, ctrl: 0, ..good }), None);
assert_eq!(a, vec![[1, 2]; len]);
}
assert_eq!(lanes::run_words(&state, &[good, lanes::GateWords { tbit: 8, ..good }]), None);
}
#[test]
fn z_on_the_most_negative_lane_is_flagged() {
let gate = |base| Gate { base, controls: vec![], target: 0, param: 0 };
for gs in Gateset::ALL {
let (z, i) = (lanes::gate_words(&gate(BaseGate::Z), gs), lanes::gate_words(&gate(BaseGate::I), gs));
let state = [[0, 0], [i32::MIN, 0]];
let mut amps = state.to_vec();
assert_eq!(lanes::apply_words(&mut amps, &z), Some(false));
assert_eq!(amps, state);
assert_eq!(lanes::fxmul_wide(-(ONE as i32), i32::MIN), (0, 1 << 31));
assert_eq!(lanes::run_words(&state, &[i, z, i]).unwrap().out_of_range, Some(1));
assert_eq!(lanes::run_words(&state, &[z, i, z]).unwrap().out_of_range, Some(0));
assert_eq!(lanes::run_words(&state, &[i, i]).unwrap(), plan::LaneRun { amps: state.to_vec(), out_of_range: None });
}
}
#[test]
fn simulate_checked_is_simulate() {
for gs in Gateset::ALL {
for c in (Corpus::Random { seed: 7, cases: 300 }).circuits(gs) {
let dim = 1usize << c.n_qubits;
for start in [0, 1, dim + 3] {
let run = lanes::simulate_checked(&c, start).unwrap();
assert_eq!(run.out_of_range, None);
assert_eq!(widened(&run.amps), native(&c, start));
}
assert_eq!(lanes::simulate_checked(&c, dim + 3), lanes::simulate_checked(&c, 3));
let mut basis = vec![[0, 0]; dim];
basis[0] = [ONE as i32, 0];
let words: Vec<lanes::GateWords> = c.ops.iter().map(|g| lanes::gate_words(g, gs)).collect();
assert_eq!(lanes::run_words(&basis, &words), Some(lanes::simulate_checked(&c, 0).unwrap()));
}
}
}
pub(super) fn configurations() -> Vec<plan::Config> {
let mut all = vec![plan::Config::PER_GATE, plan::Config::TILED];
for tile_bits in [1, 3] {
for run_max in [1, 7] {
for skip_identity in [true, false] {
all.push(plan::Config { tile_bits, run_max, skip_identity });
}
}
}
all
}
#[test]
fn a_rounded_product_is_never_negated() {
let v2 = [[759250126, 0], [1, 0], [759250126, 0], [1, 0]];
let v1 = [[759250122, 0], [0, 0], [759250122, 0], [0, 0]];
for (gs, want) in [(Gateset::V2, v2), (Gateset::V1, v1)] {
let mut c = Circuit::with_gateset(2, gs);
c.h(0).h(1).h(0);
assert_eq!(native(&c, 0), widened(&want));
assert_eq!(lanes::simulate(&c).unwrap(), want);
let run = lanes::simulate_checked(&c, 0).unwrap();
assert_eq!((run.amps.as_slice(), run.out_of_range), (want.as_slice(), None));
for cfg in configurations() {
let run = plan::execute(&plan::compile_with(&c, 0, &cfg).unwrap());
assert_eq!((run.amps.as_slice(), run.out_of_range), (want.as_slice(), None), "{cfg:?}");
}
let h = gs.inv_sqrt2() as i32;
let mut a = [[ONE as i32, 0], [0, 0], [0, 0], [0, 0]];
for t in [0, 1, 0] {
let bit = 1usize << t;
for i in (0..4).filter(|i| i & bit == 0) {
let j = i | bit;
for k in 0..2 {
let (p, q) = (lanes::fxmul(h, a[i][k]), lanes::fxmul(h, a[j][k]));
(a[i][k], a[j][k]) = (p + q, p - q);
}
}
}
match gs {
Gateset::V2 => {
assert_eq!((a[1][0], a[3][0]), (0, 0));
assert_ne!(a, want);
}
Gateset::V1 => assert_eq!(a, want),
}
}
}
#[test]
fn the_guard_horizon_is_pinned() {
assert_eq!((lanes::table_excess(Gateset::V1), lanes::table_excess(Gateset::V2)), (0, 386_868_465));
for (n, v1, v2) in [(10, 11_863_283, 11_769_578), (20, 370_727, 370_635), (26, 46_340, 46_339)] {
assert_eq!((lanes::horizon(n, Gateset::V1), lanes::horizon(n, Gateset::V2)), (v1, v2), "n = {n}");
}
for n in 1..=26 {
assert!(lanes::horizon(n, Gateset::V1) >= lanes::horizon(n, Gateset::V2), "n = {n}");
for gs in Gateset::ALL {
assert!(lanes::horizon(n, gs) <= lanes::horizon(n - 1, gs), "{gs:?} n = {n}");
}
}
for gs in Gateset::ALL {
assert_eq!((lanes::horizon(56, gs), lanes::horizon(57, gs), lanes::horizon(58, gs), lanes::horizon(u8::MAX, gs)), (1, 0, 0, 0));
}
}
#[test]
fn valid_circuits_stay_in_lanes() {
for gs in Gateset::ALL {
for c in (Corpus::Random { seed: 7, cases: 1000 }).circuits(gs) {
assert_eq!(lanes::simulate_checked(&c, 0).unwrap().out_of_range, None);
}
for n in 1..=16 {
let mut c = Circuit::qft(n);
c.gateset = gs;
assert_eq!(lanes::simulate_checked(&c, 0).unwrap().out_of_range, None, "qft({n}) {gs:?}");
}
let mut c = Circuit::with_gateset(4, gs);
let mut s = 21u64;
for _ in 0..10_000 {
let q = (next(&mut s) % 4) as u8;
match next(&mut s) % 3 {
0 => c.h(q),
1 => c.t(q),
_ => c.p(3 + (next(&mut s) % 30) as u16, q),
};
}
assert!(c.ops.len() as u64 <= lanes::horizon(4, gs));
let run = lanes::simulate_checked(&c, 0).unwrap();
assert_eq!(run.out_of_range, None, "{gs:?}");
assert_eq!(widened(&run.amps), native(&c, 0), "{gs:?}");
}
}
#[test]
fn fabric_corpus_starts_with_random_v1() {
let random_v1 = Corpus::Random { seed: 7, cases: 200 };
assert_eq!((FABRIC_DEFAULT.name(), random_v1.name()), ("fabric-v1", "random-v1"));
for (gs, pin) in [(Gateset::V1, "d18454c639acfd9c7b66450f4ded1aac4ab46cc10a7bedbcf4958a96e204fb36"), (Gateset::V2, "3dbde276c1095bf827faec71d5980e050f8a55a5ba7d97cd3bbdaec3f43a13b2")] {
let fabric = FABRIC_DEFAULT.circuits(gs);
assert_eq!(fabric.len(), 224);
assert_eq!(fabric[..200], random_v1.circuits(gs)[..]);
let mut s = 7u64;
for c in &fabric[..200] {
assert_eq!(*c, lanes::random_circuit(&mut s, gs));
}
for c in &fabric[200..] {
assert_eq!(*c, lanes::random_wide_circuit(&mut s, gs));
assert!((11..=17).contains(&c.n_qubits), "{}", c.n_qubits);
}
let cert = lanes::certify_corpus(gs, "local/test", random_v1);
assert_eq!(hex(&cert.corpus), pin);
assert_eq!(cert.generator, format!("{} seed=7 cases=200", random_generator(gs)));
assert_eq!(cert, certify_lanes(gs, "local/test", 200, 7));
}
}
#[test]
fn the_fabric_v1_corpus_of_each_gateset_is_pinned() {
for (gs, pin) in [(Gateset::V1, "41c726a0ac80f7defef92e15ecf893bdb7a3076b5e7f670fa0b7142e5c033df7"), (Gateset::V2, "9a84b55af68f1a8b07390b234cf562dd8d85cef3185a697ab85690c8790a7809")] {
let cert = lanes::certify_corpus(gs, "local/test", FABRIC_DEFAULT);
assert_eq!(cert.parity, Parity::BitExact, "{cert:?}");
assert_eq!(cert.cases, 224);
assert_eq!(cert.generator, format!("{} seed=7 cases=200 wide=24", fabric_generator(gs)));
assert_eq!(hex(&cert.corpus), pin, "{gs:?}");
}
}
#[test]
fn fabric_v1_covers_every_dispatch_shape() {
for gs in Gateset::ALL {
let cs = FABRIC_DEFAULT.circuits(gs);
let circuits = |f: &dyn Fn(&Circuit) -> bool| cs.iter().filter(|c| f(c)).count();
let ops = |f: &dyn Fn(&Gate) -> bool| cs.iter().flat_map(|c| &c.ops).filter(|g| f(g)).count();
let shapes = [
("circuit on at most 6 qubits", circuits(&|c| c.n_qubits <= 6)),
("circuit on 7 to 13 qubits", circuits(&|c| (7..=13).contains(&c.n_qubits))),
("circuit on 14 qubits or more", circuits(&|c| c.n_qubits >= 14)),
("op with a control", ops(&|g| !g.controls.is_empty())),
("op with two controls or more", ops(&|g| g.controls.len() >= 2)),
("op on a target of 10 or more", ops(&|g| g.target >= 10)),
("P(k) with k of 19 or more", ops(&|g| g.base == BaseGate::P && g.param >= 19)),
];
for (what, count) in shapes {
assert!(count > 0, "{gs:?}: no {what}");
}
}
}
#[test]
fn gate_words_are_the_table() {
use BaseGate::*;
let gates = [I, X, Y, Z, H, S, Sdg, T, Tdg].map(|b| (b, 0u16)).into_iter().chain((1..=32).map(|k| (P, k)));
for gs in Gateset::ALL {
for (base, param) in gates.clone() {
for (target, controls) in [(0u8, vec![]), (3, vec![0, 5]), (25, vec![24, 1, 7])] {
let g = Gate { base, controls: controls.clone(), target, param };
let w = lanes::gate_words(&g, gs);
let m = base.matrix(param, gs);
let table: Vec<i64> = [m[0][0], m[0][1], m[1][0], m[1][1]].iter().flat_map(|a| [a.re, a.im]).collect();
assert_eq!(w.m.map(|x| i64::from(x as i32)).to_vec(), table, "{base:?}({param}) {gs:?}");
assert_eq!(w.m.to_vec(), table.iter().map(|&e| e as i32 as u32).collect::<Vec<_>>());
assert_eq!(w.tbit, 1 << target);
assert_eq!(w.ctrl, controls.iter().fold(0u32, |acc, &c| acc | 1 << c));
}
}
}
let c = Circuit { n_qubits: 2, ops: vec![Gate { base: X, controls: vec![0, 0], target: 1, param: 0 }], gateset: Gateset::V1 };
c.validate().unwrap();
assert_eq!(lanes::gate_words(&c.ops[0], Gateset::V1).ctrl, 1);
}
fn now<F: Future>(f: F) -> F::Output {
ready(f).expect("pending after one poll")
}
fn counter(relative_ppm: u32, window_us: u64) -> EnergyClass {
EnergyClass::OnChipCounter { uncertainty: Uncertainty { relative_ppm, window_us }, filtering: CounterFiltering::Off }
}
struct TestMeter {
start: Result<(), String>,
stop: Result<Option<(u64, EnergyClass)>, String>,
starts: u32,
stops: u32,
}
impl TestMeter {
fn reads(stop: Result<Option<(u64, EnergyClass)>, String>) -> TestMeter {
TestMeter { start: Ok(()), stop, starts: 0, stops: 0 }
}
}
impl RunMeter for TestMeter {
fn start(&mut self) -> Result<(), String> {
self.starts += 1;
self.start.clone()
}
fn stop(&mut self) -> Result<Option<(u64, EnergyClass)>, String> {
self.stops += 1;
self.stop.clone()
}
}
#[test]
fn a_meter_reading_is_labelled_or_dropped() {
let c = Circuit::qft(3);
let accepted = counter(50_000, 1_000);
let mut m = TestMeter::reads(Ok(Some((1234, accepted.clone()))));
let (state, joules, class) = now(CpuReference.run(REFERENCE, &c, 0, &mut m)).unwrap();
assert_eq!(state, c.simulate().unwrap());
assert_eq!((joules, class, m.starts, m.stops), (1234, Some(accepted.clone()), 1, 1));
for stop in [Ok(Some((1, counter(1_000, 1_000)))), Ok(Some((0, EnergyClass::ModelBased))), Ok(Some((1234, counter(0, 1_000)))), Ok(Some((1234, counter(50_000, 0)))), Ok(None), Err("busy".to_string())] {
let mut m = TestMeter::reads(stop.clone());
let (state, joules, class) = now(CpuReference.run(REFERENCE, &c, 5, &mut m)).unwrap();
assert_eq!(state, c.simulate_from(5).unwrap());
assert_eq!((joules, class, m.starts, m.stops), (0, None, 1, 1), "{stop:?}");
}
let mut m = TestMeter { start: Err("no counter".into()), ..TestMeter::reads(Ok(Some((1234, accepted.clone())))) };
let (_, joules, class) = now(CpuReference.run(REFERENCE, &c, 0, &mut m)).unwrap();
assert_eq!((joules, class, m.starts, m.stops), (0, None, 1, 0));
let mut m = TestMeter::reads(Ok(Some((1234, accepted.clone()))));
let bad = &refused_circuits()[3];
assert_eq!(now(CpuReference.run(REFERENCE, bad, 0, &mut m)).unwrap_err(), MemberError::Circuit(bad.simulate_from(0).unwrap_err()));
assert_eq!((m.starts, m.stops), (1, 1));
assert!(matches!(now(CpuReference.run("lanes32", &c, 0, &mut m)), Err(MemberError::Other(_))));
assert_eq!((m.starts, m.stops), (1, 1));
}
#[test]
fn a_placement_figure_is_a_measurement_or_nothing() {
let mut cal = EnergyCalibration::new();
cal.add(3_000, 10, Some(&counter(50_000, 400)));
cal.add(1_000, 20, Some(&counter(100_000, 600)));
assert_eq!(cal.runs(), 2);
assert_eq!(cal.finish(), Some((8, counter(225_000, 1_000))));
let mut exact = EnergyCalibration::new();
exact.add(1_000, 10, Some(&counter(50_000, 5)));
assert_eq!(exact.finish(), Some((10, counter(50_000, 5))));
let mut modelled = EnergyCalibration::new();
modelled.add(10, 7, Some(&EnergyClass::ModelBased));
assert_eq!(modelled.finish(), Some((700, EnergyClass::ModelBased)));
let instrument = |r: &str| EnergyClass::CalibratedInstrument { uncertainty: Uncertainty { relative_ppm: 10_000, window_us: 7 }, calibration_ref: r.into() };
let mut one = EnergyCalibration::new();
one.add(100, 50, Some(&instrument("cert-1")));
one.add(100, 50, Some(&instrument("cert-1")));
assert_eq!(one.finish(), Some((500, EnergyClass::CalibratedInstrument { uncertainty: Uncertainty { relative_ppm: 10_000, window_us: 14 }, calibration_ref: "cert-1".into() })));
let spoiled = |runs: &[(u64, u64, Option<EnergyClass>)]| {
let mut cal = EnergyCalibration::new();
for (ops, joules, class) in runs {
cal.add(*ops, *joules, class.as_ref());
}
cal.finish()
};
let good = (100, 10, Some(counter(50_000, 1)));
let on = EnergyClass::OnChipCounter { uncertainty: Uncertainty { relative_ppm: 50_000, window_us: 1 }, filtering: CounterFiltering::On };
for runs in [
vec![good.clone(), (100, 0, None)],
vec![(100, 0, None), good.clone()],
vec![good.clone(), (100, 1, Some(counter(1_000, 1)))],
vec![good.clone(), (100, 10, Some(on))],
vec![good.clone(), (100, 10, Some(EnergyClass::ModelBased))],
vec![(100, 50, Some(instrument("cert-1"))), (100, 50, Some(instrument("cert-2")))],
vec![],
vec![(0, 10, Some(counter(50_000, 1)))],
] {
assert_eq!(spoiled(&runs), None, "{runs:?}");
}
let widened = |ppm: u32| {
let mut cal = EnergyCalibration::new();
cal.add(3, 1, Some(&counter(ppm, 1)));
assert_eq!(cal.runs(), 1, "the reading itself is accepted");
cal.finish()
};
assert_eq!(widened(u32::MAX - 2995), Some((334, counter(u32::MAX, 1))));
assert_eq!(widened(u32::MAX - 2994), None);
assert_eq!(widened(u32::MAX), None);
let mut c = Circuit::new(4);
c.ops = vec![Gate { base: BaseGate::H, controls: vec![], target: 0, param: 0 }, Gate { base: BaseGate::X, controls: vec![0, 1], target: 3, param: 0 }];
assert_eq!(pair_updates(&c), 16);
assert_eq!(pair_updates(&Circuit::new(0)), 0);
c.n_qubits = 255;
assert_eq!(pair_updates(&c), u64::MAX);
}
fn accelerator(id: &str, implementation: &str, nj: Option<u64>) -> Member {
let kernels = Gateset::ALL
.into_iter()
.map(|gs| {
let kernel = apply_kernel(gs);
let certificate = Certificate { kernel: kernel.into(), implementation: implementation.into(), member: id.into(), generator: FABRIC_DEFAULT.generator(gs), parity: Parity::BitExact, cases: 224, corpus: [7; 32], provenance: Provenance::Silicon };
KernelEntry { kernel: kernel.into(), implementation: implementation.into(), certificate, energy: nj.map(|e| (e, counter(50_000, 1_000))) }
})
.collect();
Member { id: id.into(), class: FabricClass::Gpu, presence: Presence::Detected, kernels, detail: String::new() }
}
fn local_with(nj: Option<u64>) -> Member {
let mut m = detect_local();
m.kernels.iter_mut().for_each(|k| k.energy = nj.map(|e| (e, counter(50_000, 1_000))));
m
}
const GPU: &str = "local/gpu-test-0123456789ab";
#[test]
fn figures_go_on_both_members_or_neither() {
let cpu = detect_local();
for gs in Gateset::ALL {
let kernel = apply_kernel(gs);
let placed = |members: &[Member]| place(members, kernel, &Parity::BitExact).map(|(m, _)| m.id.clone()).unwrap();
assert_eq!(placed(&[local_with(None), accelerator(GPU, "port", None)]), cpu.id);
assert_eq!(placed(&[local_with(Some(10)), accelerator(GPU, "port", Some(3))]), GPU);
assert_eq!(placed(&[local_with(Some(10)), accelerator(GPU, "port", Some(30))]), cpu.id);
assert_eq!(placed(&[local_with(Some(10)), accelerator(GPU, "port", Some(10))]), cpu.id);
assert_eq!(placed(&[local_with(None), accelerator(GPU, "port", Some(u64::MAX))]), GPU);
assert_eq!(placed(&[local_with(Some(u64::MAX)), accelerator(GPU, "port", None)]), cpu.id);
for (on_cpu, on_gpu) in [(None, Some(1)), (None, Some(u64::MAX)), (Some(1), None), (Some(u64::MAX), None)] {
let ms = [local_with(on_cpu), accelerator(GPU, "port", on_gpu)];
assert_eq!(place_for(&ms, kernel, &Parity::BitExact, |_, _| None).unwrap().0.id, cpu.id, "{on_cpu:?} {on_gpu:?}");
let mut fabric = Fabric::new();
fabric.add(ms[0].clone(), CpuReference).add(ms[1].clone(), Port(GPU));
assert_eq!(fabric.order(&Circuit::with_gateset(3, gs), &Parity::BitExact)[0].0.id, cpu.id, "{on_cpu:?} {on_gpu:?}");
}
for (on_cpu, on_gpu) in [(None, None), (Some(10), Some(3)), (Some(10), Some(30)), (Some(10), Some(10))] {
let ms = [local_with(on_cpu), accelerator(GPU, "port", on_gpu)];
assert_eq!(place_for(&ms, kernel, &Parity::BitExact, |_, _| None).unwrap().0.id, placed(&ms), "{on_cpu:?} {on_gpu:?}");
}
}
}
fn model(m: &Member, k: &KernelEntry, c: &Circuit) -> Option<u64> {
let (nj, _) = k.energy.as_ref()?;
let fixed = if m.class == FabricClass::Gpu { 20_000_000 } else { 0 };
Some(nj.saturating_mul(1000).saturating_mul(pair_updates(c)).saturating_add(fixed))
}
#[test]
fn place_for_sends_small_runs_to_the_cpu_and_large_ones_to_the_gpu() {
let members = [local_with(Some(10)), accelerator(GPU, "port", Some(1))];
let cpu = members[0].id.clone();
for gs in Gateset::ALL {
let kernel = apply_kernel(gs);
let circuit = |n: u8| {
let mut c = Circuit::with_gateset(n, gs);
c.ops = (0..10).map(|k| Gate { base: BaseGate::H, controls: vec![], target: k % n, param: 0 }).collect();
c
};
let (small, large) = (circuit(3), circuit(24));
assert_eq!((model(&members[0], &members[0].kernels[0], &small), model(&members[1], &members[1].kernels[0], &small)), (Some(400_000), Some(20_040_000)));
assert_eq!((model(&members[0], &members[0].kernels[0], &large), model(&members[1], &members[1].kernels[0], &large)), (Some(838_860_800_000), Some(83_906_080_000)));
let placed_for = |c: &Circuit| place_for(&members, kernel, &Parity::BitExact, |m, k| model(m, k, c)).map(|(m, _)| m.id.clone()).unwrap();
assert_eq!(placed_for(&small), cpu);
assert_eq!(placed_for(&large), GPU);
assert_eq!(place(&members, kernel, &Parity::BitExact).unwrap().0.id, GPU);
let unfigured = [local_with(None), accelerator(GPU, "port", Some(1))];
for c in [&small, &large] {
for missing in [FabricClass::Gpu, FabricClass::Cpu] {
let unpredicted = |ms: &[Member]| place_for(ms, kernel, &Parity::BitExact, |m, k| if m.class == missing { None } else { model(m, k, c) }).map(|(m, k)| (m.id.clone(), k.implementation.clone()));
let by_place = |ms: &[Member]| place(ms, kernel, &Parity::BitExact).map(|(m, k)| (m.id.clone(), k.implementation.clone()));
assert_eq!(unpredicted(&members), by_place(&members), "{missing:?} unpredicted, n = {}", c.n_qubits);
assert_eq!(unpredicted(&members).unwrap().0, GPU);
assert_eq!(unpredicted(&unfigured).unwrap().0, cpu, "{missing:?} unpredicted, n = {}", c.n_qubits);
assert_eq!(by_place(&unfigured).unwrap().0, GPU);
}
}
let bare = [local_with(None), accelerator(GPU, "port", None)];
assert_eq!(place_for(&bare, kernel, &Parity::BitExact, |_, _| Some(5)).unwrap().0.id, cpu);
let mut undetected = accelerator("local/gpu-test-3333333333ab", "port", Some(1));
undetected.presence = Presence::Declared;
let mut foreign = accelerator("local/gpu-test-4444444444ab", "port", Some(1));
foreign.kernels.iter_mut().for_each(|k| k.certificate.member = GPU.into());
let listed = [local_with(Some(10)), undetected, foreign];
let chosen = place_for(&listed, kernel, &Parity::BitExact, |m, _| {
assert_eq!(m.id, cpu, "a candidate that cannot be placed was predicted");
Some(1)
});
assert_eq!(chosen.unwrap().0.id, cpu);
assert!(place_for(&[], kernel, &Parity::BitExact, |_, _| Some(1)).is_none());
}
}
struct Refuses(&'static str, fn() -> MemberError);
impl Runner for Refuses {
fn member_id(&self) -> String {
self.0.into()
}
fn run<'r>(&'r self, _: &'r str, _: &'r Circuit, _: usize, _: &'r mut dyn RunMeter) -> RunFuture<'r> {
let error = (self.1)();
Box::pin(async move { Err(error) })
}
}
struct Port(&'static str);
impl Runner for Port {
fn member_id(&self) -> String {
self.0.into()
}
fn run<'r>(&'r self, implementation: &'r str, c: &'r Circuit, start: usize, meter: &'r mut dyn RunMeter) -> RunFuture<'r> {
Box::pin(async move {
assert_eq!(implementation, "port");
let mut window = Window::new(meter);
window.open();
let state = c.simulate_from(start).map_err(MemberError::Circuit)?;
let (joules, class) = window.close();
Ok((state, joules, class))
})
}
}
#[test]
fn the_fabric_falls_back_and_names_the_member_that_produced_the_result() {
let signer = SigningKey::from_bytes(&[7; 32]);
let cpu = local_with(Some(10));
let c = Circuit::qft(4);
let native = c.simulate_from(3).unwrap();
let falls_back: [fn() -> MemberError; 5] = [
|| MemberError::TooWide { n_qubits: 4, max: 3 },
|| MemberError::OutOfRange { gate: 2 },
|| MemberError::Memory("full".into()),
|| MemberError::Timeout,
|| MemberError::Device("lost".into()),
];
for refusal in falls_back {
assert!(refusal().falls_back());
let mut fabric = Fabric::new();
fabric.add(cpu.clone(), CpuReference).add(accelerator(GPU, "port", Some(1)), Refuses(GPU, refusal));
assert_eq!(fabric.order(&c, &Parity::BitExact).iter().map(|(m, _)| m.id.as_str()).collect::<Vec<_>>(), [GPU, cpu.id.as_str()]);
let out = now(fabric.run(&c, 3, &Parity::BitExact, &signer, "fabric-test")).unwrap();
assert_eq!(out.state, native);
assert_eq!((out.receipt.member_id.as_str(), out.receipt.implementation.as_str()), (cpu.id.as_str(), REFERENCE));
assert_eq!(out.receipt.result_hash, native.statevector_hash());
assert!(out.receipt.verify());
assert!(out.receipt.certificate_matches(&Certificate::reference(apply_kernel(c.gateset), &cpu.id)));
assert_eq!((out.receipt.joules_micro, out.receipt.energy_class.as_ref()), (0, None));
assert_eq!(out.refusals, [Refused { member_id: GPU.into(), implementation: "port".into(), error: refusal() }]);
}
let stops: [fn() -> MemberError; 2] = [|| MemberError::Circuit(QuantumError::Invalid("bad".into())), || MemberError::Other("defect".into())];
for refusal in stops {
assert!(!refusal().falls_back());
let mut fabric = Fabric::new();
fabric.add(cpu.clone(), CpuReference).add(accelerator(GPU, "port", Some(1)), Refuses(GPU, refusal));
let e = now(fabric.run(&c, 0, &Parity::BitExact, &signer, "fabric-test")).unwrap_err();
assert_eq!(e.refusals, [Refused { member_id: GPU.into(), implementation: "port".into(), error: refusal() }]);
}
let port = accelerator("local/gpu-test-1111111111ab", "port", Some(2));
let mut fabric = Fabric::new();
fabric.add(cpu.clone(), CpuReference).add(port.clone(), Port("local/gpu-test-1111111111ab")).add(accelerator(GPU, "port", Some(1)), Refuses(GPU, || MemberError::Timeout));
let out = now(fabric.run(&c, 3, &Parity::BitExact, &signer, "fabric-test")).unwrap();
assert_eq!((out.receipt.member_id.as_str(), out.receipt.implementation.as_str(), &out.state), (port.id.as_str(), "port", &native));
assert!(out.receipt.verify());
let entry = port.kernels.iter().find(|k| k.kernel == apply_kernel(c.gateset)).unwrap();
assert!(out.receipt.certificate_matches(&entry.certificate));
assert_eq!(out.refusals, [Refused { member_id: GPU.into(), implementation: "port".into(), error: MemberError::Timeout }]);
let mut fabric = Fabric::new();
fabric.add(accelerator(GPU, "port", None), Refuses(GPU, || MemberError::Device("lost".into()))).add(accelerator("local/gpu-test-2222222222ab", "port", None), Refuses("local/gpu-test-2222222222ab", || MemberError::TooWide { n_qubits: 4, max: 2 }));
let e = now(fabric.run(&c, 0, &Parity::BitExact, &signer, "fabric-test")).unwrap_err();
let tried: Vec<&str> = e.refusals.iter().map(|r| r.member_id.as_str()).collect();
assert_eq!(tried, [GPU, "local/gpu-test-2222222222ab"]);
let other = "local/gpu-test-1111111111ab";
let mut fabric = Fabric::new();
fabric.add(cpu.clone(), CpuReference).add(accelerator(GPU, "port", Some(1)), Port(other));
let e = now(fabric.run(&c, 3, &Parity::BitExact, &signer, "fabric-test")).unwrap_err();
assert_eq!(e.refusals.len(), 1);
assert_eq!((e.refusals[0].member_id.as_str(), e.refusals[0].implementation.as_str()), (GPU, "port"));
assert!(matches!(&e.refusals[0].error, MemberError::Other(why) if why.contains(GPU) && why.contains(other)), "{:?}", e.refusals[0].error);
assert!(!e.refusals[0].error.falls_back());
let mut fabric = Fabric::new();
fabric.add(accelerator(GPU, REFERENCE, None), CpuReference);
let e = now(fabric.run(&c, 3, &Parity::BitExact, &signer, "fabric-test")).unwrap_err();
assert!(matches!(&e.refusals[..], [Refused { member_id, error: MemberError::Other(why), .. }] if member_id == GPU && why.contains(&cpu.id)), "{:?}", e.refusals);
let port = Port(GPU);
let mut fabric = Fabric::new();
fabric.add(accelerator(GPU, "port", None), &port);
assert_eq!(now(fabric.run(&c, 3, &Parity::BitExact, &signer, "fabric-test")).unwrap().receipt.member_id, GPU);
assert_eq!(now(Fabric::new().run(&c, 0, &Parity::BitExact, &signer, "fabric-test")).unwrap_err(), FabricError { refusals: vec![] });
let mut fabric = Fabric::new();
fabric.add(detect_local(), CpuReference);
let bad = &refused_circuits()[1];
let e = now(fabric.run(bad, 0, &Parity::BitExact, &signer, "fabric-test")).unwrap_err();
assert_eq!(e.refusals.len(), 1);
assert_eq!(e.refusals[0].error, MemberError::Circuit(bad.simulate_from(0).unwrap_err()));
}
#[test]
fn a_metered_fabric_run_seals_its_reading() {
let signer = SigningKey::from_bytes(&[7; 32]);
let c = Circuit::qft(5);
let reading = counter(50_000, 1_000);
let mut fabric = Fabric::new();
fabric.add_metered(detect_local(), CpuReference, TestMeter::reads(Ok(Some((1234, reading.clone())))));
let out = now(fabric.run(&c, 0, &Parity::BitExact, &signer, "fabric-test")).unwrap();
assert_eq!((out.receipt.joules_micro, out.receipt.energy_class.as_ref()), (1234, Some(&reading)));
assert!(out.receipt.verify());
assert!(FabricReceipt::from_json(&out.receipt.to_json()).unwrap().verify());
let mut fabric = Fabric::new();
fabric.add_metered(detect_local(), CpuReference, TestMeter::reads(Ok(Some((1, counter(1_000, 1_000))))));
let out = now(fabric.run(&c, 0, &Parity::BitExact, &signer, "fabric-test")).unwrap();
assert_eq!((out.receipt.joules_micro, out.receipt.energy_class.as_ref()), (0, None));
assert!(out.receipt.verify());
struct Hands(u64, Option<EnergyClass>);
impl Runner for Hands {
fn member_id(&self) -> String {
detect_local().id
}
fn run<'r>(&'r self, _: &'r str, c: &'r Circuit, start: usize, _: &'r mut dyn RunMeter) -> RunFuture<'r> {
Box::pin(async move { Ok((c.simulate_from(start).map_err(MemberError::Circuit)?, self.0, self.1.clone())) })
}
}
for (joules, class) in [(1234, None), (1, Some(counter(1_000, 1_000))), (0, Some(reading.clone()))] {
assert!(class.as_ref().is_none_or(|cl| check_label(joules, cl).is_err()));
let mut fabric = Fabric::new();
fabric.add(detect_local(), Hands(joules, class));
let out = now(fabric.run(&c, 0, &Parity::BitExact, &signer, "fabric-test")).unwrap();
assert_eq!((out.receipt.joules_micro, out.receipt.energy_class.as_ref()), (0, None), "{joules}");
assert!(out.receipt.verify());
}
let mut fabric = Fabric::new();
fabric.add(detect_local(), Hands(1234, Some(reading.clone())));
let out = now(fabric.run(&c, 0, &Parity::BitExact, &signer, "fabric-test")).unwrap();
assert_eq!((out.receipt.joules_micro, out.receipt.energy_class.as_ref()), (1234, Some(&reading)));
assert!(out.receipt.verify());
let mut fabric = Fabric::new();
fabric.add(local_with(Some(10)), CpuReference).add(accelerator(GPU, "port", Some(1)), Port(GPU)).set_model(model);
let first = |fabric: &Fabric, n: u8| fabric.order(&Circuit::qft(n), &Parity::BitExact)[0].0.id.clone();
assert_eq!(first(&fabric, 3), detect_local().id);
assert_eq!(first(&fabric, 20), GPU);
}
#[test]
fn a_calibration_gives_the_cpu_reference_its_figure() {
let corpus = Corpus::Random { seed: 7, cases: 20 };
let reading = counter(50_000, 1_000);
let mut m = TestMeter::reads(Ok(Some((1000, reading.clone()))));
let local = detect_local_metered(corpus, &mut m);
assert_eq!((m.starts, m.stops), (40, 40));
for (entry, gs) in local.kernels.iter().zip(Gateset::ALL) {
assert_eq!(entry.kernel, apply_kernel(gs));
let ops: u64 = corpus.circuits(gs).iter().map(pair_updates).sum();
let mut expect = EnergyCalibration::new();
for c in corpus.circuits(gs) {
expect.add(pair_updates(&c), 1000, Some(&reading));
}
assert_eq!(entry.energy, expect.finish());
assert!(entry.energy.is_some());
let (nj, _) = entry.energy.clone().unwrap();
assert_eq!(u128::from(nj), (20u128 * 1000 * 1000).div_ceil(u128::from(ops)));
}
let mut none = TestMeter::reads(Ok(None));
assert!(detect_local_metered(corpus, &mut none).kernels.iter().all(|k| k.energy.is_none()));
}
}