Download runtime/quantum/core.rs from Snapkitty/carry-agent: direct link, hf CLI and curl.
- Browser
- Download file 26.4 kB
-
https://huggingface.co/Snapkitty/carry-agent/resolve/main/runtime/quantum/core.rs
- Command line
-
hf download hf://Snapkitty/carry-agent/runtime/quantum/core.rs
-
curl -L -o core.rs https://huggingface.co/Snapkitty/carry-agent/resolve/main/runtime/quantum/core.rs
26.4 kB
| // 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. | |
| 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). | |
| 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. | |
| pub struct Qubit { | |
| pub id: usize, | |
| pub label: String, | |
| pub tag: QuantumEntityTag, | |
| } | |
| impl Qubit { | |
| pub fn new(id: usize, label: impl Into<String>) -> Self { | |
| Self { | |
| id, | |
| label: label.into(), | |
| tag: QuantumEntityTag::SimulatedQubit, | |
| } | |
| } | |
| } | |
| /// Quantum Register containing multiple simulated qubits. | |
| pub struct QuantumRegister { | |
| pub qubits: Vec<Qubit>, | |
| 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. | |
| pub enum SimulationMode { | |
| StateVector, | |
| DensityMatrix, | |
| } | |
| /// Quantum State representation: Pure Statevector (|Οβ©) or Mixed Density Matrix (Ο). | |
| pub enum QuantumState { | |
| StateVector { | |
| num_qubits: usize, | |
| amplitudes: Vec<Complex>, | |
| tag: QuantumEntityTag, | |
| }, | |
| DensityMatrix { | |
| num_qubits: usize, | |
| matrix: Vec<Vec<Complex>>, // 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. | |
| pub enum GateType { | |
| I, | |
| X, | |
| Y, | |
| Z, | |
| H, | |
| S, | |
| T, | |
| Rx(f64), | |
| Ry(f64), | |
| Rz(f64), | |
| CNOT, | |
| CZ, | |
| SWAP, | |
| CustomUnitary { label: String, matrix: Vec<Vec<Complex>> }, | |
| } | |
| /// Gate operation with target and optional control qubits. | |
| pub struct Gate { | |
| pub gate_type: GateType, | |
| pub targets: Vec<usize>, | |
| pub controls: Vec<usize>, | |
| } | |
| 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. | |
| pub struct Circuit { | |
| pub num_qubits: usize, | |
| pub gates: Vec<Gate>, | |
| } | |
| 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. | |
| pub enum ErrorModel { | |
| None, | |
| BitFlip { probability: f64 }, | |
| PhaseFlip { probability: f64 }, | |
| Depolarizing { probability: f64 }, | |
| AmplitudeDamping { gamma: f64 }, | |
| } | |
| /// Measurement result record. | |
| pub struct MeasurementResult { | |
| pub qubit: usize, | |
| pub outcome: u8, // 0 or 1 | |
| pub probability: f64, | |
| } | |
| /// Entanglement tracking graph. | |
| pub struct EntanglementGraph { | |
| pub groups: Vec<Vec<usize>>, | |
| 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<usize> = 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<Complex>, | |
| 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<Vec<Complex>>, | |
| 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<MeasurementResult, String> { | |
| 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. | |
| 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, "βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ") | |
| } | |
| } | |