1use crate::error::{QuantRS2Error, QuantRS2Result};
7use scirs2_core::ndarray::{Array1, Array2};
8use scirs2_core::Complex64;
9use std::collections::HashMap;
10
11#[derive(Debug, Clone, Copy, PartialEq)]
13pub enum QuantumDotType {
14 SpinQubit,
16 ChargeQubit,
18 SingletTriplet,
20 HybridQubit,
22}
23
24#[derive(Debug, Clone)]
26pub struct QuantumDotParams {
27 pub diameter: f64,
29 pub tunnel_coupling: f64,
31 pub charging_energy: f64,
33 pub zeeman_splitting: f64,
35 pub spin_orbit_coupling: f64,
37 pub valley_splitting: f64,
39 pub temperature: f64,
41 pub magnetic_field: f64,
43}
44
45impl QuantumDotParams {
46 pub fn typical_silicon_dot() -> Self {
48 Self {
49 diameter: 50.0, tunnel_coupling: 1e-6, charging_energy: 1e-3, zeeman_splitting: 1e-5, spin_orbit_coupling: 1e-7, valley_splitting: 1e-4, temperature: 0.01, magnetic_field: 0.1, }
58 }
59
60 pub fn coherence_time(&self) -> f64 {
62 let noise_level = self.temperature * 8.617e-5; let dephasing_rate = noise_level / (6.582e-16); 1.0 / dephasing_rate }
67
68 pub fn single_qubit_gate_time(&self) -> f64 {
70 let rabi_freq = self.zeeman_splitting / (6.582e-16); std::f64::consts::PI / (2.0 * rabi_freq) }
74
75 pub fn two_qubit_gate_time(&self) -> f64 {
77 let exchange_freq = self.tunnel_coupling / (6.582e-16); std::f64::consts::PI / (4.0 * exchange_freq) }
81}
82
83#[derive(Debug, Clone)]
85pub struct SiliconQuantumDot {
86 pub dot_id: usize,
88 pub dot_type: QuantumDotType,
90 pub params: QuantumDotParams,
92 pub position: [f64; 2],
94 pub state: Array1<Complex64>,
96 pub energy_levels: Vec<f64>,
98 pub gate_voltages: HashMap<String, f64>,
100}
101
102impl SiliconQuantumDot {
103 pub fn new(
105 dot_id: usize,
106 dot_type: QuantumDotType,
107 params: QuantumDotParams,
108 position: [f64; 2],
109 ) -> Self {
110 let state_size = match dot_type {
111 QuantumDotType::SpinQubit => 2, QuantumDotType::ChargeQubit => 2, QuantumDotType::SingletTriplet => 4, QuantumDotType::HybridQubit => 4, };
116
117 let mut state = Array1::zeros(state_size);
118 state[0] = Complex64::new(1.0, 0.0); let energy_levels = Self::calculate_energy_levels(&dot_type, ¶ms);
121
122 Self {
123 dot_id,
124 dot_type,
125 params,
126 position,
127 state,
128 energy_levels,
129 gate_voltages: HashMap::new(),
130 }
131 }
132
133 fn calculate_energy_levels(dot_type: &QuantumDotType, params: &QuantumDotParams) -> Vec<f64> {
135 match dot_type {
136 QuantumDotType::SpinQubit => {
137 vec![
138 -params.zeeman_splitting / 2.0, params.zeeman_splitting / 2.0, ]
141 }
142 QuantumDotType::ChargeQubit => {
143 vec![
144 0.0, params.charging_energy, ]
147 }
148 QuantumDotType::SingletTriplet => {
149 let exchange = params.tunnel_coupling;
150 vec![
151 -exchange, 0.0, params.zeeman_splitting, -params.zeeman_splitting, ]
156 }
157 QuantumDotType::HybridQubit => {
158 vec![
159 0.0,
160 params.charging_energy,
161 params.zeeman_splitting,
162 params.charging_energy + params.zeeman_splitting,
163 ]
164 }
165 }
166 }
167
168 pub fn set_gate_voltage(&mut self, gate_name: String, voltage: f64) {
170 if gate_name.starts_with("plunger") {
172 self.params.charging_energy *= 1.0 + voltage * 0.1;
174 } else if gate_name.starts_with("barrier") {
175 self.params.tunnel_coupling *= (-voltage).exp();
177 }
178
179 self.gate_voltages.insert(gate_name, voltage);
180
181 self.energy_levels = Self::calculate_energy_levels(&self.dot_type, &self.params);
183 }
184
185 pub fn get_probabilities(&self) -> Vec<f64> {
187 self.state.iter().map(|x| x.norm_sqr()).collect()
188 }
189
190 pub fn apply_unitary(&mut self, unitary: &Array2<Complex64>) -> QuantRS2Result<()> {
192 if unitary.nrows() != self.state.len() || unitary.ncols() != self.state.len() {
193 return Err(QuantRS2Error::InvalidInput(
194 "Unitary matrix size doesn't match state".to_string(),
195 ));
196 }
197
198 self.state = unitary.dot(&self.state);
199 Ok(())
200 }
201
202 pub fn measure(&mut self) -> QuantRS2Result<usize> {
204 let probabilities = self.get_probabilities();
205
206 use scirs2_core::random::prelude::*;
208 let mut rng = thread_rng();
209 let random_value: f64 = rng.gen();
210 let mut cumulative = 0.0;
211
212 for (i, &prob) in probabilities.iter().enumerate() {
213 cumulative += prob;
214 if random_value <= cumulative {
215 self.state.fill(Complex64::new(0.0, 0.0));
217 self.state[i] = Complex64::new(1.0, 0.0);
218 return Ok(i);
219 }
220 }
221
222 Ok(probabilities.len() - 1)
224 }
225}
226
227#[derive(Debug, Clone)]
229pub struct SiliconQuantumDotSystem {
230 pub num_dots: usize,
232 pub dots: Vec<SiliconQuantumDot>,
234 pub coupling_matrix: Array2<f64>,
236 pub global_state: Option<Array1<Complex64>>,
238 pub device_params: DeviceParams,
240}
241
242#[derive(Debug, Clone)]
243pub struct DeviceParams {
244 pub temperature: f64,
246 pub magnetic_field: [f64; 3],
248 pub electric_field: [f64; 3],
250 pub substrate: String,
252 pub oxide_thickness: f64,
254}
255
256impl DeviceParams {
257 pub fn typical_silicon_device() -> Self {
259 Self {
260 temperature: 0.01, magnetic_field: [0.0, 0.0, 0.1], electric_field: [0.0, 0.0, 0.0],
263 substrate: "Si/SiGe".to_string(),
264 oxide_thickness: 10.0, }
266 }
267}
268
269impl SiliconQuantumDotSystem {
270 pub fn new(
272 dot_configs: Vec<(QuantumDotType, QuantumDotParams, [f64; 2])>,
273 device_params: DeviceParams,
274 ) -> Self {
275 let num_dots = dot_configs.len();
276
277 let dots: Vec<SiliconQuantumDot> = dot_configs
278 .into_iter()
279 .enumerate()
280 .map(|(id, (dot_type, params, position))| {
281 SiliconQuantumDot::new(id, dot_type, params, position)
282 })
283 .collect();
284
285 let coupling_matrix = Array2::zeros((num_dots, num_dots));
287
288 Self {
289 num_dots,
290 dots,
291 coupling_matrix,
292 global_state: None,
293 device_params,
294 }
295 }
296
297 pub fn set_coupling(&mut self, dot1: usize, dot2: usize, coupling: f64) -> QuantRS2Result<()> {
299 if dot1 >= self.num_dots || dot2 >= self.num_dots {
300 return Err(QuantRS2Error::InvalidInput(
301 "Dot index out of bounds".to_string(),
302 ));
303 }
304
305 self.coupling_matrix[[dot1, dot2]] = coupling;
306 self.coupling_matrix[[dot2, dot1]] = coupling; Ok(())
309 }
310
311 pub fn calculate_distance_coupling(&mut self) -> QuantRS2Result<()> {
313 for i in 0..self.num_dots {
314 for j in i + 1..self.num_dots {
315 let pos1 = self.dots[i].position;
316 let pos2 = self.dots[j].position;
317
318 let distance = ((pos1[0] - pos2[0]).powi(2) + (pos1[1] - pos2[1]).powi(2)).sqrt();
319
320 let coupling = 1e-6 * (-distance / 100.0).exp(); self.set_coupling(i, j, coupling)?;
323 }
324 }
325
326 Ok(())
327 }
328
329 pub fn apply_exchange_interaction(
331 &mut self,
332 dot1: usize,
333 dot2: usize,
334 duration: f64,
335 ) -> QuantRS2Result<()> {
336 if dot1 >= self.num_dots || dot2 >= self.num_dots {
337 return Err(QuantRS2Error::InvalidInput(
338 "Dot index out of bounds".to_string(),
339 ));
340 }
341
342 let exchange_strength = self.coupling_matrix[[dot1, dot2]];
343 let rotation_angle = exchange_strength * duration / (6.582e-16); let cos_theta = rotation_angle.cos();
347 let sin_theta = rotation_angle.sin();
348
349 let state1 = self.dots[dot1].state.clone();
351 let state2 = self.dots[dot2].state.clone();
352
353 if state1.len() == 2 && state2.len() == 2 {
355 let amp_00 = state1[0] * state2[0];
357 let amp_01 = state1[0] * state2[1];
358 let amp_10 = state1[1] * state2[0];
359 let _amp_11 = state1[1] * state2[1];
360
361 let new_01 = cos_theta * amp_01 + Complex64::new(0.0, 1.0) * sin_theta * amp_10;
362 let new_10 = cos_theta * amp_10 + Complex64::new(0.0, 1.0) * sin_theta * amp_01;
363
364 let norm1 = (amp_00.norm_sqr() + amp_10.norm_sqr()).sqrt();
366 let norm2 = (amp_00.norm_sqr() + amp_01.norm_sqr()).sqrt();
367
368 if norm1 > 1e-10 && norm2 > 1e-10 {
369 self.dots[dot1].state[0] = amp_00 / norm1;
370 self.dots[dot1].state[1] = new_10 / norm1;
371 self.dots[dot2].state[0] = amp_00 / norm2;
372 self.dots[dot2].state[1] = new_01 / norm2;
373 }
374 }
375
376 Ok(())
377 }
378
379 pub fn apply_magnetic_pulse(
381 &mut self,
382 target_dots: &[usize],
383 field_amplitude: f64,
384 duration: f64,
385 phase: f64,
386 ) -> QuantRS2Result<()> {
387 for &dot_id in target_dots {
388 if dot_id >= self.num_dots {
389 return Err(QuantRS2Error::InvalidInput(
390 "Dot ID out of bounds".to_string(),
391 ));
392 }
393
394 let dot = &mut self.dots[dot_id];
395
396 if dot.dot_type == QuantumDotType::SpinQubit && dot.state.len() == 2 {
398 let omega = field_amplitude * 2.0 * std::f64::consts::PI; let theta = omega * duration;
400
401 let cos_half = (theta / 2.0).cos();
403 let sin_half = (theta / 2.0).sin();
404
405 let old_state = dot.state.clone();
406
407 if phase.abs() < 1e-10 {
408 dot.state[0] =
410 cos_half * old_state[0] - Complex64::new(0.0, sin_half) * old_state[1];
411 dot.state[1] =
412 -Complex64::new(0.0, sin_half) * old_state[0] + cos_half * old_state[1];
413 } else if (phase - std::f64::consts::PI / 2.0).abs() < 1e-10 {
414 dot.state[0] = cos_half * old_state[0] - sin_half * old_state[1];
416 dot.state[1] = sin_half * old_state[0] + cos_half * old_state[1];
417 } else {
418 let phase_factor = Complex64::new(0.0, phase).exp();
420 dot.state[0] = cos_half * old_state[0]
421 - Complex64::new(0.0, sin_half) * phase_factor * old_state[1];
422 dot.state[1] =
423 -Complex64::new(0.0, sin_half) * phase_factor.conj() * old_state[0]
424 + cos_half * old_state[1];
425 }
426 }
427 }
428
429 Ok(())
430 }
431
432 pub fn apply_electric_pulse(
434 &mut self,
435 target_dots: &[usize],
436 field_amplitude: f64,
437 duration: f64,
438 ) -> QuantRS2Result<()> {
439 for &dot_id in target_dots {
440 if dot_id >= self.num_dots {
441 return Err(QuantRS2Error::InvalidInput(
442 "Dot ID out of bounds".to_string(),
443 ));
444 }
445
446 let dot = &mut self.dots[dot_id];
447
448 if dot.dot_type == QuantumDotType::ChargeQubit && dot.state.len() == 2 {
450 let energy_shift = field_amplitude * 1.602e-19; let omega = energy_shift / (6.582e-16); let theta = omega * duration;
454
455 let phase_0 = Complex64::new(0.0, -theta / 2.0).exp();
457 let phase_1 = Complex64::new(0.0, theta / 2.0).exp();
458
459 dot.state[0] *= phase_0;
460 dot.state[1] *= phase_1;
461 }
462 }
463
464 Ok(())
465 }
466
467 pub fn apply_decoherence(&mut self, time_step: f64) -> QuantRS2Result<()> {
469 for dot in &mut self.dots {
470 let t2_star = dot.params.coherence_time();
471 let dephasing_prob = time_step / t2_star;
472
473 if dephasing_prob > 0.01 {
474 use scirs2_core::random::prelude::*;
476 let mut rng = thread_rng();
477 let phase_noise = rng.gen_range(-dephasing_prob..dephasing_prob);
478
479 let noise_factor = Complex64::new(0.0, phase_noise).exp();
480 dot.state[1] *= noise_factor;
481 }
482 }
483
484 Ok(())
485 }
486
487 pub fn measure_all(&mut self) -> QuantRS2Result<Vec<usize>> {
489 let mut results = Vec::new();
490
491 for dot in &mut self.dots {
492 let result = dot.measure()?;
493 results.push(result);
494 }
495
496 Ok(results)
497 }
498
499 pub fn calculate_fidelity(&self, target_state: &[Vec<Complex64>]) -> f64 {
501 if target_state.len() != self.num_dots {
502 return 0.0;
503 }
504
505 let mut total_fidelity = 1.0;
506
507 for (i, dot) in self.dots.iter().enumerate() {
508 if target_state[i].len() != dot.state.len() {
509 return 0.0;
510 }
511
512 let overlap = dot
513 .state
514 .iter()
515 .zip(target_state[i].iter())
516 .map(|(a, b)| (a.conj() * b).norm_sqr())
517 .sum::<f64>();
518
519 total_fidelity *= overlap;
520 }
521
522 total_fidelity
523 }
524
525 pub fn average_coherence_time(&self) -> f64 {
527 let total_t2: f64 = self
528 .dots
529 .iter()
530 .map(|dot| dot.params.coherence_time())
531 .sum();
532
533 total_t2 / self.num_dots as f64
534 }
535}
536
537pub struct SiliconQuantumDotGates;
539
540impl SiliconQuantumDotGates {
541 pub fn spin_x_rotation(
543 system: &mut SiliconQuantumDotSystem,
544 dot_id: usize,
545 angle: f64,
546 ) -> QuantRS2Result<()> {
547 if dot_id >= system.num_dots {
548 return Err(QuantRS2Error::InvalidInput(
549 "Dot ID out of bounds".to_string(),
550 ));
551 }
552
553 let field_amplitude = 1e-3;
555 let omega = field_amplitude * 2.0 * std::f64::consts::PI;
556 let duration = angle / omega;
557
558 system.apply_magnetic_pulse(&[dot_id], field_amplitude, duration, 0.0)
559 }
560
561 pub fn spin_y_rotation(
563 system: &mut SiliconQuantumDotSystem,
564 dot_id: usize,
565 angle: f64,
566 ) -> QuantRS2Result<()> {
567 if dot_id >= system.num_dots {
568 return Err(QuantRS2Error::InvalidInput(
569 "Dot ID out of bounds".to_string(),
570 ));
571 }
572
573 let field_amplitude = 1e-3;
575 let omega = field_amplitude * 2.0 * std::f64::consts::PI;
576 let duration = angle / omega;
577
578 system.apply_magnetic_pulse(
579 &[dot_id],
580 field_amplitude,
581 duration,
582 std::f64::consts::PI / 2.0,
583 )
584 }
585
586 pub fn spin_z_rotation(
588 system: &mut SiliconQuantumDotSystem,
589 dot_id: usize,
590 angle: f64,
591 ) -> QuantRS2Result<()> {
592 if dot_id >= system.num_dots {
593 return Err(QuantRS2Error::InvalidInput(
594 "Dot ID out of bounds".to_string(),
595 ));
596 }
597
598 let dot = &mut system.dots[dot_id];
600 let phase_factor = Complex64::new(0.0, angle / 2.0).exp();
601
602 dot.state[0] *= phase_factor.conj();
603 dot.state[1] *= phase_factor;
604
605 Ok(())
606 }
607
608 pub fn hadamard(system: &mut SiliconQuantumDotSystem, dot_id: usize) -> QuantRS2Result<()> {
610 if dot_id >= system.num_dots {
611 return Err(QuantRS2Error::InvalidInput(
612 "Dot ID out of bounds".to_string(),
613 ));
614 }
615
616 let dot = &mut system.dots[dot_id];
617 if dot.dot_type == QuantumDotType::SpinQubit && dot.state.len() == 2 {
618 let old_state = dot.state.clone();
620 let inv_sqrt2 = 1.0 / std::f64::consts::SQRT_2;
621
622 dot.state[0] = inv_sqrt2 * (old_state[0] + old_state[1]);
623 dot.state[1] = inv_sqrt2 * (old_state[0] - old_state[1]);
624 }
625
626 Ok(())
627 }
628
629 pub fn cnot(
631 system: &mut SiliconQuantumDotSystem,
632 control: usize,
633 target: usize,
634 ) -> QuantRS2Result<()> {
635 if control >= system.num_dots || target >= system.num_dots {
636 return Err(QuantRS2Error::InvalidInput(
637 "Dot ID out of bounds".to_string(),
638 ));
639 }
640
641 let control_state = &system.dots[control].state;
644 let control_prob_1 = control_state[1].norm_sqr();
645
646 if control_prob_1 > 0.5 {
648 Self::spin_x_rotation(system, target, std::f64::consts::PI)?;
649 }
650
651 Ok(())
652 }
653
654 pub fn cz(
656 system: &mut SiliconQuantumDotSystem,
657 control: usize,
658 target: usize,
659 ) -> QuantRS2Result<()> {
660 if control >= system.num_dots || target >= system.num_dots {
661 return Err(QuantRS2Error::InvalidInput(
662 "Dot ID out of bounds".to_string(),
663 ));
664 }
665
666 let exchange_strength = system.coupling_matrix[[control, target]];
667 let gate_time = std::f64::consts::PI / (4.0 * exchange_strength / (6.582e-16));
668
669 system.apply_exchange_interaction(control, target, gate_time)
670 }
671
672 pub fn swap(
674 system: &mut SiliconQuantumDotSystem,
675 dot1: usize,
676 dot2: usize,
677 ) -> QuantRS2Result<()> {
678 if dot1 >= system.num_dots || dot2 >= system.num_dots {
679 return Err(QuantRS2Error::InvalidInput(
680 "Dot ID out of bounds".to_string(),
681 ));
682 }
683
684 let exchange_strength = system.coupling_matrix[[dot1, dot2]];
685 let gate_time = std::f64::consts::PI / (2.0 * exchange_strength / (6.582e-16));
686
687 system.apply_exchange_interaction(dot1, dot2, gate_time)
688 }
689
690 pub fn toffoli(
692 system: &mut SiliconQuantumDotSystem,
693 control1: usize,
694 control2: usize,
695 target: usize,
696 ) -> QuantRS2Result<()> {
697 Self::hadamard(system, target)?;
699 Self::cnot(system, control2, target)?;
700 Self::spin_z_rotation(system, target, -std::f64::consts::PI / 4.0)?;
701 Self::cnot(system, control1, target)?;
702 Self::spin_z_rotation(system, target, std::f64::consts::PI / 4.0)?;
703 Self::cnot(system, control2, target)?;
704 Self::spin_z_rotation(system, target, -std::f64::consts::PI / 4.0)?;
705 Self::cnot(system, control1, target)?;
706 Self::spin_z_rotation(system, control1, std::f64::consts::PI / 4.0)?;
707 Self::spin_z_rotation(system, control2, std::f64::consts::PI / 4.0)?;
708 Self::spin_z_rotation(system, target, std::f64::consts::PI / 4.0)?;
709 Self::hadamard(system, target)?;
710 Self::cnot(system, control1, control2)?;
711 Self::spin_z_rotation(system, control1, std::f64::consts::PI / 4.0)?;
712 Self::spin_z_rotation(system, control2, -std::f64::consts::PI / 4.0)?;
713 Self::cnot(system, control1, control2)
714 }
715}
716
717#[cfg(test)]
718mod tests {
719 use super::*;
720
721 #[test]
722 fn test_quantum_dot_params() {
723 let params = QuantumDotParams::typical_silicon_dot();
724 assert!(params.diameter > 0.0);
725 assert!(params.coherence_time() > 0.0);
726 assert!(params.single_qubit_gate_time() > 0.0);
727 assert!(params.two_qubit_gate_time() > 0.0);
728 }
729
730 #[test]
731 fn test_silicon_quantum_dot_creation() {
732 let params = QuantumDotParams::typical_silicon_dot();
733 let dot = SiliconQuantumDot::new(0, QuantumDotType::SpinQubit, params, [0.0, 0.0]);
734
735 assert_eq!(dot.dot_id, 0);
736 assert_eq!(dot.dot_type, QuantumDotType::SpinQubit);
737 assert_eq!(dot.state.len(), 2);
738 assert!((dot.state[0] - Complex64::new(1.0, 0.0)).norm() < 1e-10);
739 }
740
741 #[test]
742 fn test_quantum_dot_system() {
743 let params = QuantumDotParams::typical_silicon_dot();
744 let device_params = DeviceParams::typical_silicon_device();
745
746 let dot_configs = vec![
747 (QuantumDotType::SpinQubit, params.clone(), [0.0, 0.0]),
748 (QuantumDotType::SpinQubit, params, [100.0, 0.0]), ];
750
751 let mut system = SiliconQuantumDotSystem::new(dot_configs, device_params);
752 assert_eq!(system.num_dots, 2);
753
754 system.calculate_distance_coupling().unwrap();
755 assert!(system.coupling_matrix[[0, 1]] > 0.0);
756 }
757
758 #[test]
759 fn test_gate_voltage_effects() {
760 let params = QuantumDotParams::typical_silicon_dot();
761 let mut dot = SiliconQuantumDot::new(0, QuantumDotType::ChargeQubit, params, [0.0, 0.0]);
762
763 let initial_charging_energy = dot.params.charging_energy;
764 dot.set_gate_voltage("plunger1".to_string(), 0.1);
765
766 assert!((dot.params.charging_energy - initial_charging_energy).abs() > 1e-10);
768 }
769
770 #[test]
771 fn test_magnetic_pulse() {
772 let params = QuantumDotParams::typical_silicon_dot();
773 let device_params = DeviceParams::typical_silicon_device();
774 let dot_configs = vec![(QuantumDotType::SpinQubit, params, [0.0, 0.0])];
775
776 let mut system = SiliconQuantumDotSystem::new(dot_configs, device_params);
777
778 let field_amplitude = 1e-3;
780 let omega = field_amplitude * 2.0 * std::f64::consts::PI;
781 let duration = std::f64::consts::PI / omega; system
783 .apply_magnetic_pulse(&[0], field_amplitude, duration, 0.0)
784 .unwrap();
785
786 let probs = system.dots[0].get_probabilities();
788 assert!(probs[1] > 0.8);
789 }
790
791 #[test]
792 fn test_exchange_interaction() {
793 let params = QuantumDotParams::typical_silicon_dot();
794 let device_params = DeviceParams::typical_silicon_device();
795
796 let dot_configs = vec![
797 (QuantumDotType::SpinQubit, params.clone(), [0.0, 0.0]),
798 (QuantumDotType::SpinQubit, params, [50.0, 0.0]),
799 ];
800
801 let mut system = SiliconQuantumDotSystem::new(dot_configs, device_params);
802 system.set_coupling(0, 1, 1e-6).unwrap(); let duration = 1e-9; system.apply_exchange_interaction(0, 1, duration).unwrap();
807
808 let state1 = system.dots[0].get_probabilities();
810 let state2 = system.dots[1].get_probabilities();
811
812 assert!(state1.len() == 2);
813 assert!(state2.len() == 2);
814 }
815
816 #[test]
817 fn test_measurement() {
818 let params = QuantumDotParams::typical_silicon_dot();
819 let device_params = DeviceParams::typical_silicon_device();
820 let dot_configs = vec![(QuantumDotType::SpinQubit, params, [0.0, 0.0])];
821
822 let mut system = SiliconQuantumDotSystem::new(dot_configs, device_params);
823
824 system.dots[0].state[0] = Complex64::new(1.0 / 2.0_f64.sqrt(), 0.0);
826 system.dots[0].state[1] = Complex64::new(1.0 / 2.0_f64.sqrt(), 0.0);
827
828 let result = system.dots[0].measure().unwrap();
829 assert!(result == 0 || result == 1);
830
831 let probs = system.dots[0].get_probabilities();
833 assert!(probs[result] > 0.99);
834 }
835
836 #[test]
837 fn test_silicon_gates() {
838 let params = QuantumDotParams::typical_silicon_dot();
839 let device_params = DeviceParams::typical_silicon_device();
840 let dot_configs = vec![(QuantumDotType::SpinQubit, params, [0.0, 0.0])];
841
842 let mut system = SiliconQuantumDotSystem::new(dot_configs, device_params);
843
844 SiliconQuantumDotGates::spin_x_rotation(&mut system, 0, std::f64::consts::PI).unwrap();
846 let probs = system.dots[0].get_probabilities();
847 assert!(probs[1] > 0.8); SiliconQuantumDotGates::hadamard(&mut system, 0).unwrap();
851 let probs = system.dots[0].get_probabilities();
852 assert!(probs[0] > 0.05 && probs[0] < 0.95); }
854
855 #[test]
856 fn test_cnot_gate() {
857 let params = QuantumDotParams::typical_silicon_dot();
858 let device_params = DeviceParams::typical_silicon_device();
859
860 let dot_configs = vec![
861 (QuantumDotType::SpinQubit, params.clone(), [0.0, 0.0]),
862 (QuantumDotType::SpinQubit, params, [50.0, 0.0]),
863 ];
864
865 let mut system = SiliconQuantumDotSystem::new(dot_configs, device_params);
866 system.set_coupling(0, 1, 1e-3).unwrap(); SiliconQuantumDotGates::spin_x_rotation(&mut system, 0, std::f64::consts::PI).unwrap();
870
871 SiliconQuantumDotGates::cnot(&mut system, 0, 1).unwrap();
873
874 let target_probs = system.dots[1].get_probabilities();
876 assert!(target_probs[1] > 0.1); }
878
879 #[test]
880 fn test_decoherence() {
881 let params = QuantumDotParams::typical_silicon_dot();
882 let device_params = DeviceParams::typical_silicon_device();
883 let dot_configs = vec![(QuantumDotType::SpinQubit, params, [0.0, 0.0])];
884
885 let mut system = SiliconQuantumDotSystem::new(dot_configs, device_params);
886
887 system.dots[0].state[0] = Complex64::new(1.0 / 2.0_f64.sqrt(), 0.0);
889 system.dots[0].state[1] = Complex64::new(1.0 / 2.0_f64.sqrt(), 0.0);
890
891 let initial_state = system.dots[0].state.clone();
892
893 system.apply_decoherence(1e-6).unwrap(); let final_state = system.dots[0].state.clone();
897
898 let diff = &initial_state - &final_state;
900 let state_change = diff.iter().map(|x| x.norm_sqr()).sum::<f64>().sqrt();
901 assert!(state_change.is_finite());
902 }
903
904 #[test]
905 fn test_fidelity_calculation() {
906 let params = QuantumDotParams::typical_silicon_dot();
907 let device_params = DeviceParams::typical_silicon_device();
908 let dot_configs = vec![(QuantumDotType::SpinQubit, params, [0.0, 0.0])];
909
910 let system = SiliconQuantumDotSystem::new(dot_configs, device_params);
911
912 let target_state = vec![vec![Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)]];
914
915 let fidelity = system.calculate_fidelity(&target_state);
916 assert!((fidelity - 1.0).abs() < 1e-10); }
918
919 #[test]
920 fn test_coherence_time_average() {
921 let params = QuantumDotParams::typical_silicon_dot();
922 let device_params = DeviceParams::typical_silicon_device();
923
924 let dot_configs = vec![
925 (QuantumDotType::SpinQubit, params.clone(), [0.0, 0.0]),
926 (QuantumDotType::SpinQubit, params, [50.0, 0.0]),
927 ];
928
929 let system = SiliconQuantumDotSystem::new(dot_configs, device_params);
930
931 let avg_t2 = system.average_coherence_time();
932 assert!(avg_t2 > 0.0);
933 assert!(avg_t2.is_finite());
934 }
935}