quantrs2_circuit/
photonic.rs

1//! Photonic quantum circuit support
2//!
3//! This module provides specialized support for photonic quantum computing,
4//! including linear optical elements, measurement-based computation,
5//! and continuous variable quantum computation.
6
7use crate::builder::Circuit;
8use quantrs2_core::{
9    error::{QuantRS2Error, QuantRS2Result},
10    gate::GateOp,
11    qubit::QubitId,
12};
13use serde::{Deserialize, Serialize};
14use std::collections::{HashMap, HashSet};
15use std::f64::consts::PI;
16
17/// Photonic mode representing optical field modes
18#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
19pub struct PhotonicMode {
20    pub id: u32,
21    pub polarization: Polarization,
22    pub frequency: Option<f64>, // Optional frequency specification
23}
24
25impl PhotonicMode {
26    #[must_use]
27    pub const fn new(id: u32) -> Self {
28        Self {
29            id,
30            polarization: Polarization::Horizontal,
31            frequency: None,
32        }
33    }
34
35    #[must_use]
36    pub const fn with_polarization(mut self, polarization: Polarization) -> Self {
37        self.polarization = polarization;
38        self
39    }
40
41    #[must_use]
42    pub const fn with_frequency(mut self, frequency: f64) -> Self {
43        self.frequency = Some(frequency);
44        self
45    }
46}
47
48/// Polarization states for photonic modes
49#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
50pub enum Polarization {
51    Horizontal,
52    Vertical,
53    Diagonal,
54    AntiDiagonal,
55    LeftCircular,
56    RightCircular,
57}
58
59/// Linear optical elements for photonic circuits
60#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
61pub enum PhotonicGate {
62    /// Beam splitter with reflectivity parameter
63    BeamSplitter {
64        mode1: PhotonicMode,
65        mode2: PhotonicMode,
66        reflectivity: f64, // 0.0 = fully transmissive, 1.0 = fully reflective
67        phase: f64,
68    },
69    /// Phase shifter
70    PhaseShifter { mode: PhotonicMode, phase: f64 },
71    /// Polarization rotator
72    PolarizationRotator {
73        mode: PhotonicMode,
74        angle: f64, // Rotation angle
75    },
76    /// Half-wave plate
77    HalfWavePlate {
78        mode: PhotonicMode,
79        angle: f64, // Fast axis angle
80    },
81    /// Quarter-wave plate
82    QuarterWavePlate { mode: PhotonicMode, angle: f64 },
83    /// Polarizing beam splitter
84    PolarizingBeamSplitter {
85        input: PhotonicMode,
86        h_output: PhotonicMode, // Horizontal polarization output
87        v_output: PhotonicMode, // Vertical polarization output
88    },
89    /// Mach-Zehnder interferometer
90    MachZehnder {
91        input1: PhotonicMode,
92        input2: PhotonicMode,
93        output1: PhotonicMode,
94        output2: PhotonicMode,
95        phase_shift: f64,
96    },
97    /// Hong-Ou-Mandel effect (two-photon interference)
98    HongOuMandel {
99        mode1: PhotonicMode,
100        mode2: PhotonicMode,
101    },
102    /// Photonic controlled gate (using ancilla photons)
103    PhotonicCNOT {
104        control: PhotonicMode,
105        target: PhotonicMode,
106        ancilla: Vec<PhotonicMode>,
107    },
108    /// Kerr effect (nonlinear phase shift)
109    KerrGate { mode: PhotonicMode, strength: f64 },
110}
111
112impl PhotonicGate {
113    /// Get the modes involved in this gate
114    #[must_use]
115    pub fn modes(&self) -> Vec<PhotonicMode> {
116        match self {
117            Self::BeamSplitter { mode1, mode2, .. } => vec![*mode1, *mode2],
118            Self::PhaseShifter { mode, .. }
119            | Self::PolarizationRotator { mode, .. }
120            | Self::HalfWavePlate { mode, .. }
121            | Self::QuarterWavePlate { mode, .. } => vec![*mode],
122            Self::PolarizingBeamSplitter {
123                input,
124                h_output,
125                v_output,
126                ..
127            } => {
128                vec![*input, *h_output, *v_output]
129            }
130            Self::MachZehnder {
131                input1,
132                input2,
133                output1,
134                output2,
135                ..
136            } => {
137                vec![*input1, *input2, *output1, *output2]
138            }
139            Self::HongOuMandel { mode1, mode2, .. } => vec![*mode1, *mode2],
140            Self::PhotonicCNOT {
141                control,
142                target,
143                ancilla,
144                ..
145            } => {
146                let mut modes = vec![*control, *target];
147                modes.extend(ancilla);
148                modes
149            }
150            Self::KerrGate { mode, .. } => vec![*mode],
151        }
152    }
153
154    /// Get gate name
155    #[must_use]
156    pub const fn name(&self) -> &'static str {
157        match self {
158            Self::BeamSplitter { .. } => "BS",
159            Self::PhaseShifter { .. } => "PS",
160            Self::PolarizationRotator { .. } => "PR",
161            Self::HalfWavePlate { .. } => "HWP",
162            Self::QuarterWavePlate { .. } => "QWP",
163            Self::PolarizingBeamSplitter { .. } => "PBS",
164            Self::MachZehnder { .. } => "MZ",
165            Self::HongOuMandel { .. } => "HOM",
166            Self::PhotonicCNOT { .. } => "PCNOT",
167            Self::KerrGate { .. } => "KERR",
168        }
169    }
170}
171
172/// Photonic measurement operations
173#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
174pub enum PhotonicMeasurement {
175    /// Photon number measurement
176    PhotonNumber {
177        mode: PhotonicMode,
178        detector_efficiency: f64,
179    },
180    /// Homodyne measurement (measures quadrature)
181    Homodyne {
182        mode: PhotonicMode,
183        local_oscillator_phase: f64,
184        detection_efficiency: f64,
185    },
186    /// Heterodyne measurement (measures both quadratures)
187    Heterodyne {
188        mode: PhotonicMode,
189        detection_efficiency: f64,
190    },
191    /// Polarization measurement
192    Polarization {
193        mode: PhotonicMode,
194        measurement_basis: PolarizationBasis,
195    },
196    /// Coincidence detection
197    Coincidence {
198        modes: Vec<PhotonicMode>,
199        time_window: f64, // nanoseconds
200    },
201}
202
203/// Polarization measurement bases
204#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
205pub enum PolarizationBasis {
206    Linear,   // H/V
207    Diagonal, // D/A
208    Circular, // L/R
209}
210
211/// Photonic circuit representation
212#[derive(Debug, Clone)]
213pub struct PhotonicCircuit {
214    /// Number of photonic modes
215    pub num_modes: usize,
216    /// Photonic gates in the circuit
217    pub gates: Vec<PhotonicGate>,
218    /// Measurements in the circuit
219    pub measurements: Vec<PhotonicMeasurement>,
220    /// Mode mapping (logical to physical modes)
221    pub mode_mapping: HashMap<u32, u32>,
222}
223
224impl PhotonicCircuit {
225    /// Create a new photonic circuit
226    #[must_use]
227    pub fn new(num_modes: usize) -> Self {
228        Self {
229            num_modes,
230            gates: Vec::new(),
231            measurements: Vec::new(),
232            mode_mapping: HashMap::new(),
233        }
234    }
235
236    /// Add a photonic gate
237    pub fn add_gate(&mut self, gate: PhotonicGate) -> QuantRS2Result<()> {
238        // Validate that all modes are within bounds
239        for mode in gate.modes() {
240            if mode.id as usize >= self.num_modes {
241                return Err(QuantRS2Error::InvalidInput(format!(
242                    "Mode {} exceeds circuit size {}",
243                    mode.id, self.num_modes
244                )));
245            }
246        }
247
248        self.gates.push(gate);
249        Ok(())
250    }
251
252    /// Add a measurement
253    pub fn add_measurement(&mut self, measurement: PhotonicMeasurement) -> QuantRS2Result<()> {
254        self.measurements.push(measurement);
255        Ok(())
256    }
257
258    /// Get circuit depth (simplified)
259    #[must_use]
260    pub fn depth(&self) -> usize {
261        // For photonic circuits, depth is more complex due to parallelism
262        // This is a simplified calculation
263        self.gates.len()
264    }
265
266    /// Validate the photonic circuit
267    pub fn validate(&self) -> QuantRS2Result<()> {
268        // Check for mode conflicts
269        let mut mode_usage = HashMap::new();
270
271        for (layer, gate) in self.gates.iter().enumerate() {
272            for mode in gate.modes() {
273                if let Some(&last_usage) = mode_usage.get(&mode.id) {
274                    if last_usage == layer {
275                        return Err(QuantRS2Error::InvalidInput(format!(
276                            "Mode {} used multiple times in layer {}",
277                            mode.id, layer
278                        )));
279                    }
280                }
281                mode_usage.insert(mode.id, layer);
282            }
283        }
284
285        Ok(())
286    }
287}
288
289/// Builder for photonic circuits
290#[derive(Clone)]
291pub struct PhotonicCircuitBuilder {
292    circuit: PhotonicCircuit,
293}
294
295impl PhotonicCircuitBuilder {
296    /// Create a new builder
297    #[must_use]
298    pub fn new(num_modes: usize) -> Self {
299        Self {
300            circuit: PhotonicCircuit::new(num_modes),
301        }
302    }
303
304    /// Add a beam splitter
305    pub fn beam_splitter(
306        &mut self,
307        mode1: u32,
308        mode2: u32,
309        reflectivity: f64,
310        phase: f64,
311    ) -> QuantRS2Result<&mut Self> {
312        let gate = PhotonicGate::BeamSplitter {
313            mode1: PhotonicMode::new(mode1),
314            mode2: PhotonicMode::new(mode2),
315            reflectivity,
316            phase,
317        };
318        self.circuit.add_gate(gate)?;
319        Ok(self)
320    }
321
322    /// Add a phase shifter
323    pub fn phase_shifter(&mut self, mode: u32, phase: f64) -> QuantRS2Result<&mut Self> {
324        let gate = PhotonicGate::PhaseShifter {
325            mode: PhotonicMode::new(mode),
326            phase,
327        };
328        self.circuit.add_gate(gate)?;
329        Ok(self)
330    }
331
332    /// Add a Mach-Zehnder interferometer
333    pub fn mach_zehnder(
334        &mut self,
335        input1: u32,
336        input2: u32,
337        output1: u32,
338        output2: u32,
339        phase_shift: f64,
340    ) -> QuantRS2Result<&mut Self> {
341        let gate = PhotonicGate::MachZehnder {
342            input1: PhotonicMode::new(input1),
343            input2: PhotonicMode::new(input2),
344            output1: PhotonicMode::new(output1),
345            output2: PhotonicMode::new(output2),
346            phase_shift,
347        };
348        self.circuit.add_gate(gate)?;
349        Ok(self)
350    }
351
352    /// Add Hong-Ou-Mandel interference
353    pub fn hong_ou_mandel(&mut self, mode1: u32, mode2: u32) -> QuantRS2Result<&mut Self> {
354        let gate = PhotonicGate::HongOuMandel {
355            mode1: PhotonicMode::new(mode1),
356            mode2: PhotonicMode::new(mode2),
357        };
358        self.circuit.add_gate(gate)?;
359        Ok(self)
360    }
361
362    /// Add photon number measurement
363    pub fn measure_photon_number(&mut self, mode: u32) -> QuantRS2Result<&mut Self> {
364        let measurement = PhotonicMeasurement::PhotonNumber {
365            mode: PhotonicMode::new(mode),
366            detector_efficiency: 1.0,
367        };
368        self.circuit.add_measurement(measurement)?;
369        Ok(self)
370    }
371
372    /// Build the final circuit
373    pub fn build(self) -> QuantRS2Result<PhotonicCircuit> {
374        self.circuit.validate()?;
375        Ok(self.circuit)
376    }
377}
378
379/// Conversion between photonic and standard quantum circuits
380pub struct PhotonicConverter;
381
382impl PhotonicConverter {
383    /// Convert a standard quantum circuit to photonic representation
384    pub fn quantum_to_photonic<const N: usize>(
385        circuit: &Circuit<N>,
386    ) -> QuantRS2Result<PhotonicCircuit> {
387        let mut photonic_circuit = PhotonicCircuit::new(N * 2); // Dual-rail encoding
388
389        for gate in circuit.gates() {
390            let photonic_gates = Self::convert_gate(gate.as_ref())?;
391            for pg in photonic_gates {
392                photonic_circuit.add_gate(pg)?;
393            }
394        }
395
396        Ok(photonic_circuit)
397    }
398
399    /// Convert a quantum gate to photonic representation
400    fn convert_gate(gate: &dyn GateOp) -> QuantRS2Result<Vec<PhotonicGate>> {
401        let mut photonic_gates = Vec::new();
402        let gate_name = gate.name();
403        let qubits = gate.qubits();
404
405        match gate_name {
406            "H" => {
407                // Hadamard gate using beam splitters and phase shifters
408                let qubit = qubits[0].id();
409                let mode0 = qubit * 2; // |0⟩ rail
410                let mode1 = qubit * 2 + 1; // |1⟩ rail
411
412                // Beam splitter with 50:50 ratio
413                photonic_gates.push(PhotonicGate::BeamSplitter {
414                    mode1: PhotonicMode::new(mode0),
415                    mode2: PhotonicMode::new(mode1),
416                    reflectivity: 0.5,
417                    phase: 0.0,
418                });
419            }
420            "X" => {
421                // Pauli-X swaps the rails
422                let qubit = qubits[0].id();
423                let mode0 = qubit * 2;
424                let mode1 = qubit * 2 + 1;
425
426                // Swap using beam splitters
427                photonic_gates.push(PhotonicGate::BeamSplitter {
428                    mode1: PhotonicMode::new(mode0),
429                    mode2: PhotonicMode::new(mode1),
430                    reflectivity: 1.0, // Full reflection = swap
431                    phase: 0.0,
432                });
433            }
434            "Z" => {
435                // Pauli-Z adds phase to |1⟩ rail
436                let qubit = qubits[0].id();
437                let mode1 = qubit * 2 + 1;
438
439                photonic_gates.push(PhotonicGate::PhaseShifter {
440                    mode: PhotonicMode::new(mode1),
441                    phase: PI,
442                });
443            }
444            "CNOT" => {
445                // CNOT using photonic controlled gates (requires ancilla photons)
446                let control_qubit = qubits[0].id();
447                let target_qubit = qubits[1].id();
448
449                let control_mode = control_qubit * 2 + 1; // Control on |1⟩ rail
450                let target_mode0 = target_qubit * 2;
451                let target_mode1 = target_qubit * 2 + 1;
452
453                // Simplified photonic CNOT (would need more complex implementation)
454                photonic_gates.push(PhotonicGate::PhotonicCNOT {
455                    control: PhotonicMode::new(control_mode),
456                    target: PhotonicMode::new(target_mode0),
457                    ancilla: vec![PhotonicMode::new(target_mode1)],
458                });
459            }
460            _ => {
461                return Err(QuantRS2Error::InvalidInput(format!(
462                    "Gate {gate_name} not supported in photonic conversion"
463                )));
464            }
465        }
466
467        Ok(photonic_gates)
468    }
469}
470
471/// Continuous variable quantum computation support
472#[derive(Debug, Clone)]
473pub struct CVCircuit {
474    /// Number of modes
475    pub num_modes: usize,
476    /// CV gates
477    pub gates: Vec<CVGate>,
478    /// Position/momentum measurements
479    pub measurements: Vec<CVMeasurement>,
480}
481
482/// Continuous variable gates
483#[derive(Debug, Clone, PartialEq)]
484pub enum CVGate {
485    /// Displacement operator D(α)
486    Displacement {
487        mode: u32,
488        amplitude: f64,
489        phase: f64,
490    },
491    /// Squeezing operator S(r)
492    Squeezing {
493        mode: u32,
494        squeezing_parameter: f64,
495        squeezing_angle: f64,
496    },
497    /// Two-mode squeezing
498    TwoModeSqueezing {
499        mode1: u32,
500        mode2: u32,
501        squeezing_parameter: f64,
502    },
503    /// Rotation gate (phase space rotation)
504    Rotation { mode: u32, angle: f64 },
505    /// Beam splitter (linear transformation)
506    CVBeamSplitter {
507        mode1: u32,
508        mode2: u32,
509        theta: f64, // Beam splitter angle
510        phi: f64,   // Phase shift
511    },
512    /// Kerr gate (cubic phase)
513    CVKerr { mode: u32, strength: f64 },
514    /// Controlled displacement
515    ControlledDisplacement {
516        control_mode: u32,
517        target_mode: u32,
518        strength: f64,
519    },
520}
521
522/// CV measurements
523#[derive(Debug, Clone, PartialEq)]
524pub enum CVMeasurement {
525    /// Homodyne detection (position/momentum)
526    CVHomodyne {
527        mode: u32,
528        angle: f64, // 0 = position, π/2 = momentum
529    },
530    /// Heterodyne detection
531    CVHeterodyne { mode: u32 },
532    /// Photon number measurement
533    CVPhotonNumber { mode: u32 },
534}
535
536impl CVCircuit {
537    /// Create new CV circuit
538    #[must_use]
539    pub const fn new(num_modes: usize) -> Self {
540        Self {
541            num_modes,
542            gates: Vec::new(),
543            measurements: Vec::new(),
544        }
545    }
546
547    /// Add a displacement gate
548    pub fn displacement(&mut self, mode: u32, amplitude: f64, phase: f64) -> QuantRS2Result<()> {
549        self.gates.push(CVGate::Displacement {
550            mode,
551            amplitude,
552            phase,
553        });
554        Ok(())
555    }
556
557    /// Add squeezing
558    pub fn squeezing(&mut self, mode: u32, r: f64, angle: f64) -> QuantRS2Result<()> {
559        self.gates.push(CVGate::Squeezing {
560            mode,
561            squeezing_parameter: r,
562            squeezing_angle: angle,
563        });
564        Ok(())
565    }
566
567    /// Add beam splitter
568    pub fn beam_splitter(
569        &mut self,
570        mode1: u32,
571        mode2: u32,
572        theta: f64,
573        phi: f64,
574    ) -> QuantRS2Result<()> {
575        self.gates.push(CVGate::CVBeamSplitter {
576            mode1,
577            mode2,
578            theta,
579            phi,
580        });
581        Ok(())
582    }
583}
584
585#[cfg(test)]
586mod tests {
587    use super::*;
588    use quantrs2_core::gate::multi::CNOT;
589    use quantrs2_core::gate::single::Hadamard;
590
591    #[test]
592    fn test_photonic_circuit_creation() {
593        let mut circuit = PhotonicCircuit::new(4);
594
595        let bs_gate = PhotonicGate::BeamSplitter {
596            mode1: PhotonicMode::new(0),
597            mode2: PhotonicMode::new(1),
598            reflectivity: 0.5,
599            phase: 0.0,
600        };
601
602        assert!(circuit.add_gate(bs_gate).is_ok());
603        assert_eq!(circuit.gates.len(), 1);
604    }
605
606    #[test]
607    fn test_photonic_builder() {
608        let mut builder = PhotonicCircuitBuilder::new(4);
609
610        builder
611            .beam_splitter(0, 1, 0.5, 0.0)
612            .expect("Failed to add beam splitter");
613        builder
614            .phase_shifter(1, PI / 2.0)
615            .expect("Failed to add phase shifter");
616        builder
617            .mach_zehnder(0, 1, 2, 3, PI / 4.0)
618            .expect("Failed to add Mach-Zehnder interferometer");
619        let result = builder.build();
620
621        assert!(result.is_ok());
622        let circuit = result.expect("Failed to build photonic circuit");
623        assert_eq!(circuit.gates.len(), 3);
624    }
625
626    #[test]
627    fn test_quantum_to_photonic_conversion() {
628        let mut quantum_circuit = Circuit::<2>::new();
629        quantum_circuit
630            .add_gate(Hadamard { target: QubitId(0) })
631            .expect("Failed to add Hadamard gate");
632
633        let photonic_result = PhotonicConverter::quantum_to_photonic(&quantum_circuit);
634        assert!(photonic_result.is_ok());
635
636        let photonic_circuit = photonic_result.expect("Failed to convert to photonic circuit");
637        assert_eq!(photonic_circuit.num_modes, 4); // Dual-rail encoding
638        assert!(!photonic_circuit.gates.is_empty());
639    }
640
641    #[test]
642    fn test_cv_circuit() {
643        let mut cv_circuit = CVCircuit::new(2);
644
645        assert!(cv_circuit.displacement(0, 1.0, 0.0).is_ok());
646        assert!(cv_circuit.squeezing(1, 0.5, PI / 4.0).is_ok());
647        assert!(cv_circuit.beam_splitter(0, 1, PI / 4.0, 0.0).is_ok());
648
649        assert_eq!(cv_circuit.gates.len(), 3);
650    }
651
652    #[test]
653    fn test_photonic_modes() {
654        let mode = PhotonicMode::new(0)
655            .with_polarization(Polarization::Vertical)
656            .with_frequency(532e12); // Green light
657
658        assert_eq!(mode.id, 0);
659        assert_eq!(mode.polarization, Polarization::Vertical);
660        assert_eq!(mode.frequency, Some(532e12));
661    }
662
663    #[test]
664    fn test_hong_ou_mandel() {
665        let mut builder = PhotonicCircuitBuilder::new(2);
666        builder
667            .hong_ou_mandel(0, 1)
668            .expect("Failed to add Hong-Ou-Mandel gate");
669        let result = builder.build();
670
671        assert!(result.is_ok());
672        let circuit = result.expect("Failed to build photonic circuit");
673        assert_eq!(circuit.gates.len(), 1);
674
675        match &circuit.gates[0] {
676            PhotonicGate::HongOuMandel { mode1, mode2 } => {
677                assert_eq!(mode1.id, 0);
678                assert_eq!(mode2.id, 1);
679            }
680            _ => panic!("Expected HongOuMandel gate"),
681        }
682    }
683}