quantrs2_device/continuous_variable/
cv_gates.rs

1//! Continuous variable quantum gates
2//!
3//! This module implements the standard gate set for continuous variable quantum computing,
4//! including Gaussian operations and some non-Gaussian operations.
5
6use super::{Complex, GaussianState};
7use crate::{DeviceError, DeviceResult};
8use serde::{Deserialize, Serialize};
9use std::f64::consts::PI;
10
11/// Types of CV gates
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13pub enum CVGateType {
14    /// Displacement gate D(α)
15    Displacement { amplitude: Complex },
16    /// Squeezing gate S(r, φ)
17    Squeezing { parameter: f64, phase: f64 },
18    /// Two-mode squeezing gate S₂(r, φ)
19    TwoModeSqueezing { parameter: f64, phase: f64 },
20    /// Beamsplitter gate BS(θ, φ)
21    Beamsplitter { transmittance: f64, phase: f64 },
22    /// Phase rotation gate R(φ)
23    PhaseRotation { phase: f64 },
24    /// Controlled displacement gate CD(α)
25    ControlledDisplacement { amplitude: Complex },
26    /// Controlled phase gate CP(s)
27    ControlledPhase { parameter: f64 },
28    /// Cross-Kerr gate CK(κ)
29    CrossKerr { parameter: f64 },
30    /// Cubic phase gate V(γ)
31    CubicPhase { parameter: f64 },
32    /// Position measurement M_x(s)
33    PositionMeasurement { result: f64 },
34    /// Momentum measurement M_p(s)
35    MomentumMeasurement { result: f64 },
36}
37
38/// CV gate parameters for parameterized operations
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct CVGateParams {
41    /// Real parameters (amplitudes, phases, etc.)
42    pub real_params: Vec<f64>,
43    /// Complex parameters (displacements, etc.)
44    pub complex_params: Vec<Complex>,
45    /// Target modes
46    pub target_modes: Vec<usize>,
47    /// Control modes (if applicable)
48    pub control_modes: Vec<usize>,
49}
50
51/// Sequence of CV gates forming a quantum program
52#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct CVGateSequence {
54    /// Gates in the sequence
55    pub gates: Vec<(CVGateType, CVGateParams)>,
56    /// Total number of modes required
57    pub num_modes: usize,
58}
59
60impl CVGateSequence {
61    /// Create a new empty gate sequence
62    pub fn new(num_modes: usize) -> Self {
63        Self {
64            gates: Vec::new(),
65            num_modes,
66        }
67    }
68
69    /// Add a displacement gate
70    pub fn displacement(&mut self, mode: usize, amplitude: Complex) -> DeviceResult<()> {
71        if mode >= self.num_modes {
72            return Err(DeviceError::InvalidInput(format!(
73                "Mode {} exceeds sequence capacity",
74                mode
75            )));
76        }
77
78        self.gates.push((
79            CVGateType::Displacement { amplitude },
80            CVGateParams {
81                real_params: vec![amplitude.real, amplitude.imag],
82                complex_params: vec![amplitude],
83                target_modes: vec![mode],
84                control_modes: vec![],
85            },
86        ));
87
88        Ok(())
89    }
90
91    /// Add a squeezing gate
92    pub fn squeezing(&mut self, mode: usize, parameter: f64, phase: f64) -> DeviceResult<()> {
93        if mode >= self.num_modes {
94            return Err(DeviceError::InvalidInput(format!(
95                "Mode {} exceeds sequence capacity",
96                mode
97            )));
98        }
99
100        self.gates.push((
101            CVGateType::Squeezing { parameter, phase },
102            CVGateParams {
103                real_params: vec![parameter, phase],
104                complex_params: vec![],
105                target_modes: vec![mode],
106                control_modes: vec![],
107            },
108        ));
109
110        Ok(())
111    }
112
113    /// Add a two-mode squeezing gate
114    pub fn two_mode_squeezing(
115        &mut self,
116        mode1: usize,
117        mode2: usize,
118        parameter: f64,
119        phase: f64,
120    ) -> DeviceResult<()> {
121        if mode1 >= self.num_modes || mode2 >= self.num_modes {
122            return Err(DeviceError::InvalidInput(
123                "One or both modes exceed sequence capacity".to_string(),
124            ));
125        }
126
127        self.gates.push((
128            CVGateType::TwoModeSqueezing { parameter, phase },
129            CVGateParams {
130                real_params: vec![parameter, phase],
131                complex_params: vec![],
132                target_modes: vec![mode1, mode2],
133                control_modes: vec![],
134            },
135        ));
136
137        Ok(())
138    }
139
140    /// Add a beamsplitter gate
141    pub fn beamsplitter(
142        &mut self,
143        mode1: usize,
144        mode2: usize,
145        transmittance: f64,
146        phase: f64,
147    ) -> DeviceResult<()> {
148        if mode1 >= self.num_modes || mode2 >= self.num_modes {
149            return Err(DeviceError::InvalidInput(
150                "One or both modes exceed sequence capacity".to_string(),
151            ));
152        }
153
154        if transmittance < 0.0 || transmittance > 1.0 {
155            return Err(DeviceError::InvalidInput(
156                "Transmittance must be between 0 and 1".to_string(),
157            ));
158        }
159
160        self.gates.push((
161            CVGateType::Beamsplitter {
162                transmittance,
163                phase,
164            },
165            CVGateParams {
166                real_params: vec![transmittance, phase],
167                complex_params: vec![],
168                target_modes: vec![mode1, mode2],
169                control_modes: vec![],
170            },
171        ));
172
173        Ok(())
174    }
175
176    /// Add a phase rotation gate
177    pub fn phase_rotation(&mut self, mode: usize, phase: f64) -> DeviceResult<()> {
178        if mode >= self.num_modes {
179            return Err(DeviceError::InvalidInput(format!(
180                "Mode {} exceeds sequence capacity",
181                mode
182            )));
183        }
184
185        self.gates.push((
186            CVGateType::PhaseRotation { phase },
187            CVGateParams {
188                real_params: vec![phase],
189                complex_params: vec![],
190                target_modes: vec![mode],
191                control_modes: vec![],
192            },
193        ));
194
195        Ok(())
196    }
197
198    /// Add a controlled displacement gate
199    pub fn controlled_displacement(
200        &mut self,
201        control_mode: usize,
202        target_mode: usize,
203        amplitude: Complex,
204    ) -> DeviceResult<()> {
205        if control_mode >= self.num_modes || target_mode >= self.num_modes {
206            return Err(DeviceError::InvalidInput(
207                "Control or target mode exceeds sequence capacity".to_string(),
208            ));
209        }
210
211        self.gates.push((
212            CVGateType::ControlledDisplacement { amplitude },
213            CVGateParams {
214                real_params: vec![amplitude.real, amplitude.imag],
215                complex_params: vec![amplitude],
216                target_modes: vec![target_mode],
217                control_modes: vec![control_mode],
218            },
219        ));
220
221        Ok(())
222    }
223
224    /// Add a controlled phase gate
225    pub fn controlled_phase(
226        &mut self,
227        control_mode: usize,
228        target_mode: usize,
229        parameter: f64,
230    ) -> DeviceResult<()> {
231        if control_mode >= self.num_modes || target_mode >= self.num_modes {
232            return Err(DeviceError::InvalidInput(
233                "Control or target mode exceeds sequence capacity".to_string(),
234            ));
235        }
236
237        self.gates.push((
238            CVGateType::ControlledPhase { parameter },
239            CVGateParams {
240                real_params: vec![parameter],
241                complex_params: vec![],
242                target_modes: vec![target_mode],
243                control_modes: vec![control_mode],
244            },
245        ));
246
247        Ok(())
248    }
249
250    /// Add a cross-Kerr gate
251    pub fn cross_kerr(&mut self, mode1: usize, mode2: usize, parameter: f64) -> DeviceResult<()> {
252        if mode1 >= self.num_modes || mode2 >= self.num_modes {
253            return Err(DeviceError::InvalidInput(
254                "One or both modes exceed sequence capacity".to_string(),
255            ));
256        }
257
258        self.gates.push((
259            CVGateType::CrossKerr { parameter },
260            CVGateParams {
261                real_params: vec![parameter],
262                complex_params: vec![],
263                target_modes: vec![mode1, mode2],
264                control_modes: vec![],
265            },
266        ));
267
268        Ok(())
269    }
270
271    /// Add a cubic phase gate (non-Gaussian)
272    pub fn cubic_phase(&mut self, mode: usize, parameter: f64) -> DeviceResult<()> {
273        if mode >= self.num_modes {
274            return Err(DeviceError::InvalidInput(format!(
275                "Mode {} exceeds sequence capacity",
276                mode
277            )));
278        }
279
280        self.gates.push((
281            CVGateType::CubicPhase { parameter },
282            CVGateParams {
283                real_params: vec![parameter],
284                complex_params: vec![],
285                target_modes: vec![mode],
286                control_modes: vec![],
287            },
288        ));
289
290        Ok(())
291    }
292
293    /// Get the number of gates in the sequence
294    pub fn gate_count(&self) -> usize {
295        self.gates.len()
296    }
297
298    /// Get the depth of the sequence (maximum number of gates on any mode)
299    pub fn depth(&self) -> usize {
300        let mut mode_depths = vec![0; self.num_modes];
301
302        for (_, params) in &self.gates {
303            for &mode in &params.target_modes {
304                mode_depths[mode] += 1;
305            }
306            for &mode in &params.control_modes {
307                mode_depths[mode] += 1;
308            }
309        }
310
311        *mode_depths.iter().max().unwrap_or(&0)
312    }
313
314    /// Check if the sequence contains only Gaussian operations
315    pub fn is_gaussian(&self) -> bool {
316        for (gate_type, _) in &self.gates {
317            match gate_type {
318                CVGateType::CubicPhase { .. } => return false,
319                CVGateType::PositionMeasurement { .. } => return false,
320                CVGateType::MomentumMeasurement { .. } => return false,
321                _ => continue,
322            }
323        }
324        true
325    }
326
327    /// Execute the gate sequence on a Gaussian state
328    pub fn execute_on_state(&self, state: &mut GaussianState) -> DeviceResult<()> {
329        if state.num_modes != self.num_modes {
330            return Err(DeviceError::InvalidInput(
331                "State mode count doesn't match sequence requirements".to_string(),
332            ));
333        }
334
335        for (gate_type, params) in &self.gates {
336            self.execute_single_gate(gate_type, params, state)?;
337        }
338
339        Ok(())
340    }
341
342    /// Execute a single gate on the state
343    fn execute_single_gate(
344        &self,
345        gate_type: &CVGateType,
346        params: &CVGateParams,
347        state: &mut GaussianState,
348    ) -> DeviceResult<()> {
349        match gate_type {
350            CVGateType::Displacement { amplitude } => {
351                if params.target_modes.len() != 1 {
352                    return Err(DeviceError::InvalidInput(
353                        "Displacement gate requires exactly one target mode".to_string(),
354                    ));
355                }
356                state.apply_displacement(params.target_modes[0], *amplitude)?;
357            }
358
359            CVGateType::Squeezing { parameter, phase } => {
360                if params.target_modes.len() != 1 {
361                    return Err(DeviceError::InvalidInput(
362                        "Squeezing gate requires exactly one target mode".to_string(),
363                    ));
364                }
365                state.apply_squeezing(params.target_modes[0], *parameter, *phase)?;
366            }
367
368            CVGateType::TwoModeSqueezing { parameter, phase } => {
369                if params.target_modes.len() != 2 {
370                    return Err(DeviceError::InvalidInput(
371                        "Two-mode squeezing gate requires exactly two target modes".to_string(),
372                    ));
373                }
374                state.apply_two_mode_squeezing(
375                    params.target_modes[0],
376                    params.target_modes[1],
377                    *parameter,
378                    *phase,
379                )?;
380            }
381
382            CVGateType::Beamsplitter {
383                transmittance,
384                phase,
385            } => {
386                if params.target_modes.len() != 2 {
387                    return Err(DeviceError::InvalidInput(
388                        "Beamsplitter gate requires exactly two target modes".to_string(),
389                    ));
390                }
391                state.apply_beamsplitter(
392                    params.target_modes[0],
393                    params.target_modes[1],
394                    *transmittance,
395                    *phase,
396                )?;
397            }
398
399            CVGateType::PhaseRotation { phase } => {
400                if params.target_modes.len() != 1 {
401                    return Err(DeviceError::InvalidInput(
402                        "Phase rotation gate requires exactly one target mode".to_string(),
403                    ));
404                }
405                state.apply_phase_rotation(params.target_modes[0], *phase)?;
406            }
407
408            CVGateType::ControlledDisplacement { amplitude } => {
409                if params.control_modes.len() != 1 || params.target_modes.len() != 1 {
410                    return Err(DeviceError::InvalidInput(
411                        "Controlled displacement requires one control and one target mode"
412                            .to_string(),
413                    ));
414                }
415                self.apply_controlled_displacement(
416                    params.control_modes[0],
417                    params.target_modes[0],
418                    *amplitude,
419                    state,
420                )?;
421            }
422
423            CVGateType::ControlledPhase { parameter } => {
424                if params.control_modes.len() != 1 || params.target_modes.len() != 1 {
425                    return Err(DeviceError::InvalidInput(
426                        "Controlled phase requires one control and one target mode".to_string(),
427                    ));
428                }
429                self.apply_controlled_phase(
430                    params.control_modes[0],
431                    params.target_modes[0],
432                    *parameter,
433                    state,
434                )?;
435            }
436
437            CVGateType::CrossKerr { parameter } => {
438                if params.target_modes.len() != 2 {
439                    return Err(DeviceError::InvalidInput(
440                        "Cross-Kerr gate requires exactly two target modes".to_string(),
441                    ));
442                }
443                self.apply_cross_kerr(
444                    params.target_modes[0],
445                    params.target_modes[1],
446                    *parameter,
447                    state,
448                )?;
449            }
450
451            CVGateType::CubicPhase { parameter } => {
452                return Err(DeviceError::UnsupportedOperation(
453                    "Cubic phase gate is non-Gaussian and not supported for Gaussian states"
454                        .to_string(),
455                ));
456            }
457
458            CVGateType::PositionMeasurement { .. } | CVGateType::MomentumMeasurement { .. } => {
459                return Err(DeviceError::UnsupportedOperation(
460                    "Measurements should be performed separately from gate sequences".to_string(),
461                ));
462            }
463        }
464
465        Ok(())
466    }
467
468    /// Apply controlled displacement (simplified implementation)
469    fn apply_controlled_displacement(
470        &self,
471        control_mode: usize,
472        target_mode: usize,
473        amplitude: Complex,
474        state: &mut GaussianState,
475    ) -> DeviceResult<()> {
476        // Simplified implementation - would need full multimode transformation
477        // For now, apply displacement scaled by control mode amplitude
478        let control_amplitude = Complex::new(
479            state.mean_vector[2 * control_mode] / (2.0_f64).sqrt(),
480            state.mean_vector[2 * control_mode + 1] / (2.0_f64).sqrt(),
481        );
482
483        let scaled_amplitude = amplitude * control_amplitude.magnitude();
484        state.apply_displacement(target_mode, scaled_amplitude)?;
485
486        Ok(())
487    }
488
489    /// Apply controlled phase (simplified implementation)
490    fn apply_controlled_phase(
491        &self,
492        control_mode: usize,
493        target_mode: usize,
494        parameter: f64,
495        state: &mut GaussianState,
496    ) -> DeviceResult<()> {
497        // Simplified implementation
498        let control_photon_number = self.estimate_photon_number(control_mode, state);
499        let phase = parameter * control_photon_number;
500        state.apply_phase_rotation(target_mode, phase)?;
501
502        Ok(())
503    }
504
505    /// Apply cross-Kerr interaction
506    fn apply_cross_kerr(
507        &self,
508        mode1: usize,
509        mode2: usize,
510        parameter: f64,
511        state: &mut GaussianState,
512    ) -> DeviceResult<()> {
513        // Simplified cross-Kerr implementation
514        // Cross-Kerr induces phase shifts proportional to photon numbers
515        let n1 = self.estimate_photon_number(mode1, state);
516        let n2 = self.estimate_photon_number(mode2, state);
517
518        state.apply_phase_rotation(mode1, parameter * n2)?;
519        state.apply_phase_rotation(mode2, parameter * n1)?;
520
521        Ok(())
522    }
523
524    /// Estimate photon number for a mode (for simplified implementations)
525    fn estimate_photon_number(&self, mode: usize, state: &GaussianState) -> f64 {
526        let mean_x = state.mean_vector[2 * mode];
527        let mean_p = state.mean_vector[2 * mode + 1];
528        let var_x = state.covariancematrix[2 * mode][2 * mode];
529        let var_p = state.covariancematrix[2 * mode + 1][2 * mode + 1];
530
531        // Average photon number approximation
532        0.5 * ((mean_x.powi(2) + mean_p.powi(2)) / 2.0 + (var_x + var_p) - 1.0)
533    }
534}
535
536/// Common CV gate implementations
537pub struct CVGateLibrary;
538
539impl CVGateLibrary {
540    /// Create a displacement gate
541    pub fn displacement(amplitude: Complex) -> (CVGateType, CVGateParams) {
542        (
543            CVGateType::Displacement { amplitude },
544            CVGateParams {
545                real_params: vec![amplitude.real, amplitude.imag],
546                complex_params: vec![amplitude],
547                target_modes: vec![],
548                control_modes: vec![],
549            },
550        )
551    }
552
553    /// Create a squeezing gate
554    pub fn squeezing(parameter: f64, phase: f64) -> (CVGateType, CVGateParams) {
555        (
556            CVGateType::Squeezing { parameter, phase },
557            CVGateParams {
558                real_params: vec![parameter, phase],
559                complex_params: vec![],
560                target_modes: vec![],
561                control_modes: vec![],
562            },
563        )
564    }
565
566    /// Create a 50:50 beamsplitter
567    pub fn balanced_beamsplitter() -> (CVGateType, CVGateParams) {
568        (
569            CVGateType::Beamsplitter {
570                transmittance: 0.5,
571                phase: 0.0,
572            },
573            CVGateParams {
574                real_params: vec![0.5, 0.0],
575                complex_params: vec![],
576                target_modes: vec![],
577                control_modes: vec![],
578            },
579        )
580    }
581
582    /// Create a Hadamard-like operation for CV (Fourier transform)
583    pub fn fourier_transform() -> CVGateSequence {
584        let mut sequence = CVGateSequence::new(1);
585        sequence.phase_rotation(0, PI / 2.0).unwrap();
586        sequence
587    }
588
589    /// Create a CNOT-like operation for CV
590    pub fn cv_cnot() -> CVGateSequence {
591        let mut sequence = CVGateSequence::new(2);
592        // Simplified CV CNOT using beamsplitter and phase rotations
593        sequence.beamsplitter(0, 1, 0.5, 0.0).unwrap();
594        sequence.phase_rotation(1, PI).unwrap();
595        sequence.beamsplitter(0, 1, 0.5, 0.0).unwrap();
596        sequence
597    }
598
599    /// Create an EPR pair generation sequence
600    pub fn epr_pair_generation(squeezing_param: f64) -> CVGateSequence {
601        let mut sequence = CVGateSequence::new(2);
602        sequence
603            .two_mode_squeezing(0, 1, squeezing_param, 0.0)
604            .unwrap();
605        sequence
606    }
607
608    /// Create a GKP (Gottesman-Kitaev-Preskill) state preparation sequence
609    pub fn gkp_state_preparation() -> CVGateSequence {
610        let mut sequence = CVGateSequence::new(1);
611        // Simplified GKP preparation using multiple squeezing operations
612        for i in 0..10 {
613            let phase = 2.0 * PI * i as f64 / 10.0;
614            sequence.squeezing(0, 0.5, phase).unwrap();
615        }
616        sequence
617    }
618}
619
620#[cfg(test)]
621mod tests {
622    use super::*;
623
624    #[test]
625    fn test_gate_sequence_creation() {
626        let mut sequence = CVGateSequence::new(3);
627        assert_eq!(sequence.num_modes, 3);
628        assert_eq!(sequence.gate_count(), 0);
629    }
630
631    #[test]
632    fn test_displacement_gate_addition() {
633        let mut sequence = CVGateSequence::new(2);
634        let amplitude = Complex::new(1.0, 0.5);
635
636        sequence.displacement(0, amplitude).unwrap();
637        assert_eq!(sequence.gate_count(), 1);
638
639        match &sequence.gates[0].0 {
640            CVGateType::Displacement { amplitude: a } => {
641                assert_eq!(*a, amplitude);
642            }
643            _ => panic!("Expected displacement gate"),
644        }
645    }
646
647    #[test]
648    fn test_beamsplitter_gate_addition() {
649        let mut sequence = CVGateSequence::new(2);
650
651        sequence.beamsplitter(0, 1, 0.7, PI / 4.0).unwrap();
652        assert_eq!(sequence.gate_count(), 1);
653
654        match &sequence.gates[0].0 {
655            CVGateType::Beamsplitter {
656                transmittance,
657                phase,
658            } => {
659                assert_eq!(*transmittance, 0.7);
660                assert_eq!(*phase, PI / 4.0);
661            }
662            _ => panic!("Expected beamsplitter gate"),
663        }
664    }
665
666    #[test]
667    fn test_gaussian_property() {
668        let mut sequence = CVGateSequence::new(2);
669
670        sequence.displacement(0, Complex::new(1.0, 0.0)).unwrap();
671        sequence.squeezing(1, 0.5, 0.0).unwrap();
672        sequence.beamsplitter(0, 1, 0.5, 0.0).unwrap();
673
674        assert!(sequence.is_gaussian());
675
676        sequence.cubic_phase(0, 0.1).unwrap();
677        assert!(!sequence.is_gaussian());
678    }
679
680    #[test]
681    fn test_sequence_depth_calculation() {
682        let mut sequence = CVGateSequence::new(3);
683
684        sequence.displacement(0, Complex::new(1.0, 0.0)).unwrap();
685        sequence.displacement(0, Complex::new(0.5, 0.0)).unwrap();
686        sequence.squeezing(1, 0.5, 0.0).unwrap();
687        sequence.beamsplitter(0, 2, 0.5, 0.0).unwrap();
688
689        assert_eq!(sequence.depth(), 3); // Mode 0 has 3 operations
690    }
691
692    #[test]
693    fn test_gate_execution_on_state() {
694        let mut sequence = CVGateSequence::new(2);
695        sequence.displacement(0, Complex::new(1.0, 0.0)).unwrap();
696        sequence.squeezing(1, 0.5, 0.0).unwrap();
697
698        let mut state = GaussianState::vacuum_state(2);
699        sequence.execute_on_state(&mut state).unwrap();
700
701        // Check that the displacement was applied
702        assert!(state.mean_vector[0] > 0.0);
703
704        // Check that squeezing was applied
705        // For mode 1 (index 2 for x-quadrature), squeezing should reduce variance
706        // Expected: 0.5 * exp(-2*r) = 0.5 * exp(-1) ≈ 0.184
707        assert!(state.covariancematrix[2][2] < 0.5);
708    }
709
710    #[test]
711    fn test_epr_pair_generation() {
712        let sequence = CVGateLibrary::epr_pair_generation(1.0);
713        assert_eq!(sequence.gate_count(), 1);
714
715        let mut state = GaussianState::vacuum_state(2);
716        sequence.execute_on_state(&mut state).unwrap();
717
718        // EPR state should have correlations between modes
719        let entanglement = state.calculate_entanglement_measures();
720        assert!(entanglement.epr_correlation > 0.0);
721    }
722
723    #[test]
724    fn test_balanced_beamsplitter() {
725        let (gate_type, params) = CVGateLibrary::balanced_beamsplitter();
726
727        match gate_type {
728            CVGateType::Beamsplitter {
729                transmittance,
730                phase,
731            } => {
732                assert_eq!(transmittance, 0.5);
733                assert_eq!(phase, 0.0);
734            }
735            _ => panic!("Expected balanced beamsplitter"),
736        }
737    }
738
739    #[test]
740    fn test_invalid_mode_error() {
741        let mut sequence = CVGateSequence::new(2);
742
743        let result = sequence.displacement(3, Complex::new(1.0, 0.0));
744        assert!(result.is_err());
745
746        let result = sequence.beamsplitter(0, 3, 0.5, 0.0);
747        assert!(result.is_err());
748    }
749}