//! The dense f64 state vector on the CUDA devices of the machine that runs //! this: bit for bit the CPU's, or the certificate says not. //! //! The machine declares its devices in `WAI_QUANTUM_CUDA_EXPECT` (comma- //! separated keys, or `none`), as for `cuda_member`; `WAI_QUANTUM_CUDA_REPORT` //! names a file the established lines are appended to. #![cfg(not(target_arch = "wasm32"))] use std::io::Write; use wai_quantum::gates::Gate; use wai_quantum::quantum_fabric::sv64::{self, MUTANTS, SV_DEFAULT, SV_DEFAULT_PIN, SvCorpus}; use wai_quantum::quantum_fabric::{Certification, Parity}; use wai_quantum::quantum_fabric_cuda::{CudaMember, discover}; use wai_quantum::quantum_sv::StateVector; fn report(line: &str) { println!("{line}"); if let Some(path) = std::env::var_os("WAI_QUANTUM_CUDA_REPORT") { let mut f = std::fs::OpenOptions::new().create(true).append(true).open(&path).expect("the report file opens"); writeln!(f, "{line}").expect("the report line is written"); } } fn members() -> Vec { let d = discover(); let mut found: Vec = d.found.iter().map(|m| m.key().to_string()).collect(); found.sort(); let found_list = if found.is_empty() { "none".to_string() } else { found.join(",") }; let expect = std::env::var("WAI_QUANTUM_CUDA_EXPECT").unwrap_or_else(|_| panic!("WAI_QUANTUM_CUDA_EXPECT is not set; found {found_list}")); assert_eq!(found_list, expect, "the devices found are not the declared ones"); d.found } fn hex(b: &[u8]) -> String { b.iter().map(|x| format!("{x:02x}")).collect() } /// The CPU certifying itself on `corpus`: the digest a bit-exact device /// reproduces. fn cpu_digest(corpus: SvCorpus) -> String { let mut cert = Certification::new(); for case in corpus.cases() { let r = case.reference().unwrap(); cert.add(&case.bytes(), &r, &r); } hex(&cert.finish(sv64::KERNEL_SV_RUN, "cpu", "cpu", &corpus.generator()).corpus) } #[test] fn s0_the_state_vector_is_the_cpus_bit_for_bit() { let cpu = cpu_digest(SV_DEFAULT); assert_eq!(cpu, SV_DEFAULT_PIN, "this machine's CPU does not reproduce the pin"); for m in members() { let sv = m.sv().unwrap_or_else(|e| panic!("{}: {e}", m.key())); let c = sv.certify(SV_DEFAULT).unwrap_or_else(|e| panic!("{}: {e}", m.key())); assert_eq!(c.parity, Parity::BitExact, "{}", m.key()); assert_eq!(c.cases, SV_DEFAULT.cases as u64); assert_eq!(hex(&c.corpus), cpu, "{}: the digest is not the CPU's", m.key()); report(&format!("cuda sv certified: key={} member={} kernel={} implementation={} parity=bit-exact cases={} digest={}", m.key(), m.id(), c.kernel, c.implementation, c.cases, hex(&c.corpus))); } } #[test] fn s1_wide_states_match_the_cpu() { for m in members() { let sv = m.sv().unwrap(); for (n, width) in [(16u32, 0usize), (20, 3)] { let mut gates = Vec::new(); let mut a = 0.1f64; for layer in 0..6u32 { for q in 0..n { a += 0.731; gates.push(match (q + layer) % 5 { 0 => Gate::rx(q, a), 1 => Gate::ry(q, a), 2 => Gate::rz(q, a), 3 => Gate::sqrt_w(q), _ => Gate::t(q), }); } let mut q = layer % 2; while q + 1 < n { gates.push(if q % 3 == 0 { Gate::fsim(q, q + 1, a, 0.5 * a) } else { Gate::cz(q, q + 1) }); q += 2; } gates.push(Gate::iswap(0, n - 1)); } let mut cpu = StateVector::zero(n).unwrap(); cpu.run(&gates, width).unwrap(); let (re, im) = sv.run(n, &gates, width).unwrap(); let same = |a: &[f64], b: &[f64]| a.iter().zip(b).all(|(x, y)| x.to_bits() == y.to_bits()); assert!(same(&re, &cpu.re) && same(&im, &cpu.im), "{}: n={n} width={width}", m.key()); } report(&format!("cuda sv wide: key={} 16 and 20 qubits match the CPU bit for bit", m.key())); } } #[test] fn s2_mutants_are_caught() { let small = SvCorpus { cases: 18, ..SV_DEFAULT }; let cpu = cpu_digest(small); for m in members() { let mut killed = 0; for mutant in &MUTANTS { let sv = m.sv_with_source(&sv64::mutate(mutant)).unwrap_or_else(|e| panic!("mutant {}: {e}", mutant.name)); let c = sv.certify(small).unwrap(); assert!(c.parity != Parity::BitExact || hex(&c.corpus) != cpu, "{}: mutant {} survived", m.key(), mutant.name); killed += 1; } report(&format!("cuda sv mutants: key={} killed {killed} of {}", m.key(), MUTANTS.len())); } }