1use crate::prelude::SimulatorError;
9use scirs2_core::ndarray::{Array1, Array2};
10use scirs2_core::parallel_ops::{IndexedParallelIterator, ParallelIterator};
11use scirs2_core::Complex64;
12use serde::{Deserialize, Serialize};
13use std::collections::HashMap;
14
15use crate::error::Result;
16use crate::scirs2_integration::SciRS2Backend;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum PhotonicMethod {
21 FockBasis,
23 CoherentBasis,
25 WignerFunction,
27 SciRS2Continuous,
29 TruncatedFock,
31}
32
33#[derive(Debug, Clone)]
35pub struct PhotonicConfig {
36 pub method: PhotonicMethod,
38 pub max_photon_number: usize,
40 pub num_modes: usize,
42 pub precision: f64,
44 pub parallel: bool,
46 pub wigner_grid_size: usize,
48 pub phase_space_range: f64,
50}
51
52impl Default for PhotonicConfig {
53 fn default() -> Self {
54 Self {
55 method: PhotonicMethod::FockBasis,
56 max_photon_number: 20,
57 num_modes: 1,
58 precision: 1e-12,
59 parallel: true,
60 wigner_grid_size: 100,
61 phase_space_range: 5.0,
62 }
63 }
64}
65
66#[derive(Debug, Clone)]
68pub enum PhotonicState {
69 Fock(Array1<Complex64>),
71 Coherent {
73 amplitudes: Vec<Complex64>,
74 basis_states: Vec<FockState>,
75 },
76 Squeezed {
78 amplitudes: Vec<Complex64>,
79 squeezing_params: Vec<Complex64>,
80 basis_states: Vec<FockState>,
81 },
82 Wigner {
84 function_values: Array2<Complex64>,
85 q_grid: Array1<f64>,
86 p_grid: Array1<f64>,
87 },
88}
89
90#[derive(Debug, Clone, PartialEq, Eq, Hash)]
92pub struct FockState {
93 pub photon_numbers: Vec<usize>,
95}
96
97impl FockState {
98 #[must_use]
100 pub const fn new(photon_numbers: Vec<usize>) -> Self {
101 Self { photon_numbers }
102 }
103
104 #[must_use]
106 pub fn vacuum(num_modes: usize) -> Self {
107 Self::new(vec![0; num_modes])
108 }
109
110 #[must_use]
112 pub fn single_photon(mode: usize, num_modes: usize) -> Self {
113 let mut photon_numbers = vec![0; num_modes];
114 photon_numbers[mode] = 1;
115 Self::new(photon_numbers)
116 }
117
118 #[must_use]
120 pub fn total_photons(&self) -> usize {
121 self.photon_numbers.iter().sum()
122 }
123
124 #[must_use]
126 pub fn photons_in_mode(&self, mode: usize) -> usize {
127 self.photon_numbers.get(mode).copied().unwrap_or(0)
128 }
129}
130
131#[derive(Debug, Clone)]
133pub enum PhotonicOperator {
134 Creation(usize), Annihilation(usize), Number(usize), Displacement(usize, Complex64), Squeezing(usize, Complex64), BeamSplitter(usize, usize, f64), PhaseShift(usize, f64), Kerr(usize, f64), }
151
152#[derive(Debug, Clone, Serialize, Deserialize)]
154pub struct PhotonicResult {
155 pub final_state: Vec<Complex64>,
157 pub expectation_values: HashMap<String, Complex64>,
159 pub photon_distribution: Vec<f64>,
161 pub stats: PhotonicStats,
163}
164
165#[derive(Debug, Clone, Default, Serialize, Deserialize)]
167pub struct PhotonicStats {
168 pub execution_time_ms: f64,
170 pub memory_usage_bytes: usize,
172 pub basis_states_count: usize,
174 pub max_photons_used: usize,
176 pub fidelity: f64,
178 pub method_used: String,
180}
181
182pub struct PhotonicSimulator {
184 config: PhotonicConfig,
186 state: PhotonicState,
188 backend: Option<SciRS2Backend>,
190 basis_cache: HashMap<FockState, usize>,
192 operator_cache: HashMap<String, Array2<Complex64>>,
194}
195
196impl PhotonicSimulator {
197 pub fn new(config: PhotonicConfig) -> Result<Self> {
199 let state = PhotonicState::Fock(Array1::zeros(1));
200
201 Ok(Self {
202 config,
203 state,
204 backend: None,
205 basis_cache: HashMap::new(),
206 operator_cache: HashMap::new(),
207 })
208 }
209
210 pub fn with_backend(mut self) -> Result<Self> {
212 self.backend = Some(SciRS2Backend::new());
213 Ok(self)
214 }
215
216 pub fn initialize_vacuum(&mut self) -> Result<()> {
218 match self.config.method {
219 PhotonicMethod::FockBasis => {
220 let dim = self.calculate_fock_dimension()?;
221 let mut state_vector = Array1::zeros(dim);
222 state_vector[0] = Complex64::new(1.0, 0.0); self.state = PhotonicState::Fock(state_vector);
224 }
225 PhotonicMethod::CoherentBasis => {
226 let vacuum = FockState::vacuum(self.config.num_modes);
227 self.state = PhotonicState::Coherent {
228 amplitudes: vec![Complex64::new(1.0, 0.0)],
229 basis_states: vec![vacuum],
230 };
231 }
232 PhotonicMethod::WignerFunction => {
233 let grid_size = self.config.wigner_grid_size;
234 let function_values = Array2::zeros((grid_size, grid_size));
235 let range = self.config.phase_space_range;
236 let q_grid = Array1::linspace(-range, range, grid_size);
237 let p_grid = Array1::linspace(-range, range, grid_size);
238
239 self.state = PhotonicState::Wigner {
240 function_values,
241 q_grid,
242 p_grid,
243 };
244 }
245 _ => {
246 let dim = self.calculate_fock_dimension()?;
247 let mut state_vector = Array1::zeros(dim);
248 state_vector[0] = Complex64::new(1.0, 0.0);
249 self.state = PhotonicState::Fock(state_vector);
250 }
251 }
252
253 Ok(())
254 }
255
256 pub fn initialize_coherent_state(&mut self, alpha: Complex64, mode: usize) -> Result<()> {
258 match self.config.method {
259 PhotonicMethod::FockBasis | PhotonicMethod::TruncatedFock => {
260 let dim = self.calculate_fock_dimension()?;
261 let mut state_vector = Array1::zeros(dim);
262
263 let displacement_factor = (-alpha.norm_sqr() / 2.0).exp();
265
266 let fock_states = self.enumerate_fock_states()?;
268 for (i, fock_state) in fock_states.iter().enumerate() {
269 if i >= dim {
270 break;
271 }
272
273 let n = fock_state.photons_in_mode(mode);
274 let amplitude =
275 displacement_factor * alpha.powu(n as u32) / Self::factorial(n).sqrt();
276 state_vector[i] = amplitude;
277 }
278
279 let norm = state_vector
281 .iter()
282 .map(scirs2_core::Complex::norm_sqr)
283 .sum::<f64>()
284 .sqrt();
285 if norm > 1e-15 {
286 for amp in &mut state_vector {
287 *amp /= norm;
288 }
289 }
290
291 self.state = PhotonicState::Fock(state_vector);
292 }
293 PhotonicMethod::CoherentBasis => {
294 let vacuum = FockState::vacuum(self.config.num_modes);
295 self.state = PhotonicState::Coherent {
296 amplitudes: vec![alpha],
297 basis_states: vec![vacuum],
298 };
299 }
300 PhotonicMethod::WignerFunction => {
301 self.initialize_coherent_wigner(alpha, mode)?;
302 }
303 PhotonicMethod::SciRS2Continuous => {
304 self.initialize_coherent_scirs2(alpha, mode)?;
305 }
306 }
307
308 Ok(())
309 }
310
311 pub fn initialize_squeezed_state(&mut self, xi: Complex64, mode: usize) -> Result<()> {
313 let r = xi.norm();
314 let phi = xi.arg();
315
316 match self.config.method {
317 PhotonicMethod::FockBasis | PhotonicMethod::TruncatedFock => {
318 let dim = self.calculate_fock_dimension()?;
319 let mut state_vector = Array1::zeros(dim);
320
321 let fock_states = self.enumerate_fock_states()?;
323 for (i, fock_state) in fock_states.iter().enumerate() {
324 if i >= dim {
325 break;
326 }
327
328 let n = fock_state.photons_in_mode(mode);
329 if n % 2 == 0 {
330 let amplitude = self.calculate_squeezed_amplitude(n, r, phi);
332 state_vector[i] = amplitude;
333 }
334 }
335
336 let norm = state_vector
338 .iter()
339 .map(scirs2_core::Complex::norm_sqr)
340 .sum::<f64>()
341 .sqrt();
342 if norm > 1e-15 {
343 for amp in &mut state_vector {
344 *amp /= norm;
345 }
346 }
347
348 self.state = PhotonicState::Fock(state_vector);
349 }
350 PhotonicMethod::CoherentBasis => {
351 let vacuum = FockState::vacuum(self.config.num_modes);
352 self.state = PhotonicState::Squeezed {
353 amplitudes: vec![Complex64::new(1.0, 0.0)],
354 squeezing_params: vec![xi],
355 basis_states: vec![vacuum],
356 };
357 }
358 _ => {
359 return Err(SimulatorError::UnsupportedOperation(
360 "Squeezed states not supported for this method".to_string(),
361 ));
362 }
363 }
364
365 Ok(())
366 }
367
368 pub fn apply_operator(&mut self, operator: PhotonicOperator) -> Result<()> {
370 let start_time = std::time::Instant::now();
371
372 match operator {
373 PhotonicOperator::Creation(mode) => self.apply_creation(mode)?,
374 PhotonicOperator::Annihilation(mode) => self.apply_annihilation(mode)?,
375 PhotonicOperator::Number(mode) => self.apply_number(mode)?,
376 PhotonicOperator::Displacement(mode, alpha) => self.apply_displacement(mode, alpha)?,
377 PhotonicOperator::Squeezing(mode, xi) => self.apply_squeezing(mode, xi)?,
378 PhotonicOperator::BeamSplitter(mode1, mode2, transmittance) => {
379 self.apply_beam_splitter(mode1, mode2, transmittance)?;
380 }
381 PhotonicOperator::PhaseShift(mode, phase) => self.apply_phase_shift(mode, phase)?,
382 PhotonicOperator::Kerr(mode, strength) => self.apply_kerr(mode, strength)?,
383 }
384
385 Ok(())
386 }
387
388 fn apply_creation(&mut self, mode: usize) -> Result<()> {
390 let fock_states = self.enumerate_fock_states()?;
392
393 match &mut self.state {
394 PhotonicState::Fock(state_vector) => {
395 let mut new_state = Array1::zeros(state_vector.len());
396
397 for (i, amplitude) in state_vector.iter().enumerate() {
398 if amplitude.norm() < 1e-15 {
399 continue;
400 }
401
402 let mut new_fock = fock_states[i].clone();
403 new_fock.photon_numbers[mode] += 1;
404
405 if let Some(j) = fock_states.iter().position(|s| s == &new_fock) {
406 let creation_factor = (new_fock.photon_numbers[mode] as f64).sqrt();
407 new_state[j] += *amplitude * creation_factor;
408 }
409 }
410
411 let norm = new_state
413 .iter()
414 .map(|x: &Complex64| x.norm_sqr())
415 .sum::<f64>()
416 .sqrt();
417 if norm > 1e-15 {
418 for amp in &mut new_state {
419 *amp /= norm;
420 }
421 }
422
423 *state_vector = new_state;
424 }
425 _ => {
426 return Err(SimulatorError::UnsupportedOperation(
427 "Creation operator not supported for this state representation".to_string(),
428 ));
429 }
430 }
431
432 Ok(())
433 }
434
435 fn apply_annihilation(&mut self, mode: usize) -> Result<()> {
437 let fock_states = self.enumerate_fock_states()?;
439
440 match &mut self.state {
441 PhotonicState::Fock(state_vector) => {
442 let mut new_state = Array1::zeros(state_vector.len());
443
444 for (i, amplitude) in state_vector.iter().enumerate() {
445 if amplitude.norm() < 1e-15 {
446 continue;
447 }
448
449 let current_fock = &fock_states[i];
450 if current_fock.photon_numbers[mode] > 0 {
451 let mut new_fock = current_fock.clone();
452 new_fock.photon_numbers[mode] -= 1;
453
454 if let Some(j) = fock_states.iter().position(|s| s == &new_fock) {
455 let annihilation_factor =
456 (current_fock.photon_numbers[mode] as f64).sqrt();
457 new_state[j] += *amplitude * annihilation_factor;
458 }
459 }
460 }
461
462 let norm = new_state
464 .iter()
465 .map(|x: &Complex64| x.norm_sqr())
466 .sum::<f64>()
467 .sqrt();
468 if norm > 1e-15 {
469 for amp in &mut new_state {
470 *amp /= norm;
471 }
472 }
473
474 *state_vector = new_state;
475 }
476 _ => {
477 return Err(SimulatorError::UnsupportedOperation(
478 "Annihilation operator not supported for this state representation".to_string(),
479 ));
480 }
481 }
482
483 Ok(())
484 }
485
486 fn apply_number(&mut self, mode: usize) -> Result<()> {
488 let fock_states = self.enumerate_fock_states()?;
490
491 match &mut self.state {
492 PhotonicState::Fock(state_vector) => {
493 for (i, amplitude) in state_vector.iter_mut().enumerate() {
494 let n = fock_states[i].photon_numbers[mode] as f64;
495 *amplitude *= n;
496 }
497 }
498 _ => {
499 return Err(SimulatorError::UnsupportedOperation(
500 "Number operator not supported for this state representation".to_string(),
501 ));
502 }
503 }
504
505 Ok(())
506 }
507
508 fn apply_displacement(&mut self, mode: usize, alpha: Complex64) -> Result<()> {
510 match self.config.method {
511 PhotonicMethod::FockBasis | PhotonicMethod::TruncatedFock => {
512 self.apply_displacement_fock(mode, alpha)?;
513 }
514 PhotonicMethod::CoherentBasis => {
515 self.apply_displacement_coherent(mode, alpha)?;
516 }
517 PhotonicMethod::SciRS2Continuous => {
518 self.apply_displacement_scirs2(mode, alpha)?;
519 }
520 PhotonicMethod::WignerFunction => {
521 return Err(SimulatorError::UnsupportedOperation(
522 "Displacement not supported for this method".to_string(),
523 ));
524 }
525 }
526
527 Ok(())
528 }
529
530 fn apply_displacement_fock(&mut self, mode: usize, alpha: Complex64) -> Result<()> {
532 let displacement_matrix = self.build_displacement_matrix(mode, alpha)?;
534
535 if let PhotonicState::Fock(state_vector) = &mut self.state {
536 let new_state = displacement_matrix.dot(state_vector);
537 *state_vector = new_state;
538 }
539 Ok(())
540 }
541
542 fn apply_displacement_coherent(&mut self, mode: usize, alpha: Complex64) -> Result<()> {
544 if let PhotonicState::Coherent { amplitudes, .. } = &mut self.state {
545 if mode < amplitudes.len() {
547 amplitudes[mode] += alpha;
548 }
549 }
550 Ok(())
551 }
552
553 fn apply_squeezing(&mut self, mode: usize, xi: Complex64) -> Result<()> {
555 let squeezing_matrix = self.build_squeezing_matrix(mode, xi)?;
557
558 match &mut self.state {
559 PhotonicState::Fock(state_vector) => {
560 let new_state = squeezing_matrix.dot(state_vector);
561 *state_vector = new_state;
562 }
563 _ => {
564 return Err(SimulatorError::UnsupportedOperation(
565 "Squeezing not supported for this state representation".to_string(),
566 ));
567 }
568 }
569
570 Ok(())
571 }
572
573 fn apply_beam_splitter(
575 &mut self,
576 mode1: usize,
577 mode2: usize,
578 transmittance: f64,
579 ) -> Result<()> {
580 if mode1 == mode2 {
581 return Err(SimulatorError::InvalidInput(
582 "Beam splitter modes must be different".to_string(),
583 ));
584 }
585
586 let theta = transmittance.acos();
587
588 let bs_matrix = self.build_beam_splitter_matrix(mode1, mode2, theta)?;
590
591 match &mut self.state {
592 PhotonicState::Fock(state_vector) => {
593 let new_state = bs_matrix.dot(state_vector);
594 *state_vector = new_state;
595 }
596 _ => {
597 return Err(SimulatorError::UnsupportedOperation(
598 "Beam splitter not supported for this state representation".to_string(),
599 ));
600 }
601 }
602
603 Ok(())
604 }
605
606 fn apply_phase_shift(&mut self, mode: usize, phase: f64) -> Result<()> {
608 let fock_states = if matches!(self.state, PhotonicState::Fock(_)) {
610 Some(self.enumerate_fock_states()?)
611 } else {
612 None
613 };
614
615 match &mut self.state {
616 PhotonicState::Fock(state_vector) => {
617 let fock_states = fock_states.expect("guaranteed by Fock state check above");
619
620 for (i, amplitude) in state_vector.iter_mut().enumerate() {
621 let n = fock_states[i].photon_numbers[mode] as f64;
622 let phase_factor = Complex64::new(0.0, n * phase).exp();
623 *amplitude *= phase_factor;
624 }
625 }
626 PhotonicState::Coherent { amplitudes, .. } => {
627 if mode < amplitudes.len() {
628 amplitudes[mode] *= Complex64::new(0.0, phase).exp();
629 }
630 }
631 _ => {
632 return Err(SimulatorError::UnsupportedOperation(
633 "Phase shift not supported for this state representation".to_string(),
634 ));
635 }
636 }
637
638 Ok(())
639 }
640
641 fn apply_kerr(&mut self, mode: usize, strength: f64) -> Result<()> {
643 let fock_states = self.enumerate_fock_states()?;
645
646 match &mut self.state {
647 PhotonicState::Fock(state_vector) => {
648 for (i, amplitude) in state_vector.iter_mut().enumerate() {
649 let n = fock_states[i].photon_numbers[mode] as f64;
650 let kerr_phase = Complex64::new(0.0, strength * n * (n - 1.0) / 2.0).exp();
651 *amplitude *= kerr_phase;
652 }
653 }
654 _ => {
655 return Err(SimulatorError::UnsupportedOperation(
656 "Kerr nonlinearity not supported for this state representation".to_string(),
657 ));
658 }
659 }
660
661 Ok(())
662 }
663
664 pub fn measure_photon_number(&self, mode: usize) -> Result<f64> {
666 match &self.state {
667 PhotonicState::Fock(state_vector) => {
668 let fock_states = self.enumerate_fock_states()?;
669 let mut expectation = 0.0;
670
671 for (i, amplitude) in state_vector.iter().enumerate() {
672 let probability = amplitude.norm_sqr();
673 let n = fock_states[i].photon_numbers[mode] as f64;
674 expectation += probability * n;
675 }
676
677 Ok(expectation)
678 }
679 PhotonicState::Coherent { amplitudes, .. } => {
680 if mode < amplitudes.len() {
681 Ok(amplitudes[mode].norm_sqr())
682 } else {
683 Ok(0.0)
684 }
685 }
686 _ => Err(SimulatorError::UnsupportedOperation(
687 "Photon number measurement not supported for this state".to_string(),
688 )),
689 }
690 }
691
692 pub fn photon_distribution(&self, mode: usize) -> Result<Vec<f64>> {
694 match &self.state {
695 PhotonicState::Fock(state_vector) => {
696 let fock_states = self.enumerate_fock_states()?;
697 let mut distribution = vec![0.0; self.config.max_photon_number + 1];
698
699 for (i, amplitude) in state_vector.iter().enumerate() {
700 let probability = amplitude.norm_sqr();
701 let n = fock_states[i].photon_numbers[mode];
702 if n <= self.config.max_photon_number {
703 distribution[n] += probability;
704 }
705 }
706
707 Ok(distribution)
708 }
709 _ => Err(SimulatorError::UnsupportedOperation(
710 "Photon distribution not supported for this state".to_string(),
711 )),
712 }
713 }
714
715 pub fn wigner_function(&self) -> Result<Array2<f64>> {
717 match &self.state {
718 PhotonicState::Wigner {
719 function_values, ..
720 } => Ok(function_values.mapv(|z| z.re)),
721 PhotonicState::Fock(state_vector) => {
722 if self.config.num_modes != 1 {
723 return Err(SimulatorError::UnsupportedOperation(
724 "Wigner function calculation only supported for single mode".to_string(),
725 ));
726 }
727
728 let grid_size = self.config.wigner_grid_size;
729 let range = self.config.phase_space_range;
730 let mut wigner = Array2::zeros((grid_size, grid_size));
731
732 for i in 0..grid_size {
733 for j in 0..grid_size {
734 let q = -range + 2.0 * range * i as f64 / (grid_size - 1) as f64;
735 let p = -range + 2.0 * range * j as f64 / (grid_size - 1) as f64;
736
737 wigner[[i, j]] = self.calculate_wigner_point(q, p, state_vector)?;
738 }
739 }
740
741 Ok(wigner)
742 }
743 _ => Err(SimulatorError::UnsupportedOperation(
744 "Wigner function not supported for this state representation".to_string(),
745 )),
746 }
747 }
748
749 fn calculate_fock_dimension(&self) -> Result<usize> {
751 let n = self.config.max_photon_number;
753 let m = self.config.num_modes;
754
755 let dim = if m == 1 {
756 n + 1
758 } else {
759 Self::binomial_coefficient(n + m - 1, m - 1)
761 };
762
763 if dim > 1_000_000 {
764 return Err(SimulatorError::InvalidInput(
765 "Fock space dimension too large".to_string(),
766 ));
767 }
768
769 Ok(dim)
770 }
771
772 fn enumerate_fock_states(&self) -> Result<Vec<FockState>> {
773 let mut states = Vec::new();
774 let max_n = self.config.max_photon_number;
775 let num_modes = self.config.num_modes;
776
777 self.generate_fock_states_recursive(&mut states, &mut vec![0; num_modes], 0, 0, max_n);
779
780 Ok(states)
781 }
782
783 fn generate_fock_states_recursive(
784 &self,
785 states: &mut Vec<FockState>,
786 current_state: &mut Vec<usize>,
787 mode: usize,
788 current_total: usize,
789 max_total: usize,
790 ) {
791 if mode == self.config.num_modes {
792 states.push(FockState::new(current_state.clone()));
793 return;
794 }
795
796 for n in 0..=(max_total - current_total) {
797 current_state[mode] = n;
798 self.generate_fock_states_recursive(
799 states,
800 current_state,
801 mode + 1,
802 current_total + n,
803 max_total,
804 );
805 }
806 }
807
808 fn get_state_index(&self, state: &FockState, fock_states: &[FockState]) -> Option<usize> {
809 self.basis_cache
810 .get(state)
811 .copied()
812 .or_else(|| fock_states.iter().position(|s| s == state))
813 }
814
815 fn calculate_squeezed_amplitude(&self, n: usize, r: f64, phi: f64) -> Complex64 {
816 if n % 2 != 0 {
817 return Complex64::new(0.0, 0.0);
818 }
819
820 let m = n / 2;
821 let tanh_r = r.tanh();
822 let sech_r = 1.0 / r.cosh();
823
824 sech_r.sqrt()
825 * (-tanh_r).powi(m as i32)
826 * Complex64::new(0.0, m as f64 * phi).exp()
827 * Self::double_factorial(2 * m - 1)
828 / Self::factorial(m)
829 * tanh_r.powf(m as f64)
830 }
831
832 fn build_displacement_matrix(
833 &self,
834 mode: usize,
835 alpha: Complex64,
836 ) -> Result<Array2<Complex64>> {
837 let dim = self.calculate_fock_dimension()?;
838 let mut matrix = Array2::zeros((dim, dim));
839
840 for i in 0..dim {
843 matrix[[i, i]] = Complex64::new(1.0, 0.0);
844 }
845
846 Ok(matrix)
847 }
848
849 fn build_squeezing_matrix(&self, mode: usize, xi: Complex64) -> Result<Array2<Complex64>> {
850 let dim = self.calculate_fock_dimension()?;
851 let mut matrix = Array2::eye(dim);
852
853 Ok(matrix.mapv(|x| Complex64::new(x, 0.0)))
855 }
856
857 fn build_beam_splitter_matrix(
858 &self,
859 mode1: usize,
860 mode2: usize,
861 theta: f64,
862 ) -> Result<Array2<Complex64>> {
863 let dim = self.calculate_fock_dimension()?;
864 let mut matrix = Array2::eye(dim);
865
866 Ok(matrix.mapv(|x| Complex64::new(x, 0.0)))
868 }
869
870 fn calculate_wigner_point(&self, q: f64, p: f64, state: &Array1<Complex64>) -> Result<f64> {
871 let alpha = Complex64::new(q, p) / 2.0_f64.sqrt();
873 let displacement_state = self.apply_displacement_to_state(state, alpha)?;
874
875 let parity = self.calculate_parity_expectation(&displacement_state)?;
877
878 Ok(2.0 * parity / std::f64::consts::PI)
879 }
880
881 fn apply_displacement_to_state(
882 &self,
883 state: &Array1<Complex64>,
884 alpha: Complex64,
885 ) -> Result<Array1<Complex64>> {
886 Ok(state.clone())
888 }
889
890 const fn calculate_parity_expectation(&self, state: &Array1<Complex64>) -> Result<f64> {
891 Ok(0.5)
893 }
894
895 fn initialize_coherent_scirs2(&mut self, alpha: Complex64, mode: usize) -> Result<()> {
898 if let Some(_backend) = &mut self.backend {
899 let dim = 1000; let mut state_vector = Array1::zeros(dim);
902 state_vector[0] = Complex64::new(1.0, 0.0);
903 self.state = PhotonicState::Fock(state_vector);
904 } else {
905 self.initialize_coherent_state(alpha, mode)?;
906 }
907 Ok(())
908 }
909
910 fn apply_displacement_scirs2(&mut self, mode: usize, alpha: Complex64) -> Result<()> {
911 if let Some(_backend) = &mut self.backend {
912 self.apply_displacement_fock(mode, alpha)?;
915 } else {
916 self.apply_displacement_fock(mode, alpha)?;
917 }
918 Ok(())
919 }
920
921 fn initialize_coherent_wigner(&mut self, alpha: Complex64, mode: usize) -> Result<()> {
922 let grid_size = self.config.wigner_grid_size;
923 let range = self.config.phase_space_range;
924 let mut function_values = Array2::zeros((grid_size, grid_size));
925
926 let q0 = alpha.re * 2.0_f64.sqrt();
928 let p0 = alpha.im * 2.0_f64.sqrt();
929
930 for i in 0..grid_size {
931 for j in 0..grid_size {
932 let q = -range + 2.0 * range * i as f64 / (grid_size - 1) as f64;
933 let p = -range + 2.0 * range * j as f64 / (grid_size - 1) as f64;
934
935 let gaussian =
936 (p - p0).mul_add(-(p - p0), -(q - q0).powi(2)).exp() / std::f64::consts::PI;
937 function_values[[i, j]] = Complex64::new(gaussian, 0.0);
938 }
939 }
940
941 let q_grid = Array1::linspace(-range, range, grid_size);
942 let p_grid = Array1::linspace(-range, range, grid_size);
943
944 self.state = PhotonicState::Wigner {
945 function_values,
946 q_grid,
947 p_grid,
948 };
949
950 Ok(())
951 }
952
953 fn factorial(n: usize) -> f64 {
956 (1..=n).fold(1.0, |acc, x| acc * x as f64)
957 }
958
959 fn double_factorial(n: usize) -> f64 {
960 if n <= 1 {
961 1.0
962 } else {
963 n as f64 * Self::double_factorial(n - 2)
964 }
965 }
966
967 fn binomial_coefficient(n: usize, k: usize) -> usize {
968 if k > n {
969 0
970 } else if k == 0 || k == n {
971 1
972 } else {
973 (1..=k).fold(1, |acc, i| acc * (n - i + 1) / i)
974 }
975 }
976
977 #[must_use]
979 pub const fn get_state(&self) -> &PhotonicState {
980 &self.state
981 }
982
983 #[must_use]
985 pub const fn get_config(&self) -> &PhotonicConfig {
986 &self.config
987 }
988
989 pub const fn set_config(&mut self, config: PhotonicConfig) {
991 self.config = config;
992 }
993}
994
995pub struct PhotonicUtils;
997
998impl PhotonicUtils {
999 pub fn cat_state(
1001 alpha: Complex64,
1002 phase: f64,
1003 ) -> impl Fn(&mut PhotonicSimulator) -> Result<()> {
1004 move |simulator: &mut PhotonicSimulator| -> Result<()> {
1005 simulator.initialize_coherent_state(alpha, 0)?;
1007
1008 Ok(())
1011 }
1012 }
1013
1014 pub fn fidelity(state1: &PhotonicState, state2: &PhotonicState) -> Result<f64> {
1016 match (state1, state2) {
1017 (PhotonicState::Fock(s1), PhotonicState::Fock(s2)) => {
1018 if s1.len() != s2.len() {
1019 return Err(SimulatorError::DimensionMismatch(
1020 "State vectors have different dimensions".to_string(),
1021 ));
1022 }
1023
1024 let overlap: Complex64 = s1.iter().zip(s2.iter()).map(|(a, b)| a.conj() * b).sum();
1025
1026 Ok(overlap.norm_sqr())
1027 }
1028 _ => Err(SimulatorError::UnsupportedOperation(
1029 "Fidelity calculation not supported for these state types".to_string(),
1030 )),
1031 }
1032 }
1033
1034 pub fn von_neumann_entropy(state: &PhotonicState) -> Result<f64> {
1036 match state {
1037 PhotonicState::Fock(state_vector) => {
1038 let probabilities: Vec<f64> = state_vector
1039 .iter()
1040 .map(scirs2_core::Complex::norm_sqr)
1041 .filter(|&p| p > 1e-15)
1042 .collect();
1043
1044 let entropy = -probabilities.iter().map(|&p| p * p.ln()).sum::<f64>();
1045
1046 Ok(entropy)
1047 }
1048 _ => Err(SimulatorError::UnsupportedOperation(
1049 "Entropy calculation not supported for this state type".to_string(),
1050 )),
1051 }
1052 }
1053}
1054
1055pub fn benchmark_photonic_methods(
1057 max_photon_number: usize,
1058 num_modes: usize,
1059) -> Result<HashMap<String, PhotonicStats>> {
1060 let mut results = HashMap::new();
1061
1062 let methods = vec![
1063 ("FockBasis", PhotonicMethod::FockBasis),
1064 ("CoherentBasis", PhotonicMethod::CoherentBasis),
1065 ("TruncatedFock", PhotonicMethod::TruncatedFock),
1066 ];
1067
1068 for (name, method) in methods {
1069 let config = PhotonicConfig {
1070 method,
1071 max_photon_number,
1072 num_modes,
1073 ..Default::default()
1074 };
1075
1076 let start_time = std::time::Instant::now();
1077 let mut simulator = PhotonicSimulator::new(config.clone())?;
1078 simulator.initialize_vacuum()?;
1079
1080 simulator.apply_operator(PhotonicOperator::Creation(0))?;
1082 simulator.apply_operator(PhotonicOperator::Displacement(0, Complex64::new(1.0, 0.5)))?;
1083
1084 let execution_time = start_time.elapsed().as_secs_f64() * 1000.0;
1085
1086 let stats = PhotonicStats {
1087 execution_time_ms: execution_time,
1088 method_used: name.to_string(),
1089 basis_states_count: simulator.calculate_fock_dimension().unwrap_or(0),
1090 ..Default::default()
1091 };
1092
1093 results.insert(name.to_string(), stats);
1094 }
1095
1096 Ok(results)
1097}
1098
1099#[cfg(test)]
1100mod tests {
1101 use super::*;
1102 use approx::assert_abs_diff_eq;
1103
1104 #[test]
1105 fn test_photonic_config_default() {
1106 let config = PhotonicConfig::default();
1107 assert_eq!(config.method, PhotonicMethod::FockBasis);
1108 assert_eq!(config.max_photon_number, 20);
1109 assert_eq!(config.num_modes, 1);
1110 }
1111
1112 #[test]
1113 fn test_fock_state_creation() {
1114 let state = FockState::new(vec![2, 1, 0]);
1115 assert_eq!(state.total_photons(), 3);
1116 assert_eq!(state.photons_in_mode(0), 2);
1117 assert_eq!(state.photons_in_mode(1), 1);
1118 assert_eq!(state.photons_in_mode(2), 0);
1119 }
1120
1121 #[test]
1122 fn test_vacuum_state() {
1123 let vacuum = FockState::vacuum(3);
1124 assert_eq!(vacuum.total_photons(), 0);
1125 assert_eq!(vacuum.photons_in_mode(0), 0);
1126 }
1127
1128 #[test]
1129 fn test_single_photon_state() {
1130 let single = FockState::single_photon(1, 3);
1131 assert_eq!(single.total_photons(), 1);
1132 assert_eq!(single.photons_in_mode(1), 1);
1133 assert_eq!(single.photons_in_mode(0), 0);
1134 }
1135
1136 #[test]
1137 fn test_photonic_simulator_creation() {
1138 let config = PhotonicConfig::default();
1139 let simulator = PhotonicSimulator::new(config).expect("should create photonic simulator");
1140 assert_eq!(simulator.config.num_modes, 1);
1141 }
1142
1143 #[test]
1144 fn test_vacuum_initialization() {
1145 let config = PhotonicConfig::default();
1146 let mut simulator =
1147 PhotonicSimulator::new(config).expect("should create photonic simulator");
1148 simulator
1149 .initialize_vacuum()
1150 .expect("should initialize vacuum state");
1151
1152 if let PhotonicState::Fock(state) = &simulator.state {
1153 assert_abs_diff_eq!(state[0].norm(), 1.0, epsilon = 1e-10);
1154 }
1155 }
1156
1157 #[test]
1158 fn test_coherent_state_initialization() {
1159 let config = PhotonicConfig {
1160 max_photon_number: 10,
1161 ..Default::default()
1162 };
1163 let mut simulator =
1164 PhotonicSimulator::new(config).expect("should create photonic simulator");
1165 let alpha = Complex64::new(1.0, 0.5);
1166
1167 simulator
1168 .initialize_coherent_state(alpha, 0)
1169 .expect("should initialize coherent state");
1170
1171 if let PhotonicState::Fock(state) = &simulator.state {
1173 let norm_sqr = state.iter().map(|x| x.norm_sqr()).sum::<f64>();
1174 assert_abs_diff_eq!(norm_sqr, 1.0, epsilon = 1e-10);
1175 }
1176 }
1177
1178 #[test]
1179 fn test_creation_operator() {
1180 let config = PhotonicConfig {
1181 max_photon_number: 5,
1182 ..Default::default()
1183 };
1184 let mut simulator =
1185 PhotonicSimulator::new(config).expect("should create photonic simulator");
1186 simulator
1187 .initialize_vacuum()
1188 .expect("should initialize vacuum state");
1189
1190 simulator
1192 .apply_operator(PhotonicOperator::Creation(0))
1193 .expect("should apply creation operator");
1194
1195 let photon_number = simulator
1197 .measure_photon_number(0)
1198 .expect("should measure photon number");
1199 assert_abs_diff_eq!(photon_number, 1.0, epsilon = 1e-10);
1200 }
1201
1202 #[test]
1203 fn test_photon_number_measurement() {
1204 let config = PhotonicConfig {
1205 max_photon_number: 5,
1206 ..Default::default()
1207 };
1208 let mut simulator =
1209 PhotonicSimulator::new(config).expect("should create photonic simulator");
1210 simulator
1211 .initialize_vacuum()
1212 .expect("should initialize vacuum state");
1213
1214 simulator
1216 .apply_operator(PhotonicOperator::Creation(0))
1217 .expect("should apply creation operator");
1218 let photon_number_1 = simulator
1219 .measure_photon_number(0)
1220 .expect("should measure photon number");
1221 assert_abs_diff_eq!(photon_number_1, 1.0, epsilon = 1e-10);
1222
1223 simulator
1225 .apply_operator(PhotonicOperator::Creation(0))
1226 .expect("should apply second creation operator");
1227 let photon_number_2 = simulator
1228 .measure_photon_number(0)
1229 .expect("should measure photon number");
1230 assert_abs_diff_eq!(photon_number_2, 2.0, epsilon = 1e-10);
1231 }
1232
1233 #[test]
1234 fn test_photon_distribution() {
1235 let config = PhotonicConfig {
1236 max_photon_number: 3,
1237 ..Default::default()
1238 };
1239 let mut simulator =
1240 PhotonicSimulator::new(config).expect("should create photonic simulator");
1241 simulator
1242 .initialize_vacuum()
1243 .expect("should initialize vacuum state");
1244
1245 let distribution = simulator
1246 .photon_distribution(0)
1247 .expect("should get photon distribution");
1248
1249 assert_abs_diff_eq!(distribution[0], 1.0, epsilon = 1e-10);
1251 assert_abs_diff_eq!(distribution[1], 0.0, epsilon = 1e-10);
1252 }
1253
1254 #[test]
1255 fn test_mathematical_helpers() {
1256 assert_abs_diff_eq!(PhotonicSimulator::factorial(0), 1.0, epsilon = 1e-10);
1257 assert_abs_diff_eq!(PhotonicSimulator::factorial(5), 120.0, epsilon = 1e-10);
1258
1259 assert_eq!(PhotonicSimulator::binomial_coefficient(5, 2), 10);
1260 assert_eq!(PhotonicSimulator::binomial_coefficient(4, 0), 1);
1261 }
1262}