1use anyhow::{anyhow, Result};
11use scirs2_core::ndarray_ext::Array2;
12use scirs2_core::random::{Random, Rng};
13use serde::{Deserialize, Serialize};
14use std::collections::HashMap;
15use std::f64::consts::PI;
16
17#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
19pub struct Complex {
20 pub real: f64,
21 pub imag: f64,
22}
23
24impl Complex {
25 pub fn new(real: f64, imag: f64) -> Self {
26 Self { real, imag }
27 }
28
29 pub fn magnitude_squared(&self) -> f64 {
30 self.real * self.real + self.imag * self.imag
31 }
32
33 pub fn conjugate(&self) -> Self {
34 Self {
35 real: self.real,
36 imag: -self.imag,
37 }
38 }
39}
40
41impl std::ops::Add for Complex {
42 type Output = Self;
43 fn add(self, other: Self) -> Self {
44 Self {
45 real: self.real + other.real,
46 imag: self.imag + other.imag,
47 }
48 }
49}
50
51impl std::ops::Mul for Complex {
52 type Output = Self;
53 fn mul(self, other: Self) -> Self {
54 Self {
55 real: self.real * other.real - self.imag * other.imag,
56 imag: self.real * other.imag + self.imag * other.real,
57 }
58 }
59}
60
61impl std::ops::Mul<f64> for Complex {
62 type Output = Self;
63 fn mul(self, scalar: f64) -> Self {
64 Self {
65 real: self.real * scalar,
66 imag: self.imag * scalar,
67 }
68 }
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
73pub enum QuantumGate {
74 I,
76 X,
78 Y,
80 Z,
82 H,
84 S,
86 T,
88 RX(f64),
90 RY(f64),
92 RZ(f64),
94 CNOT(usize, usize), CZ(usize, usize),
98 Toffoli(usize, usize, usize), Unitary(Array2<Complex>),
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct QuantumCircuit {
107 pub num_qubits: usize,
109 pub gates: Vec<QuantumGate>,
111 pub parameters: Vec<f64>,
113 pub parameter_mapping: HashMap<usize, Vec<usize>>, }
116
117impl QuantumCircuit {
118 pub fn new(num_qubits: usize) -> Self {
120 Self {
121 num_qubits,
122 gates: Vec::new(),
123 parameters: Vec::new(),
124 parameter_mapping: HashMap::new(),
125 }
126 }
127
128 pub fn add_gate(&mut self, gate: QuantumGate) {
130 self.gates.push(gate);
131 }
132
133 pub fn add_parameterized_gate(&mut self, gate: QuantumGate, param_indices: Vec<usize>) {
135 let gate_index = self.gates.len();
136 self.gates.push(gate);
137 self.parameter_mapping.insert(gate_index, param_indices);
138 }
139
140 pub fn set_parameters(&mut self, parameters: Vec<f64>) {
142 self.parameters = parameters;
143 }
144
145 pub fn get_single_qubit_matrix(&self, gate: &QuantumGate) -> Array2<Complex> {
147 match gate {
148 QuantumGate::I => Array2::from_shape_vec(
149 (2, 2),
150 vec![
151 Complex::new(1.0, 0.0),
152 Complex::new(0.0, 0.0),
153 Complex::new(0.0, 0.0),
154 Complex::new(1.0, 0.0),
155 ],
156 )
157 .expect("2x2 matrix shape should match 4-element vector"),
158 QuantumGate::X => Array2::from_shape_vec(
159 (2, 2),
160 vec![
161 Complex::new(0.0, 0.0),
162 Complex::new(1.0, 0.0),
163 Complex::new(1.0, 0.0),
164 Complex::new(0.0, 0.0),
165 ],
166 )
167 .expect("2x2 matrix shape should match 4-element vector"),
168 QuantumGate::Y => Array2::from_shape_vec(
169 (2, 2),
170 vec![
171 Complex::new(0.0, 0.0),
172 Complex::new(0.0, -1.0),
173 Complex::new(0.0, 1.0),
174 Complex::new(0.0, 0.0),
175 ],
176 )
177 .expect("2x2 matrix shape should match 4-element vector"),
178 QuantumGate::Z => Array2::from_shape_vec(
179 (2, 2),
180 vec![
181 Complex::new(1.0, 0.0),
182 Complex::new(0.0, 0.0),
183 Complex::new(0.0, 0.0),
184 Complex::new(-1.0, 0.0),
185 ],
186 )
187 .expect("2x2 matrix shape should match 4-element vector"),
188 QuantumGate::H => {
189 let inv_sqrt2 = 1.0 / (2.0_f64).sqrt();
190 Array2::from_shape_vec(
191 (2, 2),
192 vec![
193 Complex::new(inv_sqrt2, 0.0),
194 Complex::new(inv_sqrt2, 0.0),
195 Complex::new(inv_sqrt2, 0.0),
196 Complex::new(-inv_sqrt2, 0.0),
197 ],
198 )
199 .expect("2x2 matrix shape should match 4-element vector")
200 }
201 QuantumGate::S => Array2::from_shape_vec(
202 (2, 2),
203 vec![
204 Complex::new(1.0, 0.0),
205 Complex::new(0.0, 0.0),
206 Complex::new(0.0, 0.0),
207 Complex::new(0.0, 1.0),
208 ],
209 )
210 .expect("2x2 matrix shape should match 4-element vector"),
211 QuantumGate::T => {
212 let phase = Complex::new((PI / 4.0).cos(), (PI / 4.0).sin());
213 Array2::from_shape_vec(
214 (2, 2),
215 vec![
216 Complex::new(1.0, 0.0),
217 Complex::new(0.0, 0.0),
218 Complex::new(0.0, 0.0),
219 phase,
220 ],
221 )
222 .expect("2x2 matrix shape should match 4-element vector")
223 }
224 QuantumGate::RX(theta) => {
225 let cos_half = (theta / 2.0).cos();
226 let sin_half = (theta / 2.0).sin();
227 Array2::from_shape_vec(
228 (2, 2),
229 vec![
230 Complex::new(cos_half, 0.0),
231 Complex::new(0.0, -sin_half),
232 Complex::new(0.0, -sin_half),
233 Complex::new(cos_half, 0.0),
234 ],
235 )
236 .expect("2x2 matrix shape should match 4-element vector")
237 }
238 QuantumGate::RY(theta) => {
239 let cos_half = (theta / 2.0).cos();
240 let sin_half = (theta / 2.0).sin();
241 Array2::from_shape_vec(
242 (2, 2),
243 vec![
244 Complex::new(cos_half, 0.0),
245 Complex::new(-sin_half, 0.0),
246 Complex::new(sin_half, 0.0),
247 Complex::new(cos_half, 0.0),
248 ],
249 )
250 .expect("2x2 matrix shape should match 4-element vector")
251 }
252 QuantumGate::RZ(theta) => {
253 let exp_neg = Complex::new((theta / 2.0).cos(), -(theta / 2.0).sin());
254 let exp_pos = Complex::new((theta / 2.0).cos(), (theta / 2.0).sin());
255 Array2::from_shape_vec(
256 (2, 2),
257 vec![
258 exp_neg,
259 Complex::new(0.0, 0.0),
260 Complex::new(0.0, 0.0),
261 exp_pos,
262 ],
263 )
264 .expect("2x2 matrix shape should match 4-element vector")
265 }
266 QuantumGate::Unitary(matrix) => matrix.clone(),
267 _ => panic!("Not a single-qubit gate"),
268 }
269 }
270}
271
272#[derive(Debug, Clone)]
274pub struct QuantumSimulator {
275 pub num_qubits: usize,
277 pub state_vector: Vec<Complex>,
279}
280
281impl QuantumSimulator {
282 pub fn new(num_qubits: usize) -> Self {
284 let state_size = 2_usize.pow(num_qubits as u32);
285 let mut state_vector = vec![Complex::new(0.0, 0.0); state_size];
286 state_vector[0] = Complex::new(1.0, 0.0); Self {
289 num_qubits,
290 state_vector,
291 }
292 }
293
294 pub fn apply_single_qubit_gate(&mut self, gate_matrix: &Array2<Complex>, qubit: usize) {
296 let state_size = self.state_vector.len();
297 let mut new_state = vec![Complex::new(0.0, 0.0); state_size];
298
299 let num_qubits = (state_size as f64).log2() as usize;
301 let bit_pos = num_qubits - 1 - qubit;
302
303 for i in 0..state_size {
304 let bit = (i >> bit_pos) & 1;
305 let i_complement = i ^ (1 << bit_pos);
306
307 if bit == 0 {
309 new_state[i] = new_state[i] + gate_matrix[(0, 0)] * self.state_vector[i];
311 new_state[i_complement] =
312 new_state[i_complement] + gate_matrix[(1, 0)] * self.state_vector[i];
313 } else {
314 new_state[i] = new_state[i] + gate_matrix[(1, 1)] * self.state_vector[i];
316 new_state[i_complement] =
317 new_state[i_complement] + gate_matrix[(0, 1)] * self.state_vector[i];
318 }
319 }
320
321 self.state_vector = new_state;
322 }
323
324 pub fn apply_cnot(&mut self, control: usize, target: usize) {
326 let state_size = self.state_vector.len();
327 let mut new_state = vec![Complex::new(0.0, 0.0); state_size];
328
329 let num_qubits = (state_size as f64).log2() as usize;
331 let control_bit_pos = num_qubits - 1 - control;
332 let target_bit_pos = num_qubits - 1 - target;
333
334 for i in 0..state_size {
335 let control_bit = (i >> control_bit_pos) & 1;
336 if control_bit == 1 {
337 let i_flip = i ^ (1 << target_bit_pos);
339 new_state[i_flip] = self.state_vector[i];
340 } else {
341 new_state[i] = self.state_vector[i];
343 }
344 }
345
346 self.state_vector = new_state;
347 }
348
349 pub fn execute_circuit(&mut self, circuit: &QuantumCircuit) -> Result<()> {
351 for (gate_idx, gate) in circuit.gates.iter().enumerate() {
352 match gate {
353 QuantumGate::I => {
354 }
356 QuantumGate::X
357 | QuantumGate::Y
358 | QuantumGate::Z
359 | QuantumGate::H
360 | QuantumGate::S
361 | QuantumGate::T => {
362 let matrix = circuit.get_single_qubit_matrix(gate);
363 self.apply_single_qubit_gate(&matrix, 0);
365 }
366 QuantumGate::RX(theta) | QuantumGate::RY(theta) | QuantumGate::RZ(theta) => {
367 let mut theta_val = *theta;
368
369 if let Some(param_indices) = circuit.parameter_mapping.get(&gate_idx) {
371 if !param_indices.is_empty() && param_indices[0] < circuit.parameters.len()
372 {
373 theta_val = circuit.parameters[param_indices[0]];
374 }
375 }
376
377 let matrix = match gate {
378 QuantumGate::RX(_) => {
379 circuit.get_single_qubit_matrix(&QuantumGate::RX(theta_val))
380 }
381 QuantumGate::RY(_) => {
382 circuit.get_single_qubit_matrix(&QuantumGate::RY(theta_val))
383 }
384 QuantumGate::RZ(_) => {
385 circuit.get_single_qubit_matrix(&QuantumGate::RZ(theta_val))
386 }
387 _ => unreachable!(),
388 };
389 self.apply_single_qubit_gate(&matrix, 0);
390 }
391 QuantumGate::CNOT(control, target) => {
392 self.apply_cnot(*control, *target);
393 }
394 QuantumGate::CZ(control, target) => {
395 let state_size = self.state_vector.len();
397 for i in 0..state_size {
398 let control_bit = (i >> control) & 1;
399 let target_bit = (i >> target) & 1;
400 if control_bit == 1 && target_bit == 1 {
401 self.state_vector[i] = self.state_vector[i] * Complex::new(-1.0, 0.0);
402 }
403 }
404 }
405 QuantumGate::Toffoli(control1, control2, target) => {
406 let state_size = self.state_vector.len();
408 let mut new_state = self.state_vector.clone();
409
410 for i in 0..state_size {
411 let c1_bit = (i >> control1) & 1;
412 let c2_bit = (i >> control2) & 1;
413 if c1_bit == 1 && c2_bit == 1 {
414 let i_flip = i ^ (1 << target);
415 new_state.swap(i, i_flip);
416 }
417 }
418 self.state_vector = new_state;
419 }
420 QuantumGate::Unitary(matrix) => {
421 self.apply_single_qubit_gate(matrix, 0);
423 }
424 }
425 }
426 Ok(())
427 }
428
429 pub fn measure_qubit(&self, qubit: usize) -> (f64, f64) {
431 let mut prob_0 = 0.0;
432 let mut prob_1 = 0.0;
433
434 for (i, amplitude) in self.state_vector.iter().enumerate() {
435 let bit = (i >> qubit) & 1;
436 let prob = amplitude.magnitude_squared();
437
438 if bit == 0 {
439 prob_0 += prob;
440 } else {
441 prob_1 += prob;
442 }
443 }
444
445 (prob_0, prob_1)
446 }
447
448 pub fn expectation_z(&self, qubit: usize) -> f64 {
450 let (prob_0, prob_1) = self.measure_qubit(qubit);
451 prob_0 - prob_1
452 }
453
454 pub fn get_probabilities(&self) -> Vec<f64> {
456 self.state_vector
457 .iter()
458 .map(|amp| amp.magnitude_squared())
459 .collect()
460 }
461}
462
463#[derive(Debug, Clone)]
465pub struct VariationalQuantumEigensolver {
466 pub ansatz: QuantumCircuit,
468 pub hamiltonian: Vec<(f64, Vec<(usize, char)>)>, pub parameters: Vec<f64>,
472 pub energy_history: Vec<f64>,
474}
475
476impl VariationalQuantumEigensolver {
477 pub fn new(num_qubits: usize, ansatz_depth: usize) -> Self {
479 let mut ansatz = QuantumCircuit::new(num_qubits);
480 let mut parameters = Vec::new();
481 let mut param_idx = 0;
482
483 for _layer in 0..ansatz_depth {
485 for _qubit in 0..num_qubits {
487 ansatz.add_parameterized_gate(QuantumGate::RY(0.0), vec![param_idx]);
488 let random_value = {
489 let mut random = Random::default();
490 0.1 * random.random::<f64>()
491 };
492 parameters.push(random_value);
493 param_idx += 1;
494 }
495
496 for qubit in 0..num_qubits - 1 {
498 ansatz.add_gate(QuantumGate::CNOT(qubit, qubit + 1));
499 }
500
501 for _qubit in 0..num_qubits {
503 ansatz.add_parameterized_gate(QuantumGate::RZ(0.0), vec![param_idx]);
504 let random_value = {
505 let mut random = Random::default();
506 0.1 * random.random::<f64>()
507 };
508 parameters.push(random_value);
509 param_idx += 1;
510 }
511 }
512
513 Self {
514 ansatz,
515 hamiltonian: Vec::new(),
516 parameters,
517 energy_history: Vec::new(),
518 }
519 }
520
521 pub fn add_hamiltonian_term(&mut self, coefficient: f64, pauli_string: Vec<(usize, char)>) {
523 self.hamiltonian.push((coefficient, pauli_string));
524 }
525
526 pub fn compute_energy(&self, parameters: &[f64]) -> Result<f64> {
528 let mut total_energy = 0.0;
529
530 for (coefficient, pauli_string) in &self.hamiltonian {
531 let mut simulator = QuantumSimulator::new(self.ansatz.num_qubits);
532 let mut circuit = self.ansatz.clone();
533 circuit.set_parameters(parameters.to_vec());
534
535 simulator.execute_circuit(&circuit)?;
536
537 let mut expectation = 1.0;
539 for &(qubit, pauli_op) in pauli_string {
540 match pauli_op {
541 'Z' => expectation *= simulator.expectation_z(qubit),
542 'X' => {
543 let mut sim_copy = simulator.clone();
545 let h_matrix = circuit.get_single_qubit_matrix(&QuantumGate::H);
546 sim_copy.apply_single_qubit_gate(&h_matrix, qubit);
547 expectation *= sim_copy.expectation_z(qubit);
548 }
549 'Y' => {
550 let mut sim_copy = simulator.clone();
552 let s_dag = Array2::from_shape_vec(
553 (2, 2),
554 vec![
555 Complex::new(1.0, 0.0),
556 Complex::new(0.0, 0.0),
557 Complex::new(0.0, 0.0),
558 Complex::new(0.0, -1.0),
559 ],
560 )
561 .expect("2x2 matrix shape should match 4-element vector");
562 let h_matrix = circuit.get_single_qubit_matrix(&QuantumGate::H);
563 sim_copy.apply_single_qubit_gate(&s_dag, qubit);
564 sim_copy.apply_single_qubit_gate(&h_matrix, qubit);
565 expectation *= sim_copy.expectation_z(qubit);
566 }
567 'I' => {
568 }
570 _ => return Err(anyhow!("Unknown Pauli operator: {}", pauli_op)),
571 }
572 }
573
574 total_energy += coefficient * expectation;
575 }
576
577 Ok(total_energy)
578 }
579
580 pub fn optimize(&mut self, max_iterations: usize, learning_rate: f64) -> Result<f64> {
582 for iteration in 0..max_iterations {
583 let current_energy = self.compute_energy(&self.parameters)?;
584 self.energy_history.push(current_energy);
585
586 let mut gradients = vec![0.0; self.parameters.len()];
588 let shift = PI / 2.0;
589
590 for (i, ¶m) in self.parameters.iter().enumerate() {
591 let mut params_plus = self.parameters.clone();
593 params_plus[i] = param + shift;
594 let energy_plus = self.compute_energy(¶ms_plus)?;
595
596 let mut params_minus = self.parameters.clone();
598 params_minus[i] = param - shift;
599 let energy_minus = self.compute_energy(¶ms_minus)?;
600
601 gradients[i] = 0.5 * (energy_plus - energy_minus);
603 }
604
605 for (i, &gradient) in gradients.iter().enumerate() {
607 self.parameters[i] -= learning_rate * gradient;
608 }
609
610 if iteration > 10 {
612 let recent_energies = &self.energy_history[iteration.saturating_sub(5)..];
613 let energy_variance = recent_energies
614 .iter()
615 .map(|&e| (e - current_energy).powi(2))
616 .sum::<f64>()
617 / recent_energies.len() as f64;
618
619 if energy_variance < 1e-8 {
620 break;
621 }
622 }
623 }
624
625 self.compute_energy(&self.parameters)
626 }
627}
628
629#[derive(Debug, Clone)]
631pub struct QuantumApproximateOptimization {
632 pub num_qubits: usize,
634 pub depth: usize,
636 pub cost_hamiltonian: Vec<(f64, Vec<(usize, char)>)>,
638 pub mixer_hamiltonian: Vec<(f64, Vec<(usize, char)>)>,
640 pub beta_params: Vec<f64>,
642 pub gamma_params: Vec<f64>,
644 pub cost_history: Vec<f64>,
646}
647
648impl QuantumApproximateOptimization {
649 pub fn new(num_qubits: usize, depth: usize) -> Self {
651 let mut mixer_hamiltonian = Vec::new();
652
653 for qubit in 0..num_qubits {
655 mixer_hamiltonian.push((1.0, vec![(qubit, 'X')]));
656 }
657
658 Self {
659 num_qubits,
660 depth,
661 cost_hamiltonian: Vec::new(),
662 mixer_hamiltonian,
663 beta_params: vec![0.1; depth],
664 gamma_params: vec![0.1; depth],
665 cost_history: Vec::new(),
666 }
667 }
668
669 pub fn add_cost_term(&mut self, coefficient: f64, pauli_string: Vec<(usize, char)>) {
671 self.cost_hamiltonian.push((coefficient, pauli_string));
672 }
673
674 pub fn build_circuit(&self) -> QuantumCircuit {
676 let mut circuit = QuantumCircuit::new(self.num_qubits);
677
678 for _qubit in 0..self.num_qubits {
680 circuit.add_gate(QuantumGate::H);
681 }
682
683 for layer in 0..self.depth {
685 for (coefficient, pauli_string) in &self.cost_hamiltonian {
687 let angle = self.gamma_params[layer] * coefficient;
688
689 if pauli_string.len() == 2 && pauli_string.iter().all(|(_, op)| *op == 'Z') {
691 let qubit1 = pauli_string[0].0;
692 let qubit2 = pauli_string[1].0;
693
694 circuit.add_gate(QuantumGate::CNOT(qubit1, qubit2));
695 circuit.add_gate(QuantumGate::RZ(angle));
696 circuit.add_gate(QuantumGate::CNOT(qubit1, qubit2));
697 }
698 }
699
700 let beta = self.beta_params[layer];
702 for _qubit in 0..self.num_qubits {
703 circuit.add_gate(QuantumGate::RX(2.0 * beta));
704 }
705 }
706
707 circuit
708 }
709
710 pub fn compute_cost(&self) -> Result<f64> {
712 let circuit = self.build_circuit();
713 let mut simulator = QuantumSimulator::new(self.num_qubits);
714 simulator.execute_circuit(&circuit)?;
715
716 let mut total_cost = 0.0;
717 for (coefficient, pauli_string) in &self.cost_hamiltonian {
718 let mut expectation = 1.0;
719 for &(qubit, pauli_op) in pauli_string {
720 match pauli_op {
721 'Z' => expectation *= simulator.expectation_z(qubit),
722 _ => return Err(anyhow!("QAOA cost function only supports Z operators")),
723 }
724 }
725 total_cost += coefficient * expectation;
726 }
727
728 Ok(total_cost)
729 }
730
731 pub fn optimize(&mut self, max_iterations: usize, learning_rate: f64) -> Result<f64> {
733 for iteration in 0..max_iterations {
734 let current_cost = self.compute_cost()?;
735 self.cost_history.push(current_cost);
736
737 let mut beta_gradients = vec![0.0; self.depth];
739 let mut gamma_gradients = vec![0.0; self.depth];
740 let shift = 0.1;
741
742 for (i, grad) in beta_gradients.iter_mut().enumerate().take(self.depth) {
744 self.beta_params[i] += shift;
746 let cost_plus = self.compute_cost()?;
747
748 self.beta_params[i] -= 2.0 * shift;
750 let cost_minus = self.compute_cost()?;
751
752 self.beta_params[i] += shift;
754
755 *grad = (cost_plus - cost_minus) / (2.0 * shift);
756 }
757
758 for (i, grad) in gamma_gradients.iter_mut().enumerate().take(self.depth) {
760 self.gamma_params[i] += shift;
762 let cost_plus = self.compute_cost()?;
763
764 self.gamma_params[i] -= 2.0 * shift;
766 let cost_minus = self.compute_cost()?;
767
768 self.gamma_params[i] += shift;
770
771 *grad = (cost_plus - cost_minus) / (2.0 * shift);
772 }
773
774 for i in 0..self.depth {
776 self.beta_params[i] -= learning_rate * beta_gradients[i];
777 self.gamma_params[i] -= learning_rate * gamma_gradients[i];
778 }
779
780 if iteration > 10 {
782 let recent_variance = self.cost_history[iteration.saturating_sub(5)..]
783 .iter()
784 .map(|&c| (c - current_cost).powi(2))
785 .sum::<f64>()
786 / 5.0;
787
788 if recent_variance < 1e-8 {
789 break;
790 }
791 }
792 }
793
794 self.compute_cost()
795 }
796}
797
798#[derive(Debug, Clone)]
800pub struct QuantumNeuralNetworkLayer {
801 pub num_qubits: usize,
803 pub parameters: Vec<f64>,
805 pub layer_type: QNNLayerType,
807}
808
809#[derive(Debug, Clone)]
811pub enum QNNLayerType {
812 StronglyEntangling,
814 BasicEntangling,
816 AmplitudeEmbedding,
818 AngleEmbedding,
820}
821
822impl QuantumNeuralNetworkLayer {
823 pub fn new(num_qubits: usize, layer_type: QNNLayerType) -> Self {
825 let num_params = match layer_type {
826 QNNLayerType::StronglyEntangling => 3 * num_qubits,
827 QNNLayerType::BasicEntangling => num_qubits,
828 QNNLayerType::AmplitudeEmbedding => 2_usize.pow(num_qubits as u32) - 1,
829 QNNLayerType::AngleEmbedding => num_qubits,
830 };
831
832 let parameters = (0..num_params)
833 .map(|_| {
834 let mut random = Random::default();
835 2.0 * PI * random.random::<f64>()
836 })
837 .collect();
838
839 Self {
840 num_qubits,
841 parameters,
842 layer_type,
843 }
844 }
845
846 pub fn build_circuit(&self, input_data: Option<&[f64]>) -> QuantumCircuit {
848 let mut circuit = QuantumCircuit::new(self.num_qubits);
849
850 match &self.layer_type {
851 QNNLayerType::StronglyEntangling => {
852 for i in 0..self.num_qubits {
854 circuit.add_gate(QuantumGate::RX(self.parameters[3 * i]));
855 circuit.add_gate(QuantumGate::RY(self.parameters[3 * i + 1]));
856 circuit.add_gate(QuantumGate::RZ(self.parameters[3 * i + 2]));
857 }
858
859 for i in 0..self.num_qubits {
861 circuit.add_gate(QuantumGate::CNOT(i, (i + 1) % self.num_qubits));
862 }
863 }
864 QNNLayerType::BasicEntangling => {
865 for i in 0..self.num_qubits {
867 circuit.add_gate(QuantumGate::RY(self.parameters[i]));
868 }
869
870 for i in 0..self.num_qubits {
872 circuit.add_gate(QuantumGate::CNOT(i, (i + 1) % self.num_qubits));
873 }
874 }
875 QNNLayerType::AmplitudeEmbedding => {
876 if let Some(data) = input_data {
877 let normalized_data = self.normalize_data(data);
879 for (i, &value) in normalized_data.iter().enumerate() {
882 if i < self.num_qubits {
883 circuit.add_gate(QuantumGate::RY(value * PI));
884 }
885 }
886 }
887 }
888 QNNLayerType::AngleEmbedding => {
889 if let Some(data) = input_data {
890 for (i, &value) in data.iter().enumerate() {
892 if i < self.num_qubits {
893 circuit.add_gate(QuantumGate::RY(value * self.parameters[i]));
894 }
895 }
896 }
897 }
898 }
899
900 circuit
901 }
902
903 fn normalize_data(&self, data: &[f64]) -> Vec<f64> {
905 let norm = data.iter().map(|x| x * x).sum::<f64>().sqrt();
906 if norm > 0.0 {
907 data.iter().map(|x| x / norm).collect()
908 } else {
909 data.to_vec()
910 }
911 }
912}
913
914#[derive(Debug, Clone, Serialize, Deserialize)]
916pub struct ErrorSyndrome {
917 pub error_pattern: Vec<bool>,
919 pub corrections: Vec<QuantumGate>,
921 pub confidence: f64,
923 pub error_types: Vec<ErrorType>,
925}
926
927#[derive(Debug, Clone, Serialize, Deserialize)]
929pub enum ErrorType {
930 BitFlip(usize),
932 PhaseFlip(usize),
934 Depolarizing(usize, f64),
936 CoherenceDecay(usize, f64),
938 CrossTalk(usize, usize, f64),
940}
941
942#[derive(Debug, Clone)]
944pub struct QuantumErrorCorrection {
945 pub detection_threshold: f64,
947 pub correction_threshold: f64,
949 pub syndrome_history: Vec<ErrorSyndrome>,
951 pub mitigation_strategies: Vec<ErrorMitigationStrategy>,
953}
954
955impl Default for QuantumErrorCorrection {
956 fn default() -> Self {
957 Self::new()
958 }
959}
960
961#[derive(Debug, Clone, PartialEq)]
963pub enum ErrorMitigationStrategy {
964 ZeroNoiseExtrapolation,
966 ReadoutErrorMitigation,
968 SymmetryVerification,
970 VirtualDistillation,
972}
973
974impl QuantumErrorCorrection {
975 pub fn new() -> Self {
977 Self {
978 detection_threshold: 0.01,
979 correction_threshold: 0.8,
980 syndrome_history: Vec::new(),
981 mitigation_strategies: vec![
982 ErrorMitigationStrategy::ZeroNoiseExtrapolation,
983 ErrorMitigationStrategy::ReadoutErrorMitigation,
984 ErrorMitigationStrategy::SymmetryVerification,
985 ],
986 }
987 }
988
989 pub fn detect_errors(&mut self, state_vector: &[Complex]) -> Result<ErrorSyndrome> {
991 let mut error_pattern = Vec::new();
992 let mut corrections = Vec::new();
993 let mut error_types = Vec::new();
994 let mut total_error_magnitude = 0.0;
995
996 let expected_normalization = state_vector
998 .iter()
999 .map(|amp| amp.magnitude_squared())
1000 .sum::<f64>();
1001
1002 if (expected_normalization - 1.0).abs() > self.detection_threshold {
1003 error_types.push(ErrorType::CoherenceDecay(0, expected_normalization - 1.0));
1004 corrections.push(QuantumGate::I); total_error_magnitude += (expected_normalization - 1.0).abs();
1006 }
1007
1008 for (i, amplitude) in state_vector.iter().enumerate() {
1010 let phase = amplitude.imag.atan2(amplitude.real);
1011 if phase.abs() > PI * 0.9 && amplitude.magnitude_squared() > 0.01 {
1012 error_pattern.push(true);
1013 error_types.push(ErrorType::PhaseFlip(i));
1014 corrections.push(QuantumGate::Z);
1015 total_error_magnitude += phase.abs() / PI;
1016 } else {
1017 error_pattern.push(false);
1018 }
1019 }
1020
1021 let confidence = if total_error_magnitude > 0.0 {
1023 (1.0 - total_error_magnitude.min(1.0)).max(0.0)
1024 } else {
1025 1.0
1026 };
1027
1028 let syndrome = ErrorSyndrome {
1029 error_pattern,
1030 corrections,
1031 confidence,
1032 error_types,
1033 };
1034
1035 self.syndrome_history.push(syndrome.clone());
1036 if self.syndrome_history.len() > 100 {
1037 self.syndrome_history.remove(0);
1038 }
1039
1040 Ok(syndrome)
1041 }
1042
1043 pub fn apply_corrections(
1045 &self,
1046 circuit: &mut QuantumCircuit,
1047 syndrome: &ErrorSyndrome,
1048 ) -> Result<()> {
1049 if syndrome.confidence < self.correction_threshold {
1050 return Ok(()); }
1052
1053 for correction in syndrome.corrections.iter() {
1054 match correction {
1055 QuantumGate::Z => {
1056 circuit.add_gate(QuantumGate::Z);
1058 }
1059 QuantumGate::X => {
1060 circuit.add_gate(QuantumGate::X);
1062 }
1063 QuantumGate::I => {
1064 }
1066 _ => {
1067 circuit.add_gate(correction.clone());
1069 }
1070 }
1071 }
1072
1073 Ok(())
1074 }
1075
1076 pub fn get_correction_stats(&self) -> (f64, f64, usize) {
1078 if self.syndrome_history.is_empty() {
1079 return (0.0, 0.0, 0);
1080 }
1081
1082 let avg_confidence = self
1083 .syndrome_history
1084 .iter()
1085 .map(|s| s.confidence)
1086 .sum::<f64>()
1087 / self.syndrome_history.len() as f64;
1088
1089 let error_rate = self
1090 .syndrome_history
1091 .iter()
1092 .filter(|s| !s.error_types.is_empty())
1093 .count() as f64
1094 / self.syndrome_history.len() as f64;
1095
1096 (avg_confidence, error_rate, self.syndrome_history.len())
1097 }
1098}
1099
1100#[derive(Debug, Clone)]
1102pub struct CoherenceTimeManager {
1103 pub t1_times: Vec<f64>,
1105 pub t2_times: Vec<f64>,
1107 pub execution_time: f64,
1109 pub decay_models: Vec<CoherenceDecayModel>,
1111}
1112
1113#[derive(Debug, Clone)]
1115pub enum CoherenceDecayModel {
1116 Exponential,
1118 Gaussian,
1120 PowerLaw(f64), }
1123
1124impl CoherenceTimeManager {
1125 pub fn new(num_qubits: usize) -> Self {
1127 let t1_times = vec![50e-6; num_qubits]; let t2_times = vec![25e-6; num_qubits]; let decay_models = vec![CoherenceDecayModel::Exponential; num_qubits];
1131
1132 Self {
1133 t1_times,
1134 t2_times,
1135 execution_time: 0.0,
1136 decay_models,
1137 }
1138 }
1139
1140 pub fn set_coherence_times(&mut self, t1_times: Vec<f64>, t2_times: Vec<f64>) {
1142 self.t1_times = t1_times;
1143 self.t2_times = t2_times;
1144 }
1145
1146 pub fn calculate_coherence_factor(&self, qubit: usize) -> f64 {
1148 if qubit >= self.t1_times.len() || qubit >= self.t2_times.len() {
1149 return 1.0;
1150 }
1151
1152 let t1 = self.t1_times[qubit];
1153 let t2 = self.t2_times[qubit];
1154 let time = self.execution_time;
1155
1156 match &self.decay_models[qubit] {
1157 CoherenceDecayModel::Exponential => {
1158 let relaxation_factor = (-time / t1).exp();
1159 let dephasing_factor = (-2.0 * time / t2).exp();
1160 (relaxation_factor * dephasing_factor).max(0.01) }
1162 CoherenceDecayModel::Gaussian => {
1163 let sigma = t2 / (2.0 * (2.0 * (2.0_f64).ln()).sqrt());
1164 (-(time * time) / (2.0 * sigma * sigma)).exp().max(0.01)
1165 }
1166 CoherenceDecayModel::PowerLaw(exponent) => (1.0 + time / t2).powf(-exponent).max(0.01),
1167 }
1168 }
1169
1170 pub fn apply_coherence_decay(&self, state_vector: &mut [Complex]) -> Result<()> {
1172 let num_qubits = (state_vector.len() as f64).log2() as usize;
1173
1174 for qubit in 0..num_qubits {
1175 let coherence_factor = self.calculate_coherence_factor(qubit);
1176
1177 for (i, amplitude) in state_vector.iter_mut().enumerate() {
1179 let bit = (i >> qubit) & 1;
1180 if bit == 1 {
1181 *amplitude = *amplitude * coherence_factor;
1183 }
1184 }
1185
1186 if coherence_factor < 1.0 {
1188 let phase_noise = {
1189 let mut random = Random::default();
1190 (1.0 - coherence_factor) * random.random::<f64>() * PI
1191 };
1192 for amplitude in state_vector.iter_mut() {
1193 let phase_factor = Complex::new(phase_noise.cos(), phase_noise.sin());
1194 *amplitude = *amplitude * phase_factor;
1195 }
1196 }
1197 }
1198
1199 let norm = state_vector
1201 .iter()
1202 .map(|amp| amp.magnitude_squared())
1203 .sum::<f64>()
1204 .sqrt();
1205
1206 if norm > 0.0 {
1207 for amp in state_vector.iter_mut() {
1208 *amp = *amp * (1.0 / norm);
1209 }
1210 }
1211
1212 Ok(())
1213 }
1214
1215 pub fn update_execution_time(&mut self, delta_time: f64) {
1217 self.execution_time += delta_time;
1218 }
1219
1220 pub fn reset_execution_time(&mut self) {
1222 self.execution_time = 0.0;
1223 }
1224
1225 pub fn get_coherence_report(&self) -> CoherenceReport {
1227 let coherence_factors: Vec<f64> = (0..self.t1_times.len())
1228 .map(|qubit| self.calculate_coherence_factor(qubit))
1229 .collect();
1230
1231 let avg_coherence = coherence_factors.iter().sum::<f64>() / coherence_factors.len() as f64;
1232 let min_coherence = coherence_factors
1233 .iter()
1234 .fold(f64::INFINITY, |a, &b| a.min(b));
1235 let max_coherence = coherence_factors
1236 .iter()
1237 .fold(f64::NEG_INFINITY, |a, &b| a.max(b));
1238
1239 CoherenceReport {
1240 execution_time: self.execution_time,
1241 qubit_coherence_factors: coherence_factors,
1242 average_coherence: avg_coherence,
1243 minimum_coherence: min_coherence,
1244 maximum_coherence: max_coherence,
1245 coherence_uniformity: 1.0 - (max_coherence - min_coherence) / max_coherence,
1246 }
1247 }
1248}
1249
1250#[derive(Debug, Clone, Serialize, Deserialize)]
1252pub struct CoherenceReport {
1253 pub execution_time: f64,
1254 pub qubit_coherence_factors: Vec<f64>,
1255 pub average_coherence: f64,
1256 pub minimum_coherence: f64,
1257 pub maximum_coherence: f64,
1258 pub coherence_uniformity: f64,
1259}
1260
1261#[derive(Debug, Clone, Serialize, Deserialize)]
1263pub struct QuantumDiagnostics {
1264 pub error_correction_confidence: f64,
1265 pub error_rate: f64,
1266 pub num_error_measurements: usize,
1267 pub coherence_report: CoherenceReport,
1268 pub error_correction_enabled: bool,
1269 pub coherence_modeling_enabled: bool,
1270}
1271
1272#[derive(Debug, Clone)]
1274pub struct QuantumNeuralNetwork {
1275 pub num_qubits: usize,
1277 pub layers: Vec<QuantumNeuralNetworkLayer>,
1279 pub measurement_strategy: MeasurementStrategy,
1281 pub loss_history: Vec<f64>,
1283 pub error_correction: QuantumErrorCorrection,
1285 pub coherence_manager: CoherenceTimeManager,
1287 pub enable_error_correction: bool,
1289 pub enable_coherence_modeling: bool,
1291}
1292
1293#[derive(Debug, Clone)]
1295pub enum MeasurementStrategy {
1296 ExpectationZ,
1298 ExpectationX,
1300 Probability0,
1302 CustomPauli(Vec<(usize, char)>),
1304}
1305
1306impl QuantumNeuralNetwork {
1307 pub fn new(num_qubits: usize, layer_configs: Vec<QNNLayerType>) -> Self {
1309 let layers = layer_configs
1310 .into_iter()
1311 .map(|layer_type| QuantumNeuralNetworkLayer::new(num_qubits, layer_type))
1312 .collect();
1313
1314 Self {
1315 num_qubits,
1316 layers,
1317 measurement_strategy: MeasurementStrategy::ExpectationZ,
1318 loss_history: Vec::new(),
1319 error_correction: QuantumErrorCorrection::new(),
1320 coherence_manager: CoherenceTimeManager::new(num_qubits),
1321 enable_error_correction: true,
1322 enable_coherence_modeling: true,
1323 }
1324 }
1325
1326 pub fn new_with_error_correction(
1328 num_qubits: usize,
1329 layer_configs: Vec<QNNLayerType>,
1330 enable_error_correction: bool,
1331 enable_coherence_modeling: bool,
1332 ) -> Self {
1333 let layers = layer_configs
1334 .into_iter()
1335 .map(|layer_type| QuantumNeuralNetworkLayer::new(num_qubits, layer_type))
1336 .collect();
1337
1338 Self {
1339 num_qubits,
1340 layers,
1341 measurement_strategy: MeasurementStrategy::ExpectationZ,
1342 loss_history: Vec::new(),
1343 error_correction: QuantumErrorCorrection::new(),
1344 coherence_manager: CoherenceTimeManager::new(num_qubits),
1345 enable_error_correction,
1346 enable_coherence_modeling,
1347 }
1348 }
1349
1350 pub fn set_coherence_times(&mut self, t1_times: Vec<f64>, t2_times: Vec<f64>) {
1352 self.coherence_manager
1353 .set_coherence_times(t1_times, t2_times);
1354 }
1355
1356 pub fn forward(&mut self, input_data: &[f64]) -> Result<Vec<f64>> {
1358 let mut circuit = QuantumCircuit::new(self.num_qubits);
1359
1360 self.coherence_manager.reset_execution_time();
1362
1363 for (i, layer) in self.layers.iter().enumerate() {
1365 let layer_circuit = if i == 0 {
1366 layer.build_circuit(Some(input_data))
1368 } else {
1369 layer.build_circuit(None)
1371 };
1372
1373 if self.enable_coherence_modeling {
1375 let gate_time = 0.1e-6; self.coherence_manager
1377 .update_execution_time(gate_time * layer_circuit.gates.len() as f64);
1378 }
1379
1380 for gate in &layer_circuit.gates {
1382 circuit.add_gate(gate.clone());
1383 }
1384 }
1385
1386 let mut simulator = QuantumSimulator::new(self.num_qubits);
1388 simulator.execute_circuit(&circuit)?;
1389
1390 if self.enable_coherence_modeling {
1392 self.coherence_manager
1393 .apply_coherence_decay(&mut simulator.state_vector)?;
1394 }
1395
1396 if self.enable_error_correction {
1398 let syndrome = self
1399 .error_correction
1400 .detect_errors(&simulator.state_vector)?;
1401
1402 if syndrome.confidence > 0.5 {
1403 let mut correction_circuit = QuantumCircuit::new(self.num_qubits);
1405 self.error_correction
1406 .apply_corrections(&mut correction_circuit, &syndrome)?;
1407
1408 if !correction_circuit.gates.is_empty() {
1409 simulator.execute_circuit(&correction_circuit)?;
1410 }
1411 }
1412 }
1413
1414 let output = match &self.measurement_strategy {
1416 MeasurementStrategy::ExpectationZ => (0..self.num_qubits)
1417 .map(|qubit| simulator.expectation_z(qubit))
1418 .collect(),
1419 MeasurementStrategy::ExpectationX => {
1420 let mut outputs = Vec::new();
1421 for qubit in 0..self.num_qubits {
1422 let mut sim_copy = simulator.clone();
1423 let h_matrix = circuit.get_single_qubit_matrix(&QuantumGate::H);
1424 sim_copy.apply_single_qubit_gate(&h_matrix, qubit);
1425 outputs.push(sim_copy.expectation_z(qubit));
1426 }
1427 outputs
1428 }
1429 MeasurementStrategy::Probability0 => (0..self.num_qubits)
1430 .map(|qubit| simulator.measure_qubit(qubit).0)
1431 .collect(),
1432 MeasurementStrategy::CustomPauli(pauli_string) => {
1433 let mut expectation = 1.0;
1434 for &(qubit, pauli_op) in pauli_string {
1435 match pauli_op {
1436 'Z' => expectation *= simulator.expectation_z(qubit),
1437 'X' => {
1438 let mut sim_copy = simulator.clone();
1439 let h_matrix = circuit.get_single_qubit_matrix(&QuantumGate::H);
1440 sim_copy.apply_single_qubit_gate(&h_matrix, qubit);
1441 expectation *= sim_copy.expectation_z(qubit);
1442 }
1443 'I' => {} _ => return Err(anyhow!("Unsupported Pauli operator: {}", pauli_op)),
1445 }
1446 }
1447 vec![expectation]
1448 }
1449 };
1450
1451 Ok(output)
1452 }
1453
1454 pub fn get_quantum_diagnostics(&self) -> QuantumDiagnostics {
1456 let (avg_confidence, error_rate, num_measurements) =
1457 self.error_correction.get_correction_stats();
1458 let coherence_report = self.coherence_manager.get_coherence_report();
1459
1460 QuantumDiagnostics {
1461 error_correction_confidence: avg_confidence,
1462 error_rate,
1463 num_error_measurements: num_measurements,
1464 coherence_report,
1465 error_correction_enabled: self.enable_error_correction,
1466 coherence_modeling_enabled: self.enable_coherence_modeling,
1467 }
1468 }
1469
1470 pub fn train(
1472 &mut self,
1473 training_data: &[(Vec<f64>, Vec<f64>)],
1474 epochs: usize,
1475 learning_rate: f64,
1476 ) -> Result<()> {
1477 for epoch in 0..epochs {
1478 let mut total_loss = 0.0;
1479
1480 for (input, target) in training_data {
1481 let prediction = self.forward(input)?;
1482
1483 let loss = prediction
1485 .iter()
1486 .zip(target.iter())
1487 .map(|(p, t)| (p - t).powi(2))
1488 .sum::<f64>()
1489 / prediction.len() as f64;
1490
1491 total_loss += loss;
1492
1493 self.update_parameters(input, target, learning_rate)?;
1495 }
1496
1497 self.loss_history
1498 .push(total_loss / training_data.len() as f64);
1499
1500 if epoch % 10 == 0 {
1501 println!(
1502 "Epoch {}: Average Loss = {:.6}",
1503 epoch,
1504 self.loss_history
1505 .last()
1506 .expect("loss_history should not be empty after training")
1507 );
1508 }
1509 }
1510
1511 Ok(())
1512 }
1513
1514 fn update_parameters(
1516 &mut self,
1517 input: &[f64],
1518 target: &[f64],
1519 learning_rate: f64,
1520 ) -> Result<()> {
1521 let shift = 0.01;
1522
1523 let mut gradients = Vec::new();
1525
1526 let layer_info: Vec<(usize, usize)> = self
1528 .layers
1529 .iter()
1530 .enumerate()
1531 .map(|(idx, layer)| (idx, layer.parameters.len()))
1532 .collect();
1533
1534 for (layer_idx, param_count) in layer_info {
1535 let mut layer_gradients = Vec::new();
1536
1537 for i in 0..param_count {
1538 self.layers[layer_idx].parameters[i] += shift;
1540 let prediction_plus = self.forward(input)?;
1541 let loss_plus = prediction_plus
1542 .iter()
1543 .zip(target.iter())
1544 .map(|(p, t)| (p - t).powi(2))
1545 .sum::<f64>();
1546
1547 self.layers[layer_idx].parameters[i] -= 2.0 * shift;
1549 let prediction_minus = self.forward(input)?;
1550 let loss_minus = prediction_minus
1551 .iter()
1552 .zip(target.iter())
1553 .map(|(p, t)| (p - t).powi(2))
1554 .sum::<f64>();
1555
1556 self.layers[layer_idx].parameters[i] += shift;
1558
1559 let gradient = (loss_plus - loss_minus) / (2.0 * shift);
1561 layer_gradients.push(gradient);
1562 }
1563 gradients.push(layer_gradients);
1564 }
1565
1566 for (layer_idx, layer_gradients) in gradients.iter().enumerate() {
1568 for (param_idx, gradient) in layer_gradients.iter().enumerate() {
1569 self.layers[layer_idx].parameters[param_idx] -= learning_rate * gradient;
1570 }
1571 }
1572
1573 Ok(())
1574 }
1575}
1576
1577#[cfg(test)]
1578mod tests {
1579 use super::*;
1580
1581 #[test]
1582 fn test_complex_arithmetic() {
1583 let a = Complex::new(1.0, 2.0);
1584 let b = Complex::new(3.0, 4.0);
1585
1586 let sum = a + b;
1587 assert_eq!(sum.real, 4.0);
1588 assert_eq!(sum.imag, 6.0);
1589
1590 let product = a * b;
1591 assert_eq!(product.real, -5.0); assert_eq!(product.imag, 10.0); }
1594
1595 #[test]
1596 fn test_quantum_gates() {
1597 let circuit = QuantumCircuit::new(1);
1598
1599 let x_matrix = circuit.get_single_qubit_matrix(&QuantumGate::X);
1601 assert_eq!(x_matrix[(0, 0)].real, 0.0);
1602 assert_eq!(x_matrix[(0, 1)].real, 1.0);
1603 assert_eq!(x_matrix[(1, 0)].real, 1.0);
1604 assert_eq!(x_matrix[(1, 1)].real, 0.0);
1605
1606 let h_matrix = circuit.get_single_qubit_matrix(&QuantumGate::H);
1608 let inv_sqrt2 = 1.0 / (2.0_f64).sqrt();
1609 assert!((h_matrix[(0, 0)].real - inv_sqrt2).abs() < 1e-10);
1610 assert!((h_matrix[(1, 1)].real + inv_sqrt2).abs() < 1e-10);
1611 }
1612
1613 #[test]
1614 fn test_quantum_simulator() {
1615 let mut simulator = QuantumSimulator::new(2);
1616
1617 assert!((simulator.state_vector[0].real - 1.0).abs() < 1e-10);
1619 assert!((simulator.state_vector[0].imag).abs() < 1e-10);
1620 assert!((simulator.state_vector[1].real).abs() < 1e-10);
1621 assert!((simulator.state_vector[1].imag).abs() < 1e-10);
1622 assert!((simulator.state_vector[2].real).abs() < 1e-10);
1623 assert!((simulator.state_vector[2].imag).abs() < 1e-10);
1624 assert!((simulator.state_vector[3].real).abs() < 1e-10);
1625 assert!((simulator.state_vector[3].imag).abs() < 1e-10);
1626
1627 let circuit = QuantumCircuit::new(2);
1629 let h_matrix = circuit.get_single_qubit_matrix(&QuantumGate::H);
1630 simulator.apply_single_qubit_gate(&h_matrix, 0);
1631
1632 let inv_sqrt2 = 1.0 / (2.0_f64).sqrt();
1634 assert!((simulator.state_vector[0].real - inv_sqrt2).abs() < 1e-6);
1635 assert!((simulator.state_vector[2].real - inv_sqrt2).abs() < 1e-6);
1636 assert!((simulator.state_vector[1].real).abs() < 1e-10);
1637 assert!((simulator.state_vector[3].real).abs() < 1e-10);
1638 }
1639
1640 #[test]
1641 fn test_cnot_gate() {
1642 let mut simulator = QuantumSimulator::new(2);
1643
1644 let circuit = QuantumCircuit::new(2);
1646 let x_matrix = circuit.get_single_qubit_matrix(&QuantumGate::X);
1647 simulator.apply_single_qubit_gate(&x_matrix, 0);
1648
1649 simulator.apply_cnot(0, 1);
1651
1652 assert!((simulator.state_vector[0].real).abs() < 1e-10);
1654 assert!((simulator.state_vector[0].imag).abs() < 1e-10);
1655 assert!((simulator.state_vector[1].real).abs() < 1e-10);
1656 assert!((simulator.state_vector[1].imag).abs() < 1e-10);
1657 assert!((simulator.state_vector[2].real).abs() < 1e-10);
1658 assert!((simulator.state_vector[2].imag).abs() < 1e-10);
1659 assert!((simulator.state_vector[3].real - 1.0).abs() < 1e-10);
1660 assert!((simulator.state_vector[3].imag).abs() < 1e-10);
1661 }
1662
1663 #[test]
1664 fn test_vqe_creation() {
1665 let vqe = VariationalQuantumEigensolver::new(2, 1);
1666 assert_eq!(vqe.ansatz.num_qubits, 2);
1667 assert!(!vqe.parameters.is_empty());
1668 }
1669
1670 #[test]
1671 fn test_qaoa_creation() {
1672 let mut qaoa = QuantumApproximateOptimization::new(3, 2);
1673 assert_eq!(qaoa.num_qubits, 3);
1674 assert_eq!(qaoa.depth, 2);
1675 assert_eq!(qaoa.beta_params.len(), 2);
1676 assert_eq!(qaoa.gamma_params.len(), 2);
1677
1678 qaoa.add_cost_term(0.5, vec![(0, 'Z'), (1, 'Z')]);
1680 qaoa.add_cost_term(0.5, vec![(1, 'Z'), (2, 'Z')]);
1681
1682 assert_eq!(qaoa.cost_hamiltonian.len(), 2);
1683 }
1684
1685 #[test]
1686 fn test_qnn_layer() {
1687 let layer = QuantumNeuralNetworkLayer::new(2, QNNLayerType::BasicEntangling);
1688 assert_eq!(layer.num_qubits, 2);
1689 assert_eq!(layer.parameters.len(), 2);
1690
1691 let circuit = layer.build_circuit(None);
1692 assert_eq!(circuit.num_qubits, 2);
1693 assert!(!circuit.gates.is_empty());
1694 }
1695
1696 #[test]
1697 fn test_qnn_forward() {
1698 let mut qnn = QuantumNeuralNetwork::new(
1699 2,
1700 vec![QNNLayerType::AngleEmbedding, QNNLayerType::BasicEntangling],
1701 );
1702
1703 let input = vec![0.5, 0.8];
1704 let output = qnn.forward(&input).unwrap();
1705
1706 assert_eq!(output.len(), 2);
1707 assert!(output.iter().all(|&x| (-1.1..=1.1).contains(&x)));
1709 assert!(output.iter().all(|&x| x.is_finite()));
1711 }
1712
1713 #[test]
1714 fn test_rotation_gates() {
1715 let circuit = QuantumCircuit::new(1);
1716
1717 let ry_matrix = circuit.get_single_qubit_matrix(&QuantumGate::RY(PI / 2.0));
1719 let inv_sqrt2 = 1.0 / (2.0_f64).sqrt();
1720
1721 assert!((ry_matrix[(0, 0)].real - inv_sqrt2).abs() < 1e-10);
1722 assert!((ry_matrix[(0, 1)].real + inv_sqrt2).abs() < 1e-10);
1723 assert!((ry_matrix[(1, 0)].real - inv_sqrt2).abs() < 1e-10);
1724 assert!((ry_matrix[(1, 1)].real - inv_sqrt2).abs() < 1e-10);
1725 }
1726
1727 #[test]
1728 fn test_error_correction() {
1729 let mut error_correction = QuantumErrorCorrection::new();
1730
1731 let state_vector = vec![
1733 Complex::new(0.7, 0.0), Complex::new(0.0, 0.0), Complex::new(0.7, 0.0), Complex::new(0.0, 0.0), ];
1738
1739 let syndrome = error_correction.detect_errors(&state_vector).unwrap();
1740
1741 assert!(!syndrome.error_types.is_empty());
1743 assert!(syndrome.confidence > 0.0);
1744 }
1745
1746 #[test]
1747 fn test_coherence_time_manager() {
1748 let mut coherence_manager = CoherenceTimeManager::new(2);
1749
1750 coherence_manager.set_coherence_times(vec![100e-6, 50e-6], vec![50e-6, 25e-6]);
1752
1753 let factor_qubit0 = coherence_manager.calculate_coherence_factor(0);
1755 let factor_qubit1 = coherence_manager.calculate_coherence_factor(1);
1756
1757 assert!(factor_qubit0 > 0.0);
1758 assert!(factor_qubit1 > 0.0);
1759 assert!(factor_qubit0 <= 1.0);
1760 assert!(factor_qubit1 <= 1.0);
1761
1762 coherence_manager.update_execution_time(10e-6); let factor_after = coherence_manager.calculate_coherence_factor(0);
1766 assert!(factor_after < factor_qubit0); }
1768
1769 #[test]
1770 fn test_enhanced_qnn() {
1771 let mut qnn = QuantumNeuralNetwork::new(
1772 2,
1773 vec![QNNLayerType::AngleEmbedding, QNNLayerType::BasicEntangling],
1774 );
1775
1776 assert!(qnn.enable_error_correction);
1778 assert!(qnn.enable_coherence_modeling);
1779
1780 qnn.set_coherence_times(vec![100e-6, 50e-6], vec![50e-6, 25e-6]);
1782
1783 let input = vec![0.5, 0.8];
1784 let output = qnn.forward(&input).unwrap();
1785
1786 assert_eq!(output.len(), 2);
1787 assert!(output.iter().all(|&x| (-1.1..=1.1).contains(&x)));
1788 assert!(output.iter().all(|&x| x.is_finite()));
1789
1790 let diagnostics = qnn.get_quantum_diagnostics();
1792 assert!(diagnostics.error_correction_enabled);
1793 assert!(diagnostics.coherence_modeling_enabled);
1794 assert!(diagnostics.coherence_report.execution_time >= 0.0);
1795 }
1796
1797 #[test]
1798 fn test_coherence_decay_models() {
1799 let mut manager = CoherenceTimeManager::new(3);
1800
1801 manager.decay_models = vec![
1803 CoherenceDecayModel::Exponential,
1804 CoherenceDecayModel::Gaussian,
1805 CoherenceDecayModel::PowerLaw(1.5),
1806 ];
1807
1808 manager.update_execution_time(5e-6);
1809
1810 for qubit in 0..3 {
1811 let factor = manager.calculate_coherence_factor(qubit);
1812 assert!(factor > 0.0);
1813 assert!(factor <= 1.0);
1814 }
1815
1816 let report = manager.get_coherence_report();
1818 assert_eq!(report.qubit_coherence_factors.len(), 3);
1819 assert!(report.average_coherence > 0.0);
1820 assert!(report.coherence_uniformity >= 0.0);
1821 assert!(report.coherence_uniformity <= 1.0);
1822 }
1823
1824 #[test]
1825 fn test_error_mitigation_strategies() {
1826 let error_correction = QuantumErrorCorrection::new();
1827
1828 assert!(!error_correction.mitigation_strategies.is_empty());
1830 assert!(error_correction
1831 .mitigation_strategies
1832 .contains(&ErrorMitigationStrategy::ZeroNoiseExtrapolation));
1833 assert!(error_correction
1834 .mitigation_strategies
1835 .contains(&ErrorMitigationStrategy::ReadoutErrorMitigation));
1836 assert!(error_correction
1837 .mitigation_strategies
1838 .contains(&ErrorMitigationStrategy::SymmetryVerification));
1839 }
1840}