quantrs2_device/photonic/
cv_gates.rs

1//! Continuous Variable Gate Operations
2//!
3//! This module implements specific gate operations for continuous variable quantum computing,
4//! including displacement, squeezing, beamsplitters, and non-linear operations.
5
6use serde::{Deserialize, Serialize};
7use std::f64::consts::{PI, SQRT_2};
8use thiserror::Error;
9
10use super::continuous_variable::{CVError, CVResult, Complex, GaussianState};
11
12/// CV Gate operation errors
13#[derive(Error, Debug)]
14pub enum CVGateError {
15    #[error("Invalid gate parameter: {0}")]
16    InvalidParameter(String),
17    #[error("Gate not supported: {0}")]
18    UnsupportedGate(String),
19    #[error("Mode index out of bounds: {0}")]
20    ModeOutOfBounds(usize),
21}
22
23/// Types of CV gates
24#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
25pub enum CVGateType {
26    /// Displacement gate D(α)
27    Displacement,
28    /// Single-mode squeezing S(r,φ)
29    Squeezing,
30    /// Two-mode squeezing S₂(r,φ)
31    TwoModeSqueezing,
32    /// Beamsplitter BS(θ,φ)
33    Beamsplitter,
34    /// Phase rotation R(φ)
35    PhaseRotation,
36    /// Kerr interaction K(κ)
37    Kerr,
38    /// Cross-Kerr interaction CK(κ)
39    CrossKerr,
40    /// Cubic phase gate V(γ)
41    CubicPhase,
42    /// Position measurement
43    PositionMeasurement,
44    /// Momentum measurement
45    MomentumMeasurement,
46    /// Homodyne measurement
47    HomodyneMeasurement,
48    /// Heterodyne measurement
49    HeterodyneMeasurement,
50}
51
52/// CV gate parameters
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct CVGateParams {
55    /// Gate type
56    pub gate_type: CVGateType,
57    /// Target mode(s)
58    pub modes: Vec<usize>,
59    /// Gate parameters (interpretation depends on gate type)
60    pub params: Vec<f64>,
61    /// Complex parameters (for displacement, etc.)
62    pub complex_params: Vec<Complex>,
63    /// Gate duration (for time-dependent gates)
64    pub duration: Option<f64>,
65    /// Gate fidelity
66    pub fidelity: Option<f64>,
67}
68
69/// Displacement gate implementation
70pub struct DisplacementGate {
71    /// Displacement amplitude
72    pub alpha: Complex,
73    /// Target mode
74    pub mode: usize,
75}
76
77impl DisplacementGate {
78    pub const fn new(alpha: Complex, mode: usize) -> Self {
79        Self { alpha, mode }
80    }
81
82    /// Apply displacement to state
83    pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
84        state.displace(self.alpha, self.mode)
85    }
86
87    /// Get gate matrix representation (for smaller Fock spaces)
88    pub fn matrix(&self, cutoff: usize) -> Vec<Vec<Complex>> {
89        let mut matrix = vec![vec![Complex::new(0.0, 0.0); cutoff]; cutoff];
90
91        for n in 0..cutoff {
92            for m in 0..cutoff {
93                // Displacement matrix element <m|D(α)|n>
94                let element = self.displacement_matrix_element(m, n, cutoff);
95                matrix[m][n] = element;
96            }
97        }
98
99        matrix
100    }
101
102    const fn displacement_matrix_element(&self, m: usize, n: usize, cutoff: usize) -> Complex {
103        // Simplified calculation - full implementation would use Laguerre polynomials
104        if m == n {
105            Complex::new(1.0, 0.0)
106        } else {
107            Complex::new(0.0, 0.0)
108        }
109    }
110
111    /// Get inverse displacement
112    #[must_use]
113    pub fn inverse(&self) -> Self {
114        Self {
115            alpha: Complex::new(-self.alpha.real, -self.alpha.imag),
116            mode: self.mode,
117        }
118    }
119}
120
121/// Squeezing gate implementation
122pub struct SqueezingGate {
123    /// Squeezing parameter
124    pub r: f64,
125    /// Squeezing angle
126    pub phi: f64,
127    /// Target mode
128    pub mode: usize,
129}
130
131impl SqueezingGate {
132    pub fn new(r: f64, phi: f64, mode: usize) -> Result<Self, CVGateError> {
133        if r.abs() > 20.0 {
134            return Err(CVGateError::InvalidParameter(
135                "Squeezing parameter too large".to_string(),
136            ));
137        }
138
139        Ok(Self { r, phi, mode })
140    }
141
142    /// Apply squeezing to state
143    pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
144        state.squeeze(self.r, self.phi, self.mode)
145    }
146
147    /// Get squeezing in dB
148    pub fn squeezing_db(&self) -> f64 {
149        10.0 * self.r.abs() / 2.0_f64.log(10.0_f64)
150    }
151
152    /// Create amplitude squeezing (φ=0)
153    pub fn amplitude_squeezing(r: f64, mode: usize) -> Result<Self, CVGateError> {
154        Self::new(r, 0.0, mode)
155    }
156
157    /// Create phase squeezing (φ=π/2)
158    pub fn phase_squeezing(r: f64, mode: usize) -> Result<Self, CVGateError> {
159        Self::new(r, PI / 2.0, mode)
160    }
161}
162
163/// Two-mode squeezing gate implementation
164pub struct TwoModeSqueezingGate {
165    /// Squeezing parameter
166    pub r: f64,
167    /// Squeezing phase
168    pub phi: f64,
169    /// First mode
170    pub mode1: usize,
171    /// Second mode
172    pub mode2: usize,
173}
174
175impl TwoModeSqueezingGate {
176    pub fn new(r: f64, phi: f64, mode1: usize, mode2: usize) -> Result<Self, CVGateError> {
177        if mode1 == mode2 {
178            return Err(CVGateError::InvalidParameter(
179                "Two-mode squeezing requires different modes".to_string(),
180            ));
181        }
182
183        if r.abs() > 20.0 {
184            return Err(CVGateError::InvalidParameter(
185                "Squeezing parameter too large".to_string(),
186            ));
187        }
188
189        Ok(Self {
190            r,
191            phi,
192            mode1,
193            mode2,
194        })
195    }
196
197    /// Apply two-mode squeezing to state
198    pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
199        state.two_mode_squeeze(self.r, self.phi, self.mode1, self.mode2)
200    }
201
202    /// Get entanglement strength
203    pub fn entanglement_strength(&self) -> f64 {
204        // Logarithmic negativity approximation
205        2.0 * self.r.abs()
206    }
207}
208
209/// Beamsplitter gate implementation
210pub struct BeamsplitterGate {
211    /// Transmission angle
212    pub theta: f64,
213    /// Phase
214    pub phi: f64,
215    /// First input mode
216    pub mode1: usize,
217    /// Second input mode
218    pub mode2: usize,
219}
220
221impl BeamsplitterGate {
222    pub fn new(theta: f64, phi: f64, mode1: usize, mode2: usize) -> Result<Self, CVGateError> {
223        if mode1 == mode2 {
224            return Err(CVGateError::InvalidParameter(
225                "Beamsplitter requires different modes".to_string(),
226            ));
227        }
228
229        Ok(Self {
230            theta,
231            phi,
232            mode1,
233            mode2,
234        })
235    }
236
237    /// Apply beamsplitter to state
238    pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
239        state.beamsplitter(self.theta, self.phi, self.mode1, self.mode2)
240    }
241
242    /// Create 50:50 beamsplitter
243    pub fn fifty_fifty(mode1: usize, mode2: usize) -> Result<Self, CVGateError> {
244        Self::new(PI / 4.0, 0.0, mode1, mode2)
245    }
246
247    /// Get transmission coefficient
248    pub fn transmission(&self) -> f64 {
249        self.theta.cos().powi(2)
250    }
251
252    /// Get reflection coefficient
253    pub fn reflection(&self) -> f64 {
254        self.theta.sin().powi(2)
255    }
256
257    /// Create variable beamsplitter with transmission T
258    pub fn with_transmission(
259        transmission: f64,
260        phi: f64,
261        mode1: usize,
262        mode2: usize,
263    ) -> Result<Self, CVGateError> {
264        if !(0.0..=1.0).contains(&transmission) {
265            return Err(CVGateError::InvalidParameter(
266                "Transmission must be between 0 and 1".to_string(),
267            ));
268        }
269
270        let theta = transmission.sqrt().acos();
271        Self::new(theta, phi, mode1, mode2)
272    }
273}
274
275/// Phase rotation gate implementation
276pub struct PhaseRotationGate {
277    /// Rotation angle
278    pub phi: f64,
279    /// Target mode
280    pub mode: usize,
281}
282
283impl PhaseRotationGate {
284    pub const fn new(phi: f64, mode: usize) -> Self {
285        Self { phi, mode }
286    }
287
288    /// Apply phase rotation to state
289    pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
290        state.phase_rotation(self.phi, self.mode)
291    }
292
293    /// Normalize phase to [0, 2π)
294    pub fn normalized_phase(&self) -> f64 {
295        self.phi.rem_euclid(2.0 * PI)
296    }
297}
298
299/// Kerr gate implementation (non-linear)
300pub struct KerrGate {
301    /// Kerr parameter
302    pub kappa: f64,
303    /// Target mode
304    pub mode: usize,
305    /// Interaction time
306    pub time: f64,
307}
308
309impl KerrGate {
310    pub const fn new(kappa: f64, mode: usize, time: f64) -> Self {
311        Self { kappa, mode, time }
312    }
313
314    /// Apply Kerr interaction (approximation for Gaussian states)
315    pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
316        // Kerr interaction is non-Gaussian, so this is an approximation
317        // In practice, this would require non-Gaussian state representation
318
319        // Apply phase shift proportional to photon number
320        let n_avg = state.average_photon_number(self.mode)?;
321        let phase_shift = self.kappa * n_avg * self.time;
322
323        state.phase_rotation(phase_shift, self.mode)
324    }
325
326    /// Get effective phase shift
327    pub fn phase_shift(&self, photon_number: f64) -> f64 {
328        self.kappa * photon_number * self.time
329    }
330}
331
332/// Cross-Kerr gate implementation
333pub struct CrossKerrGate {
334    /// Cross-Kerr parameter
335    pub kappa: f64,
336    /// First mode
337    pub mode1: usize,
338    /// Second mode
339    pub mode2: usize,
340    /// Interaction time
341    pub time: f64,
342}
343
344impl CrossKerrGate {
345    pub fn new(kappa: f64, mode1: usize, mode2: usize, time: f64) -> Result<Self, CVGateError> {
346        if mode1 == mode2 {
347            return Err(CVGateError::InvalidParameter(
348                "Cross-Kerr requires different modes".to_string(),
349            ));
350        }
351
352        Ok(Self {
353            kappa,
354            mode1,
355            mode2,
356            time,
357        })
358    }
359
360    /// Apply Cross-Kerr interaction (approximation)
361    pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
362        // Cross-Kerr is non-Gaussian, approximation for Gaussian states
363        let n1 = state.average_photon_number(self.mode1)?;
364        let n2 = state.average_photon_number(self.mode2)?;
365
366        // Apply conditional phase shifts
367        let phase_shift1 = self.kappa * n2 * self.time;
368        let phase_shift2 = self.kappa * n1 * self.time;
369
370        state.phase_rotation(phase_shift1, self.mode1)?;
371        state.phase_rotation(phase_shift2, self.mode2)?;
372
373        Ok(())
374    }
375
376    /// Get conditional phase shift
377    pub fn conditional_phase_shift(&self, control_photons: f64) -> f64 {
378        self.kappa * control_photons * self.time
379    }
380}
381
382/// Cubic phase gate implementation (non-Gaussian)
383pub struct CubicPhaseGate {
384    /// Cubic parameter
385    pub gamma: f64,
386    /// Target mode
387    pub mode: usize,
388}
389
390impl CubicPhaseGate {
391    pub const fn new(gamma: f64, mode: usize) -> Self {
392        Self { gamma, mode }
393    }
394
395    /// Apply cubic phase (this breaks Gaussianity)
396    pub fn apply(&self, _state: &mut GaussianState) -> CVResult<()> {
397        // Cubic phase gate makes the state non-Gaussian
398        // This would require a more general state representation
399        Err(CVError::IncompatibleOperation(
400            "Cubic phase gate is non-Gaussian and not supported for Gaussian states".to_string(),
401        ))
402    }
403}
404
405/// Gate sequence builder for CV operations
406pub struct CVGateSequence {
407    /// Sequence of gates
408    pub gates: Vec<CVGateParams>,
409    /// Number of modes
410    pub num_modes: usize,
411}
412
413impl CVGateSequence {
414    pub const fn new(num_modes: usize) -> Self {
415        Self {
416            gates: Vec::new(),
417            num_modes,
418        }
419    }
420
421    /// Add displacement gate
422    pub fn displacement(&mut self, alpha: Complex, mode: usize) -> Result<&mut Self, CVGateError> {
423        if mode >= self.num_modes {
424            return Err(CVGateError::ModeOutOfBounds(mode));
425        }
426
427        self.gates.push(CVGateParams {
428            gate_type: CVGateType::Displacement,
429            modes: vec![mode],
430            params: vec![],
431            complex_params: vec![alpha],
432            duration: None,
433            fidelity: Some(0.99),
434        });
435
436        Ok(self)
437    }
438
439    /// Add squeezing gate
440    pub fn squeezing(&mut self, r: f64, phi: f64, mode: usize) -> Result<&mut Self, CVGateError> {
441        if mode >= self.num_modes {
442            return Err(CVGateError::ModeOutOfBounds(mode));
443        }
444
445        self.gates.push(CVGateParams {
446            gate_type: CVGateType::Squeezing,
447            modes: vec![mode],
448            params: vec![r, phi],
449            complex_params: vec![],
450            duration: None,
451            fidelity: Some(0.98),
452        });
453
454        Ok(self)
455    }
456
457    /// Add two-mode squeezing gate
458    pub fn two_mode_squeezing(
459        &mut self,
460        r: f64,
461        phi: f64,
462        mode1: usize,
463        mode2: usize,
464    ) -> Result<&mut Self, CVGateError> {
465        if mode1 >= self.num_modes || mode2 >= self.num_modes {
466            return Err(CVGateError::ModeOutOfBounds(mode1.max(mode2)));
467        }
468
469        self.gates.push(CVGateParams {
470            gate_type: CVGateType::TwoModeSqueezing,
471            modes: vec![mode1, mode2],
472            params: vec![r, phi],
473            complex_params: vec![],
474            duration: None,
475            fidelity: Some(0.97),
476        });
477
478        Ok(self)
479    }
480
481    /// Add beamsplitter gate
482    pub fn beamsplitter(
483        &mut self,
484        theta: f64,
485        phi: f64,
486        mode1: usize,
487        mode2: usize,
488    ) -> Result<&mut Self, CVGateError> {
489        if mode1 >= self.num_modes || mode2 >= self.num_modes {
490            return Err(CVGateError::ModeOutOfBounds(mode1.max(mode2)));
491        }
492
493        self.gates.push(CVGateParams {
494            gate_type: CVGateType::Beamsplitter,
495            modes: vec![mode1, mode2],
496            params: vec![theta, phi],
497            complex_params: vec![],
498            duration: None,
499            fidelity: Some(0.995),
500        });
501
502        Ok(self)
503    }
504
505    /// Add phase rotation gate
506    pub fn phase_rotation(&mut self, phi: f64, mode: usize) -> Result<&mut Self, CVGateError> {
507        if mode >= self.num_modes {
508            return Err(CVGateError::ModeOutOfBounds(mode));
509        }
510
511        self.gates.push(CVGateParams {
512            gate_type: CVGateType::PhaseRotation,
513            modes: vec![mode],
514            params: vec![phi],
515            complex_params: vec![],
516            duration: None,
517            fidelity: Some(0.999),
518        });
519
520        Ok(self)
521    }
522
523    /// Apply entire sequence to a state
524    pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
525        for gate in &self.gates {
526            match gate.gate_type {
527                CVGateType::Displacement => {
528                    if let (Some(alpha), Some(&mode)) =
529                        (gate.complex_params.first(), gate.modes.first())
530                    {
531                        state.displace(*alpha, mode)?;
532                    }
533                }
534                CVGateType::Squeezing => {
535                    if let (Some(&r), Some(&phi), Some(&mode)) =
536                        (gate.params.first(), gate.params.get(1), gate.modes.first())
537                    {
538                        state.squeeze(r, phi, mode)?;
539                    }
540                }
541                CVGateType::TwoModeSqueezing => {
542                    if let (Some(&r), Some(&phi), Some(&mode1), Some(&mode2)) = (
543                        gate.params.first(),
544                        gate.params.get(1),
545                        gate.modes.first(),
546                        gate.modes.get(1),
547                    ) {
548                        state.two_mode_squeeze(r, phi, mode1, mode2)?;
549                    }
550                }
551                CVGateType::Beamsplitter => {
552                    if let (Some(&theta), Some(&phi), Some(&mode1), Some(&mode2)) = (
553                        gate.params.first(),
554                        gate.params.get(1),
555                        gate.modes.first(),
556                        gate.modes.get(1),
557                    ) {
558                        state.beamsplitter(theta, phi, mode1, mode2)?;
559                    }
560                }
561                CVGateType::PhaseRotation => {
562                    if let (Some(&phi), Some(&mode)) = (gate.params.first(), gate.modes.first()) {
563                        state.phase_rotation(phi, mode)?;
564                    }
565                }
566                _ => {
567                    return Err(CVError::IncompatibleOperation(format!(
568                        "Gate type {:?} not yet implemented",
569                        gate.gate_type
570                    )));
571                }
572            }
573        }
574
575        Ok(())
576    }
577
578    /// Get total sequence fidelity
579    pub fn total_fidelity(&self) -> f64 {
580        self.gates
581            .iter()
582            .map(|gate| gate.fidelity.unwrap_or(1.0))
583            .product()
584    }
585
586    /// Get gate count by type
587    pub fn gate_count(&self, gate_type: CVGateType) -> usize {
588        self.gates
589            .iter()
590            .filter(|gate| gate.gate_type == gate_type)
591            .count()
592    }
593
594    /// Optimize sequence (basic optimization)
595    pub fn optimize(&mut self) -> Result<(), CVGateError> {
596        // Remove redundant identity operations
597        self.gates.retain(|gate| match gate.gate_type {
598            CVGateType::PhaseRotation => {
599                if let Some(&phi) = gate.params.first() {
600                    (phi % (2.0 * PI)).abs() > 1e-10
601                } else {
602                    true
603                }
604            }
605            CVGateType::Displacement => gate
606                .complex_params
607                .first()
608                .map_or(true, |alpha| alpha.magnitude() > 1e-10),
609            _ => true,
610        });
611
612        // Combine consecutive phase rotations on same mode
613        // TODO: Implement more sophisticated optimizations
614
615        Ok(())
616    }
617}
618
619#[cfg(test)]
620mod tests {
621    use super::*;
622    use crate::photonic::continuous_variable::GaussianState;
623
624    #[test]
625    fn test_displacement_gate() {
626        let alpha = Complex::new(1.0, 0.5);
627        let gate = DisplacementGate::new(alpha, 0);
628        let mut state = GaussianState::vacuum(1);
629
630        gate.apply(&mut state)
631            .expect("Displacement gate application should succeed");
632
633        assert!((state.mean[0] - alpha.real * SQRT_2).abs() < 1e-10);
634        assert!((state.mean[1] - alpha.imag * SQRT_2).abs() < 1e-10);
635    }
636
637    #[test]
638    fn test_squeezing_gate() {
639        let gate = SqueezingGate::new(1.0, 0.0, 0).expect("Squeezing gate creation should succeed");
640        let mut state = GaussianState::vacuum(1);
641
642        gate.apply(&mut state)
643            .expect("Squeezing gate application should succeed");
644
645        // Check that X quadrature is squeezed
646        assert!(state.covariance[0][0] < 0.5);
647        assert!(state.covariance[1][1] > 0.5);
648    }
649
650    #[test]
651    fn test_beamsplitter_gate() {
652        let gate = BeamsplitterGate::fifty_fifty(0, 1)
653            .expect("50:50 beamsplitter creation should succeed");
654        let mut state = GaussianState::coherent(Complex::new(2.0, 0.0), 0, 2)
655            .expect("Coherent state creation should succeed");
656
657        gate.apply(&mut state)
658            .expect("Beamsplitter gate application should succeed");
659
660        // Check that amplitude is distributed
661        assert!(state.mean[0].abs() > 0.0);
662        assert!(state.mean[2].abs() > 0.0);
663        assert!((state.mean[0].abs() - state.mean[2].abs()).abs() < 1e-10);
664    }
665
666    #[test]
667    fn test_gate_sequence() {
668        let mut sequence = CVGateSequence::new(2);
669
670        sequence
671            .displacement(Complex::new(1.0, 0.0), 0)
672            .expect("Adding displacement gate should succeed")
673            .squeezing(0.5, 0.0, 0)
674            .expect("Adding squeezing gate should succeed")
675            .beamsplitter(PI / 4.0, 0.0, 0, 1)
676            .expect("Adding beamsplitter gate should succeed");
677
678        assert_eq!(sequence.gates.len(), 3);
679        assert_eq!(sequence.gate_count(CVGateType::Displacement), 1);
680        assert_eq!(sequence.gate_count(CVGateType::Squeezing), 1);
681        assert_eq!(sequence.gate_count(CVGateType::Beamsplitter), 1);
682    }
683
684    #[test]
685    fn test_sequence_application() {
686        let mut sequence = CVGateSequence::new(1);
687        sequence
688            .displacement(Complex::new(1.0, 0.0), 0)
689            .expect("Adding displacement gate should succeed")
690            .phase_rotation(PI / 2.0, 0)
691            .expect("Adding phase rotation gate should succeed");
692
693        let mut state = GaussianState::vacuum(1);
694        sequence
695            .apply(&mut state)
696            .expect("Gate sequence application should succeed");
697
698        // State should be displaced and rotated
699        assert!(state.mean[0].abs() > 0.0 || state.mean[1].abs() > 0.0);
700    }
701
702    #[test]
703    fn test_sequence_optimization() {
704        let mut sequence = CVGateSequence::new(1);
705        sequence
706            .displacement(Complex::new(0.0, 0.0), 0)
707            .expect("Adding zero displacement should succeed") // Zero displacement
708            .phase_rotation(0.0, 0)
709            .expect("Adding zero phase rotation should succeed"); // Zero rotation
710
711        sequence
712            .optimize()
713            .expect("Gate sequence optimization should succeed");
714
715        // Should remove identity operations
716        assert_eq!(sequence.gates.len(), 0);
717    }
718}