| |
| |
| |
| |
|
|
| use serde::{Deserialize, Serialize}; |
| use std::collections::HashMap; |
|
|
| |
| |
| |
|
|
| #[derive(Debug, Clone, Copy)] |
| pub struct QubitId(pub usize); |
|
|
| #[derive(Debug, Clone, Copy)] |
| pub struct BitId(pub usize); |
|
|
| #[derive(Debug, Clone, Serialize, Deserialize)] |
| pub enum GateKind { |
| H, |
| X, |
| Y, |
| Z, |
| S, |
| Sdg, |
| T, |
| Tdg, |
| Rx(f64), |
| Ry(f64), |
| Rz(f64), |
| Phase(f64), |
| CX, |
| CZ, |
| CCX, |
| Swap, |
| Measure { target_bit: usize }, |
| Barrier, |
| Reset, |
| Custom { name: String, params: Vec<f64> }, |
| } |
|
|
| #[derive(Debug, Clone, Serialize, Deserialize)] |
| pub struct Gate { |
| pub kind: GateKind, |
| pub qubits: Vec<usize>, |
| } |
|
|
| impl Gate { |
| pub fn new(kind: GateKind, qubits: Vec<usize>) -> Self { |
| Self { kind, qubits } |
| } |
| } |
|
|
| #[derive(Debug, Clone, Serialize, Deserialize)] |
| pub struct GateProgram { |
| pub n_qubits: usize, |
| pub n_cbits: usize, |
| pub gates: Vec<Gate>, |
| } |
|
|
| impl GateProgram { |
| pub fn new(n_qubits: usize, n_cbits: usize) -> Self { |
| Self { |
| n_qubits, |
| n_cbits, |
| gates: Vec::new(), |
| } |
| } |
|
|
| pub fn add_gate(&mut self, gate: Gate) { |
| self.gates.push(gate); |
| } |
| } |
|
|
| |
| |
| |
|
|
| #[derive(Debug, Deserialize)] |
| pub struct QuantumIR { |
| pub version: String, |
| pub source_lang: String, |
| pub qubits: usize, |
| pub cbits: usize, |
| pub ops: Vec<QIROp>, |
| pub metadata: QIRMetadata, |
| pub resources: QIRResources, |
| } |
|
|
| #[derive(Debug, Deserialize)] |
| #[serde(tag = "type")] |
| pub enum QIROp { |
| #[serde(rename = "gate")] |
| Gate { |
| name: String, |
| params: Vec<f64>, |
| qubits: Vec<usize>, |
| }, |
| #[serde(rename = "measure")] |
| Measure { qubit: usize, cbit: usize }, |
| #[serde(rename = "barrier")] |
| Barrier { qubits: Vec<usize> }, |
| #[serde(rename = "reset")] |
| Reset { qubit: usize }, |
| } |
|
|
| #[derive(Debug, Deserialize)] |
| pub struct QIRMetadata { |
| pub source_lang: String, |
| pub version: String, |
| pub unsupported: Vec<String>, |
| } |
|
|
| #[derive(Debug, Deserialize)] |
| pub struct QIRResources { |
| pub gate_count: usize, |
| pub depth: usize, |
| pub t_count: usize, |
| pub width: usize, |
| } |
|
|
| |
| |
| |
|
|
| impl QuantumIR { |
| pub fn to_gate_program(&self) -> GateProgram { |
| let mut program = GateProgram::new(self.qubits, self.cbits); |
|
|
| for op in &self.ops { |
| match op { |
| QIROp::Gate { |
| name, |
| params, |
| qubits, |
| } => { |
| let gate_kind = qir_gate_to_kind(name, params); |
| let gate = Gate::new(gate_kind, qubits.clone()); |
| program.add_gate(gate); |
| } |
| QIROp::Measure { qubit, cbit } => { |
| let gate = Gate::new( |
| GateKind::Measure { target_bit: *cbit }, |
| vec![*qubit], |
| ); |
| program.add_gate(gate); |
| } |
| QIROp::Barrier { qubits } => { |
| let gate = Gate::new(GateKind::Barrier, qubits.clone()); |
| program.add_gate(gate); |
| } |
| QIROp::Reset { qubit } => { |
| let gate = Gate::new(GateKind::Reset, vec![*qubit]); |
| program.add_gate(gate); |
| } |
| } |
| } |
|
|
| program |
| } |
| } |
|
|
| fn qir_gate_to_kind(name: &str, params: &[f64]) -> GateKind { |
| match name { |
| "H" => GateKind::H, |
| "X" => GateKind::X, |
| "Y" => GateKind::Y, |
| "Z" => GateKind::Z, |
| "T" => GateKind::T, |
| "Tdg" | "T†" => GateKind::Tdg, |
| "S" => GateKind::S, |
| "Sdg" | "S†" => GateKind::Sdg, |
| "Rx" => GateKind::Rx(params[0]), |
| "Ry" => GateKind::Ry(params[0]), |
| "Rz" => GateKind::Rz(params[0]), |
| "Phase" => GateKind::Phase(params[0]), |
| "CX" => GateKind::CX, |
| "CZ" => GateKind::CZ, |
| "CCX" => GateKind::CCX, |
| "Swap" => GateKind::Swap, |
| _ => GateKind::Custom { |
| name: name.to_string(), |
| params: params.to_vec(), |
| }, |
| } |
| } |
|
|
| |
| |
| |
|
|
| pub struct KernelExecutor { |
| pub n_qubits: usize, |
| pub n_cbits: usize, |
| } |
|
|
| impl KernelExecutor { |
| pub fn new(n_qubits: usize, n_cbits: usize) -> Self { |
| Self { n_qubits, n_cbits } |
| } |
|
|
| pub fn execute_dfe_shot(&self, program: &GateProgram, pauli_basis: &[char]) -> f64 { |
| let mut has_xy = false; |
| let mut z_weight: i32 = 0; |
| let mut eigenvalue: i32 = 1; |
|
|
| for (q, &pauli) in pauli_basis.iter().enumerate() { |
| match pauli { |
| 'X' | 'Y' => has_xy = true, |
| 'Z' => { |
| z_weight += 1; |
| |
| |
| } |
| _ => {} |
| } |
| } |
|
|
| if has_xy { |
| 0.0 |
| } else { |
| 3.0_f64.powi(z_weight) * eigenvalue as f64 |
| } |
| } |
| } |
|
|
| |
| |
| |
|
|
| #[derive(Debug, Clone, Serialize, Deserialize)] |
| pub struct KernelReceipt { |
| pub circuit_hash: String, |
| pub kernel_matrix: Vec<Vec<f64>>, |
| pub svm_alpha: Vec<f64>, |
| pub svm_bias: f64, |
| pub backend: String, |
| pub timestamp: String, |
| pub entropy_source: String, |
| pub entropy_proof: String, |
| pub zne_applied: bool, |
| pub noise_factors: Vec<f64>, |
| pub raw_fidelities: Vec<Vec<f64>>, |
| pub shots_per_entry: usize, |
| pub n_qubits: usize, |
| pub n_layers: usize, |
| } |
|
|
| impl KernelReceipt { |
| pub fn verify(&self) -> bool { |
| |
| let n = self.kernel_matrix.len(); |
| for i in 0..n { |
| for j in 0..n { |
| let diff = (self.kernel_matrix[i][j] - self.kernel_matrix[j][i]).abs(); |
| if diff > 1e-10 { |
| return false; |
| } |
| } |
| } |
|
|
| |
| if self.zne_applied && self.noise_factors.is_empty() { |
| return false; |
| } |
|
|
| true |
| } |
| } |
|
|
| #[cfg(test)] |
| mod tests { |
| use super::*; |
|
|
| #[test] |
| fn test_qir_parsing() { |
| let json = r#"{ |
| "version": "0.1.0", |
| "source_lang": "yao", |
| "qubits": 2, |
| "cbits": 2, |
| "ops": [ |
| {"type": "gate", "name": "H", "params": [], "qubits": [0]}, |
| {"type": "gate", "name": "CX", "params": [], "qubits": [0, 1]}, |
| {"type": "measure", "qubit": 0, "cbit": 0}, |
| {"type": "measure", "qubit": 1, "cbit": 1} |
| ], |
| "metadata": {"source_lang": "yao", "version": "0.1.0", "unsupported": []}, |
| "resources": {"gate_count": 2, "depth": 2, "t_count": 0, "width": 2} |
| }"#; |
|
|
| let ir: QuantumIR = serde_json::from_str(json).unwrap(); |
| assert_eq!(ir.qubits, 2); |
| assert_eq!(ir.ops.len(), 4); |
|
|
| let program = ir.to_gate_program(); |
| assert_eq!(program.n_qubits, 2); |
| assert_eq!(program.gates.len(), 4); |
| } |
|
|
| #[test] |
| fn test_receipt_verification() { |
| let receipt = KernelReceipt { |
| circuit_hash: "abc123".to_string(), |
| kernel_matrix: vec![vec![1.0, 0.5], vec![0.5, 1.0]], |
| svm_alpha: vec![0.5, 0.5], |
| svm_bias: 0.0, |
| backend: "simulator".to_string(), |
| timestamp: "2026-08-21T00:00:00Z".to_string(), |
| entropy_source: "ANU_QRNG".to_string(), |
| entropy_proof: "proof".to_string(), |
| zne_applied: true, |
| noise_factors: vec![1.0, 1.5, 2.0, 3.0], |
| raw_fidelities: vec![vec![0.9], vec![0.85], vec![0.8], vec![0.7]], |
| shots_per_entry: 1000, |
| n_qubits: 5, |
| n_layers: 2, |
| }; |
|
|
| assert!(receipt.verify()); |
| } |
| } |
|
|