1use crate::error::{QuantRS2Error, QuantRS2Result};
8use scirs2_core::ndarray::{Array1, Array2};
9use scirs2_core::Complex64;
10use std::collections::HashMap;
11
12#[derive(Debug, Clone, Copy, PartialEq)]
14pub enum PhotonicGateType {
15 BeamSplitter { reflectivity: f64 },
17 PhaseShifter { phase: f64 },
19 MachZehnder { phase1: f64, phase2: f64 },
21 ControlledZ,
23 ControlledNot,
25 HongOuMandel,
27 PhotonNumber,
29 Homodyne { phase: f64 },
31 Heterodyne,
33}
34
35#[derive(Debug, Clone, Copy, PartialEq)]
37pub enum PhotonicEncoding {
38 DualRail,
40 Polarization,
42 TimeBin,
44 Frequency,
46 ContinuousVariable,
48}
49
50#[derive(Debug, Clone)]
52pub struct OpticalMode {
53 pub mode_id: usize,
55 pub fock_state: Array1<Complex64>,
57 pub max_photons: usize,
59 pub frequency: Option<f64>,
61 pub polarization: Option<String>,
63}
64
65impl OpticalMode {
66 pub fn vacuum(mode_id: usize, max_photons: usize) -> Self {
68 let mut fock_state = Array1::zeros(max_photons + 1);
69 fock_state[0] = Complex64::new(1.0, 0.0); Self {
72 mode_id,
73 fock_state,
74 max_photons,
75 frequency: None,
76 polarization: None,
77 }
78 }
79
80 pub fn single_photon(mode_id: usize, max_photons: usize) -> Self {
82 let mut fock_state = Array1::zeros(max_photons + 1);
83 fock_state[1] = Complex64::new(1.0, 0.0); Self {
86 mode_id,
87 fock_state,
88 max_photons,
89 frequency: None,
90 polarization: None,
91 }
92 }
93
94 pub fn coherent(mode_id: usize, max_photons: usize, alpha: Complex64) -> Self {
96 let mut fock_state = Array1::zeros(max_photons + 1);
97
98 let alpha_norm_sq = alpha.norm_sqr();
100 let prefactor = (-alpha_norm_sq / 2.0).exp();
101
102 let mut factorial = 1.0;
103 for n in 0..=max_photons {
104 if n > 0 {
105 factorial *= n as f64;
106 }
107
108 let coefficient = prefactor * alpha.powf(n as f64) / factorial.sqrt();
109 fock_state[n] = coefficient;
110 }
111
112 Self {
113 mode_id,
114 fock_state,
115 max_photons,
116 frequency: None,
117 polarization: None,
118 }
119 }
120
121 pub fn photon_number_expectation(&self) -> f64 {
123 let mut expectation = 0.0;
124 for n in 0..=self.max_photons {
125 expectation += (n as f64) * self.fock_state[n].norm_sqr();
126 }
127 expectation
128 }
129
130 pub fn photon_probability(&self, n: usize) -> f64 {
132 if n > self.max_photons {
133 0.0
134 } else {
135 self.fock_state[n].norm_sqr()
136 }
137 }
138}
139
140#[derive(Debug, Clone)]
142pub struct PhotonicSystem {
143 pub num_modes: usize,
145 pub modes: Vec<OpticalMode>,
147 pub state: Option<Array1<Complex64>>,
149 pub max_photons_per_mode: usize,
151 pub max_total_photons: usize,
153}
154
155impl PhotonicSystem {
156 pub fn new(num_modes: usize, max_photons_per_mode: usize) -> Self {
158 let modes = (0..num_modes)
159 .map(|i| OpticalMode::vacuum(i, max_photons_per_mode))
160 .collect();
161
162 let max_total_photons = num_modes * max_photons_per_mode;
163
164 Self {
165 num_modes,
166 modes,
167 state: None,
168 max_photons_per_mode,
169 max_total_photons,
170 }
171 }
172
173 pub fn initialize_from_modes(&mut self) -> QuantRS2Result<()> {
175 let total_dim = (self.max_photons_per_mode + 1).pow(self.num_modes as u32);
176 let mut state = Array1::zeros(total_dim);
177
178 state[0] = Complex64::new(1.0, 0.0);
180
181 for (mode_idx, mode) in self.modes.iter().enumerate() {
182 let mut new_state = Array1::zeros(total_dim);
183 let mode_dim = self.max_photons_per_mode + 1;
184
185 for (state_idx, &litude) in state.iter().enumerate() {
186 if amplitude.norm() > 1e-12 {
187 for (n, &mode_amp) in mode.fock_state.iter().enumerate() {
188 if mode_amp.norm() > 1e-12 {
189 let new_idx = state_idx + n * mode_dim.pow(mode_idx as u32);
190 if new_idx < total_dim {
191 new_state[new_idx] += amplitude * mode_amp;
192 }
193 }
194 }
195 }
196 }
197 state = new_state;
198 }
199
200 self.state = Some(state);
201 Ok(())
202 }
203
204 pub fn apply_beam_splitter(
206 &mut self,
207 mode1: usize,
208 mode2: usize,
209 reflectivity: f64,
210 ) -> QuantRS2Result<()> {
211 if mode1 >= self.num_modes || mode2 >= self.num_modes {
212 return Err(QuantRS2Error::InvalidInput(
213 "Mode index out of bounds".to_string(),
214 ));
215 }
216
217 if mode1 == mode2 {
218 return Err(QuantRS2Error::InvalidInput(
219 "Cannot apply beam splitter to same mode".to_string(),
220 ));
221 }
222
223 let r = reflectivity;
227 let t = (1.0 - r).sqrt();
228 let r_sqrt = r.sqrt();
229
230 let mode1_state = self.modes[mode1].fock_state.clone();
232 let mode2_state = self.modes[mode2].fock_state.clone();
233
234 let mut new_mode1_state = Array1::zeros(self.max_photons_per_mode + 1);
235 let mut new_mode2_state = Array1::zeros(self.max_photons_per_mode + 1);
236
237 for n in 0..=self.max_photons_per_mode {
240 new_mode1_state[n] = r_sqrt * mode1_state[n] + t * mode2_state[n];
241 new_mode2_state[n] = t * mode1_state[n] - r_sqrt * mode2_state[n];
242 }
243
244 self.modes[mode1].fock_state = new_mode1_state;
245 self.modes[mode2].fock_state = new_mode2_state;
246
247 self.initialize_from_modes()?;
249
250 Ok(())
251 }
252
253 pub fn apply_phase_shifter(&mut self, mode: usize, phase: f64) -> QuantRS2Result<()> {
255 if mode >= self.num_modes {
256 return Err(QuantRS2Error::InvalidInput(
257 "Mode index out of bounds".to_string(),
258 ));
259 }
260
261 for n in 0..=self.max_photons_per_mode {
263 let phase_factor = Complex64::new(0.0, (n as f64) * phase).exp();
264 self.modes[mode].fock_state[n] *= phase_factor;
265 }
266
267 self.initialize_from_modes()?;
269
270 Ok(())
271 }
272
273 pub fn measure_photon_number(&mut self, mode: usize) -> QuantRS2Result<usize> {
275 if mode >= self.num_modes {
276 return Err(QuantRS2Error::InvalidInput(
277 "Mode index out of bounds".to_string(),
278 ));
279 }
280
281 let probabilities: Vec<f64> = (0..=self.max_photons_per_mode)
283 .map(|n| self.modes[mode].photon_probability(n))
284 .collect();
285
286 use scirs2_core::random::prelude::*;
288 let mut rng = thread_rng();
289 let random_value: f64 = rng.gen();
290 let mut cumulative = 0.0;
291
292 for (n, &prob) in probabilities.iter().enumerate() {
293 cumulative += prob;
294 if random_value <= cumulative {
295 let mut new_state = Array1::zeros(self.max_photons_per_mode + 1);
297 new_state[n] = Complex64::new(1.0, 0.0);
298 self.modes[mode].fock_state = new_state;
299
300 self.initialize_from_modes()?;
301 return Ok(n);
302 }
303 }
304
305 Ok(self.max_photons_per_mode)
307 }
308
309 pub fn homodyne_measurement(&mut self, mode: usize, phase: f64) -> QuantRS2Result<f64> {
311 if mode >= self.num_modes {
312 return Err(QuantRS2Error::InvalidInput(
313 "Mode index out of bounds".to_string(),
314 ));
315 }
316
317 let expectation = self.quadrature_expectation(mode, phase)?;
320
321 use scirs2_core::random::prelude::*;
323 let mut rng = thread_rng();
324 let noise = rng.gen_range(-0.1..0.1); Ok(expectation + noise)
327 }
328
329 fn quadrature_expectation(&self, mode: usize, phase: f64) -> QuantRS2Result<f64> {
331 let photon_expectation = self.modes[mode].photon_number_expectation();
333 Ok(photon_expectation.sqrt() * phase.cos())
334 }
335}
336
337#[derive(Debug, Clone)]
339pub struct PhotonicGate {
340 pub gate_type: PhotonicGateType,
342 pub target_modes: Vec<usize>,
344 pub parameters: HashMap<String, f64>,
346}
347
348impl PhotonicGate {
349 pub fn beam_splitter(mode1: usize, mode2: usize, reflectivity: f64) -> Self {
351 Self {
352 gate_type: PhotonicGateType::BeamSplitter { reflectivity },
353 target_modes: vec![mode1, mode2],
354 parameters: {
355 let mut params = HashMap::new();
356 params.insert("reflectivity".to_string(), reflectivity);
357 params
358 },
359 }
360 }
361
362 pub fn phase_shifter(mode: usize, phase: f64) -> Self {
364 Self {
365 gate_type: PhotonicGateType::PhaseShifter { phase },
366 target_modes: vec![mode],
367 parameters: {
368 let mut params = HashMap::new();
369 params.insert("phase".to_string(), phase);
370 params
371 },
372 }
373 }
374
375 pub fn mach_zehnder(mode1: usize, mode2: usize, phase1: f64, phase2: f64) -> Self {
377 Self {
378 gate_type: PhotonicGateType::MachZehnder { phase1, phase2 },
379 target_modes: vec![mode1, mode2],
380 parameters: {
381 let mut params = HashMap::new();
382 params.insert("phase1".to_string(), phase1);
383 params.insert("phase2".to_string(), phase2);
384 params
385 },
386 }
387 }
388
389 pub fn apply(&self, system: &mut PhotonicSystem) -> QuantRS2Result<()> {
391 match self.gate_type {
392 PhotonicGateType::BeamSplitter { reflectivity } => {
393 if self.target_modes.len() != 2 {
394 return Err(QuantRS2Error::InvalidInput(
395 "Beam splitter requires exactly 2 modes".to_string(),
396 ));
397 }
398 system.apply_beam_splitter(self.target_modes[0], self.target_modes[1], reflectivity)
399 }
400 PhotonicGateType::PhaseShifter { phase } => {
401 if self.target_modes.len() != 1 {
402 return Err(QuantRS2Error::InvalidInput(
403 "Phase shifter requires exactly 1 mode".to_string(),
404 ));
405 }
406 system.apply_phase_shifter(self.target_modes[0], phase)
407 }
408 PhotonicGateType::MachZehnder { phase1, phase2 } => {
409 if self.target_modes.len() != 2 {
410 return Err(QuantRS2Error::InvalidInput(
411 "Mach-Zehnder requires exactly 2 modes".to_string(),
412 ));
413 }
414 system.apply_beam_splitter(self.target_modes[0], self.target_modes[1], 0.5)?;
416 system.apply_phase_shifter(self.target_modes[0], phase1)?;
417 system.apply_phase_shifter(self.target_modes[1], phase2)?;
418 system.apply_beam_splitter(self.target_modes[0], self.target_modes[1], 0.5)
419 }
420 PhotonicGateType::ControlledZ => {
421 if self.target_modes.len() != 2 {
423 return Err(QuantRS2Error::InvalidInput(
424 "Controlled-Z requires exactly 2 modes".to_string(),
425 ));
426 }
427 system.apply_phase_shifter(self.target_modes[1], std::f64::consts::PI)
429 }
430 PhotonicGateType::ControlledNot => {
431 if self.target_modes.len() != 2 {
433 return Err(QuantRS2Error::InvalidInput(
434 "Controlled-NOT requires exactly 2 modes".to_string(),
435 ));
436 }
437 system.apply_beam_splitter(self.target_modes[0], self.target_modes[1], 0.5)
439 }
440 _ => Err(QuantRS2Error::InvalidInput(
441 "Gate type not yet implemented".to_string(),
442 )),
443 }
444 }
445}
446
447#[derive(Debug, Clone)]
449pub struct PhotonicCircuit {
450 pub num_modes: usize,
452 pub gates: Vec<PhotonicGate>,
454 pub max_photons_per_mode: usize,
456}
457
458impl PhotonicCircuit {
459 pub fn new(num_modes: usize, max_photons_per_mode: usize) -> Self {
461 Self {
462 num_modes,
463 gates: Vec::new(),
464 max_photons_per_mode,
465 }
466 }
467
468 pub fn add_gate(&mut self, gate: PhotonicGate) -> QuantRS2Result<()> {
470 for &mode in &gate.target_modes {
472 if mode >= self.num_modes {
473 return Err(QuantRS2Error::InvalidInput(
474 "Gate target mode out of bounds".to_string(),
475 ));
476 }
477 }
478
479 self.gates.push(gate);
480 Ok(())
481 }
482
483 pub fn execute(&self, system: &mut PhotonicSystem) -> QuantRS2Result<()> {
485 if system.num_modes != self.num_modes {
486 return Err(QuantRS2Error::InvalidInput(
487 "System and circuit mode count mismatch".to_string(),
488 ));
489 }
490
491 for gate in &self.gates {
492 gate.apply(system)?;
493 }
494
495 Ok(())
496 }
497
498 pub fn optimize_linear_optics(&mut self) -> QuantRS2Result<()> {
500 let mut optimized_gates = Vec::new();
502 let mut i = 0;
503
504 while i < self.gates.len() {
505 let current_gate = &self.gates[i];
506
507 if let PhotonicGateType::PhaseShifter { phase } = current_gate.gate_type {
508 let mode = current_gate.target_modes[0];
509 let mut total_phase = phase;
510 let mut j = i + 1;
511
512 while j < self.gates.len() {
514 if let PhotonicGateType::PhaseShifter { phase: next_phase } =
515 self.gates[j].gate_type
516 {
517 if self.gates[j].target_modes[0] == mode {
518 total_phase += next_phase;
519 j += 1;
520 } else {
521 break;
522 }
523 } else {
524 break;
525 }
526 }
527
528 if (total_phase % (2.0 * std::f64::consts::PI)).abs() > 1e-10 {
530 optimized_gates.push(PhotonicGate::phase_shifter(mode, total_phase));
531 }
532
533 i = j;
534 } else {
535 optimized_gates.push(current_gate.clone());
536 i += 1;
537 }
538 }
539
540 self.gates = optimized_gates;
541 Ok(())
542 }
543
544 pub fn to_matrix(&self) -> QuantRS2Result<Array2<Complex64>> {
546 let dim = (self.max_photons_per_mode + 1).pow(self.num_modes as u32);
547 let mut matrix = Array2::eye(dim);
548
549 for gate in &self.gates {
550 let gate_matrix = self.gate_to_matrix(gate)?;
551 matrix = gate_matrix.dot(&matrix);
552 }
553
554 Ok(matrix)
555 }
556
557 fn gate_to_matrix(&self, gate: &PhotonicGate) -> QuantRS2Result<Array2<Complex64>> {
559 let dim = (self.max_photons_per_mode + 1).pow(self.num_modes as u32);
560
561 match gate.gate_type {
562 PhotonicGateType::PhaseShifter { phase } => {
563 let mut matrix = Array2::eye(dim);
564 let mode = gate.target_modes[0];
565
566 for i in 0..dim {
568 let photon_count = self.extract_photon_count(i, mode);
569 let phase_factor = Complex64::new(0.0, (photon_count as f64) * phase).exp();
570 matrix[[i, i]] = phase_factor;
571 }
572
573 Ok(matrix)
574 }
575 _ => {
576 Ok(Array2::eye(dim))
578 }
579 }
580 }
581
582 fn extract_photon_count(&self, state_index: usize, mode: usize) -> usize {
584 let mode_dim = self.max_photons_per_mode + 1;
585 (state_index / mode_dim.pow(mode as u32)) % mode_dim
586 }
587}
588
589#[derive(Debug, Clone)]
591pub struct PhotonicErrorCorrection {
592 pub physical_modes_per_logical: usize,
594 pub code_type: String,
596 pub syndrome_circuits: Vec<PhotonicCircuit>,
598}
599
600impl PhotonicErrorCorrection {
601 pub fn repetition_code(num_repetitions: usize) -> Self {
603 Self {
604 physical_modes_per_logical: num_repetitions,
605 code_type: "Repetition".to_string(),
606 syndrome_circuits: Vec::new(),
607 }
608 }
609
610 pub fn encode_logical_qubit(
612 &self,
613 logical_state: &[Complex64; 2],
614 system: &mut PhotonicSystem,
615 ) -> QuantRS2Result<()> {
616 for i in 0..self.physical_modes_per_logical {
618 system.modes[i].fock_state[0] = logical_state[0];
619 system.modes[i].fock_state[1] = logical_state[1];
620 }
621
622 system.initialize_from_modes()?;
623 Ok(())
624 }
625
626 pub fn correct_errors(&self, system: &mut PhotonicSystem) -> QuantRS2Result<Vec<usize>> {
628 let mut corrections = Vec::new();
630
631 for i in 0..self.physical_modes_per_logical {
633 let photon_prob = system.modes[i].photon_probability(1);
634 if photon_prob > 0.5 {
635 corrections.push(i);
636 }
637 }
638
639 Ok(corrections)
640 }
641}
642
643#[cfg(test)]
644mod tests {
645 use super::*;
646
647 #[test]
648 fn test_optical_mode_creation() {
649 let vacuum = OpticalMode::vacuum(0, 5);
650 assert_eq!(vacuum.mode_id, 0);
651 assert_eq!(vacuum.max_photons, 5);
652 assert!((vacuum.fock_state[0] - Complex64::new(1.0, 0.0)).norm() < 1e-10);
653 assert!(vacuum.photon_number_expectation() < 1e-10);
654
655 let single_photon = OpticalMode::single_photon(1, 5);
656 assert!((single_photon.photon_number_expectation() - 1.0).abs() < 1e-10);
657 }
658
659 #[test]
660 fn test_coherent_state() {
661 let alpha = Complex64::new(1.0, 0.0);
662 let coherent = OpticalMode::coherent(0, 10, alpha);
663
664 assert!((coherent.photon_number_expectation() - 1.0).abs() < 0.1);
666 }
667
668 #[test]
669 fn test_photonic_system_initialization() {
670 let mut system = PhotonicSystem::new(3, 2);
671 assert_eq!(system.num_modes, 3);
672 assert_eq!(system.max_photons_per_mode, 2);
673
674 system.initialize_from_modes().unwrap();
675 assert!(system.state.is_some());
676 }
677
678 #[test]
679 fn test_beam_splitter() {
680 let mut system = PhotonicSystem::new(2, 3);
681
682 system.modes[0] = OpticalMode::single_photon(0, 3);
684 system.initialize_from_modes().unwrap();
685
686 system.apply_beam_splitter(0, 1, 0.5).unwrap();
688
689 let prob0 = system.modes[0].photon_probability(1);
691 let prob1 = system.modes[1].photon_probability(1);
692 assert!(prob0 > 0.0);
693 assert!(prob1 > 0.0);
694 }
695
696 #[test]
697 fn test_phase_shifter() {
698 let mut system = PhotonicSystem::new(1, 3);
699
700 system.modes[0] = OpticalMode::single_photon(0, 3);
702 system.initialize_from_modes().unwrap();
703
704 let phase = std::f64::consts::PI / 2.0;
706 system.apply_phase_shifter(0, phase).unwrap();
707
708 assert!((system.modes[0].photon_number_expectation() - 1.0).abs() < 1e-10);
710
711 let expected_phase = Complex64::new(0.0, phase).exp();
713 assert!((system.modes[0].fock_state[1] - expected_phase).norm() < 1e-10);
714 }
715
716 #[test]
717 fn test_photonic_gate_creation() {
718 let bs_gate = PhotonicGate::beam_splitter(0, 1, 0.3);
719 assert_eq!(bs_gate.target_modes, vec![0, 1]);
720 assert!((bs_gate.parameters["reflectivity"] - 0.3).abs() < 1e-10);
721
722 let ps_gate = PhotonicGate::phase_shifter(0, std::f64::consts::PI);
723 assert_eq!(ps_gate.target_modes, vec![0]);
724 assert!((ps_gate.parameters["phase"] - std::f64::consts::PI).abs() < 1e-10);
725 }
726
727 #[test]
728 fn test_photonic_circuit() {
729 let mut circuit = PhotonicCircuit::new(2, 2);
730
731 let bs_gate = PhotonicGate::beam_splitter(0, 1, 0.5);
732 let ps_gate = PhotonicGate::phase_shifter(0, std::f64::consts::PI / 4.0);
733
734 circuit.add_gate(bs_gate).unwrap();
735 circuit.add_gate(ps_gate).unwrap();
736
737 assert_eq!(circuit.gates.len(), 2);
738
739 let mut system = PhotonicSystem::new(2, 2);
740 circuit.execute(&mut system).unwrap();
741 }
742
743 #[test]
744 fn test_mach_zehnder_interferometer() {
745 let mut system = PhotonicSystem::new(2, 2);
746
747 system.modes[0] = OpticalMode::single_photon(0, 2);
749 system.initialize_from_modes().unwrap();
750
751 let mz_gate = PhotonicGate::mach_zehnder(0, 1, 0.0, std::f64::consts::PI);
753 mz_gate.apply(&mut system).unwrap();
754
755 let prob0 = system.modes[0].photon_probability(1);
757 let prob1 = system.modes[1].photon_probability(1);
758 assert!((prob0 + prob1 - 1.0).abs() < 1e-10);
759 }
760
761 #[test]
762 fn test_photon_number_measurement() {
763 let mut system = PhotonicSystem::new(1, 3);
764
765 system.modes[0] = OpticalMode::single_photon(0, 3);
767 system.initialize_from_modes().unwrap();
768
769 let measurement_result = system.measure_photon_number(0).unwrap();
770
771 assert_eq!(measurement_result, 1);
773
774 assert!((system.modes[0].photon_probability(1) - 1.0).abs() < 1e-10);
776 }
777
778 #[test]
779 fn test_homodyne_measurement() {
780 let mut system = PhotonicSystem::new(1, 3);
781
782 let alpha = Complex64::new(2.0, 0.0);
784 system.modes[0] = OpticalMode::coherent(0, 3, alpha);
785 system.initialize_from_modes().unwrap();
786
787 let measurement_result = system.homodyne_measurement(0, 0.0).unwrap();
788
789 assert!(measurement_result.is_finite());
791 }
792
793 #[test]
794 fn test_circuit_optimization() {
795 let mut circuit = PhotonicCircuit::new(2, 2);
796
797 circuit
799 .add_gate(PhotonicGate::phase_shifter(0, std::f64::consts::PI / 4.0))
800 .unwrap();
801 circuit
802 .add_gate(PhotonicGate::phase_shifter(0, std::f64::consts::PI / 4.0))
803 .unwrap();
804 circuit
805 .add_gate(PhotonicGate::phase_shifter(0, std::f64::consts::PI / 2.0))
806 .unwrap();
807
808 assert_eq!(circuit.gates.len(), 3);
809
810 circuit.optimize_linear_optics().unwrap();
811
812 assert_eq!(circuit.gates.len(), 1);
814 if let PhotonicGateType::PhaseShifter { phase } = circuit.gates[0].gate_type {
815 assert!((phase - std::f64::consts::PI).abs() < 1e-10);
816 }
817 }
818
819 #[test]
820 fn test_photonic_error_correction() {
821 let error_correction = PhotonicErrorCorrection::repetition_code(3);
822 assert_eq!(error_correction.physical_modes_per_logical, 3);
823 assert_eq!(error_correction.code_type, "Repetition");
824
825 let mut system = PhotonicSystem::new(3, 2);
826 let logical_state = [Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)]; error_correction
829 .encode_logical_qubit(&logical_state, &mut system)
830 .unwrap();
831
832 let corrections = error_correction.correct_errors(&mut system).unwrap();
833 assert!(corrections.len() <= 3);
834 }
835}