1use serde::{Deserialize, Serialize};
7use std::f64::consts::{PI, SQRT_2};
8use thiserror::Error;
9
10use super::continuous_variable::{CVError, CVResult, Complex, GaussianState};
11
12#[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#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
25pub enum CVGateType {
26 Displacement,
28 Squeezing,
30 TwoModeSqueezing,
32 Beamsplitter,
34 PhaseRotation,
36 Kerr,
38 CrossKerr,
40 CubicPhase,
42 PositionMeasurement,
44 MomentumMeasurement,
46 HomodyneMeasurement,
48 HeterodyneMeasurement,
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct CVGateParams {
55 pub gate_type: CVGateType,
57 pub modes: Vec<usize>,
59 pub params: Vec<f64>,
61 pub complex_params: Vec<Complex>,
63 pub duration: Option<f64>,
65 pub fidelity: Option<f64>,
67}
68
69pub struct DisplacementGate {
71 pub alpha: Complex,
73 pub mode: usize,
75}
76
77impl DisplacementGate {
78 pub const fn new(alpha: Complex, mode: usize) -> Self {
79 Self { alpha, mode }
80 }
81
82 pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
84 state.displace(self.alpha, self.mode)
85 }
86
87 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 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 if m == n {
105 Complex::new(1.0, 0.0)
106 } else {
107 Complex::new(0.0, 0.0)
108 }
109 }
110
111 #[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
121pub struct SqueezingGate {
123 pub r: f64,
125 pub phi: f64,
127 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 pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
144 state.squeeze(self.r, self.phi, self.mode)
145 }
146
147 pub fn squeezing_db(&self) -> f64 {
149 10.0 * self.r.abs() / 2.0_f64.log(10.0_f64)
150 }
151
152 pub fn amplitude_squeezing(r: f64, mode: usize) -> Result<Self, CVGateError> {
154 Self::new(r, 0.0, mode)
155 }
156
157 pub fn phase_squeezing(r: f64, mode: usize) -> Result<Self, CVGateError> {
159 Self::new(r, PI / 2.0, mode)
160 }
161}
162
163pub struct TwoModeSqueezingGate {
165 pub r: f64,
167 pub phi: f64,
169 pub mode1: usize,
171 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 pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
199 state.two_mode_squeeze(self.r, self.phi, self.mode1, self.mode2)
200 }
201
202 pub fn entanglement_strength(&self) -> f64 {
204 2.0 * self.r.abs()
206 }
207}
208
209pub struct BeamsplitterGate {
211 pub theta: f64,
213 pub phi: f64,
215 pub mode1: usize,
217 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 pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
239 state.beamsplitter(self.theta, self.phi, self.mode1, self.mode2)
240 }
241
242 pub fn fifty_fifty(mode1: usize, mode2: usize) -> Result<Self, CVGateError> {
244 Self::new(PI / 4.0, 0.0, mode1, mode2)
245 }
246
247 pub fn transmission(&self) -> f64 {
249 self.theta.cos().powi(2)
250 }
251
252 pub fn reflection(&self) -> f64 {
254 self.theta.sin().powi(2)
255 }
256
257 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
275pub struct PhaseRotationGate {
277 pub phi: f64,
279 pub mode: usize,
281}
282
283impl PhaseRotationGate {
284 pub const fn new(phi: f64, mode: usize) -> Self {
285 Self { phi, mode }
286 }
287
288 pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
290 state.phase_rotation(self.phi, self.mode)
291 }
292
293 pub fn normalized_phase(&self) -> f64 {
295 self.phi.rem_euclid(2.0 * PI)
296 }
297}
298
299pub struct KerrGate {
301 pub kappa: f64,
303 pub mode: usize,
305 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 pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
316 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 pub fn phase_shift(&self, photon_number: f64) -> f64 {
328 self.kappa * photon_number * self.time
329 }
330}
331
332pub struct CrossKerrGate {
334 pub kappa: f64,
336 pub mode1: usize,
338 pub mode2: usize,
340 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 pub fn apply(&self, state: &mut GaussianState) -> CVResult<()> {
362 let n1 = state.average_photon_number(self.mode1)?;
364 let n2 = state.average_photon_number(self.mode2)?;
365
366 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 pub fn conditional_phase_shift(&self, control_photons: f64) -> f64 {
378 self.kappa * control_photons * self.time
379 }
380}
381
382pub struct CubicPhaseGate {
384 pub gamma: f64,
386 pub mode: usize,
388}
389
390impl CubicPhaseGate {
391 pub const fn new(gamma: f64, mode: usize) -> Self {
392 Self { gamma, mode }
393 }
394
395 pub fn apply(&self, _state: &mut GaussianState) -> CVResult<()> {
397 Err(CVError::IncompatibleOperation(
400 "Cubic phase gate is non-Gaussian and not supported for Gaussian states".to_string(),
401 ))
402 }
403}
404
405pub struct CVGateSequence {
407 pub gates: Vec<CVGateParams>,
409 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 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 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 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 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 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 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 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 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 pub fn optimize(&mut self) -> Result<(), CVGateError> {
596 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 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 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 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 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") .phase_rotation(0.0, 0)
709 .expect("Adding zero phase rotation should succeed"); sequence
712 .optimize()
713 .expect("Gate sequence optimization should succeed");
714
715 assert_eq!(sequence.gates.len(), 0);
717 }
718}