1use crate::error::{LoopError, Result};
7use crate::types::{ComplexVector, QuantumAmplitude};
8use num_complex::Complex64;
9use rand::{thread_rng, Rng};
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12
13#[derive(Clone, Debug, Serialize, Deserialize)]
15pub struct QuantumState {
16 pub num_qubits: usize,
18 pub amplitudes: ComplexVector,
20 pub phases: Vec<f64>,
22 probability_cache: Option<Vec<f64>>,
24}
25
26impl QuantumState {
27 pub fn new(num_qubits: usize) -> Result<Self> {
29 if num_qubits == 0 {
30 return Err(LoopError::quantum_error("Number of qubits must be positive"));
31 }
32 if num_qubits > 20 {
33 return Err(LoopError::quantum_error("Too many qubits (memory limit)"));
34 }
35
36 let num_states = 1 << num_qubits; let mut amplitudes = vec![Complex64::new(0.0, 0.0); num_states];
38 amplitudes[0] = Complex64::new(1.0, 0.0); Ok(Self {
41 num_qubits,
42 amplitudes,
43 phases: vec![0.0; num_qubits],
44 probability_cache: None,
45 })
46 }
47
48 pub fn uniform_superposition(num_qubits: usize) -> Result<Self> {
50 let mut state = Self::new(num_qubits)?;
51 let num_states = 1 << num_qubits;
52 let amplitude = Complex64::new(1.0 / (num_states as f64).sqrt(), 0.0);
53
54 for i in 0..num_states {
55 state.amplitudes[i] = amplitude;
56 }
57
58 state.invalidate_cache();
59 Ok(state)
60 }
61
62 pub fn random(num_qubits: usize) -> Result<Self> {
64 let mut state = Self::new(num_qubits)?;
65 let mut rng = thread_rng();
66 let num_states = 1 << num_qubits;
67
68 for i in 0..num_states {
70 let real: f64 = rng.gen_range(-1.0..1.0);
71 let imag: f64 = rng.gen_range(-1.0..1.0);
72 state.amplitudes[i] = Complex64::new(real, imag);
73 }
74
75 state.normalize()?;
77 Ok(state)
78 }
79
80 pub fn get_probability(&self, state_index: usize) -> f64 {
82 if state_index >= self.amplitudes.len() {
83 return 0.0;
84 }
85 self.amplitudes[state_index].norm_sqr()
86 }
87
88 pub fn probabilities(&mut self) -> &[f64] {
90 if self.probability_cache.is_none() {
91 self.probability_cache = Some(
92 self.amplitudes.iter()
93 .map(|amp| amp.norm_sqr())
94 .collect()
95 );
96 }
97 self.probability_cache.as_ref().unwrap()
98 }
99
100 pub fn normalize(&mut self) -> Result<()> {
102 let norm_squared: f64 = self.amplitudes.iter()
103 .map(|amp| amp.norm_sqr())
104 .sum();
105
106 if norm_squared < f64::EPSILON {
107 return Err(LoopError::quantum_error("Cannot normalize zero state"));
108 }
109
110 let norm = norm_squared.sqrt();
111 for amplitude in &mut self.amplitudes {
112 *amplitude /= norm;
113 }
114
115 self.invalidate_cache();
116 Ok(())
117 }
118
119 pub fn apply_single_qubit_gate(&mut self, qubit: usize, gate: &Gate) -> Result<()> {
121 if qubit >= self.num_qubits {
122 return Err(LoopError::quantum_error("Qubit index out of range"));
123 }
124
125 let matrix = gate.matrix();
126 let mut new_amplitudes = self.amplitudes.clone();
127
128 for state in 0..(1 << self.num_qubits) {
129 let qubit_bit = (state >> qubit) & 1;
130 let other_state = state ^ (1 << qubit); if qubit_bit == 0 {
133 let amp0 = self.amplitudes[state];
135 let amp1 = self.amplitudes[other_state];
136
137 new_amplitudes[state] = matrix[(0, 0)] * amp0 + matrix[(0, 1)] * amp1;
138 new_amplitudes[other_state] = matrix[(1, 0)] * amp0 + matrix[(1, 1)] * amp1;
139 }
140 }
141
142 self.amplitudes = new_amplitudes;
143 self.invalidate_cache();
144 Ok(())
145 }
146
147 pub fn apply_two_qubit_gate(&mut self, control: usize, target: usize, gate: &TwoQubitGate) -> Result<()> {
149 if control >= self.num_qubits || target >= self.num_qubits {
150 return Err(LoopError::quantum_error("Qubit index out of range"));
151 }
152 if control == target {
153 return Err(LoopError::quantum_error("Control and target qubits must be different"));
154 }
155
156 let matrix = gate.matrix();
157 let mut new_amplitudes = self.amplitudes.clone();
158
159 for state in 0..(1 << self.num_qubits) {
160 let control_bit = (state >> control) & 1;
161 let target_bit = (state >> target) & 1;
162 let two_bit_state = (control_bit << 1) | target_bit;
163
164 let base_state = state & !(1 << control) & !(1 << target);
166 let states = [
167 base_state,
168 base_state | (1 << control),
169 base_state | (1 << target),
170 base_state | (1 << control) | (1 << target),
171 ];
172
173 if state == states[two_bit_state] {
175 let mut new_amp = Complex64::new(0.0, 0.0);
176 for i in 0..4 {
177 new_amp += matrix[(two_bit_state, i)] * self.amplitudes[states[i]];
178 }
179 new_amplitudes[state] = new_amp;
180 }
181 }
182
183 self.amplitudes = new_amplitudes;
184 self.invalidate_cache();
185 Ok(())
186 }
187
188 pub fn measure(&mut self) -> usize {
190 let probabilities = self.probabilities().to_vec();
191 let mut rng = thread_rng();
192 let random_value: f64 = rng.gen();
193
194 let mut cumulative_prob = 0.0;
195 for (index, &prob) in probabilities.iter().enumerate() {
196 cumulative_prob += prob;
197 if random_value <= cumulative_prob {
198 self.amplitudes.fill(Complex64::new(0.0, 0.0));
200 self.amplitudes[index] = Complex64::new(1.0, 0.0);
201 self.invalidate_cache();
202 return index;
203 }
204 }
205
206 let last_index = self.amplitudes.len() - 1;
208 self.amplitudes.fill(Complex64::new(0.0, 0.0));
209 self.amplitudes[last_index] = Complex64::new(1.0, 0.0);
210 self.invalidate_cache();
211 last_index
212 }
213
214 pub fn measure_qubit(&mut self, qubit: usize) -> Result<u8> {
216 if qubit >= self.num_qubits {
217 return Err(LoopError::quantum_error("Qubit index out of range"));
218 }
219
220 let prob_one: f64 = self.amplitudes.iter()
222 .enumerate()
223 .filter(|(state, _)| (state >> qubit) & 1 == 1)
224 .map(|(_, amp)| amp.norm_sqr())
225 .sum();
226
227 let mut rng = thread_rng();
228 let result = if rng.gen::<f64>() < prob_one { 1 } else { 0 };
229
230 let norm_factor = if result == 1 { prob_one.sqrt() } else { (1.0 - prob_one).sqrt() };
232
233 for (state, amplitude) in self.amplitudes.iter_mut().enumerate() {
234 if ((state >> qubit) & 1) as u8 != result {
235 *amplitude = Complex64::new(0.0, 0.0);
236 } else {
237 *amplitude /= norm_factor;
238 }
239 }
240
241 self.invalidate_cache();
242 Ok(result)
243 }
244
245 pub fn entanglement_entropy(&self, qubit_a: usize, qubit_b: usize) -> Result<f64> {
247 if qubit_a >= self.num_qubits || qubit_b >= self.num_qubits {
248 return Err(LoopError::quantum_error("Qubit index out of range"));
249 }
250
251 let mut joint_probs = HashMap::new();
253
254 for (state, amplitude) in self.amplitudes.iter().enumerate() {
255 let bit_a = (state >> qubit_a) & 1;
256 let bit_b = (state >> qubit_b) & 1;
257 let joint_state = (bit_a << 1) | bit_b;
258
259 *joint_probs.entry(joint_state).or_insert(0.0) += amplitude.norm_sqr();
260 }
261
262 let mut entropy = 0.0;
264 for &prob in joint_probs.values() {
265 if prob > f64::EPSILON {
266 entropy -= prob * prob.log2();
267 }
268 }
269
270 Ok(entropy)
271 }
272
273 pub fn fidelity(&self, other: &QuantumState) -> Result<f64> {
275 if self.num_qubits != other.num_qubits {
276 return Err(LoopError::quantum_error("States must have the same number of qubits"));
277 }
278
279 let overlap: Complex64 = self.amplitudes.iter()
280 .zip(other.amplitudes.iter())
281 .map(|(a, b)| a.conj() * b)
282 .sum();
283
284 Ok(overlap.norm_sqr())
285 }
286
287 pub fn apply_phase(&mut self, qubit: usize, phase: f64) -> Result<()> {
289 if qubit >= self.num_qubits {
290 return Err(LoopError::quantum_error("Qubit index out of range"));
291 }
292
293 let phase_factor = Complex64::new(phase.cos(), phase.sin());
294
295 for (state, amplitude) in self.amplitudes.iter_mut().enumerate() {
296 if (state >> qubit) & 1 == 1 {
297 *amplitude *= phase_factor;
298 }
299 }
300
301 self.phases[qubit] += phase;
302 self.invalidate_cache();
303 Ok(())
304 }
305
306 pub fn expectation_pauli(&self, qubit: usize, pauli: PauliOperator) -> Result<f64> {
308 if qubit >= self.num_qubits {
309 return Err(LoopError::quantum_error("Qubit index out of range"));
310 }
311
312 match pauli {
313 PauliOperator::X => {
314 let mut expectation = 0.0;
316 for (state, amplitude) in self.amplitudes.iter().enumerate() {
317 let flipped_state = state ^ (1 << qubit);
318 expectation += 2.0 * (amplitude.conj() * self.amplitudes[flipped_state]).re;
319 }
320 Ok(expectation)
321 }
322 PauliOperator::Y => {
323 let mut expectation = 0.0;
325 for (state, amplitude) in self.amplitudes.iter().enumerate() {
326 let flipped_state = state ^ (1 << qubit);
327 let sign = if (state >> qubit) & 1 == 0 { 1.0 } else { -1.0 };
328 expectation += 2.0 * sign * (amplitude.conj() * self.amplitudes[flipped_state]).im;
329 }
330 Ok(expectation)
331 }
332 PauliOperator::Z => {
333 let mut expectation = 0.0;
335 for (state, amplitude) in self.amplitudes.iter().enumerate() {
336 let sign = if (state >> qubit) & 1 == 0 { 1.0 } else { -1.0 };
337 expectation += sign * amplitude.norm_sqr();
338 }
339 Ok(expectation)
340 }
341 }
342 }
343
344 fn invalidate_cache(&mut self) {
345 self.probability_cache = None;
346 }
347}
348
349#[derive(Clone, Copy, Debug, PartialEq, Eq)]
351pub enum PauliOperator {
352 X, Y, Z, }
356
357#[derive(Clone, Debug)]
359pub enum Gate {
360 I,
362 X,
364 Y,
366 Z,
368 H,
370 S,
372 T,
374 RX(f64),
376 RY(f64),
378 RZ(f64),
380 Custom(nalgebra::Matrix2<Complex64>),
382}
383
384impl Gate {
385 pub fn matrix(&self) -> nalgebra::Matrix2<Complex64> {
387 use nalgebra::Matrix2;
388
389 match self {
390 Gate::I => Matrix2::new(
391 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0),
392 Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0),
393 ),
394 Gate::X => Matrix2::new(
395 Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0),
396 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0),
397 ),
398 Gate::Y => Matrix2::new(
399 Complex64::new(0.0, 0.0), Complex64::new(0.0, -1.0),
400 Complex64::new(0.0, 1.0), Complex64::new(0.0, 0.0),
401 ),
402 Gate::Z => Matrix2::new(
403 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0),
404 Complex64::new(0.0, 0.0), Complex64::new(-1.0, 0.0),
405 ),
406 Gate::H => {
407 let inv_sqrt2 = 1.0 / 2.0_f64.sqrt();
408 Matrix2::new(
409 Complex64::new(inv_sqrt2, 0.0), Complex64::new(inv_sqrt2, 0.0),
410 Complex64::new(inv_sqrt2, 0.0), Complex64::new(-inv_sqrt2, 0.0),
411 )
412 }
413 Gate::S => Matrix2::new(
414 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0),
415 Complex64::new(0.0, 0.0), Complex64::new(0.0, 1.0),
416 ),
417 Gate::T => Matrix2::new(
418 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0),
419 Complex64::new(0.0, 0.0), Complex64::new(1.0/2.0_f64.sqrt(), 1.0/2.0_f64.sqrt()),
420 ),
421 Gate::RX(theta) => {
422 let half_theta = theta / 2.0;
423 let cos_val = half_theta.cos();
424 let sin_val = half_theta.sin();
425 Matrix2::new(
426 Complex64::new(cos_val, 0.0), Complex64::new(0.0, -sin_val),
427 Complex64::new(0.0, -sin_val), Complex64::new(cos_val, 0.0),
428 )
429 }
430 Gate::RY(theta) => {
431 let half_theta = theta / 2.0;
432 let cos_val = half_theta.cos();
433 let sin_val = half_theta.sin();
434 Matrix2::new(
435 Complex64::new(cos_val, 0.0), Complex64::new(-sin_val, 0.0),
436 Complex64::new(sin_val, 0.0), Complex64::new(cos_val, 0.0),
437 )
438 }
439 Gate::RZ(theta) => {
440 let half_theta = theta / 2.0;
441 Matrix2::new(
442 Complex64::new(half_theta.cos(), -half_theta.sin()), Complex64::new(0.0, 0.0),
443 Complex64::new(0.0, 0.0), Complex64::new(half_theta.cos(), half_theta.sin()),
444 )
445 }
446 Gate::Custom(matrix) => *matrix,
447 }
448 }
449}
450
451#[derive(Clone, Debug)]
453pub enum TwoQubitGate {
454 CNOT,
456 CZ,
458 SWAP,
460 Custom(nalgebra::Matrix4<Complex64>),
462}
463
464impl TwoQubitGate {
465 pub fn matrix(&self) -> nalgebra::Matrix4<Complex64> {
467 use nalgebra::Matrix4;
468
469 match self {
470 TwoQubitGate::CNOT => Matrix4::new(
471 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0),
472 Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0),
473 Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0),
474 Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0),
475 ),
476 TwoQubitGate::CZ => Matrix4::new(
477 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0),
478 Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0),
479 Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0),
480 Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(-1.0, 0.0),
481 ),
482 TwoQubitGate::SWAP => Matrix4::new(
483 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0),
484 Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0),
485 Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0),
486 Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0),
487 ),
488 TwoQubitGate::Custom(matrix) => *matrix,
489 }
490 }
491}
492
493pub struct QuantumContainer {
495 quantum_state: QuantumState,
496 classical_memory: HashMap<String, f64>,
497 hybrid_operations: Vec<HybridOperation>,
498 entanglement_map: HashMap<(usize, usize), f64>,
499}
500
501impl QuantumContainer {
502 pub fn new(num_qubits: usize) -> Self {
504 Self {
505 quantum_state: QuantumState::new(num_qubits).expect("Failed to create quantum state"),
506 classical_memory: HashMap::new(),
507 hybrid_operations: Vec::new(),
508 entanglement_map: HashMap::new(),
509 }
510 }
511
512 pub fn set_superposition_state(&mut self, state_index: usize, amplitude: QuantumAmplitude) {
514 if state_index < self.quantum_state.amplitudes.len() {
515 self.quantum_state.amplitudes[state_index] = amplitude;
516 self.quantum_state.invalidate_cache();
517 }
518 }
519
520 pub fn get_probability(&self, state_index: usize) -> f64 {
522 self.quantum_state.get_probability(state_index)
523 }
524
525 pub fn measure(&mut self) -> usize {
527 self.quantum_state.measure()
528 }
529
530 pub fn store_classical(&mut self, key: String, value: f64) {
532 self.classical_memory.insert(key, value);
533 }
534
535 pub fn get_classical(&self, key: &str) -> Option<f64> {
537 self.classical_memory.get(key).copied()
538 }
539
540 pub fn hybrid_operation(&mut self, operation: HybridOperation) -> Result<f64> {
542 match operation {
543 HybridOperation::QuantumToClassical { qubit, target_key } => {
544 let measurement = self.quantum_state.measure_qubit(qubit)? as f64;
545 self.classical_memory.insert(target_key, measurement);
546 Ok(measurement)
547 }
548 HybridOperation::ClassicalToQuantum { source_key, qubit, gate_type } => {
549 let classical_value = self.classical_memory.get(&source_key)
550 .ok_or_else(|| LoopError::quantum_error("Classical key not found"))?;
551
552 match gate_type.as_str() {
553 "RX" => self.quantum_state.apply_single_qubit_gate(qubit, &Gate::RX(*classical_value))?,
554 "RY" => self.quantum_state.apply_single_qubit_gate(qubit, &Gate::RY(*classical_value))?,
555 "RZ" => self.quantum_state.apply_single_qubit_gate(qubit, &Gate::RZ(*classical_value))?,
556 _ => return Err(LoopError::quantum_error("Unknown gate type")),
557 }
558 Ok(*classical_value)
559 }
560 HybridOperation::EntanglementCheck { qubit_a, qubit_b } => {
561 let entropy = self.quantum_state.entanglement_entropy(qubit_a, qubit_b)?;
562 self.entanglement_map.insert((qubit_a, qubit_b), entropy);
563 Ok(entropy)
564 }
565 }
566 }
567
568 pub fn apply_gate(&mut self, qubit: usize, gate: Gate) -> Result<()> {
570 self.quantum_state.apply_single_qubit_gate(qubit, &gate)
571 }
572
573 pub fn apply_two_qubit_gate(&mut self, control: usize, target: usize, gate: TwoQubitGate) -> Result<()> {
575 self.quantum_state.apply_two_qubit_gate(control, target, &gate)
576 }
577
578 pub fn quantum_state(&self) -> &QuantumState {
580 &self.quantum_state
581 }
582
583 pub fn quantum_state_mut(&mut self) -> &mut QuantumState {
585 &mut self.quantum_state
586 }
587
588 pub fn classical_memory(&self) -> &HashMap<String, f64> {
590 &self.classical_memory
591 }
592
593 pub fn create_superposition_from_classical(&mut self, probabilities: &[f64]) -> Result<()> {
595 if probabilities.len() != self.quantum_state.amplitudes.len() {
596 return Err(LoopError::quantum_error("Probability array length mismatch"));
597 }
598
599 for (i, &prob) in probabilities.iter().enumerate() {
601 if prob < 0.0 {
602 return Err(LoopError::quantum_error("Probabilities must be non-negative"));
603 }
604 self.quantum_state.amplitudes[i] = Complex64::new(prob.sqrt(), 0.0);
605 }
606
607 self.quantum_state.normalize()?;
608 Ok(())
609 }
610
611 pub fn classical_feedback_evolution(&mut self, feedback_fn: impl Fn(&HashMap<String, f64>) -> Vec<f64>) -> Result<()> {
613 let feedback = feedback_fn(&self.classical_memory);
614
615 for (i, &angle) in feedback.iter().enumerate() {
617 if i < self.quantum_state.num_qubits {
618 self.quantum_state.apply_phase(i, angle)?;
619 }
620 }
621
622 Ok(())
623 }
624
625 pub fn quantum_classical_correlation(&self, qubit: usize, classical_key: &str) -> Result<f64> {
627 let classical_value = self.classical_memory.get(classical_key)
628 .ok_or_else(|| LoopError::quantum_error("Classical key not found"))?;
629
630 let z_expectation = self.quantum_state.expectation_pauli(qubit, PauliOperator::Z)?;
632
633 Ok(z_expectation * classical_value)
635 }
636}
637
638#[derive(Clone, Debug, Serialize, Deserialize)]
640pub enum HybridOperation {
641 QuantumToClassical {
643 qubit: usize,
644 target_key: String,
645 },
646 ClassicalToQuantum {
648 source_key: String,
649 qubit: usize,
650 gate_type: String,
651 },
652 EntanglementCheck {
654 qubit_a: usize,
655 qubit_b: usize,
656 },
657}
658
659pub trait Superposition<T> {
661 fn from_states(states: Vec<T>, amplitudes: Vec<Complex64>) -> Result<Self>
663 where
664 Self: Sized;
665
666 fn collapse(&mut self) -> T;
668
669 fn probability(&self, state: &T) -> f64;
671
672 fn transform<F>(&mut self, f: F) -> Result<()>
674 where
675 F: Fn(&mut T);
676}
677
678#[cfg(test)]
679mod tests {
680 use super::*;
681 use approx::assert_relative_eq;
682
683 #[test]
684 fn test_quantum_state_creation() {
685 let state = QuantumState::new(2).unwrap();
686 assert_eq!(state.num_qubits, 2);
687 assert_eq!(state.amplitudes.len(), 4);
688 assert_eq!(state.get_probability(0), 1.0); }
690
691 #[test]
692 fn test_uniform_superposition() {
693 let state = QuantumState::uniform_superposition(2).unwrap();
694
695 for i in 0..4 {
697 assert_relative_eq!(state.get_probability(i), 0.25, epsilon = 1e-10);
698 }
699 }
700
701 #[test]
702 fn test_quantum_gate_application() {
703 let mut state = QuantumState::new(1).unwrap();
704
705 state.apply_single_qubit_gate(0, &Gate::X).unwrap();
707 assert_relative_eq!(state.get_probability(0), 0.0, epsilon = 1e-10);
708 assert_relative_eq!(state.get_probability(1), 1.0, epsilon = 1e-10);
709 }
710
711 #[test]
712 fn test_hadamard_gate() {
713 let mut state = QuantumState::new(1).unwrap();
714
715 state.apply_single_qubit_gate(0, &Gate::H).unwrap();
717 assert_relative_eq!(state.get_probability(0), 0.5, epsilon = 1e-10);
718 assert_relative_eq!(state.get_probability(1), 0.5, epsilon = 1e-10);
719 }
720
721 #[test]
722 fn test_cnot_gate() {
723 let mut state = QuantumState::new(2).unwrap();
724
725 state.apply_single_qubit_gate(0, &Gate::H).unwrap();
727
728 state.apply_two_qubit_gate(0, 1, &TwoQubitGate::CNOT).unwrap();
730
731 assert_relative_eq!(state.get_probability(0), 0.5, epsilon = 1e-10); assert_relative_eq!(state.get_probability(3), 0.5, epsilon = 1e-10); assert_relative_eq!(state.get_probability(1), 0.0, epsilon = 1e-10); assert_relative_eq!(state.get_probability(2), 0.0, epsilon = 1e-10); }
737
738 #[test]
739 fn test_measurement() {
740 let mut state = QuantumState::new(1).unwrap();
741 state.apply_single_qubit_gate(0, &Gate::H).unwrap(); let measurement = state.measure();
744 assert!(measurement == 0 || measurement == 1);
745
746 if measurement == 0 {
748 assert_relative_eq!(state.get_probability(0), 1.0, epsilon = 1e-10);
749 } else {
750 assert_relative_eq!(state.get_probability(1), 1.0, epsilon = 1e-10);
751 }
752 }
753
754 #[test]
755 fn test_qubit_measurement() {
756 let mut state = QuantumState::new(2).unwrap();
757 state.apply_single_qubit_gate(0, &Gate::H).unwrap(); let result = state.measure_qubit(0).unwrap();
760 assert!(result == 0 || result == 1);
761
762 if result == 0 {
764 assert_relative_eq!(state.get_probability(0), 1.0, epsilon = 1e-10); } else {
766 assert_relative_eq!(state.get_probability(2), 1.0, epsilon = 1e-10); }
768 }
769
770 #[test]
771 fn test_pauli_expectation() {
772 let mut state = QuantumState::new(1).unwrap();
773
774 let z_exp = state.expectation_pauli(0, PauliOperator::Z).unwrap();
776 assert_relative_eq!(z_exp, 1.0, epsilon = 1e-10);
777
778 state.apply_single_qubit_gate(0, &Gate::X).unwrap();
780 let z_exp = state.expectation_pauli(0, PauliOperator::Z).unwrap();
781 assert_relative_eq!(z_exp, -1.0, epsilon = 1e-10);
782 }
783
784 #[test]
785 fn test_quantum_container() {
786 let mut container = QuantumContainer::new(2);
787
788 container.store_classical("test".to_string(), 3.14);
790 assert_eq!(container.get_classical("test"), Some(3.14));
791
792 let measurement = container.hybrid_operation(HybridOperation::QuantumToClassical {
794 qubit: 0,
795 target_key: "measurement".to_string(),
796 }).unwrap();
797
798 assert!(measurement == 0.0 || measurement == 1.0);
799 assert!(container.get_classical("measurement").is_some());
800 }
801
802 #[test]
803 fn test_entanglement_entropy() {
804 let mut state = QuantumState::new(2).unwrap();
805
806 state.apply_single_qubit_gate(0, &Gate::H).unwrap();
808 state.apply_two_qubit_gate(0, 1, &TwoQubitGate::CNOT).unwrap();
809
810 let entropy = state.entanglement_entropy(0, 1).unwrap();
811 assert!(entropy > 0.0); }
813
814 #[test]
815 fn test_state_fidelity() {
816 let state1 = QuantumState::new(1).unwrap();
817 let state2 = QuantumState::new(1).unwrap();
818
819 let fidelity = state1.fidelity(&state2).unwrap();
821 assert_relative_eq!(fidelity, 1.0, epsilon = 1e-10);
822 }
823
824 #[test]
825 fn test_phase_application() {
826 let mut state = QuantumState::new(1).unwrap();
827 state.apply_single_qubit_gate(0, &Gate::H).unwrap(); state.apply_phase(0, std::f64::consts::PI/2.0).unwrap();
831
832 assert_relative_eq!(state.get_probability(0), 0.5, epsilon = 1e-10);
834 assert_relative_eq!(state.get_probability(1), 0.5, epsilon = 1e-10);
835 }
836
837 #[test]
838 fn test_random_state() {
839 let state = QuantumState::random(2).unwrap();
840
841 let total_prob: f64 = (0..4).map(|i| state.get_probability(i)).sum();
843 assert_relative_eq!(total_prob, 1.0, epsilon = 1e-10);
844 }
845
846 #[test]
847 fn test_superposition_from_classical() {
848 let mut container = QuantumContainer::new(2);
849 let probabilities = vec![0.4, 0.3, 0.2, 0.1];
850
851 container.create_superposition_from_classical(&probabilities).unwrap();
852
853 for (i, &expected_prob) in probabilities.iter().enumerate() {
855 let actual_prob = container.get_probability(i);
856 assert_relative_eq!(actual_prob, expected_prob, epsilon = 1e-10);
857 }
858 }
859}