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, Eq)]
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 const 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 | QuantumDotType::ChargeQubit => 2, QuantumDotType::SingletTriplet | QuantumDotType::HybridQubit => 4, };
114
115 let mut state = Array1::zeros(state_size);
116 state[0] = Complex64::new(1.0, 0.0); let energy_levels = Self::calculate_energy_levels(&dot_type, ¶ms);
119
120 Self {
121 dot_id,
122 dot_type,
123 params,
124 position,
125 state,
126 energy_levels,
127 gate_voltages: HashMap::new(),
128 }
129 }
130
131 fn calculate_energy_levels(dot_type: &QuantumDotType, params: &QuantumDotParams) -> Vec<f64> {
133 match dot_type {
134 QuantumDotType::SpinQubit => {
135 vec![
136 -params.zeeman_splitting / 2.0, params.zeeman_splitting / 2.0, ]
139 }
140 QuantumDotType::ChargeQubit => {
141 vec![
142 0.0, params.charging_energy, ]
145 }
146 QuantumDotType::SingletTriplet => {
147 let exchange = params.tunnel_coupling;
148 vec![
149 -exchange, 0.0, params.zeeman_splitting, -params.zeeman_splitting, ]
154 }
155 QuantumDotType::HybridQubit => {
156 vec![
157 0.0,
158 params.charging_energy,
159 params.zeeman_splitting,
160 params.charging_energy + params.zeeman_splitting,
161 ]
162 }
163 }
164 }
165
166 pub fn set_gate_voltage(&mut self, gate_name: String, voltage: f64) {
168 if gate_name.starts_with("plunger") {
170 self.params.charging_energy *= voltage.mul_add(0.1, 1.0);
172 } else if gate_name.starts_with("barrier") {
173 self.params.tunnel_coupling *= (-voltage).exp();
175 }
176
177 self.gate_voltages.insert(gate_name, voltage);
178
179 self.energy_levels = Self::calculate_energy_levels(&self.dot_type, &self.params);
181 }
182
183 pub fn get_probabilities(&self) -> Vec<f64> {
185 self.state.iter().map(|x| x.norm_sqr()).collect()
186 }
187
188 pub fn apply_unitary(&mut self, unitary: &Array2<Complex64>) -> QuantRS2Result<()> {
190 if unitary.nrows() != self.state.len() || unitary.ncols() != self.state.len() {
191 return Err(QuantRS2Error::InvalidInput(
192 "Unitary matrix size doesn't match state".to_string(),
193 ));
194 }
195
196 self.state = unitary.dot(&self.state);
197 Ok(())
198 }
199
200 pub fn measure(&mut self) -> QuantRS2Result<usize> {
202 let probabilities = self.get_probabilities();
203
204 use scirs2_core::random::prelude::*;
206 let mut rng = thread_rng();
207 let random_value: f64 = rng.gen();
208 let mut cumulative = 0.0;
209
210 for (i, &prob) in probabilities.iter().enumerate() {
211 cumulative += prob;
212 if random_value <= cumulative {
213 self.state.fill(Complex64::new(0.0, 0.0));
215 self.state[i] = Complex64::new(1.0, 0.0);
216 return Ok(i);
217 }
218 }
219
220 Ok(probabilities.len() - 1)
222 }
223}
224
225#[derive(Debug, Clone)]
227pub struct SiliconQuantumDotSystem {
228 pub num_dots: usize,
230 pub dots: Vec<SiliconQuantumDot>,
232 pub coupling_matrix: Array2<f64>,
234 pub global_state: Option<Array1<Complex64>>,
236 pub device_params: DeviceParams,
238}
239
240#[derive(Debug, Clone)]
241pub struct DeviceParams {
242 pub temperature: f64,
244 pub magnetic_field: [f64; 3],
246 pub electric_field: [f64; 3],
248 pub substrate: String,
250 pub oxide_thickness: f64,
252}
253
254impl DeviceParams {
255 pub fn typical_silicon_device() -> Self {
257 Self {
258 temperature: 0.01, magnetic_field: [0.0, 0.0, 0.1], electric_field: [0.0, 0.0, 0.0],
261 substrate: "Si/SiGe".to_string(),
262 oxide_thickness: 10.0, }
264 }
265}
266
267impl SiliconQuantumDotSystem {
268 pub fn new(
270 dot_configs: Vec<(QuantumDotType, QuantumDotParams, [f64; 2])>,
271 device_params: DeviceParams,
272 ) -> Self {
273 let num_dots = dot_configs.len();
274
275 let dots: Vec<SiliconQuantumDot> = dot_configs
276 .into_iter()
277 .enumerate()
278 .map(|(id, (dot_type, params, position))| {
279 SiliconQuantumDot::new(id, dot_type, params, position)
280 })
281 .collect();
282
283 let coupling_matrix = Array2::zeros((num_dots, num_dots));
285
286 Self {
287 num_dots,
288 dots,
289 coupling_matrix,
290 global_state: None,
291 device_params,
292 }
293 }
294
295 pub fn set_coupling(&mut self, dot1: usize, dot2: usize, coupling: f64) -> QuantRS2Result<()> {
297 if dot1 >= self.num_dots || dot2 >= self.num_dots {
298 return Err(QuantRS2Error::InvalidInput(
299 "Dot index out of bounds".to_string(),
300 ));
301 }
302
303 self.coupling_matrix[[dot1, dot2]] = coupling;
304 self.coupling_matrix[[dot2, dot1]] = coupling; Ok(())
307 }
308
309 pub fn calculate_distance_coupling(&mut self) -> QuantRS2Result<()> {
311 for i in 0..self.num_dots {
312 for j in i + 1..self.num_dots {
313 let pos1 = self.dots[i].position;
314 let pos2 = self.dots[j].position;
315
316 let distance = (pos1[0] - pos2[0]).hypot(pos1[1] - pos2[1]);
317
318 let coupling = 1e-6 * (-distance / 100.0).exp(); self.set_coupling(i, j, coupling)?;
321 }
322 }
323
324 Ok(())
325 }
326
327 pub fn apply_exchange_interaction(
329 &mut self,
330 dot1: usize,
331 dot2: usize,
332 duration: f64,
333 ) -> QuantRS2Result<()> {
334 if dot1 >= self.num_dots || dot2 >= self.num_dots {
335 return Err(QuantRS2Error::InvalidInput(
336 "Dot index out of bounds".to_string(),
337 ));
338 }
339
340 let exchange_strength = self.coupling_matrix[[dot1, dot2]];
341 let rotation_angle = exchange_strength * duration / (6.582e-16); let cos_theta = rotation_angle.cos();
345 let sin_theta = rotation_angle.sin();
346
347 let state1 = self.dots[dot1].state.clone();
349 let state2 = self.dots[dot2].state.clone();
350
351 if state1.len() == 2 && state2.len() == 2 {
353 let amp_00 = state1[0] * state2[0];
355 let amp_01 = state1[0] * state2[1];
356 let amp_10 = state1[1] * state2[0];
357 let _amp_11 = state1[1] * state2[1];
358
359 let new_01 = cos_theta * amp_01 + Complex64::new(0.0, 1.0) * sin_theta * amp_10;
360 let new_10 = cos_theta * amp_10 + Complex64::new(0.0, 1.0) * sin_theta * amp_01;
361
362 let norm1 = (amp_00.norm_sqr() + amp_10.norm_sqr()).sqrt();
364 let norm2 = (amp_00.norm_sqr() + amp_01.norm_sqr()).sqrt();
365
366 if norm1 > 1e-10 && norm2 > 1e-10 {
367 self.dots[dot1].state[0] = amp_00 / norm1;
368 self.dots[dot1].state[1] = new_10 / norm1;
369 self.dots[dot2].state[0] = amp_00 / norm2;
370 self.dots[dot2].state[1] = new_01 / norm2;
371 }
372 }
373
374 Ok(())
375 }
376
377 pub fn apply_magnetic_pulse(
379 &mut self,
380 target_dots: &[usize],
381 field_amplitude: f64,
382 duration: f64,
383 phase: f64,
384 ) -> QuantRS2Result<()> {
385 for &dot_id in target_dots {
386 if dot_id >= self.num_dots {
387 return Err(QuantRS2Error::InvalidInput(
388 "Dot ID out of bounds".to_string(),
389 ));
390 }
391
392 let dot = &mut self.dots[dot_id];
393
394 if dot.dot_type == QuantumDotType::SpinQubit && dot.state.len() == 2 {
396 let omega = field_amplitude * 2.0 * std::f64::consts::PI; let theta = omega * duration;
398
399 let cos_half = (theta / 2.0).cos();
401 let sin_half = (theta / 2.0).sin();
402
403 let old_state = dot.state.clone();
404
405 if phase.abs() < 1e-10 {
406 dot.state[0] =
408 cos_half * old_state[0] - Complex64::new(0.0, sin_half) * old_state[1];
409 dot.state[1] =
410 -Complex64::new(0.0, sin_half) * old_state[0] + cos_half * old_state[1];
411 } else if (phase - std::f64::consts::PI / 2.0).abs() < 1e-10 {
412 dot.state[0] = cos_half * old_state[0] - sin_half * old_state[1];
414 dot.state[1] = sin_half * old_state[0] + cos_half * old_state[1];
415 } else {
416 let phase_factor = Complex64::new(0.0, phase).exp();
418 dot.state[0] = cos_half * old_state[0]
419 - Complex64::new(0.0, sin_half) * phase_factor * old_state[1];
420 dot.state[1] =
421 -Complex64::new(0.0, sin_half) * phase_factor.conj() * old_state[0]
422 + cos_half * old_state[1];
423 }
424 }
425 }
426
427 Ok(())
428 }
429
430 pub fn apply_electric_pulse(
432 &mut self,
433 target_dots: &[usize],
434 field_amplitude: f64,
435 duration: f64,
436 ) -> QuantRS2Result<()> {
437 for &dot_id in target_dots {
438 if dot_id >= self.num_dots {
439 return Err(QuantRS2Error::InvalidInput(
440 "Dot ID out of bounds".to_string(),
441 ));
442 }
443
444 let dot = &mut self.dots[dot_id];
445
446 if dot.dot_type == QuantumDotType::ChargeQubit && dot.state.len() == 2 {
448 let energy_shift = field_amplitude * 1.602e-19; let omega = energy_shift / (6.582e-16); let theta = omega * duration;
452
453 let phase_0 = Complex64::new(0.0, -theta / 2.0).exp();
455 let phase_1 = Complex64::new(0.0, theta / 2.0).exp();
456
457 dot.state[0] *= phase_0;
458 dot.state[1] *= phase_1;
459 }
460 }
461
462 Ok(())
463 }
464
465 pub fn apply_decoherence(&mut self, time_step: f64) -> QuantRS2Result<()> {
467 for dot in &mut self.dots {
468 let t2_star = dot.params.coherence_time();
469 let dephasing_prob = time_step / t2_star;
470
471 if dephasing_prob > 0.01 {
472 use scirs2_core::random::prelude::*;
474 let mut rng = thread_rng();
475 let phase_noise = rng.gen_range(-dephasing_prob..dephasing_prob);
476
477 let noise_factor = Complex64::new(0.0, phase_noise).exp();
478 dot.state[1] *= noise_factor;
479 }
480 }
481
482 Ok(())
483 }
484
485 pub fn measure_all(&mut self) -> QuantRS2Result<Vec<usize>> {
487 let mut results = Vec::new();
488
489 for dot in &mut self.dots {
490 let result = dot.measure()?;
491 results.push(result);
492 }
493
494 Ok(results)
495 }
496
497 pub fn calculate_fidelity(&self, target_state: &[Vec<Complex64>]) -> f64 {
499 if target_state.len() != self.num_dots {
500 return 0.0;
501 }
502
503 let mut total_fidelity = 1.0;
504
505 for (i, dot) in self.dots.iter().enumerate() {
506 if target_state[i].len() != dot.state.len() {
507 return 0.0;
508 }
509
510 let overlap = dot
511 .state
512 .iter()
513 .zip(target_state[i].iter())
514 .map(|(a, b)| (a.conj() * b).norm_sqr())
515 .sum::<f64>();
516
517 total_fidelity *= overlap;
518 }
519
520 total_fidelity
521 }
522
523 pub fn average_coherence_time(&self) -> f64 {
525 let total_t2: f64 = self
526 .dots
527 .iter()
528 .map(|dot| dot.params.coherence_time())
529 .sum();
530
531 total_t2 / self.num_dots as f64
532 }
533}
534
535pub struct SiliconQuantumDotGates;
537
538impl SiliconQuantumDotGates {
539 pub fn spin_x_rotation(
541 system: &mut SiliconQuantumDotSystem,
542 dot_id: usize,
543 angle: f64,
544 ) -> QuantRS2Result<()> {
545 if dot_id >= system.num_dots {
546 return Err(QuantRS2Error::InvalidInput(
547 "Dot ID out of bounds".to_string(),
548 ));
549 }
550
551 let field_amplitude = 1e-3;
553 let omega = field_amplitude * 2.0 * std::f64::consts::PI;
554 let duration = angle / omega;
555
556 system.apply_magnetic_pulse(&[dot_id], field_amplitude, duration, 0.0)
557 }
558
559 pub fn spin_y_rotation(
561 system: &mut SiliconQuantumDotSystem,
562 dot_id: usize,
563 angle: f64,
564 ) -> QuantRS2Result<()> {
565 if dot_id >= system.num_dots {
566 return Err(QuantRS2Error::InvalidInput(
567 "Dot ID out of bounds".to_string(),
568 ));
569 }
570
571 let field_amplitude = 1e-3;
573 let omega = field_amplitude * 2.0 * std::f64::consts::PI;
574 let duration = angle / omega;
575
576 system.apply_magnetic_pulse(
577 &[dot_id],
578 field_amplitude,
579 duration,
580 std::f64::consts::PI / 2.0,
581 )
582 }
583
584 pub fn spin_z_rotation(
586 system: &mut SiliconQuantumDotSystem,
587 dot_id: usize,
588 angle: f64,
589 ) -> QuantRS2Result<()> {
590 if dot_id >= system.num_dots {
591 return Err(QuantRS2Error::InvalidInput(
592 "Dot ID out of bounds".to_string(),
593 ));
594 }
595
596 let dot = &mut system.dots[dot_id];
598 let phase_factor = Complex64::new(0.0, angle / 2.0).exp();
599
600 dot.state[0] *= phase_factor.conj();
601 dot.state[1] *= phase_factor;
602
603 Ok(())
604 }
605
606 pub fn hadamard(system: &mut SiliconQuantumDotSystem, dot_id: usize) -> QuantRS2Result<()> {
608 if dot_id >= system.num_dots {
609 return Err(QuantRS2Error::InvalidInput(
610 "Dot ID out of bounds".to_string(),
611 ));
612 }
613
614 let dot = &mut system.dots[dot_id];
615 if dot.dot_type == QuantumDotType::SpinQubit && dot.state.len() == 2 {
616 let old_state = dot.state.clone();
618 let inv_sqrt2 = 1.0 / std::f64::consts::SQRT_2;
619
620 dot.state[0] = inv_sqrt2 * (old_state[0] + old_state[1]);
621 dot.state[1] = inv_sqrt2 * (old_state[0] - old_state[1]);
622 }
623
624 Ok(())
625 }
626
627 pub fn cnot(
629 system: &mut SiliconQuantumDotSystem,
630 control: usize,
631 target: usize,
632 ) -> QuantRS2Result<()> {
633 if control >= system.num_dots || target >= system.num_dots {
634 return Err(QuantRS2Error::InvalidInput(
635 "Dot ID out of bounds".to_string(),
636 ));
637 }
638
639 let control_state = &system.dots[control].state;
642 let control_prob_1 = control_state[1].norm_sqr();
643
644 if control_prob_1 > 0.5 {
646 Self::spin_x_rotation(system, target, std::f64::consts::PI)?;
647 }
648
649 Ok(())
650 }
651
652 pub fn cz(
654 system: &mut SiliconQuantumDotSystem,
655 control: usize,
656 target: usize,
657 ) -> QuantRS2Result<()> {
658 if control >= system.num_dots || target >= system.num_dots {
659 return Err(QuantRS2Error::InvalidInput(
660 "Dot ID out of bounds".to_string(),
661 ));
662 }
663
664 let exchange_strength = system.coupling_matrix[[control, target]];
665 let gate_time = std::f64::consts::PI / (4.0 * exchange_strength / (6.582e-16));
666
667 system.apply_exchange_interaction(control, target, gate_time)
668 }
669
670 pub fn swap(
672 system: &mut SiliconQuantumDotSystem,
673 dot1: usize,
674 dot2: usize,
675 ) -> QuantRS2Result<()> {
676 if dot1 >= system.num_dots || dot2 >= system.num_dots {
677 return Err(QuantRS2Error::InvalidInput(
678 "Dot ID out of bounds".to_string(),
679 ));
680 }
681
682 let exchange_strength = system.coupling_matrix[[dot1, dot2]];
683 let gate_time = std::f64::consts::PI / (2.0 * exchange_strength / (6.582e-16));
684
685 system.apply_exchange_interaction(dot1, dot2, gate_time)
686 }
687
688 pub fn toffoli(
690 system: &mut SiliconQuantumDotSystem,
691 control1: usize,
692 control2: usize,
693 target: usize,
694 ) -> QuantRS2Result<()> {
695 Self::hadamard(system, target)?;
697 Self::cnot(system, control2, target)?;
698 Self::spin_z_rotation(system, target, -std::f64::consts::PI / 4.0)?;
699 Self::cnot(system, control1, target)?;
700 Self::spin_z_rotation(system, target, std::f64::consts::PI / 4.0)?;
701 Self::cnot(system, control2, target)?;
702 Self::spin_z_rotation(system, target, -std::f64::consts::PI / 4.0)?;
703 Self::cnot(system, control1, target)?;
704 Self::spin_z_rotation(system, control1, std::f64::consts::PI / 4.0)?;
705 Self::spin_z_rotation(system, control2, std::f64::consts::PI / 4.0)?;
706 Self::spin_z_rotation(system, target, std::f64::consts::PI / 4.0)?;
707 Self::hadamard(system, target)?;
708 Self::cnot(system, control1, control2)?;
709 Self::spin_z_rotation(system, control1, std::f64::consts::PI / 4.0)?;
710 Self::spin_z_rotation(system, control2, -std::f64::consts::PI / 4.0)?;
711 Self::cnot(system, control1, control2)
712 }
713}
714
715#[cfg(test)]
716mod tests {
717 use super::*;
718
719 #[test]
720 fn test_quantum_dot_params() {
721 let params = QuantumDotParams::typical_silicon_dot();
722 assert!(params.diameter > 0.0);
723 assert!(params.coherence_time() > 0.0);
724 assert!(params.single_qubit_gate_time() > 0.0);
725 assert!(params.two_qubit_gate_time() > 0.0);
726 }
727
728 #[test]
729 fn test_silicon_quantum_dot_creation() {
730 let params = QuantumDotParams::typical_silicon_dot();
731 let dot = SiliconQuantumDot::new(0, QuantumDotType::SpinQubit, params, [0.0, 0.0]);
732
733 assert_eq!(dot.dot_id, 0);
734 assert_eq!(dot.dot_type, QuantumDotType::SpinQubit);
735 assert_eq!(dot.state.len(), 2);
736 assert!((dot.state[0] - Complex64::new(1.0, 0.0)).norm() < 1e-10);
737 }
738
739 #[test]
740 fn test_quantum_dot_system() {
741 let params = QuantumDotParams::typical_silicon_dot();
742 let device_params = DeviceParams::typical_silicon_device();
743
744 let dot_configs = vec![
745 (QuantumDotType::SpinQubit, params.clone(), [0.0, 0.0]),
746 (QuantumDotType::SpinQubit, params, [100.0, 0.0]), ];
748
749 let mut system = SiliconQuantumDotSystem::new(dot_configs, device_params);
750 assert_eq!(system.num_dots, 2);
751
752 system
753 .calculate_distance_coupling()
754 .expect("distance coupling calculation should succeed");
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 .expect("magnetic pulse application should succeed");
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
803 .set_coupling(0, 1, 1e-6)
804 .expect("set_coupling should succeed"); let duration = 1e-9; system
809 .apply_exchange_interaction(0, 1, duration)
810 .expect("exchange interaction should succeed");
811
812 let state1 = system.dots[0].get_probabilities();
814 let state2 = system.dots[1].get_probabilities();
815
816 assert!(state1.len() == 2);
817 assert!(state2.len() == 2);
818 }
819
820 #[test]
821 fn test_measurement() {
822 let params = QuantumDotParams::typical_silicon_dot();
823 let device_params = DeviceParams::typical_silicon_device();
824 let dot_configs = vec![(QuantumDotType::SpinQubit, params, [0.0, 0.0])];
825
826 let mut system = SiliconQuantumDotSystem::new(dot_configs, device_params);
827
828 system.dots[0].state[0] = Complex64::new(1.0 / 2.0_f64.sqrt(), 0.0);
830 system.dots[0].state[1] = Complex64::new(1.0 / 2.0_f64.sqrt(), 0.0);
831
832 let result = system.dots[0]
833 .measure()
834 .expect("measurement should succeed");
835 assert!(result == 0 || result == 1);
836
837 let probs = system.dots[0].get_probabilities();
839 assert!(probs[result] > 0.99);
840 }
841
842 #[test]
843 fn test_silicon_gates() {
844 let params = QuantumDotParams::typical_silicon_dot();
845 let device_params = DeviceParams::typical_silicon_device();
846 let dot_configs = vec![(QuantumDotType::SpinQubit, params, [0.0, 0.0])];
847
848 let mut system = SiliconQuantumDotSystem::new(dot_configs, device_params);
849
850 SiliconQuantumDotGates::spin_x_rotation(&mut system, 0, std::f64::consts::PI)
852 .expect("spin X rotation should succeed");
853 let probs = system.dots[0].get_probabilities();
854 assert!(probs[1] > 0.8); SiliconQuantumDotGates::hadamard(&mut system, 0).expect("hadamard gate should succeed");
858 let probs = system.dots[0].get_probabilities();
859 assert!(probs[0] > 0.05 && probs[0] < 0.95); }
861
862 #[test]
863 fn test_cnot_gate() {
864 let params = QuantumDotParams::typical_silicon_dot();
865 let device_params = DeviceParams::typical_silicon_device();
866
867 let dot_configs = vec![
868 (QuantumDotType::SpinQubit, params.clone(), [0.0, 0.0]),
869 (QuantumDotType::SpinQubit, params, [50.0, 0.0]),
870 ];
871
872 let mut system = SiliconQuantumDotSystem::new(dot_configs, device_params);
873 system
874 .set_coupling(0, 1, 1e-3)
875 .expect("set_coupling should succeed"); SiliconQuantumDotGates::spin_x_rotation(&mut system, 0, std::f64::consts::PI)
879 .expect("spin X rotation should succeed");
880
881 SiliconQuantumDotGates::cnot(&mut system, 0, 1).expect("CNOT gate should succeed");
883
884 let target_probs = system.dots[1].get_probabilities();
886 assert!(target_probs[1] > 0.1); }
888
889 #[test]
890 fn test_decoherence() {
891 let params = QuantumDotParams::typical_silicon_dot();
892 let device_params = DeviceParams::typical_silicon_device();
893 let dot_configs = vec![(QuantumDotType::SpinQubit, params, [0.0, 0.0])];
894
895 let mut system = SiliconQuantumDotSystem::new(dot_configs, device_params);
896
897 system.dots[0].state[0] = Complex64::new(1.0 / 2.0_f64.sqrt(), 0.0);
899 system.dots[0].state[1] = Complex64::new(1.0 / 2.0_f64.sqrt(), 0.0);
900
901 let initial_state = system.dots[0].state.clone();
902
903 system
905 .apply_decoherence(1e-6)
906 .expect("decoherence application should succeed"); let final_state = system.dots[0].state.clone();
909
910 let diff = &initial_state - &final_state;
912 let state_change = diff.iter().map(|x| x.norm_sqr()).sum::<f64>().sqrt();
913 assert!(state_change.is_finite());
914 }
915
916 #[test]
917 fn test_fidelity_calculation() {
918 let params = QuantumDotParams::typical_silicon_dot();
919 let device_params = DeviceParams::typical_silicon_device();
920 let dot_configs = vec![(QuantumDotType::SpinQubit, params, [0.0, 0.0])];
921
922 let system = SiliconQuantumDotSystem::new(dot_configs, device_params);
923
924 let target_state = vec![vec![Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)]];
926
927 let fidelity = system.calculate_fidelity(&target_state);
928 assert!((fidelity - 1.0).abs() < 1e-10); }
930
931 #[test]
932 fn test_coherence_time_average() {
933 let params = QuantumDotParams::typical_silicon_dot();
934 let device_params = DeviceParams::typical_silicon_device();
935
936 let dot_configs = vec![
937 (QuantumDotType::SpinQubit, params.clone(), [0.0, 0.0]),
938 (QuantumDotType::SpinQubit, params, [50.0, 0.0]),
939 ];
940
941 let system = SiliconQuantumDotSystem::new(dot_configs, device_params);
942
943 let avg_t2 = system.average_coherence_time();
944 assert!(avg_t2 > 0.0);
945 assert!(avg_t2.is_finite());
946 }
947}