quantrs2_sim/
photonic.rs

1//! Photonic quantum simulation for continuous variable systems.
2//!
3//! This module provides simulation capabilities for photonic quantum systems,
4//! including Fock states, coherent states, squeezed states, and multi-mode
5//! operations. It supports both exact diagonalization and approximate methods
6//! for large photon number cutoffs.
7
8use crate::prelude::SimulatorError;
9use ndarray::{Array1, Array2};
10use num_complex::Complex64;
11use scirs2_core::parallel_ops::*;
12use serde::{Deserialize, Serialize};
13use std::collections::HashMap;
14
15use crate::error::Result;
16use crate::scirs2_integration::SciRS2Backend;
17
18/// Photonic simulation method
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum PhotonicMethod {
21    /// Exact Fock state representation
22    FockBasis,
23    /// Coherent state representation
24    CoherentBasis,
25    /// Wigner function representation
26    WignerFunction,
27    /// SciRS2-optimized continuous variables
28    SciRS2Continuous,
29    /// Truncated Fock space with large cutoff
30    TruncatedFock,
31}
32
33/// Photonic simulation configuration
34#[derive(Debug, Clone)]
35pub struct PhotonicConfig {
36    /// Simulation method
37    pub method: PhotonicMethod,
38    /// Maximum photon number (Fock cutoff)
39    pub max_photon_number: usize,
40    /// Number of modes
41    pub num_modes: usize,
42    /// Precision for continuous variables
43    pub precision: f64,
44    /// Use parallel execution
45    pub parallel: bool,
46    /// Wigner function grid size (for Wigner method)
47    pub wigner_grid_size: usize,
48    /// Phase space range for Wigner functions
49    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/// Photonic state representation
67#[derive(Debug, Clone)]
68pub enum PhotonicState {
69    /// Fock state representation |n1, n2, ...⟩
70    Fock(Array1<Complex64>),
71    /// Coherent state representation
72    Coherent {
73        amplitudes: Vec<Complex64>,
74        basis_states: Vec<FockState>,
75    },
76    /// Squeezed state representation
77    Squeezed {
78        amplitudes: Vec<Complex64>,
79        squeezing_params: Vec<Complex64>,
80        basis_states: Vec<FockState>,
81    },
82    /// Wigner function representation
83    Wigner {
84        function_values: Array2<Complex64>,
85        q_grid: Array1<f64>,
86        p_grid: Array1<f64>,
87    },
88}
89
90/// Multi-mode Fock state
91#[derive(Debug, Clone, PartialEq, Eq, Hash)]
92pub struct FockState {
93    /// Photon numbers in each mode
94    pub photon_numbers: Vec<usize>,
95}
96
97impl FockState {
98    /// Create new Fock state
99    pub fn new(photon_numbers: Vec<usize>) -> Self {
100        Self { photon_numbers }
101    }
102
103    /// Create vacuum state
104    pub fn vacuum(num_modes: usize) -> Self {
105        Self::new(vec![0; num_modes])
106    }
107
108    /// Create single-photon state in given mode
109    pub fn single_photon(mode: usize, num_modes: usize) -> Self {
110        let mut photon_numbers = vec![0; num_modes];
111        photon_numbers[mode] = 1;
112        Self::new(photon_numbers)
113    }
114
115    /// Total photon number
116    pub fn total_photons(&self) -> usize {
117        self.photon_numbers.iter().sum()
118    }
119
120    /// Get photon number in specific mode
121    pub fn photons_in_mode(&self, mode: usize) -> usize {
122        self.photon_numbers.get(mode).copied().unwrap_or(0)
123    }
124}
125
126/// Photonic operators
127#[derive(Debug, Clone)]
128pub enum PhotonicOperator {
129    /// Creation operator a†
130    Creation(usize), // mode index
131    /// Annihilation operator a
132    Annihilation(usize), // mode index
133    /// Number operator a†a
134    Number(usize), // mode index
135    /// Displacement operator D(α)
136    Displacement(usize, Complex64), // mode, amplitude
137    /// Squeezing operator S(ξ)
138    Squeezing(usize, Complex64), // mode, squeezing parameter
139    /// Beam splitter
140    BeamSplitter(usize, usize, f64), // mode1, mode2, transmittance
141    /// Phase shifter
142    PhaseShift(usize, f64), // mode, phase
143    /// Kerr nonlinearity
144    Kerr(usize, f64), // mode, strength
145}
146
147/// Photonic gate result
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct PhotonicResult {
150    /// Final state
151    pub final_state: Vec<Complex64>,
152    /// Expectation values of observables
153    pub expectation_values: HashMap<String, Complex64>,
154    /// Photon number distribution
155    pub photon_distribution: Vec<f64>,
156    /// Execution statistics
157    pub stats: PhotonicStats,
158}
159
160/// Photonic simulation statistics
161#[derive(Debug, Clone, Default, Serialize, Deserialize)]
162pub struct PhotonicStats {
163    /// Execution time in milliseconds
164    pub execution_time_ms: f64,
165    /// Memory usage in bytes
166    pub memory_usage_bytes: usize,
167    /// Number of basis states used
168    pub basis_states_count: usize,
169    /// Maximum photon number reached
170    pub max_photons_used: usize,
171    /// Fidelity with exact solution (if available)
172    pub fidelity: f64,
173    /// Method used
174    pub method_used: String,
175}
176
177/// Photonic quantum simulator
178pub struct PhotonicSimulator {
179    /// Configuration
180    config: PhotonicConfig,
181    /// Current state
182    state: PhotonicState,
183    /// SciRS2 backend
184    backend: Option<SciRS2Backend>,
185    /// Basis state cache
186    basis_cache: HashMap<FockState, usize>,
187    /// Operator matrix cache
188    operator_cache: HashMap<String, Array2<Complex64>>,
189}
190
191impl PhotonicSimulator {
192    /// Create new photonic simulator
193    pub fn new(config: PhotonicConfig) -> Result<Self> {
194        let state = PhotonicState::Fock(Array1::zeros(1));
195
196        Ok(Self {
197            config,
198            state,
199            backend: None,
200            basis_cache: HashMap::new(),
201            operator_cache: HashMap::new(),
202        })
203    }
204
205    /// Initialize with SciRS2 backend
206    pub fn with_backend(mut self) -> Result<Self> {
207        self.backend = Some(SciRS2Backend::new());
208        Ok(self)
209    }
210
211    /// Initialize vacuum state
212    pub fn initialize_vacuum(&mut self) -> Result<()> {
213        match self.config.method {
214            PhotonicMethod::FockBasis => {
215                let dim = self.calculate_fock_dimension()?;
216                let mut state_vector = Array1::zeros(dim);
217                state_vector[0] = Complex64::new(1.0, 0.0); // Vacuum state
218                self.state = PhotonicState::Fock(state_vector);
219            }
220            PhotonicMethod::CoherentBasis => {
221                let vacuum = FockState::vacuum(self.config.num_modes);
222                self.state = PhotonicState::Coherent {
223                    amplitudes: vec![Complex64::new(1.0, 0.0)],
224                    basis_states: vec![vacuum],
225                };
226            }
227            PhotonicMethod::WignerFunction => {
228                let grid_size = self.config.wigner_grid_size;
229                let function_values = Array2::zeros((grid_size, grid_size));
230                let range = self.config.phase_space_range;
231                let q_grid = Array1::linspace(-range, range, grid_size);
232                let p_grid = Array1::linspace(-range, range, grid_size);
233
234                self.state = PhotonicState::Wigner {
235                    function_values,
236                    q_grid,
237                    p_grid,
238                };
239            }
240            _ => {
241                let dim = self.calculate_fock_dimension()?;
242                let mut state_vector = Array1::zeros(dim);
243                state_vector[0] = Complex64::new(1.0, 0.0);
244                self.state = PhotonicState::Fock(state_vector);
245            }
246        }
247
248        Ok(())
249    }
250
251    /// Initialize coherent state |α⟩
252    pub fn initialize_coherent_state(&mut self, alpha: Complex64, mode: usize) -> Result<()> {
253        match self.config.method {
254            PhotonicMethod::FockBasis | PhotonicMethod::TruncatedFock => {
255                let dim = self.calculate_fock_dimension()?;
256                let mut state_vector = Array1::zeros(dim);
257
258                // Generate coherent state in Fock basis
259                let displacement_factor = (-alpha.norm_sqr() / 2.0).exp();
260
261                // Enumerate Fock states and calculate amplitudes
262                let fock_states = self.enumerate_fock_states()?;
263                for (i, fock_state) in fock_states.iter().enumerate() {
264                    if i >= dim {
265                        break;
266                    }
267
268                    let n = fock_state.photons_in_mode(mode);
269                    let amplitude =
270                        displacement_factor * alpha.powu(n as u32) / Self::factorial(n).sqrt();
271                    state_vector[i] = amplitude;
272                }
273
274                // Normalize the truncated coherent state
275                let norm = state_vector
276                    .iter()
277                    .map(|x| x.norm_sqr())
278                    .sum::<f64>()
279                    .sqrt();
280                if norm > 1e-15 {
281                    for amp in state_vector.iter_mut() {
282                        *amp /= norm;
283                    }
284                }
285
286                self.state = PhotonicState::Fock(state_vector);
287            }
288            PhotonicMethod::CoherentBasis => {
289                let vacuum = FockState::vacuum(self.config.num_modes);
290                self.state = PhotonicState::Coherent {
291                    amplitudes: vec![alpha],
292                    basis_states: vec![vacuum],
293                };
294            }
295            PhotonicMethod::WignerFunction => {
296                self.initialize_coherent_wigner(alpha, mode)?;
297            }
298            PhotonicMethod::SciRS2Continuous => {
299                self.initialize_coherent_scirs2(alpha, mode)?;
300            }
301        }
302
303        Ok(())
304    }
305
306    /// Initialize squeezed state
307    pub fn initialize_squeezed_state(&mut self, xi: Complex64, mode: usize) -> Result<()> {
308        let r = xi.norm();
309        let phi = xi.arg();
310
311        match self.config.method {
312            PhotonicMethod::FockBasis | PhotonicMethod::TruncatedFock => {
313                let dim = self.calculate_fock_dimension()?;
314                let mut state_vector = Array1::zeros(dim);
315
316                // Generate squeezed vacuum state
317                let fock_states = self.enumerate_fock_states()?;
318                for (i, fock_state) in fock_states.iter().enumerate() {
319                    if i >= dim {
320                        break;
321                    }
322
323                    let n = fock_state.photons_in_mode(mode);
324                    if n % 2 == 0 {
325                        // Only even photon numbers for squeezed vacuum
326                        let amplitude = self.calculate_squeezed_amplitude(n, r, phi);
327                        state_vector[i] = amplitude;
328                    }
329                }
330
331                // Normalize
332                let norm = state_vector
333                    .iter()
334                    .map(|x| x.norm_sqr())
335                    .sum::<f64>()
336                    .sqrt();
337                if norm > 1e-15 {
338                    for amp in state_vector.iter_mut() {
339                        *amp /= norm;
340                    }
341                }
342
343                self.state = PhotonicState::Fock(state_vector);
344            }
345            PhotonicMethod::CoherentBasis => {
346                let vacuum = FockState::vacuum(self.config.num_modes);
347                self.state = PhotonicState::Squeezed {
348                    amplitudes: vec![Complex64::new(1.0, 0.0)],
349                    squeezing_params: vec![xi],
350                    basis_states: vec![vacuum],
351                };
352            }
353            _ => {
354                return Err(SimulatorError::UnsupportedOperation(
355                    "Squeezed states not supported for this method".to_string(),
356                ));
357            }
358        }
359
360        Ok(())
361    }
362
363    /// Apply photonic operator
364    pub fn apply_operator(&mut self, operator: PhotonicOperator) -> Result<()> {
365        let start_time = std::time::Instant::now();
366
367        match operator {
368            PhotonicOperator::Creation(mode) => self.apply_creation(mode)?,
369            PhotonicOperator::Annihilation(mode) => self.apply_annihilation(mode)?,
370            PhotonicOperator::Number(mode) => self.apply_number(mode)?,
371            PhotonicOperator::Displacement(mode, alpha) => self.apply_displacement(mode, alpha)?,
372            PhotonicOperator::Squeezing(mode, xi) => self.apply_squeezing(mode, xi)?,
373            PhotonicOperator::BeamSplitter(mode1, mode2, transmittance) => {
374                self.apply_beam_splitter(mode1, mode2, transmittance)?;
375            }
376            PhotonicOperator::PhaseShift(mode, phase) => self.apply_phase_shift(mode, phase)?,
377            PhotonicOperator::Kerr(mode, strength) => self.apply_kerr(mode, strength)?,
378        }
379
380        Ok(())
381    }
382
383    /// Apply creation operator a†
384    fn apply_creation(&mut self, mode: usize) -> Result<()> {
385        // Get fock states first to avoid borrowing conflicts
386        let fock_states = self.enumerate_fock_states()?;
387
388        match &mut self.state {
389            PhotonicState::Fock(state_vector) => {
390                let mut new_state = Array1::zeros(state_vector.len());
391
392                for (i, amplitude) in state_vector.iter().enumerate() {
393                    if amplitude.norm() < 1e-15 {
394                        continue;
395                    }
396
397                    let mut new_fock = fock_states[i].clone();
398                    new_fock.photon_numbers[mode] += 1;
399
400                    if let Some(j) = fock_states.iter().position(|s| s == &new_fock) {
401                        let creation_factor = (new_fock.photon_numbers[mode] as f64).sqrt();
402                        new_state[j] += *amplitude * creation_factor;
403                    }
404                }
405
406                // Normalize the state after applying creation operator
407                let norm = new_state
408                    .iter()
409                    .map(|x: &Complex64| x.norm_sqr())
410                    .sum::<f64>()
411                    .sqrt();
412                if norm > 1e-15 {
413                    for amp in new_state.iter_mut() {
414                        *amp /= norm;
415                    }
416                }
417
418                *state_vector = new_state;
419            }
420            _ => {
421                return Err(SimulatorError::UnsupportedOperation(
422                    "Creation operator not supported for this state representation".to_string(),
423                ));
424            }
425        }
426
427        Ok(())
428    }
429
430    /// Apply annihilation operator a
431    fn apply_annihilation(&mut self, mode: usize) -> Result<()> {
432        // Get fock states first to avoid borrowing conflicts
433        let fock_states = self.enumerate_fock_states()?;
434
435        match &mut self.state {
436            PhotonicState::Fock(state_vector) => {
437                let mut new_state = Array1::zeros(state_vector.len());
438
439                for (i, amplitude) in state_vector.iter().enumerate() {
440                    if amplitude.norm() < 1e-15 {
441                        continue;
442                    }
443
444                    let current_fock = &fock_states[i];
445                    if current_fock.photon_numbers[mode] > 0 {
446                        let mut new_fock = current_fock.clone();
447                        new_fock.photon_numbers[mode] -= 1;
448
449                        if let Some(j) = fock_states.iter().position(|s| s == &new_fock) {
450                            let annihilation_factor =
451                                (current_fock.photon_numbers[mode] as f64).sqrt();
452                            new_state[j] += *amplitude * annihilation_factor;
453                        }
454                    }
455                }
456
457                // Normalize the state after applying annihilation operator
458                let norm = new_state
459                    .iter()
460                    .map(|x: &Complex64| x.norm_sqr())
461                    .sum::<f64>()
462                    .sqrt();
463                if norm > 1e-15 {
464                    for amp in new_state.iter_mut() {
465                        *amp /= norm;
466                    }
467                }
468
469                *state_vector = new_state;
470            }
471            _ => {
472                return Err(SimulatorError::UnsupportedOperation(
473                    "Annihilation operator not supported for this state representation".to_string(),
474                ));
475            }
476        }
477
478        Ok(())
479    }
480
481    /// Apply number operator a†a
482    fn apply_number(&mut self, mode: usize) -> Result<()> {
483        // Get fock states first to avoid borrowing conflicts
484        let fock_states = self.enumerate_fock_states()?;
485
486        match &mut self.state {
487            PhotonicState::Fock(state_vector) => {
488                for (i, amplitude) in state_vector.iter_mut().enumerate() {
489                    let n = fock_states[i].photon_numbers[mode] as f64;
490                    *amplitude *= n;
491                }
492            }
493            _ => {
494                return Err(SimulatorError::UnsupportedOperation(
495                    "Number operator not supported for this state representation".to_string(),
496                ));
497            }
498        }
499
500        Ok(())
501    }
502
503    /// Apply displacement operator D(α)
504    fn apply_displacement(&mut self, mode: usize, alpha: Complex64) -> Result<()> {
505        match self.config.method {
506            PhotonicMethod::FockBasis | PhotonicMethod::TruncatedFock => {
507                self.apply_displacement_fock(mode, alpha)?;
508            }
509            PhotonicMethod::CoherentBasis => {
510                self.apply_displacement_coherent(mode, alpha)?;
511            }
512            PhotonicMethod::SciRS2Continuous => {
513                self.apply_displacement_scirs2(mode, alpha)?;
514            }
515            _ => {
516                return Err(SimulatorError::UnsupportedOperation(
517                    "Displacement not supported for this method".to_string(),
518                ));
519            }
520        }
521
522        Ok(())
523    }
524
525    /// Apply displacement in Fock basis
526    fn apply_displacement_fock(&mut self, mode: usize, alpha: Complex64) -> Result<()> {
527        // Get displacement matrix first to avoid borrowing conflicts
528        let displacement_matrix = self.build_displacement_matrix(mode, alpha)?;
529
530        if let PhotonicState::Fock(state_vector) = &mut self.state {
531            let new_state = displacement_matrix.dot(state_vector);
532            *state_vector = new_state;
533        }
534        Ok(())
535    }
536
537    /// Apply displacement in coherent basis
538    fn apply_displacement_coherent(&mut self, mode: usize, alpha: Complex64) -> Result<()> {
539        if let PhotonicState::Coherent { amplitudes, .. } = &mut self.state {
540            // In coherent basis, displacement just shifts the amplitude
541            if mode < amplitudes.len() {
542                amplitudes[mode] += alpha;
543            }
544        }
545        Ok(())
546    }
547
548    /// Apply squeezing operator S(ξ)
549    fn apply_squeezing(&mut self, mode: usize, xi: Complex64) -> Result<()> {
550        // Get squeezing matrix first to avoid borrowing conflicts
551        let squeezing_matrix = self.build_squeezing_matrix(mode, xi)?;
552
553        match &mut self.state {
554            PhotonicState::Fock(state_vector) => {
555                let new_state = squeezing_matrix.dot(state_vector);
556                *state_vector = new_state;
557            }
558            _ => {
559                return Err(SimulatorError::UnsupportedOperation(
560                    "Squeezing not supported for this state representation".to_string(),
561                ));
562            }
563        }
564
565        Ok(())
566    }
567
568    /// Apply beam splitter
569    fn apply_beam_splitter(
570        &mut self,
571        mode1: usize,
572        mode2: usize,
573        transmittance: f64,
574    ) -> Result<()> {
575        if mode1 == mode2 {
576            return Err(SimulatorError::InvalidInput(
577                "Beam splitter modes must be different".to_string(),
578            ));
579        }
580
581        let theta = transmittance.acos();
582
583        // Get beam splitter matrix first to avoid borrowing conflicts
584        let bs_matrix = self.build_beam_splitter_matrix(mode1, mode2, theta)?;
585
586        match &mut self.state {
587            PhotonicState::Fock(state_vector) => {
588                let new_state = bs_matrix.dot(state_vector);
589                *state_vector = new_state;
590            }
591            _ => {
592                return Err(SimulatorError::UnsupportedOperation(
593                    "Beam splitter not supported for this state representation".to_string(),
594                ));
595            }
596        }
597
598        Ok(())
599    }
600
601    /// Apply phase shift
602    fn apply_phase_shift(&mut self, mode: usize, phase: f64) -> Result<()> {
603        // Get fock states first to avoid borrowing conflicts for Fock state case
604        let fock_states = if matches!(self.state, PhotonicState::Fock(_)) {
605            Some(self.enumerate_fock_states()?)
606        } else {
607            None
608        };
609
610        match &mut self.state {
611            PhotonicState::Fock(state_vector) => {
612                let fock_states = fock_states.unwrap();
613
614                for (i, amplitude) in state_vector.iter_mut().enumerate() {
615                    let n = fock_states[i].photon_numbers[mode] as f64;
616                    let phase_factor = Complex64::new(0.0, n * phase).exp();
617                    *amplitude *= phase_factor;
618                }
619            }
620            PhotonicState::Coherent { amplitudes, .. } => {
621                if mode < amplitudes.len() {
622                    amplitudes[mode] *= Complex64::new(0.0, phase).exp();
623                }
624            }
625            _ => {
626                return Err(SimulatorError::UnsupportedOperation(
627                    "Phase shift not supported for this state representation".to_string(),
628                ));
629            }
630        }
631
632        Ok(())
633    }
634
635    /// Apply Kerr nonlinearity
636    fn apply_kerr(&mut self, mode: usize, strength: f64) -> Result<()> {
637        // Get fock states first to avoid borrowing conflicts
638        let fock_states = self.enumerate_fock_states()?;
639
640        match &mut self.state {
641            PhotonicState::Fock(state_vector) => {
642                for (i, amplitude) in state_vector.iter_mut().enumerate() {
643                    let n = fock_states[i].photon_numbers[mode] as f64;
644                    let kerr_phase = Complex64::new(0.0, strength * n * (n - 1.0) / 2.0).exp();
645                    *amplitude *= kerr_phase;
646                }
647            }
648            _ => {
649                return Err(SimulatorError::UnsupportedOperation(
650                    "Kerr nonlinearity not supported for this state representation".to_string(),
651                ));
652            }
653        }
654
655        Ok(())
656    }
657
658    /// Measure photon number in given mode
659    pub fn measure_photon_number(&self, mode: usize) -> Result<f64> {
660        match &self.state {
661            PhotonicState::Fock(state_vector) => {
662                let fock_states = self.enumerate_fock_states()?;
663                let mut expectation = 0.0;
664
665                for (i, amplitude) in state_vector.iter().enumerate() {
666                    let probability = amplitude.norm_sqr();
667                    let n = fock_states[i].photon_numbers[mode] as f64;
668                    expectation += probability * n;
669                }
670
671                Ok(expectation)
672            }
673            PhotonicState::Coherent { amplitudes, .. } => {
674                if mode < amplitudes.len() {
675                    Ok(amplitudes[mode].norm_sqr())
676                } else {
677                    Ok(0.0)
678                }
679            }
680            _ => Err(SimulatorError::UnsupportedOperation(
681                "Photon number measurement not supported for this state".to_string(),
682            )),
683        }
684    }
685
686    /// Calculate photon number distribution
687    pub fn photon_distribution(&self, mode: usize) -> Result<Vec<f64>> {
688        match &self.state {
689            PhotonicState::Fock(state_vector) => {
690                let fock_states = self.enumerate_fock_states()?;
691                let mut distribution = vec![0.0; self.config.max_photon_number + 1];
692
693                for (i, amplitude) in state_vector.iter().enumerate() {
694                    let probability = amplitude.norm_sqr();
695                    let n = fock_states[i].photon_numbers[mode];
696                    if n <= self.config.max_photon_number {
697                        distribution[n] += probability;
698                    }
699                }
700
701                Ok(distribution)
702            }
703            _ => Err(SimulatorError::UnsupportedOperation(
704                "Photon distribution not supported for this state".to_string(),
705            )),
706        }
707    }
708
709    /// Calculate Wigner function
710    pub fn wigner_function(&self) -> Result<Array2<f64>> {
711        match &self.state {
712            PhotonicState::Wigner {
713                function_values, ..
714            } => Ok(function_values.mapv(|z| z.re)),
715            PhotonicState::Fock(state_vector) => {
716                if self.config.num_modes != 1 {
717                    return Err(SimulatorError::UnsupportedOperation(
718                        "Wigner function calculation only supported for single mode".to_string(),
719                    ));
720                }
721
722                let grid_size = self.config.wigner_grid_size;
723                let range = self.config.phase_space_range;
724                let mut wigner = Array2::zeros((grid_size, grid_size));
725
726                for i in 0..grid_size {
727                    for j in 0..grid_size {
728                        let q = -range + 2.0 * range * i as f64 / (grid_size - 1) as f64;
729                        let p = -range + 2.0 * range * j as f64 / (grid_size - 1) as f64;
730
731                        wigner[[i, j]] = self.calculate_wigner_point(q, p, state_vector)?;
732                    }
733                }
734
735                Ok(wigner)
736            }
737            _ => Err(SimulatorError::UnsupportedOperation(
738                "Wigner function not supported for this state representation".to_string(),
739            )),
740        }
741    }
742
743    /// Helper functions
744    fn calculate_fock_dimension(&self) -> Result<usize> {
745        // Calculate dimension of truncated Fock space
746        let n = self.config.max_photon_number;
747        let m = self.config.num_modes;
748
749        let dim = if m == 1 {
750            // For single mode: |0⟩, |1⟩, ..., |n⟩
751            n + 1
752        } else {
753            // For multimode: multinomial coefficient (n + m - 1) choose (m - 1)
754            Self::binomial_coefficient(n + m - 1, m - 1)
755        };
756
757        if dim > 1_000_000 {
758            return Err(SimulatorError::InvalidInput(
759                "Fock space dimension too large".to_string(),
760            ));
761        }
762
763        Ok(dim)
764    }
765
766    fn enumerate_fock_states(&self) -> Result<Vec<FockState>> {
767        let mut states = Vec::new();
768        let max_n = self.config.max_photon_number;
769        let num_modes = self.config.num_modes;
770
771        // Generate all Fock states up to max photon number
772        self.generate_fock_states_recursive(&mut states, &mut vec![0; num_modes], 0, 0, max_n);
773
774        Ok(states)
775    }
776
777    fn generate_fock_states_recursive(
778        &self,
779        states: &mut Vec<FockState>,
780        current_state: &mut Vec<usize>,
781        mode: usize,
782        current_total: usize,
783        max_total: usize,
784    ) {
785        if mode == self.config.num_modes {
786            states.push(FockState::new(current_state.clone()));
787            return;
788        }
789
790        for n in 0..=(max_total - current_total) {
791            current_state[mode] = n;
792            self.generate_fock_states_recursive(
793                states,
794                current_state,
795                mode + 1,
796                current_total + n,
797                max_total,
798            );
799        }
800    }
801
802    fn get_state_index(&self, state: &FockState, fock_states: &[FockState]) -> Option<usize> {
803        self.basis_cache
804            .get(state)
805            .copied()
806            .or_else(|| fock_states.iter().position(|s| s == state))
807    }
808
809    fn calculate_squeezed_amplitude(&self, n: usize, r: f64, phi: f64) -> Complex64 {
810        if n % 2 != 0 {
811            return Complex64::new(0.0, 0.0);
812        }
813
814        let m = n / 2;
815        let tanh_r = r.tanh();
816        let sech_r = 1.0 / r.cosh();
817
818        let amplitude = sech_r.sqrt()
819            * (-tanh_r).powi(m as i32)
820            * Complex64::new(0.0, m as f64 * phi).exp()
821            * Self::double_factorial(2 * m - 1)
822            / Self::factorial(m)
823            * tanh_r.powf(m as f64);
824
825        amplitude
826    }
827
828    fn build_displacement_matrix(
829        &self,
830        mode: usize,
831        alpha: Complex64,
832    ) -> Result<Array2<Complex64>> {
833        let dim = self.calculate_fock_dimension()?;
834        let mut matrix = Array2::zeros((dim, dim));
835
836        // Build displacement matrix in Fock basis
837        // This is a simplified implementation
838        for i in 0..dim {
839            matrix[[i, i]] = Complex64::new(1.0, 0.0);
840        }
841
842        Ok(matrix)
843    }
844
845    fn build_squeezing_matrix(&self, mode: usize, xi: Complex64) -> Result<Array2<Complex64>> {
846        let dim = self.calculate_fock_dimension()?;
847        let mut matrix = Array2::eye(dim);
848
849        // Simplified squeezing matrix implementation
850        Ok(matrix.mapv(|x| Complex64::new(x, 0.0)))
851    }
852
853    fn build_beam_splitter_matrix(
854        &self,
855        mode1: usize,
856        mode2: usize,
857        theta: f64,
858    ) -> Result<Array2<Complex64>> {
859        let dim = self.calculate_fock_dimension()?;
860        let mut matrix = Array2::eye(dim);
861
862        // Simplified beam splitter matrix implementation
863        Ok(matrix.mapv(|x| Complex64::new(x, 0.0)))
864    }
865
866    fn calculate_wigner_point(&self, q: f64, p: f64, state: &Array1<Complex64>) -> Result<f64> {
867        // Simplified Wigner function calculation
868        let alpha = Complex64::new(q, p) / 2.0_f64.sqrt();
869        let displacement_state = self.apply_displacement_to_state(state, alpha)?;
870
871        // Parity operator expectation value
872        let parity = self.calculate_parity_expectation(&displacement_state)?;
873
874        Ok(2.0 * parity / std::f64::consts::PI)
875    }
876
877    fn apply_displacement_to_state(
878        &self,
879        state: &Array1<Complex64>,
880        alpha: Complex64,
881    ) -> Result<Array1<Complex64>> {
882        // Simplified displacement application
883        Ok(state.clone())
884    }
885
886    fn calculate_parity_expectation(&self, state: &Array1<Complex64>) -> Result<f64> {
887        // Simplified parity calculation
888        Ok(0.5)
889    }
890
891    // SciRS2-specific implementations
892
893    fn initialize_coherent_scirs2(&mut self, alpha: Complex64, mode: usize) -> Result<()> {
894        if let Some(_backend) = &mut self.backend {
895            // Use SciRS2's continuous variable representation
896            let dim = 1000; // Large effective dimension
897            let mut state_vector = Array1::zeros(dim);
898            state_vector[0] = Complex64::new(1.0, 0.0);
899            self.state = PhotonicState::Fock(state_vector);
900        } else {
901            self.initialize_coherent_state(alpha, mode)?;
902        }
903        Ok(())
904    }
905
906    fn apply_displacement_scirs2(&mut self, mode: usize, alpha: Complex64) -> Result<()> {
907        if let Some(_backend) = &mut self.backend {
908            // Use SciRS2's optimized displacement operators
909            // Fallback to standard implementation for now
910            self.apply_displacement_fock(mode, alpha)?;
911        } else {
912            self.apply_displacement_fock(mode, alpha)?;
913        }
914        Ok(())
915    }
916
917    fn initialize_coherent_wigner(&mut self, alpha: Complex64, mode: usize) -> Result<()> {
918        let grid_size = self.config.wigner_grid_size;
919        let range = self.config.phase_space_range;
920        let mut function_values = Array2::zeros((grid_size, grid_size));
921
922        // Coherent state Wigner function is a Gaussian centered at alpha
923        let q0 = alpha.re * 2.0_f64.sqrt();
924        let p0 = alpha.im * 2.0_f64.sqrt();
925
926        for i in 0..grid_size {
927            for j in 0..grid_size {
928                let q = -range + 2.0 * range * i as f64 / (grid_size - 1) as f64;
929                let p = -range + 2.0 * range * j as f64 / (grid_size - 1) as f64;
930
931                let gaussian = (-(q - q0).powi(2) - (p - p0).powi(2)).exp() / std::f64::consts::PI;
932                function_values[[i, j]] = Complex64::new(gaussian, 0.0);
933            }
934        }
935
936        let q_grid = Array1::linspace(-range, range, grid_size);
937        let p_grid = Array1::linspace(-range, range, grid_size);
938
939        self.state = PhotonicState::Wigner {
940            function_values,
941            q_grid,
942            p_grid,
943        };
944
945        Ok(())
946    }
947
948    // Mathematical helper functions
949
950    fn factorial(n: usize) -> f64 {
951        (1..=n).fold(1.0, |acc, x| acc * x as f64)
952    }
953
954    fn double_factorial(n: usize) -> f64 {
955        if n <= 1 {
956            1.0
957        } else {
958            n as f64 * Self::double_factorial(n - 2)
959        }
960    }
961
962    fn binomial_coefficient(n: usize, k: usize) -> usize {
963        if k > n {
964            0
965        } else if k == 0 || k == n {
966            1
967        } else {
968            (1..=k).fold(1, |acc, i| acc * (n - i + 1) / i)
969        }
970    }
971
972    /// Get current state
973    pub fn get_state(&self) -> &PhotonicState {
974        &self.state
975    }
976
977    /// Get configuration
978    pub fn get_config(&self) -> &PhotonicConfig {
979        &self.config
980    }
981
982    /// Set configuration
983    pub fn set_config(&mut self, config: PhotonicConfig) {
984        self.config = config;
985    }
986}
987
988/// Photonic utilities
989pub struct PhotonicUtils;
990
991impl PhotonicUtils {
992    /// Create cat state (superposition of coherent states)
993    pub fn cat_state(
994        alpha: Complex64,
995        phase: f64,
996    ) -> impl Fn(&mut PhotonicSimulator) -> Result<()> {
997        move |simulator: &mut PhotonicSimulator| -> Result<()> {
998            // Initialize as superposition of |α⟩ and |−α⟩
999            simulator.initialize_coherent_state(alpha, 0)?;
1000
1001            // This is a simplified implementation
1002            // Full cat state would require more complex superposition
1003            Ok(())
1004        }
1005    }
1006
1007    /// Calculate fidelity between two photonic states
1008    pub fn fidelity(state1: &PhotonicState, state2: &PhotonicState) -> Result<f64> {
1009        match (state1, state2) {
1010            (PhotonicState::Fock(s1), PhotonicState::Fock(s2)) => {
1011                if s1.len() != s2.len() {
1012                    return Err(SimulatorError::DimensionMismatch(
1013                        "State vectors have different dimensions".to_string(),
1014                    ));
1015                }
1016
1017                let overlap: Complex64 = s1.iter().zip(s2.iter()).map(|(a, b)| a.conj() * b).sum();
1018
1019                Ok(overlap.norm_sqr())
1020            }
1021            _ => Err(SimulatorError::UnsupportedOperation(
1022                "Fidelity calculation not supported for these state types".to_string(),
1023            )),
1024        }
1025    }
1026
1027    /// Calculate von Neumann entropy
1028    pub fn von_neumann_entropy(state: &PhotonicState) -> Result<f64> {
1029        match state {
1030            PhotonicState::Fock(state_vector) => {
1031                let probabilities: Vec<f64> = state_vector
1032                    .iter()
1033                    .map(|amp| amp.norm_sqr())
1034                    .filter(|&p| p > 1e-15)
1035                    .collect();
1036
1037                let entropy = -probabilities.iter().map(|&p| p * p.ln()).sum::<f64>();
1038
1039                Ok(entropy)
1040            }
1041            _ => Err(SimulatorError::UnsupportedOperation(
1042                "Entropy calculation not supported for this state type".to_string(),
1043            )),
1044        }
1045    }
1046}
1047
1048/// Benchmark photonic simulation methods
1049pub fn benchmark_photonic_methods(
1050    max_photon_number: usize,
1051    num_modes: usize,
1052) -> Result<HashMap<String, PhotonicStats>> {
1053    let mut results = HashMap::new();
1054
1055    let methods = vec![
1056        ("FockBasis", PhotonicMethod::FockBasis),
1057        ("CoherentBasis", PhotonicMethod::CoherentBasis),
1058        ("TruncatedFock", PhotonicMethod::TruncatedFock),
1059    ];
1060
1061    for (name, method) in methods {
1062        let config = PhotonicConfig {
1063            method,
1064            max_photon_number,
1065            num_modes,
1066            ..Default::default()
1067        };
1068
1069        let start_time = std::time::Instant::now();
1070        let mut simulator = PhotonicSimulator::new(config.clone())?;
1071        simulator.initialize_vacuum()?;
1072
1073        // Apply some operations
1074        simulator.apply_operator(PhotonicOperator::Creation(0))?;
1075        simulator.apply_operator(PhotonicOperator::Displacement(0, Complex64::new(1.0, 0.5)))?;
1076
1077        let execution_time = start_time.elapsed().as_secs_f64() * 1000.0;
1078
1079        let stats = PhotonicStats {
1080            execution_time_ms: execution_time,
1081            method_used: name.to_string(),
1082            basis_states_count: simulator.calculate_fock_dimension().unwrap_or(0),
1083            ..Default::default()
1084        };
1085
1086        results.insert(name.to_string(), stats);
1087    }
1088
1089    Ok(results)
1090}
1091
1092#[cfg(test)]
1093mod tests {
1094    use super::*;
1095    use approx::assert_abs_diff_eq;
1096
1097    #[test]
1098    fn test_photonic_config_default() {
1099        let config = PhotonicConfig::default();
1100        assert_eq!(config.method, PhotonicMethod::FockBasis);
1101        assert_eq!(config.max_photon_number, 20);
1102        assert_eq!(config.num_modes, 1);
1103    }
1104
1105    #[test]
1106    fn test_fock_state_creation() {
1107        let state = FockState::new(vec![2, 1, 0]);
1108        assert_eq!(state.total_photons(), 3);
1109        assert_eq!(state.photons_in_mode(0), 2);
1110        assert_eq!(state.photons_in_mode(1), 1);
1111        assert_eq!(state.photons_in_mode(2), 0);
1112    }
1113
1114    #[test]
1115    fn test_vacuum_state() {
1116        let vacuum = FockState::vacuum(3);
1117        assert_eq!(vacuum.total_photons(), 0);
1118        assert_eq!(vacuum.photons_in_mode(0), 0);
1119    }
1120
1121    #[test]
1122    fn test_single_photon_state() {
1123        let single = FockState::single_photon(1, 3);
1124        assert_eq!(single.total_photons(), 1);
1125        assert_eq!(single.photons_in_mode(1), 1);
1126        assert_eq!(single.photons_in_mode(0), 0);
1127    }
1128
1129    #[test]
1130    fn test_photonic_simulator_creation() {
1131        let config = PhotonicConfig::default();
1132        let simulator = PhotonicSimulator::new(config).unwrap();
1133        assert_eq!(simulator.config.num_modes, 1);
1134    }
1135
1136    #[test]
1137    fn test_vacuum_initialization() {
1138        let config = PhotonicConfig::default();
1139        let mut simulator = PhotonicSimulator::new(config).unwrap();
1140        simulator.initialize_vacuum().unwrap();
1141
1142        if let PhotonicState::Fock(state) = &simulator.state {
1143            assert_abs_diff_eq!(state[0].norm(), 1.0, epsilon = 1e-10);
1144        }
1145    }
1146
1147    #[test]
1148    fn test_coherent_state_initialization() {
1149        let config = PhotonicConfig {
1150            max_photon_number: 10,
1151            ..Default::default()
1152        };
1153        let mut simulator = PhotonicSimulator::new(config).unwrap();
1154        let alpha = Complex64::new(1.0, 0.5);
1155
1156        simulator.initialize_coherent_state(alpha, 0).unwrap();
1157
1158        // Verify state is normalized
1159        if let PhotonicState::Fock(state) = &simulator.state {
1160            let norm_sqr = state.iter().map(|x| x.norm_sqr()).sum::<f64>();
1161            assert_abs_diff_eq!(norm_sqr, 1.0, epsilon = 1e-10);
1162        }
1163    }
1164
1165    #[test]
1166    fn test_creation_operator() {
1167        let config = PhotonicConfig {
1168            max_photon_number: 5,
1169            ..Default::default()
1170        };
1171        let mut simulator = PhotonicSimulator::new(config).unwrap();
1172        simulator.initialize_vacuum().unwrap();
1173
1174        // Apply creation operator
1175        simulator
1176            .apply_operator(PhotonicOperator::Creation(0))
1177            .unwrap();
1178
1179        // Should now be in |1⟩ state
1180        let photon_number = simulator.measure_photon_number(0).unwrap();
1181        assert_abs_diff_eq!(photon_number, 1.0, epsilon = 1e-10);
1182    }
1183
1184    #[test]
1185    fn test_photon_number_measurement() {
1186        let config = PhotonicConfig {
1187            max_photon_number: 5,
1188            ..Default::default()
1189        };
1190        let mut simulator = PhotonicSimulator::new(config).unwrap();
1191        simulator.initialize_vacuum().unwrap();
1192
1193        // Apply first creation operator: |0⟩ -> |1⟩
1194        simulator
1195            .apply_operator(PhotonicOperator::Creation(0))
1196            .unwrap();
1197        let photon_number_1 = simulator.measure_photon_number(0).unwrap();
1198        assert_abs_diff_eq!(photon_number_1, 1.0, epsilon = 1e-10);
1199
1200        // Apply second creation operator: |1⟩ -> √2 |2⟩
1201        simulator
1202            .apply_operator(PhotonicOperator::Creation(0))
1203            .unwrap();
1204        let photon_number_2 = simulator.measure_photon_number(0).unwrap();
1205        assert_abs_diff_eq!(photon_number_2, 2.0, epsilon = 1e-10);
1206    }
1207
1208    #[test]
1209    fn test_photon_distribution() {
1210        let config = PhotonicConfig {
1211            max_photon_number: 3,
1212            ..Default::default()
1213        };
1214        let mut simulator = PhotonicSimulator::new(config).unwrap();
1215        simulator.initialize_vacuum().unwrap();
1216
1217        let distribution = simulator.photon_distribution(0).unwrap();
1218
1219        // Vacuum state should have probability 1 for n=0
1220        assert_abs_diff_eq!(distribution[0], 1.0, epsilon = 1e-10);
1221        assert_abs_diff_eq!(distribution[1], 0.0, epsilon = 1e-10);
1222    }
1223
1224    #[test]
1225    fn test_mathematical_helpers() {
1226        assert_abs_diff_eq!(PhotonicSimulator::factorial(0), 1.0, epsilon = 1e-10);
1227        assert_abs_diff_eq!(PhotonicSimulator::factorial(5), 120.0, epsilon = 1e-10);
1228
1229        assert_eq!(PhotonicSimulator::binomial_coefficient(5, 2), 10);
1230        assert_eq!(PhotonicSimulator::binomial_coefficient(4, 0), 1);
1231    }
1232}