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, Eq)]
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.random();
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.random_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 const 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 other => {
576 Err(QuantRS2Error::UnsupportedOperation(format!(
581 "photonic gate matrix not implemented for {other:?}"
582 )))
583 }
584 }
585 }
586
587 const fn extract_photon_count(&self, state_index: usize, mode: usize) -> usize {
589 let mode_dim = self.max_photons_per_mode + 1;
590 (state_index / mode_dim.pow(mode as u32)) % mode_dim
591 }
592}
593
594#[derive(Debug, Clone)]
596pub struct PhotonicErrorCorrection {
597 pub physical_modes_per_logical: usize,
599 pub code_type: String,
601 pub syndrome_circuits: Vec<PhotonicCircuit>,
603}
604
605impl PhotonicErrorCorrection {
606 pub fn repetition_code(num_repetitions: usize) -> Self {
608 Self {
609 physical_modes_per_logical: num_repetitions,
610 code_type: "Repetition".to_string(),
611 syndrome_circuits: Vec::new(),
612 }
613 }
614
615 pub fn encode_logical_qubit(
617 &self,
618 logical_state: &[Complex64; 2],
619 system: &mut PhotonicSystem,
620 ) -> QuantRS2Result<()> {
621 for i in 0..self.physical_modes_per_logical {
623 system.modes[i].fock_state[0] = logical_state[0];
624 system.modes[i].fock_state[1] = logical_state[1];
625 }
626
627 system.initialize_from_modes()?;
628 Ok(())
629 }
630
631 pub fn correct_errors(&self, system: &mut PhotonicSystem) -> QuantRS2Result<Vec<usize>> {
633 let mut corrections = Vec::new();
635
636 for i in 0..self.physical_modes_per_logical {
638 let photon_prob = system.modes[i].photon_probability(1);
639 if photon_prob > 0.5 {
640 corrections.push(i);
641 }
642 }
643
644 Ok(corrections)
645 }
646}
647
648#[cfg(test)]
649mod tests {
650 use super::*;
651
652 #[test]
653 fn test_optical_mode_creation() {
654 let vacuum = OpticalMode::vacuum(0, 5);
655 assert_eq!(vacuum.mode_id, 0);
656 assert_eq!(vacuum.max_photons, 5);
657 assert!((vacuum.fock_state[0] - Complex64::new(1.0, 0.0)).norm() < 1e-10);
658 assert!(vacuum.photon_number_expectation() < 1e-10);
659
660 let single_photon = OpticalMode::single_photon(1, 5);
661 assert!((single_photon.photon_number_expectation() - 1.0).abs() < 1e-10);
662 }
663
664 #[test]
665 fn test_coherent_state() {
666 let alpha = Complex64::new(1.0, 0.0);
667 let coherent = OpticalMode::coherent(0, 10, alpha);
668
669 assert!((coherent.photon_number_expectation() - 1.0).abs() < 0.1);
671 }
672
673 #[test]
674 fn test_photonic_system_initialization() {
675 let mut system = PhotonicSystem::new(3, 2);
676 assert_eq!(system.num_modes, 3);
677 assert_eq!(system.max_photons_per_mode, 2);
678
679 system
680 .initialize_from_modes()
681 .expect("Failed to initialize from modes");
682 assert!(system.state.is_some());
683 }
684
685 #[test]
686 fn test_beam_splitter() {
687 let mut system = PhotonicSystem::new(2, 3);
688
689 system.modes[0] = OpticalMode::single_photon(0, 3);
691 system
692 .initialize_from_modes()
693 .expect("Failed to initialize from modes");
694
695 system
697 .apply_beam_splitter(0, 1, 0.5)
698 .expect("Failed to apply beam splitter");
699
700 let prob0 = system.modes[0].photon_probability(1);
702 let prob1 = system.modes[1].photon_probability(1);
703 assert!(prob0 > 0.0);
704 assert!(prob1 > 0.0);
705 }
706
707 #[test]
708 fn test_phase_shifter() {
709 let mut system = PhotonicSystem::new(1, 3);
710
711 system.modes[0] = OpticalMode::single_photon(0, 3);
713 system
714 .initialize_from_modes()
715 .expect("Failed to initialize from modes");
716
717 let phase = std::f64::consts::PI / 2.0;
719 system
720 .apply_phase_shifter(0, phase)
721 .expect("Failed to apply phase shifter");
722
723 assert!((system.modes[0].photon_number_expectation() - 1.0).abs() < 1e-10);
725
726 let expected_phase = Complex64::new(0.0, phase).exp();
728 assert!((system.modes[0].fock_state[1] - expected_phase).norm() < 1e-10);
729 }
730
731 #[test]
732 fn test_photonic_gate_creation() {
733 let bs_gate = PhotonicGate::beam_splitter(0, 1, 0.3);
734 assert_eq!(bs_gate.target_modes, vec![0, 1]);
735 assert!((bs_gate.parameters["reflectivity"] - 0.3).abs() < 1e-10);
736
737 let ps_gate = PhotonicGate::phase_shifter(0, std::f64::consts::PI);
738 assert_eq!(ps_gate.target_modes, vec![0]);
739 assert!((ps_gate.parameters["phase"] - std::f64::consts::PI).abs() < 1e-10);
740 }
741
742 #[test]
743 fn test_photonic_circuit() {
744 let mut circuit = PhotonicCircuit::new(2, 2);
745
746 let bs_gate = PhotonicGate::beam_splitter(0, 1, 0.5);
747 let ps_gate = PhotonicGate::phase_shifter(0, std::f64::consts::PI / 4.0);
748
749 circuit
750 .add_gate(bs_gate)
751 .expect("Failed to add beam splitter gate");
752 circuit
753 .add_gate(ps_gate)
754 .expect("Failed to add phase shifter gate");
755
756 assert_eq!(circuit.gates.len(), 2);
757
758 let mut system = PhotonicSystem::new(2, 2);
759 circuit
760 .execute(&mut system)
761 .expect("Failed to execute circuit");
762 }
763
764 #[test]
765 fn test_mach_zehnder_interferometer() {
766 let mut system = PhotonicSystem::new(2, 2);
767
768 system.modes[0] = OpticalMode::single_photon(0, 2);
770 system
771 .initialize_from_modes()
772 .expect("Failed to initialize from modes");
773
774 let mz_gate = PhotonicGate::mach_zehnder(0, 1, 0.0, std::f64::consts::PI);
776 mz_gate
777 .apply(&mut system)
778 .expect("Failed to apply Mach-Zehnder gate");
779
780 let prob0 = system.modes[0].photon_probability(1);
782 let prob1 = system.modes[1].photon_probability(1);
783 assert!((prob0 + prob1 - 1.0).abs() < 1e-10);
784 }
785
786 #[test]
787 fn test_photon_number_measurement() {
788 let mut system = PhotonicSystem::new(1, 3);
789
790 system.modes[0] = OpticalMode::single_photon(0, 3);
792 system
793 .initialize_from_modes()
794 .expect("Failed to initialize from modes");
795
796 let measurement_result = system
797 .measure_photon_number(0)
798 .expect("Failed to measure photon number");
799
800 assert_eq!(measurement_result, 1);
802
803 assert!((system.modes[0].photon_probability(1) - 1.0).abs() < 1e-10);
805 }
806
807 #[test]
808 fn test_homodyne_measurement() {
809 let mut system = PhotonicSystem::new(1, 3);
810
811 let alpha = Complex64::new(2.0, 0.0);
813 system.modes[0] = OpticalMode::coherent(0, 3, alpha);
814 system
815 .initialize_from_modes()
816 .expect("Failed to initialize from modes");
817
818 let measurement_result = system
819 .homodyne_measurement(0, 0.0)
820 .expect("Failed homodyne measurement");
821
822 assert!(measurement_result.is_finite());
824 }
825
826 #[test]
827 fn test_circuit_optimization() {
828 let mut circuit = PhotonicCircuit::new(2, 2);
829
830 circuit
832 .add_gate(PhotonicGate::phase_shifter(0, std::f64::consts::PI / 4.0))
833 .expect("Failed to add first phase shifter");
834 circuit
835 .add_gate(PhotonicGate::phase_shifter(0, std::f64::consts::PI / 4.0))
836 .expect("Failed to add second phase shifter");
837 circuit
838 .add_gate(PhotonicGate::phase_shifter(0, std::f64::consts::PI / 2.0))
839 .expect("Failed to add third phase shifter");
840
841 assert_eq!(circuit.gates.len(), 3);
842
843 circuit
844 .optimize_linear_optics()
845 .expect("Failed to optimize linear optics");
846
847 assert_eq!(circuit.gates.len(), 1);
849 if let PhotonicGateType::PhaseShifter { phase } = circuit.gates[0].gate_type {
850 assert!((phase - std::f64::consts::PI).abs() < 1e-10);
851 }
852 }
853
854 #[test]
855 fn test_photonic_error_correction() {
856 let error_correction = PhotonicErrorCorrection::repetition_code(3);
857 assert_eq!(error_correction.physical_modes_per_logical, 3);
858 assert_eq!(error_correction.code_type, "Repetition");
859
860 let mut system = PhotonicSystem::new(3, 2);
861 let logical_state = [Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0)]; error_correction
864 .encode_logical_qubit(&logical_state, &mut system)
865 .expect("Failed to encode logical qubit");
866
867 let corrections = error_correction
868 .correct_errors(&mut system)
869 .expect("Failed to correct errors");
870 assert!(corrections.len() <= 3);
871 }
872
873 #[test]
874 fn test_to_matrix_phase_shifter_supported() {
875 let mut circuit = PhotonicCircuit::new(2, 2);
877 circuit
878 .add_gate(PhotonicGate::phase_shifter(0, std::f64::consts::PI / 3.0))
879 .expect("adding phase shifter should succeed");
880 let matrix = circuit
881 .to_matrix()
882 .expect("to_matrix for phase shifter should succeed");
883 assert_eq!(matrix.shape(), &[9, 9]);
885 }
886
887 #[test]
888 fn test_to_matrix_unsupported_gate_errors_not_identity() {
889 let mut circuit = PhotonicCircuit::new(2, 2);
892 circuit
893 .add_gate(PhotonicGate::beam_splitter(0, 1, 0.5))
894 .expect("adding beam splitter should succeed");
895 let result = circuit.to_matrix();
896 match result {
897 Err(QuantRS2Error::UnsupportedOperation(msg)) => {
898 assert!(
899 msg.contains("BeamSplitter"),
900 "error should name the unsupported gate, got: {msg}"
901 );
902 }
903 other => panic!("expected UnsupportedOperation error, got {other:?}"),
904 }
905 }
906}