// CARRY Quantum Simulator Core // Pure First-Principles Quantum Simulation Engine // Supports StateVector (|ψ⟩) & Density Matrix (ρ) simulation, Gates, Noise, and Measurements. // // DISCLAIMER & SAFETY REQUIREMENT: // This system is explicitly a SIMULATOR AND RESEARCH PLATFORM. // Simulated quantum entities are tagged with SIMULATED_* to distinguish from PHYSICAL_QUBIT. use std::fmt; /// Labels distinguishing simulated quantum constructs from physical hardware. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum QuantumEntityTag { SimulatedQubit, SimulatedQuantumState, SimulatedEntanglement, SimulatedTopologicalQubit, PhysicalQubit, // Reserved for hardware disclaimers - never instantiated in simulator } impl fmt::Display for QuantumEntityTag { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { QuantumEntityTag::SimulatedQubit => write!(f, "SIMULATED_QUBIT"), QuantumEntityTag::SimulatedQuantumState => write!(f, "SIMULATED_QUANTUM_STATE"), QuantumEntityTag::SimulatedEntanglement => write!(f, "SIMULATED_ENTANGLEMENT"), QuantumEntityTag::SimulatedTopologicalQubit => write!(f, "SIMULATED_TOPOLOGICAL_QUBIT"), QuantumEntityTag::PhysicalQubit => write!(f, "PHYSICAL_QUBIT"), } } } /// Complex numbers for quantum amplitude representation (64-bit precision). #[derive(Debug, Clone, Copy, PartialEq)] pub struct Complex { pub re: f64, pub im: f64, } impl Complex { pub fn new(re: f64, im: f64) -> Self { Self { re, im } } pub fn zero() -> Self { Self { re: 0.0, im: 0.0 } } pub fn one() -> Self { Self { re: 1.0, im: 0.0 } } pub fn i() -> Self { Self { re: 0.0, im: 1.0 } } pub fn norm_sq(&self) -> f64 { self.re * self.re + self.im * self.im } pub fn norm(&self) -> f64 { self.norm_sq().sqrt() } pub fn conj(&self) -> Self { Self { re: self.re, im: -self.im } } pub fn add(&self, rhs: Self) -> Self { Self { re: self.re + rhs.re, im: self.im + rhs.im } } pub fn sub(&self, rhs: Self) -> Self { Self { re: self.re - rhs.re, im: self.im - rhs.im } } pub fn mul(&self, rhs: Self) -> Self { Self { re: self.re * rhs.re - self.im * rhs.im, im: self.re * rhs.im + self.im * rhs.re, } } pub fn scale(&self, s: f64) -> Self { Self { re: self.re * s, im: self.im * s } } pub fn exp_i(theta: f64) -> Self { Self { re: theta.cos(), im: theta.sin() } } } impl fmt::Display for Complex { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.im >= 0.0 { write!(f, "{:.4}+{:.4}i", self.re, self.im) } else { write!(f, "{:.4}{:.4}i", self.re, self.im) } } } /// Simulated Qubit entity. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Qubit { pub id: usize, pub label: String, pub tag: QuantumEntityTag, } impl Qubit { pub fn new(id: usize, label: impl Into) -> Self { Self { id, label: label.into(), tag: QuantumEntityTag::SimulatedQubit, } } } /// Quantum Register containing multiple simulated qubits. #[derive(Debug, Clone)] pub struct QuantumRegister { pub qubits: Vec, pub tag: QuantumEntityTag, } impl QuantumRegister { pub fn new(num_qubits: usize) -> Self { let qubits = (0..num_qubits) .map(|i| Qubit::new(i, format!("q{}", i))) .collect(); Self { qubits, tag: QuantumEntityTag::SimulatedQubit, } } pub fn num_qubits(&self) -> usize { self.qubits.len() } } /// Simulation Mode: StateVector vs Density Matrix. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SimulationMode { StateVector, DensityMatrix, } /// Quantum State representation: Pure Statevector (|ψ⟩) or Mixed Density Matrix (ρ). #[derive(Debug, Clone)] pub enum QuantumState { StateVector { num_qubits: usize, amplitudes: Vec, tag: QuantumEntityTag, }, DensityMatrix { num_qubits: usize, matrix: Vec>, // 2^n x 2^n tag: QuantumEntityTag, }, } impl QuantumState { /// Initialize statevector |0...0⟩ for n qubits. pub fn new_statevector(num_qubits: usize) -> Self { let dim = 1 << num_qubits; let mut amplitudes = vec![Complex::zero(); dim]; amplitudes[0] = Complex::one(); // |0...0⟩ QuantumState::StateVector { num_qubits, amplitudes, tag: QuantumEntityTag::SimulatedQuantumState, } } /// Initialize density matrix |0...0⟩⟨0...0| for n qubits. pub fn new_density_matrix(num_qubits: usize) -> Self { let dim = 1 << num_qubits; let mut matrix = vec![vec![Complex::zero(); dim]; dim]; matrix[0][0] = Complex::one(); QuantumState::DensityMatrix { num_qubits, matrix, tag: QuantumEntityTag::SimulatedQuantumState, } } pub fn num_qubits(&self) -> usize { match self { QuantumState::StateVector { num_qubits, .. } => *num_qubits, QuantumState::DensityMatrix { num_qubits, .. } => *num_qubits, } } pub fn dimension(&self) -> usize { 1 << self.num_qubits() } pub fn tag(&self) -> QuantumEntityTag { match self { QuantumState::StateVector { tag, .. } => *tag, QuantumState::DensityMatrix { tag, .. } => *tag, } } /// Verify norm of statevector is 1.0 (or trace of density matrix is 1.0). pub fn is_valid_state(&self) -> bool { match self { QuantumState::StateVector { amplitudes, .. } => { let norm_sq: f64 = amplitudes.iter().map(|a| a.norm_sq()).sum(); (norm_sq - 1.0).abs() < 1e-6 } QuantumState::DensityMatrix { matrix, .. } => { let trace: f64 = (0..matrix.len()).map(|i| matrix[i][i].re).sum(); (trace - 1.0).abs() < 1e-6 } } } /// Compute state purity Tr(ρ^2). For pure states, purity = 1.0. pub fn purity(&self) -> f64 { match self { QuantumState::StateVector { .. } => 1.0, QuantumState::DensityMatrix { matrix, .. } => { let dim = matrix.len(); let mut trace_sq = 0.0; for i in 0..dim { for j in 0..dim { // (ρ^2)_ii = sum_j ρ_ij * ρ_ji let prod = matrix[i][j].mul(matrix[j][i]); trace_sq += prod.re; } } trace_sq } } } } /// Standard single and multi-qubit quantum gate definitions. #[derive(Debug, Clone)] pub enum GateType { I, X, Y, Z, H, S, T, Rx(f64), Ry(f64), Rz(f64), CNOT, CZ, SWAP, CustomUnitary { label: String, matrix: Vec> }, } /// Gate operation with target and optional control qubits. #[derive(Debug, Clone)] pub struct Gate { pub gate_type: GateType, pub targets: Vec, pub controls: Vec, } impl Gate { pub fn h(target: usize) -> Self { Self { gate_type: GateType::H, targets: vec![target], controls: vec![] } } pub fn x(target: usize) -> Self { Self { gate_type: GateType::X, targets: vec![target], controls: vec![] } } pub fn y(target: usize) -> Self { Self { gate_type: GateType::Y, targets: vec![target], controls: vec![] } } pub fn z(target: usize) -> Self { Self { gate_type: GateType::Z, targets: vec![target], controls: vec![] } } pub fn s(target: usize) -> Self { Self { gate_type: GateType::S, targets: vec![target], controls: vec![] } } pub fn t(target: usize) -> Self { Self { gate_type: GateType::T, targets: vec![target], controls: vec![] } } pub fn rx(target: usize, theta: f64) -> Self { Self { gate_type: GateType::Rx(theta), targets: vec![target], controls: vec![] } } pub fn ry(target: usize, theta: f64) -> Self { Self { gate_type: GateType::Ry(theta), targets: vec![target], controls: vec![] } } pub fn rz(target: usize, theta: f64) -> Self { Self { gate_type: GateType::Rz(theta), targets: vec![target], controls: vec![] } } pub fn cnot(control: usize, target: usize) -> Self { Self { gate_type: GateType::CNOT, targets: vec![target], controls: vec![control] } } pub fn cz(control: usize, target: usize) -> Self { Self { gate_type: GateType::CZ, targets: vec![target], controls: vec![control] } } pub fn swap(q1: usize, q2: usize) -> Self { Self { gate_type: GateType::SWAP, targets: vec![q1, q2], controls: vec![] } } /// Return 2x2 matrix representation for single-qubit gate. pub fn single_qubit_matrix(&self) -> Result<[[Complex; 2]; 2], String> { let inv_sqrt2 = 1.0 / 2.0f64.sqrt(); match &self.gate_type { GateType::I => Ok([ [Complex::one(), Complex::zero()], [Complex::zero(), Complex::one()], ]), GateType::X => Ok([ [Complex::zero(), Complex::one()], [Complex::one(), Complex::zero()], ]), GateType::Y => Ok([ [Complex::zero(), Complex::new(0.0, -1.0)], [Complex::new(0.0, 1.0), Complex::zero()], ]), GateType::Z => Ok([ [Complex::one(), Complex::zero()], [Complex::zero(), Complex::new(-1.0, 0.0)], ]), GateType::H => Ok([ [Complex::new(inv_sqrt2, 0.0), Complex::new(inv_sqrt2, 0.0)], [Complex::new(inv_sqrt2, 0.0), Complex::new(-inv_sqrt2, 0.0)], ]), GateType::S => Ok([ [Complex::one(), Complex::zero()], [Complex::zero(), Complex::i()], ]), GateType::T => Ok([ [Complex::one(), Complex::zero()], [Complex::zero(), Complex::exp_i(std::f64::consts::FRAC_PI_4)], ]), GateType::Rx(theta) => { let cos = (theta / 2.0).cos(); let sin = (theta / 2.0).sin(); Ok([ [Complex::new(cos, 0.0), Complex::new(0.0, -sin)], [Complex::new(0.0, -sin), Complex::new(cos, 0.0)], ]) } GateType::Ry(theta) => { let cos = (theta / 2.0).cos(); let sin = (theta / 2.0).sin(); Ok([ [Complex::new(cos, 0.0), Complex::new(-sin, 0.0)], [Complex::new(sin, 0.0), Complex::new(cos, 0.0)], ]) } GateType::Rz(theta) => Ok([ [Complex::exp_i(-theta / 2.0), Complex::zero()], [Complex::zero(), Complex::exp_i(theta / 2.0)], ]), _ => Err("Not a single qubit gate".into()), } } } /// Quantum Circuit containing sequence of gates and measurements. #[derive(Debug, Clone)] pub struct Circuit { pub num_qubits: usize, pub gates: Vec, } impl Circuit { pub fn new(num_qubits: usize) -> Self { Self { num_qubits, gates: Vec::new(), } } pub fn add_gate(&mut self, gate: Gate) { self.gates.push(gate); } } /// Noise & Error Models for quantum channel simulation. #[derive(Debug, Clone)] pub enum ErrorModel { None, BitFlip { probability: f64 }, PhaseFlip { probability: f64 }, Depolarizing { probability: f64 }, AmplitudeDamping { gamma: f64 }, } /// Measurement result record. #[derive(Debug, Clone)] pub struct MeasurementResult { pub qubit: usize, pub outcome: u8, // 0 or 1 pub probability: f64, } /// Entanglement tracking graph. #[derive(Debug, Clone)] pub struct EntanglementGraph { pub groups: Vec>, pub tag: QuantumEntityTag, } impl EntanglementGraph { pub fn new(num_qubits: usize) -> Self { // Initially each qubit is independent let groups = (0..num_qubits).map(|i| vec![i]).collect(); Self { groups, tag: QuantumEntityTag::SimulatedEntanglement, } } pub fn entangle(&mut self, q1: usize, q2: usize) { let g1_idx = self.groups.iter().position(|g| g.contains(&q1)); let g2_idx = self.groups.iter().position(|g| g.contains(&q2)); if let (Some(i1), Some(i2)) = (g1_idx, g2_idx) { if i1 != i2 { let mut g2 = self.groups.remove(i2.max(i1)); let g1_idx_adjusted = i1.min(i2); self.groups[g1_idx_adjusted].append(&mut g2); } } } pub fn are_entangled(&self, q1: usize, q2: usize) -> bool { self.groups.iter().any(|g| g.contains(&q1) && g.contains(&q2)) } } /// Simulation Executor Engine. pub struct QuantumSimulator { pub state: QuantumState, pub entanglement_graph: EntanglementGraph, pub error_model: ErrorModel, } impl QuantumSimulator { pub fn new(num_qubits: usize, mode: SimulationMode, error_model: ErrorModel) -> Self { let state = match mode { SimulationMode::StateVector => QuantumState::new_statevector(num_qubits), SimulationMode::DensityMatrix => QuantumState::new_density_matrix(num_qubits), }; let entanglement_graph = EntanglementGraph::new(num_qubits); Self { state, entanglement_graph, error_model, } } pub fn num_qubits(&self) -> usize { self.state.num_qubits() } /// Apply a gate to the simulator state. pub fn apply_gate(&mut self, gate: &Gate) -> Result<(), String> { match &mut self.state { QuantumState::StateVector { num_qubits, amplitudes, .. } => { Self::apply_gate_to_statevector(*num_qubits, amplitudes, gate)?; } QuantumState::DensityMatrix { num_qubits, matrix, .. } => { Self::apply_gate_to_density_matrix(*num_qubits, matrix, gate)?; } } // Track entanglement if two-qubit gate if gate.targets.len() + gate.controls.len() >= 2 { let all_qubits: Vec = gate.controls.iter().chain(gate.targets.iter()).cloned().collect(); for window in all_qubits.windows(2) { self.entanglement_graph.entangle(window[0], window[1]); } } Ok(()) } fn apply_gate_to_statevector( num_qubits: usize, amplitudes: &mut Vec, gate: &Gate, ) -> Result<(), String> { let dim = 1 << num_qubits; match &gate.gate_type { GateType::H | GateType::X | GateType::Y | GateType::Z | GateType::S | GateType::T | GateType::Rx(_) | GateType::Ry(_) | GateType::Rz(_) => { let target = gate.targets[0]; let matrix = gate.single_qubit_matrix()?; let bit_mask = 1 << target; let mut new_amps = amplitudes.clone(); for i in 0..dim { if (i & bit_mask) == 0 { let i0 = i; let i1 = i | bit_mask; let a0 = amplitudes[i0]; let a1 = amplitudes[i1]; new_amps[i0] = matrix[0][0].mul(a0).add(matrix[0][1].mul(a1)); new_amps[i1] = matrix[1][0].mul(a0).add(matrix[1][1].mul(a1)); } } *amplitudes = new_amps; } GateType::CNOT => { let control = gate.controls[0]; let target = gate.targets[0]; let c_mask = 1 << control; let t_mask = 1 << target; for i in 0..dim { if (i & c_mask) != 0 && (i & t_mask) == 0 { let i0 = i; let i1 = i | t_mask; amplitudes.swap(i0, i1); } } } GateType::CZ => { let control = gate.controls[0]; let target = gate.targets[0]; let c_mask = 1 << control; let t_mask = 1 << target; for i in 0..dim { if (i & c_mask) != 0 && (i & t_mask) != 0 { amplitudes[i] = amplitudes[i].scale(-1.0); } } } GateType::SWAP => { let q1 = gate.targets[0]; let q2 = gate.targets[1]; let mask1 = 1 << q1; let mask2 = 1 << q2; for i in 0..dim { let b1 = (i & mask1) != 0; let b2 = (i & mask2) != 0; if b1 && !b2 { let i_other = (i & !mask1) | mask2; if i < i_other { amplitudes.swap(i, i_other); } } } } GateType::I => {} GateType::CustomUnitary { matrix, .. } => { if gate.targets.len() == 1 { let target = gate.targets[0]; let bit_mask = 1 << target; let mut new_amps = amplitudes.clone(); for i in 0..dim { if (i & bit_mask) == 0 { let i0 = i; let i1 = i | bit_mask; let a0 = amplitudes[i0]; let a1 = amplitudes[i1]; new_amps[i0] = matrix[0][0].mul(a0).add(matrix[0][1].mul(a1)); new_amps[i1] = matrix[1][0].mul(a0).add(matrix[1][1].mul(a1)); } } *amplitudes = new_amps; } else { return Err("Multi-qubit custom unitaries not supported in basic vector engine".into()); } } } Ok(()) } fn apply_gate_to_density_matrix( num_qubits: usize, matrix: &mut Vec>, gate: &Gate, ) -> Result<(), String> { // Density matrix transformation: ρ' = U ρ U† let dim = 1 << num_qubits; let mut u = vec![vec![Complex::zero(); dim]; dim]; for i in 0..dim { u[i][i] = Complex::one(); } let mut temp_amps = vec![Complex::zero(); dim]; // Build U matrix by applying gate to basis vectors for col in 0..dim { temp_amps.fill(Complex::zero()); temp_amps[col] = Complex::one(); Self::apply_gate_to_statevector(num_qubits, &mut temp_amps, gate)?; for row in 0..dim { u[row][col] = temp_amps[row]; } } // Compute U ρ U† let mut temp = vec![vec![Complex::zero(); dim]; dim]; // Temp = U * ρ for i in 0..dim { for j in 0..dim { let mut sum = Complex::zero(); for k in 0..dim { sum = sum.add(u[i][k].mul(matrix[k][j])); } temp[i][j] = sum; } } // Matrix = Temp * U† for i in 0..dim { for j in 0..dim { let mut sum = Complex::zero(); for k in 0..dim { sum = sum.add(temp[i][k].mul(u[j][k].conj())); } matrix[i][j] = sum; } } Ok(()) } /// Measure target qubit, returning probability of 1 and collapsing the state based on standard seed/threshold. pub fn measure(&mut self, target: usize, random_draw: f64) -> Result { let num_qubits = self.state.num_qubits(); if target >= num_qubits { return Err(format!("Target qubit {} out of bounds", target)); } let bit_mask = 1 << target; let prob_1 = match &self.state { QuantumState::StateVector { amplitudes, .. } => { amplitudes .iter() .enumerate() .filter(|(idx, _)| (idx & bit_mask) != 0) .map(|(_, amp)| amp.norm_sq()) .sum() } QuantumState::DensityMatrix { matrix, .. } => { let dim = matrix.len(); (0..dim) .filter(|idx| (idx & bit_mask) != 0) .map(|idx| matrix[idx][idx].re) .sum() } }; // CE-1 fix: clamp random_draw to [0,1) so callers cannot produce a // zero-norm collapsed state by passing values >= 1.0 or < 0.0. let random_draw = random_draw.clamp(0.0, 1.0 - f64::EPSILON); let outcome = if random_draw < prob_1 { 1 } else { 0 }; // Collapse state match &mut self.state { QuantumState::StateVector { amplitudes, .. } => { let norm = if outcome == 1 { prob_1.sqrt() } else { (1.0 - prob_1).sqrt() }; if norm <= 0.0 { return Err(format!( "MEASUREMENT_COLLAPSE_INVALID: outcome={} prob_1={} norm={}", outcome, prob_1, norm )); } for (idx, amp) in amplitudes.iter_mut().enumerate() { let matches = if outcome == 1 { (idx & bit_mask) != 0 } else { (idx & bit_mask) == 0 }; if matches { *amp = amp.scale(1.0 / norm); } else { *amp = Complex::zero(); } } } QuantumState::DensityMatrix { matrix, .. } => { let dim = matrix.len(); let norm = if outcome == 1 { prob_1 } else { 1.0 - prob_1 }; for i in 0..dim { for j in 0..dim { let i_match = if outcome == 1 { (i & bit_mask) != 0 } else { (i & bit_mask) == 0 }; let j_match = if outcome == 1 { (j & bit_mask) != 0 } else { (j & bit_mask) == 0 }; if i_match && j_match && norm > 0.0 { matrix[i][j] = matrix[i][j].scale(1.0 / norm); } else { matrix[i][j] = Complex::zero(); } } } } } Ok(MeasurementResult { qubit: target, outcome, probability: prob_1, }) } } /// Execution Receipt generated at the completion of a quantum job or simulation cycle limit. #[derive(Debug, Clone)] pub struct ExecutionReceipt { pub job_id: String, pub status: String, // "SUCCESS", "HALT", "CYCLE_LIMIT", "UNSAT" pub cycles_executed: usize, pub qubits: usize, pub gates: usize, pub agents: usize, pub entanglement_groups: usize, pub measurements: usize, pub icp_checks: usize, pub asp_checks: usize, pub failures: usize, pub execution_time_ms: u128, pub state_tag: QuantumEntityTag, pub memory_bytes: usize, } impl fmt::Display for ExecutionReceipt { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "═══════════════════════════════════════════════════════════════")?; writeln!(f, " EXECUTION RECEIPT — CARRY QUANTUM SIMULATOR ")?; writeln!(f, "═══════════════════════════════════════════════════════════════")?; writeln!(f, " Job ID: {}", self.job_id)?; writeln!(f, " Status: {}", self.status)?; writeln!(f, " State Tag: {}", self.state_tag)?; writeln!(f, " Cycles Executed: {}", self.cycles_executed)?; writeln!(f, " Qubits: {}", self.qubits)?; writeln!(f, " Gates: {}", self.gates)?; writeln!(f, " Agents: {}", self.agents)?; writeln!(f, " Entanglement Groups: {}", self.entanglement_groups)?; writeln!(f, " Measurements: {}", self.measurements)?; writeln!(f, " ICP Checks: {}", self.icp_checks)?; writeln!(f, " ASP Checks: {}", self.asp_checks)?; writeln!(f, " Failures: {}", self.failures)?; writeln!(f, " Execution Time: {} ms", self.execution_time_ms)?; writeln!(f, " Memory Consumption: {} bytes", self.memory_bytes)?; writeln!(f, "═══════════════════════════════════════════════════════════════") } }