quantrs2_device/photonic/
encoding.rs

1//! Quantum Information Encoding for Photonic Systems
2//!
3//! This module implements various encoding schemes for quantum information in photonic systems,
4//! including error correction codes, concatenated codes, and hardware-specific encodings.
5
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::f64::consts::PI;
9use thiserror::Error;
10
11use super::continuous_variable::{Complex, GaussianState};
12use super::gate_based::{PhotonicQubitEncoding, PhotonicQubitState};
13use super::{PhotonicMode, PhotonicSystemType};
14use crate::DeviceResult;
15
16/// Errors for quantum encoding operations
17#[derive(Error, Debug)]
18pub enum EncodingError {
19    #[error("Invalid encoding parameters: {0}")]
20    InvalidParameters(String),
21    #[error("Encoding not supported: {0}")]
22    UnsupportedEncoding(String),
23    #[error("Decoding failed: {0}")]
24    DecodingFailed(String),
25    #[error("Insufficient physical qubits: {0}")]
26    InsufficientQubits(String),
27    #[error("Code distance too small: {0}")]
28    CodeDistanceTooSmall(usize),
29}
30
31type EncodingResult<T> = Result<T, EncodingError>;
32
33/// Quantum error correction code types for photonic systems
34#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35pub enum PhotonicQECCode {
36    /// Repetition code
37    Repetition { distance: usize },
38    /// Surface code (adapted for photonic systems)
39    Surface { distance: usize },
40    /// Color code
41    Color { distance: usize },
42    /// Concatenated code
43    Concatenated {
44        inner_code: Box<Self>,
45        outer_code: Box<Self>,
46        levels: usize,
47    },
48    /// CV quantum error correction
49    ContinuousVariable {
50        code_type: CVCodeType,
51        parameters: CVCodeParameters,
52    },
53    /// Bosonic codes
54    Bosonic {
55        code_type: BosonicCodeType,
56        cutoff: usize,
57    },
58}
59
60/// Continuous variable QEC code types
61#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
62pub enum CVCodeType {
63    /// Gottesman-Kitaev-Preskill (GKP) code
64    GKP,
65    /// Cat codes
66    Cat,
67    /// Binomial codes
68    Binomial,
69    /// Coherent state codes
70    CoherentState,
71}
72
73/// Parameters for CV QEC codes
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct CVCodeParameters {
76    /// Squeezing parameter
77    pub squeezing: f64,
78    /// Displacement parameter
79    pub displacement: Complex,
80    /// Loss tolerance
81    pub loss_tolerance: f64,
82    /// Code rate
83    pub code_rate: f64,
84}
85
86impl PartialEq for CVCodeParameters {
87    fn eq(&self, other: &Self) -> bool {
88        self.squeezing == other.squeezing
89            && self.displacement.real == other.displacement.real
90            && self.displacement.imag == other.displacement.imag
91            && self.loss_tolerance == other.loss_tolerance
92            && self.code_rate == other.code_rate
93    }
94}
95
96/// Bosonic code types
97#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
98pub enum BosonicCodeType {
99    /// Fock state codes
100    Fock { basis_states: Vec<usize> },
101    /// Coherent state codes
102    Coherent { alpha_values: Vec<Complex> },
103    /// Squeezed state codes
104    Squeezed { squeezing_params: Vec<(f64, f64)> },
105}
106
107/// Logical qubit representation
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct LogicalQubit {
110    /// Encoding scheme used
111    pub encoding: PhotonicQECCode,
112    /// Physical qubits/modes involved
113    pub physical_qubits: Vec<usize>,
114    /// Logical state parameters
115    pub logical_state: LogicalState,
116    /// Error syndrome information
117    pub syndrome: Option<ErrorSyndrome>,
118}
119
120/// Logical quantum state
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct LogicalState {
123    /// Amplitude for logical |0⟩
124    pub amplitude_0: f64,
125    /// Amplitude for logical |1⟩
126    pub amplitude_1: f64,
127    /// Relative phase
128    pub phase: f64,
129    /// State fidelity
130    pub fidelity: f64,
131}
132
133impl LogicalState {
134    /// Create logical |0⟩ state
135    pub const fn zero() -> Self {
136        Self {
137            amplitude_0: 1.0,
138            amplitude_1: 0.0,
139            phase: 0.0,
140            fidelity: 1.0,
141        }
142    }
143
144    /// Create logical |1⟩ state
145    pub const fn one() -> Self {
146        Self {
147            amplitude_0: 0.0,
148            amplitude_1: 1.0,
149            phase: 0.0,
150            fidelity: 1.0,
151        }
152    }
153
154    /// Create logical |+⟩ state
155    pub fn plus() -> Self {
156        Self {
157            amplitude_0: 1.0 / (2.0_f64).sqrt(),
158            amplitude_1: 1.0 / (2.0_f64).sqrt(),
159            phase: 0.0,
160            fidelity: 1.0,
161        }
162    }
163
164    /// Create arbitrary logical state
165    pub fn arbitrary(amplitude_0: f64, amplitude_1: f64, phase: f64) -> EncodingResult<Self> {
166        let norm_squared = amplitude_0.mul_add(amplitude_0, amplitude_1 * amplitude_1);
167        if (norm_squared - 1.0).abs() > 1e-6 {
168            return Err(EncodingError::InvalidParameters(
169                "State amplitudes not normalized".to_string(),
170            ));
171        }
172
173        Ok(Self {
174            amplitude_0,
175            amplitude_1,
176            phase,
177            fidelity: 1.0,
178        })
179    }
180
181    /// Get probability of measuring logical |0⟩
182    pub fn prob_zero(&self) -> f64 {
183        self.amplitude_0 * self.amplitude_0
184    }
185
186    /// Get probability of measuring logical |1⟩
187    pub fn prob_one(&self) -> f64 {
188        self.amplitude_1 * self.amplitude_1
189    }
190}
191
192/// Error syndrome for quantum error correction
193#[derive(Debug, Clone, Serialize, Deserialize)]
194pub struct ErrorSyndrome {
195    /// Syndrome bits
196    pub syndrome_bits: Vec<bool>,
197    /// Error type detected
198    pub error_type: Option<ErrorType>,
199    /// Error location (if identifiable)
200    pub error_location: Option<Vec<usize>>,
201    /// Correction applied
202    pub correction_applied: Option<Correction>,
203}
204
205/// Types of quantum errors
206#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
207pub enum ErrorType {
208    /// Bit flip error (X error)
209    BitFlip,
210    /// Phase flip error (Z error)
211    PhaseFlip,
212    /// Combined error (Y error)
213    Combined,
214    /// Amplitude damping
215    AmplitudeDamping,
216    /// Phase damping
217    PhaseDamping,
218    /// Photon loss
219    PhotonLoss,
220    /// Thermal noise
221    ThermalNoise,
222}
223
224/// Quantum error correction operations
225#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct Correction {
227    /// Type of correction
228    pub correction_type: ErrorType,
229    /// Qubits to apply correction to
230    pub target_qubits: Vec<usize>,
231    /// Correction parameters
232    pub parameters: Vec<f64>,
233}
234
235/// Photonic encoding engine
236pub struct PhotonicEncoder {
237    /// Available encoding schemes
238    pub available_codes: Vec<PhotonicQECCode>,
239    /// Encoding performance cache
240    pub performance_cache: HashMap<String, EncodingPerformance>,
241}
242
243/// Performance metrics for encoding schemes
244#[derive(Debug, Clone, Serialize, Deserialize)]
245pub struct EncodingPerformance {
246    /// Code distance
247    pub distance: usize,
248    /// Code rate (logical/physical)
249    pub rate: f64,
250    /// Threshold error rate
251    pub threshold: f64,
252    /// Resource overhead
253    pub overhead: usize,
254    /// Encoding fidelity
255    pub encoding_fidelity: f64,
256    /// Decoding fidelity
257    pub decoding_fidelity: f64,
258}
259
260impl PhotonicEncoder {
261    pub fn new() -> Self {
262        let available_codes = vec![
263            PhotonicQECCode::Repetition { distance: 3 },
264            PhotonicQECCode::Repetition { distance: 5 },
265            PhotonicQECCode::Surface { distance: 3 },
266            PhotonicQECCode::Surface { distance: 5 },
267            PhotonicQECCode::ContinuousVariable {
268                code_type: CVCodeType::GKP,
269                parameters: CVCodeParameters {
270                    squeezing: 10.0,
271                    displacement: Complex::new(0.0, 0.0),
272                    loss_tolerance: 0.1,
273                    code_rate: 1.0,
274                },
275            },
276            PhotonicQECCode::Bosonic {
277                code_type: BosonicCodeType::Coherent {
278                    alpha_values: vec![Complex::new(2.0, 0.0), Complex::new(-2.0, 0.0)],
279                },
280                cutoff: 10,
281            },
282        ];
283
284        Self {
285            available_codes,
286            performance_cache: HashMap::new(),
287        }
288    }
289
290    /// Encode a logical qubit using the specified code
291    pub fn encode_logical_qubit(
292        &self,
293        logical_state: LogicalState,
294        code: &PhotonicQECCode,
295        physical_qubits: Vec<usize>,
296    ) -> EncodingResult<LogicalQubit> {
297        // Validate resources
298        let required_qubits = self.get_required_physical_qubits(code)?;
299        if physical_qubits.len() < required_qubits {
300            return Err(EncodingError::InsufficientQubits(format!(
301                "Need {} qubits, got {}",
302                required_qubits,
303                physical_qubits.len()
304            )));
305        }
306
307        match code {
308            PhotonicQECCode::Repetition { distance } => {
309                self.encode_repetition_code(logical_state, *distance, physical_qubits)
310            }
311            PhotonicQECCode::Surface { distance } => {
312                self.encode_surface_code(logical_state, *distance, physical_qubits)
313            }
314            PhotonicQECCode::ContinuousVariable {
315                code_type,
316                parameters,
317            } => self.encode_cv_code(logical_state, code_type, parameters, physical_qubits),
318            PhotonicQECCode::Bosonic { code_type, cutoff } => {
319                self.encode_bosonic_code(logical_state, code_type, *cutoff, physical_qubits)
320            }
321            PhotonicQECCode::Concatenated {
322                inner_code,
323                outer_code,
324                levels,
325            } => self.encode_concatenated_code(
326                logical_state,
327                inner_code,
328                outer_code,
329                *levels,
330                physical_qubits,
331            ),
332            PhotonicQECCode::Color { .. } => Err(EncodingError::UnsupportedEncoding(format!(
333                "Code {code:?} not yet implemented"
334            ))),
335        }
336    }
337
338    /// Encode using repetition code
339    fn encode_repetition_code(
340        &self,
341        logical_state: LogicalState,
342        distance: usize,
343        physical_qubits: Vec<usize>,
344    ) -> EncodingResult<LogicalQubit> {
345        if distance % 2 == 0 {
346            return Err(EncodingError::CodeDistanceTooSmall(distance));
347        }
348
349        // Repetition code: encode logical state into multiple physical qubits
350        let encoding_fidelity = 0.99; // High fidelity for repetition codes
351
352        let logical_state_encoded = LogicalState {
353            fidelity: logical_state.fidelity * encoding_fidelity,
354            ..logical_state
355        };
356
357        Ok(LogicalQubit {
358            encoding: PhotonicQECCode::Repetition { distance },
359            physical_qubits: physical_qubits[0..distance].to_vec(),
360            logical_state: logical_state_encoded,
361            syndrome: None,
362        })
363    }
364
365    /// Encode using surface code
366    fn encode_surface_code(
367        &self,
368        logical_state: LogicalState,
369        distance: usize,
370        physical_qubits: Vec<usize>,
371    ) -> EncodingResult<LogicalQubit> {
372        if distance < 3 {
373            return Err(EncodingError::CodeDistanceTooSmall(distance));
374        }
375
376        // Surface code requires d² data qubits + (d²-1) syndrome qubits
377        let required_qubits = 2 * distance * distance - 1;
378        let encoding_fidelity = 0.95; // Lower than repetition due to complexity
379
380        let logical_state_encoded = LogicalState {
381            fidelity: logical_state.fidelity * encoding_fidelity,
382            ..logical_state
383        };
384
385        Ok(LogicalQubit {
386            encoding: PhotonicQECCode::Surface { distance },
387            physical_qubits: physical_qubits[0..required_qubits].to_vec(),
388            logical_state: logical_state_encoded,
389            syndrome: None,
390        })
391    }
392
393    /// Encode using continuous variable code
394    fn encode_cv_code(
395        &self,
396        logical_state: LogicalState,
397        code_type: &CVCodeType,
398        parameters: &CVCodeParameters,
399        physical_modes: Vec<usize>,
400    ) -> EncodingResult<LogicalQubit> {
401        match code_type {
402            CVCodeType::GKP => {
403                // GKP encoding: map logical qubit to position/momentum eigenstate grid
404                let encoding_fidelity = 0.85; // Lower due to finite squeezing
405
406                let logical_state_encoded = LogicalState {
407                    fidelity: logical_state.fidelity * encoding_fidelity,
408                    ..logical_state
409                };
410
411                Ok(LogicalQubit {
412                    encoding: PhotonicQECCode::ContinuousVariable {
413                        code_type: code_type.clone(),
414                        parameters: parameters.clone(),
415                    },
416                    physical_qubits: physical_modes[0..1].to_vec(), // Single mode for GKP
417                    logical_state: logical_state_encoded,
418                    syndrome: None,
419                })
420            }
421            CVCodeType::Cat => {
422                // Cat code encoding: superposition of coherent states
423                let encoding_fidelity = 0.90;
424
425                let logical_state_encoded = LogicalState {
426                    fidelity: logical_state.fidelity * encoding_fidelity,
427                    ..logical_state
428                };
429
430                Ok(LogicalQubit {
431                    encoding: PhotonicQECCode::ContinuousVariable {
432                        code_type: code_type.clone(),
433                        parameters: parameters.clone(),
434                    },
435                    physical_qubits: physical_modes[0..1].to_vec(),
436                    logical_state: logical_state_encoded,
437                    syndrome: None,
438                })
439            }
440            _ => Err(EncodingError::UnsupportedEncoding(format!(
441                "CV code {code_type:?} not implemented"
442            ))),
443        }
444    }
445
446    /// Encode using bosonic code
447    fn encode_bosonic_code(
448        &self,
449        logical_state: LogicalState,
450        code_type: &BosonicCodeType,
451        cutoff: usize,
452        physical_modes: Vec<usize>,
453    ) -> EncodingResult<LogicalQubit> {
454        match code_type {
455            BosonicCodeType::Coherent { alpha_values } => {
456                if alpha_values.len() < 2 {
457                    return Err(EncodingError::InvalidParameters(
458                        "Coherent state code requires at least 2 alpha values".to_string(),
459                    ));
460                }
461
462                let encoding_fidelity = 0.88;
463
464                let logical_state_encoded = LogicalState {
465                    fidelity: logical_state.fidelity * encoding_fidelity,
466                    ..logical_state
467                };
468
469                Ok(LogicalQubit {
470                    encoding: PhotonicQECCode::Bosonic {
471                        code_type: code_type.clone(),
472                        cutoff,
473                    },
474                    physical_qubits: physical_modes[0..1].to_vec(),
475                    logical_state: logical_state_encoded,
476                    syndrome: None,
477                })
478            }
479            _ => Err(EncodingError::UnsupportedEncoding(format!(
480                "Bosonic code {code_type:?} not implemented"
481            ))),
482        }
483    }
484
485    /// Encode using concatenated code
486    fn encode_concatenated_code(
487        &self,
488        logical_state: LogicalState,
489        inner_code: &PhotonicQECCode,
490        outer_code: &PhotonicQECCode,
491        levels: usize,
492        physical_qubits: Vec<usize>,
493    ) -> EncodingResult<LogicalQubit> {
494        if levels == 0 {
495            return Err(EncodingError::InvalidParameters(
496                "Concatenation levels must be > 0".to_string(),
497            ));
498        }
499
500        // Recursive encoding: first inner code, then outer code
501        let inner_required = self.get_required_physical_qubits(inner_code)?;
502        let outer_required = self.get_required_physical_qubits(outer_code)?;
503        let total_required = inner_required * outer_required;
504
505        if physical_qubits.len() < total_required {
506            return Err(EncodingError::InsufficientQubits(format!(
507                "Concatenated code needs {total_required} qubits"
508            )));
509        }
510
511        // Encoding fidelity decreases with concatenation complexity
512        let encoding_fidelity = 0.80;
513
514        let logical_state_encoded = LogicalState {
515            fidelity: logical_state.fidelity * encoding_fidelity,
516            ..logical_state
517        };
518
519        Ok(LogicalQubit {
520            encoding: PhotonicQECCode::Concatenated {
521                inner_code: Box::new(inner_code.clone()),
522                outer_code: Box::new(outer_code.clone()),
523                levels,
524            },
525            physical_qubits: physical_qubits[0..total_required].to_vec(),
526            logical_state: logical_state_encoded,
527            syndrome: None,
528        })
529    }
530
531    /// Decode a logical qubit back to logical state
532    pub fn decode_logical_qubit(
533        &self,
534        logical_qubit: &LogicalQubit,
535    ) -> EncodingResult<LogicalState> {
536        // Apply error correction based on syndrome
537        let mut corrected_state = logical_qubit.logical_state.clone();
538
539        if let Some(syndrome) = &logical_qubit.syndrome {
540            corrected_state = self.apply_error_correction(corrected_state, syndrome)?;
541        }
542
543        // Apply decoding fidelity loss
544        let decoding_fidelity = self.get_decoding_fidelity(&logical_qubit.encoding)?;
545        corrected_state.fidelity *= decoding_fidelity;
546
547        Ok(corrected_state)
548    }
549
550    /// Apply error correction based on syndrome
551    fn apply_error_correction(
552        &self,
553        logical_state: LogicalState,
554        syndrome: &ErrorSyndrome,
555    ) -> EncodingResult<LogicalState> {
556        let mut corrected_state = logical_state;
557
558        if let Some(correction) = &syndrome.correction_applied {
559            match correction.correction_type {
560                ErrorType::BitFlip => {
561                    // Apply bit flip correction
562                    std::mem::swap(
563                        &mut corrected_state.amplitude_0,
564                        &mut corrected_state.amplitude_1,
565                    );
566                }
567                ErrorType::PhaseFlip => {
568                    // Apply phase flip correction
569                    corrected_state.phase += PI;
570                }
571                ErrorType::PhotonLoss => {
572                    // Reduce fidelity due to photon loss
573                    corrected_state.fidelity *= 0.9;
574                }
575                _ => {
576                    // General error correction reduces fidelity
577                    corrected_state.fidelity *= 0.95;
578                }
579            }
580        }
581
582        Ok(corrected_state)
583    }
584
585    /// Get required number of physical qubits for a code
586    pub fn get_required_physical_qubits(&self, code: &PhotonicQECCode) -> EncodingResult<usize> {
587        match code {
588            PhotonicQECCode::Repetition { distance } => Ok(*distance),
589            PhotonicQECCode::Surface { distance } => Ok(2 * distance * distance - 1),
590            PhotonicQECCode::Color { distance } => Ok(3 * distance * distance / 2),
591            PhotonicQECCode::ContinuousVariable { .. } | PhotonicQECCode::Bosonic { .. } => Ok(1), // Single mode
592            PhotonicQECCode::Concatenated {
593                inner_code,
594                outer_code,
595                ..
596            } => {
597                let inner_qubits = self.get_required_physical_qubits(inner_code)?;
598                let outer_qubits = self.get_required_physical_qubits(outer_code)?;
599                Ok(inner_qubits * outer_qubits)
600            }
601        }
602    }
603
604    /// Get decoding fidelity for a code
605    const fn get_decoding_fidelity(&self, code: &PhotonicQECCode) -> EncodingResult<f64> {
606        match code {
607            PhotonicQECCode::Repetition { .. } => Ok(0.995),
608            PhotonicQECCode::Surface { .. } => Ok(0.99),
609            PhotonicQECCode::ContinuousVariable { code_type, .. } => match code_type {
610                CVCodeType::GKP => Ok(0.90),
611                CVCodeType::Cat => Ok(0.92),
612                _ => Ok(0.85),
613            },
614            PhotonicQECCode::Bosonic { .. } => Ok(0.88),
615            PhotonicQECCode::Concatenated { .. } => Ok(0.85),
616            PhotonicQECCode::Color { .. } => Ok(0.80),
617        }
618    }
619
620    /// Calculate error syndrome for a logical qubit
621    pub fn calculate_syndrome(
622        &self,
623        logical_qubit: &LogicalQubit,
624    ) -> EncodingResult<ErrorSyndrome> {
625        match &logical_qubit.encoding {
626            PhotonicQECCode::Repetition { distance } => {
627                self.calculate_repetition_syndrome(logical_qubit, *distance)
628            }
629            PhotonicQECCode::Surface { distance } => {
630                self.calculate_surface_syndrome(logical_qubit, *distance)
631            }
632            _ => {
633                // Default syndrome calculation
634                Ok(ErrorSyndrome {
635                    syndrome_bits: vec![false; 4], // Placeholder
636                    error_type: None,
637                    error_location: None,
638                    correction_applied: None,
639                })
640            }
641        }
642    }
643
644    /// Calculate syndrome for repetition code
645    fn calculate_repetition_syndrome(
646        &self,
647        logical_qubit: &LogicalQubit,
648        distance: usize,
649    ) -> EncodingResult<ErrorSyndrome> {
650        // Simplified syndrome calculation for repetition code
651        let syndrome_bits = vec![false; distance - 1]; // d-1 syndrome bits
652
653        // Detect majority disagreement (simplified)
654        let error_detected = logical_qubit.logical_state.fidelity < 0.95;
655
656        let error_type = if error_detected {
657            Some(ErrorType::BitFlip)
658        } else {
659            None
660        };
661
662        Ok(ErrorSyndrome {
663            syndrome_bits,
664            error_type,
665            error_location: None,
666            correction_applied: None,
667        })
668    }
669
670    /// Calculate syndrome for surface code
671    fn calculate_surface_syndrome(
672        &self,
673        logical_qubit: &LogicalQubit,
674        distance: usize,
675    ) -> EncodingResult<ErrorSyndrome> {
676        // Surface code has (d²-1) syndrome bits
677        let num_syndromes = distance * distance - 1;
678        let syndrome_bits = vec![false; num_syndromes];
679
680        // Simplified error detection
681        let error_detected = logical_qubit.logical_state.fidelity < 0.90;
682
683        let error_type = if error_detected {
684            Some(ErrorType::Combined) // Surface code corrects both X and Z errors
685        } else {
686            None
687        };
688
689        Ok(ErrorSyndrome {
690            syndrome_bits,
691            error_type,
692            error_location: None,
693            correction_applied: None,
694        })
695    }
696
697    /// Get performance metrics for a code
698    pub fn get_performance(&self, code: &PhotonicQECCode) -> EncodingResult<EncodingPerformance> {
699        let cache_key = format!("{code:?}");
700
701        if let Some(performance) = self.performance_cache.get(&cache_key) {
702            return Ok(performance.clone());
703        }
704
705        // Calculate performance metrics
706        let performance = match code {
707            PhotonicQECCode::Repetition { distance } => EncodingPerformance {
708                distance: *distance,
709                rate: 1.0 / (*distance as f64),
710                threshold: 0.5, // 50% for repetition code
711                overhead: *distance,
712                encoding_fidelity: 0.99,
713                decoding_fidelity: 0.995,
714            },
715            PhotonicQECCode::Surface { distance } => EncodingPerformance {
716                distance: *distance,
717                rate: 1.0 / ((2 * distance * distance - 1) as f64),
718                threshold: 0.11, // ~11% for surface code
719                overhead: 2 * distance * distance - 1,
720                encoding_fidelity: 0.95,
721                decoding_fidelity: 0.99,
722            },
723            _ => EncodingPerformance {
724                distance: 3,
725                rate: 0.5,
726                threshold: 0.1,
727                overhead: 10,
728                encoding_fidelity: 0.90,
729                decoding_fidelity: 0.85,
730            },
731        };
732
733        Ok(performance)
734    }
735}
736
737impl Default for PhotonicEncoder {
738    fn default() -> Self {
739        Self::new()
740    }
741}
742
743#[cfg(test)]
744mod tests {
745    use super::*;
746
747    #[test]
748    fn test_logical_state_creation() {
749        let zero = LogicalState::zero();
750        assert_eq!(zero.prob_zero(), 1.0);
751        assert_eq!(zero.prob_one(), 0.0);
752
753        let one = LogicalState::one();
754        assert_eq!(one.prob_zero(), 0.0);
755        assert_eq!(one.prob_one(), 1.0);
756
757        let plus = LogicalState::plus();
758        assert!((plus.prob_zero() - 0.5).abs() < 1e-10);
759        assert!((plus.prob_one() - 0.5).abs() < 1e-10);
760    }
761
762    #[test]
763    fn test_encoder_creation() {
764        let encoder = PhotonicEncoder::new();
765        assert!(!encoder.available_codes.is_empty());
766    }
767
768    #[test]
769    fn test_repetition_code_encoding() {
770        let encoder = PhotonicEncoder::new();
771        let logical_state = LogicalState::zero();
772        let code = PhotonicQECCode::Repetition { distance: 3 };
773        let physical_qubits = vec![0, 1, 2];
774
775        let encoded = encoder
776            .encode_logical_qubit(logical_state, &code, physical_qubits)
777            .expect("Repetition code encoding should succeed");
778        assert_eq!(encoded.physical_qubits.len(), 3);
779        assert!(matches!(
780            encoded.encoding,
781            PhotonicQECCode::Repetition { distance: 3 }
782        ));
783    }
784
785    #[test]
786    fn test_surface_code_encoding() {
787        let encoder = PhotonicEncoder::new();
788        let logical_state = LogicalState::plus();
789        let code = PhotonicQECCode::Surface { distance: 3 };
790        let physical_qubits: Vec<usize> = (0..17).collect(); // 2*3²-1 = 17 qubits
791
792        let encoded = encoder
793            .encode_logical_qubit(logical_state, &code, physical_qubits)
794            .expect("Surface code encoding should succeed");
795        assert_eq!(encoded.physical_qubits.len(), 17);
796    }
797
798    #[test]
799    fn test_cv_code_encoding() {
800        let encoder = PhotonicEncoder::new();
801        let logical_state = LogicalState::zero();
802        let code = PhotonicQECCode::ContinuousVariable {
803            code_type: CVCodeType::GKP,
804            parameters: CVCodeParameters {
805                squeezing: 10.0,
806                displacement: Complex::new(0.0, 0.0),
807                loss_tolerance: 0.1,
808                code_rate: 1.0,
809            },
810        };
811        let physical_modes = vec![0];
812
813        let encoded = encoder
814            .encode_logical_qubit(logical_state, &code, physical_modes)
815            .expect("CV code encoding should succeed");
816        assert_eq!(encoded.physical_qubits.len(), 1);
817    }
818
819    #[test]
820    fn test_performance_calculation() {
821        let encoder = PhotonicEncoder::new();
822        let code = PhotonicQECCode::Repetition { distance: 5 };
823
824        let performance = encoder
825            .get_performance(&code)
826            .expect("Performance calculation should succeed");
827        assert_eq!(performance.distance, 5);
828        assert_eq!(performance.rate, 0.2); // 1/5
829        assert_eq!(performance.overhead, 5);
830    }
831
832    #[test]
833    fn test_syndrome_calculation() {
834        let encoder = PhotonicEncoder::new();
835        let logical_state = LogicalState::zero();
836        let code = PhotonicQECCode::Repetition { distance: 3 };
837        let encoded = encoder
838            .encode_logical_qubit(logical_state, &code, vec![0, 1, 2])
839            .expect("Repetition code encoding should succeed");
840
841        let syndrome = encoder
842            .calculate_syndrome(&encoded)
843            .expect("Syndrome calculation should succeed");
844        assert_eq!(syndrome.syndrome_bits.len(), 2); // d-1 = 2
845    }
846
847    #[test]
848    fn test_decoding() {
849        let encoder = PhotonicEncoder::new();
850        let original_state = LogicalState::plus();
851        let code = PhotonicQECCode::Repetition { distance: 3 };
852        let encoded = encoder
853            .encode_logical_qubit(original_state.clone(), &code, vec![0, 1, 2])
854            .expect("Repetition code encoding should succeed");
855
856        let decoded = encoder
857            .decode_logical_qubit(&encoded)
858            .expect("Decoding should succeed");
859        assert!((decoded.prob_zero() - original_state.prob_zero()).abs() < 0.1);
860        assert!((decoded.prob_one() - original_state.prob_one()).abs() < 0.1);
861    }
862}