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 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/// 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    #[must_use]
100    pub const fn new(photon_numbers: Vec<usize>) -> Self {
101        Self { photon_numbers }
102    }
103
104    /// Create vacuum state
105    #[must_use]
106    pub fn vacuum(num_modes: usize) -> Self {
107        Self::new(vec![0; num_modes])
108    }
109
110    /// Create single-photon state in given mode
111    #[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    /// Total photon number
119    #[must_use]
120    pub fn total_photons(&self) -> usize {
121        self.photon_numbers.iter().sum()
122    }
123
124    /// Get photon number in specific mode
125    #[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/// Photonic operators
132#[derive(Debug, Clone)]
133pub enum PhotonicOperator {
134    /// Creation operator a†
135    Creation(usize), // mode index
136    /// Annihilation operator a
137    Annihilation(usize), // mode index
138    /// Number operator a†a
139    Number(usize), // mode index
140    /// Displacement operator D(α)
141    Displacement(usize, Complex64), // mode, amplitude
142    /// Squeezing operator S(ξ)
143    Squeezing(usize, Complex64), // mode, squeezing parameter
144    /// Beam splitter
145    BeamSplitter(usize, usize, f64), // mode1, mode2, transmittance
146    /// Phase shifter
147    PhaseShift(usize, f64), // mode, phase
148    /// Kerr nonlinearity
149    Kerr(usize, f64), // mode, strength
150}
151
152/// Photonic gate result
153#[derive(Debug, Clone, Serialize, Deserialize)]
154pub struct PhotonicResult {
155    /// Final state
156    pub final_state: Vec<Complex64>,
157    /// Expectation values of observables
158    pub expectation_values: HashMap<String, Complex64>,
159    /// Photon number distribution
160    pub photon_distribution: Vec<f64>,
161    /// Execution statistics
162    pub stats: PhotonicStats,
163}
164
165/// Photonic simulation statistics
166#[derive(Debug, Clone, Default, Serialize, Deserialize)]
167pub struct PhotonicStats {
168    /// Execution time in milliseconds
169    pub execution_time_ms: f64,
170    /// Memory usage in bytes
171    pub memory_usage_bytes: usize,
172    /// Number of basis states used
173    pub basis_states_count: usize,
174    /// Maximum photon number reached
175    pub max_photons_used: usize,
176    /// Fidelity with exact solution (if available)
177    pub fidelity: f64,
178    /// Method used
179    pub method_used: String,
180}
181
182/// Photonic quantum simulator
183pub struct PhotonicSimulator {
184    /// Configuration
185    config: PhotonicConfig,
186    /// Current state
187    state: PhotonicState,
188    /// `SciRS2` backend
189    backend: Option<SciRS2Backend>,
190    /// Basis state cache
191    basis_cache: HashMap<FockState, usize>,
192    /// Operator matrix cache
193    operator_cache: HashMap<String, Array2<Complex64>>,
194}
195
196impl PhotonicSimulator {
197    /// Create new photonic simulator
198    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    /// Initialize with `SciRS2` backend
211    pub fn with_backend(mut self) -> Result<Self> {
212        self.backend = Some(SciRS2Backend::new());
213        Ok(self)
214    }
215
216    /// Initialize vacuum state
217    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); // Vacuum state
223                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    /// Initialize coherent state |α⟩
257    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                // Generate coherent state in Fock basis
264                let displacement_factor = (-alpha.norm_sqr() / 2.0).exp();
265
266                // Enumerate Fock states and calculate amplitudes
267                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                // Normalize the truncated coherent state
280                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    /// Initialize squeezed state
312    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                // Generate squeezed vacuum state
322                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                        // Only even photon numbers for squeezed vacuum
331                        let amplitude = self.calculate_squeezed_amplitude(n, r, phi);
332                        state_vector[i] = amplitude;
333                    }
334                }
335
336                // Normalize
337                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    /// Apply photonic operator
369    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    /// Apply creation operator a†
389    fn apply_creation(&mut self, mode: usize) -> Result<()> {
390        // Get fock states first to avoid borrowing conflicts
391        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                // Normalize the state after applying creation operator
412                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    /// Apply annihilation operator a
436    fn apply_annihilation(&mut self, mode: usize) -> Result<()> {
437        // Get fock states first to avoid borrowing conflicts
438        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                // Normalize the state after applying annihilation operator
463                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    /// Apply number operator a†a
487    fn apply_number(&mut self, mode: usize) -> Result<()> {
488        // Get fock states first to avoid borrowing conflicts
489        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    /// Apply displacement operator D(α)
509    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    /// Apply displacement in Fock basis
531    fn apply_displacement_fock(&mut self, mode: usize, alpha: Complex64) -> Result<()> {
532        // Get displacement matrix first to avoid borrowing conflicts
533        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    /// Apply displacement in coherent basis
543    fn apply_displacement_coherent(&mut self, mode: usize, alpha: Complex64) -> Result<()> {
544        if let PhotonicState::Coherent { amplitudes, .. } = &mut self.state {
545            // In coherent basis, displacement just shifts the amplitude
546            if mode < amplitudes.len() {
547                amplitudes[mode] += alpha;
548            }
549        }
550        Ok(())
551    }
552
553    /// Apply squeezing operator S(ξ)
554    fn apply_squeezing(&mut self, mode: usize, xi: Complex64) -> Result<()> {
555        // Get squeezing matrix first to avoid borrowing conflicts
556        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    /// Apply beam splitter
574    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        // Get beam splitter matrix first to avoid borrowing conflicts
589        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    /// Apply phase shift
607    fn apply_phase_shift(&mut self, mode: usize, phase: f64) -> Result<()> {
608        // Get fock states first to avoid borrowing conflicts for Fock state case
609        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                // Safety: fock_states is Some() since we checked for Fock state above
618                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    /// Apply Kerr nonlinearity
642    fn apply_kerr(&mut self, mode: usize, strength: f64) -> Result<()> {
643        // Get fock states first to avoid borrowing conflicts
644        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    /// Measure photon number in given mode
665    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    /// Calculate photon number distribution
693    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    /// Calculate Wigner function
716    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    /// Helper functions
750    fn calculate_fock_dimension(&self) -> Result<usize> {
751        // Calculate dimension of truncated Fock space
752        let n = self.config.max_photon_number;
753        let m = self.config.num_modes;
754
755        let dim = if m == 1 {
756            // For single mode: |0⟩, |1⟩, ..., |n⟩
757            n + 1
758        } else {
759            // For multimode: multinomial coefficient (n + m - 1) choose (m - 1)
760            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        // Generate all Fock states up to max photon number
778        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        // Build displacement matrix in Fock basis
841        // This is a simplified implementation
842        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        // Simplified squeezing matrix implementation
854        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        // Simplified beam splitter matrix implementation
867        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        // Simplified Wigner function calculation
872        let alpha = Complex64::new(q, p) / 2.0_f64.sqrt();
873        let displacement_state = self.apply_displacement_to_state(state, alpha)?;
874
875        // Parity operator expectation value
876        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        // Simplified displacement application
887        Ok(state.clone())
888    }
889
890    const fn calculate_parity_expectation(&self, state: &Array1<Complex64>) -> Result<f64> {
891        // Simplified parity calculation
892        Ok(0.5)
893    }
894
895    // SciRS2-specific implementations
896
897    fn initialize_coherent_scirs2(&mut self, alpha: Complex64, mode: usize) -> Result<()> {
898        if let Some(_backend) = &mut self.backend {
899            // Use SciRS2's continuous variable representation
900            let dim = 1000; // Large effective dimension
901            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            // Use SciRS2's optimized displacement operators
913            // Fallback to standard implementation for now
914            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        // Coherent state Wigner function is a Gaussian centered at alpha
927        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    // Mathematical helper functions
954
955    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    /// Get current state
978    #[must_use]
979    pub const fn get_state(&self) -> &PhotonicState {
980        &self.state
981    }
982
983    /// Get configuration
984    #[must_use]
985    pub const fn get_config(&self) -> &PhotonicConfig {
986        &self.config
987    }
988
989    /// Set configuration
990    pub const fn set_config(&mut self, config: PhotonicConfig) {
991        self.config = config;
992    }
993}
994
995/// Photonic utilities
996pub struct PhotonicUtils;
997
998impl PhotonicUtils {
999    /// Create cat state (superposition of coherent states)
1000    pub fn cat_state(
1001        alpha: Complex64,
1002        phase: f64,
1003    ) -> impl Fn(&mut PhotonicSimulator) -> Result<()> {
1004        move |simulator: &mut PhotonicSimulator| -> Result<()> {
1005            // Initialize as superposition of |α⟩ and |−α⟩
1006            simulator.initialize_coherent_state(alpha, 0)?;
1007
1008            // This is a simplified implementation
1009            // Full cat state would require more complex superposition
1010            Ok(())
1011        }
1012    }
1013
1014    /// Calculate fidelity between two photonic states
1015    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    /// Calculate von Neumann entropy
1035    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
1055/// Benchmark photonic simulation methods
1056pub 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        // Apply some operations
1081        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        // Verify state is normalized
1172        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        // Apply creation operator
1191        simulator
1192            .apply_operator(PhotonicOperator::Creation(0))
1193            .expect("should apply creation operator");
1194
1195        // Should now be in |1⟩ state
1196        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        // Apply first creation operator: |0⟩ -> |1⟩
1215        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        // Apply second creation operator: |1⟩ -> √2 |2⟩
1224        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        // Vacuum state should have probability 1 for n=0
1250        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}