quantrs2_device/continuous_variable/
cluster_states.rs

1//! Cluster states for continuous variable quantum computing
2//!
3//! This module implements cluster state generation and manipulation for CV systems,
4//! enabling measurement-based quantum computing with continuous variables.
5
6use super::{CVDeviceConfig, CVGateSequence, Complex, GaussianState};
7use crate::{DeviceError, DeviceResult};
8use serde::{Deserialize, Serialize};
9use std::collections::{HashMap, HashSet};
10use std::f64::consts::PI;
11
12/// Types of CV cluster states
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
14pub enum ClusterStateType {
15    /// Linear cluster (1D chain)
16    Linear,
17    /// Square lattice cluster (2D)
18    Square,
19    /// Hexagonal lattice cluster
20    Hexagonal,
21    /// Custom graph cluster
22    Custom { adjacency_matrix: Vec<Vec<bool>> },
23}
24
25/// Cluster state configuration
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct ClusterStateConfig {
28    /// Type of cluster state
29    pub cluster_type: ClusterStateType,
30    /// Number of modes in the cluster
31    pub num_modes: usize,
32    /// Squeezing parameter for initial squeezed states
33    pub squeezing_parameter: f64,
34    /// Entangling gate strength
35    pub entangling_strength: f64,
36    /// Graph structure (adjacency list)
37    pub graph_structure: HashMap<usize, Vec<usize>>,
38    /// Enable finite squeezing compensation
39    pub finite_squeezing_compensation: bool,
40}
41
42impl ClusterStateConfig {
43    /// Create a linear cluster configuration
44    pub fn linear(num_modes: usize, squeezing: f64) -> Self {
45        let mut graph_structure = HashMap::new();
46
47        for i in 0..num_modes {
48            let mut neighbors = Vec::new();
49            if i > 0 {
50                neighbors.push(i - 1);
51            }
52            if i < num_modes - 1 {
53                neighbors.push(i + 1);
54            }
55            graph_structure.insert(i, neighbors);
56        }
57
58        Self {
59            cluster_type: ClusterStateType::Linear,
60            num_modes,
61            squeezing_parameter: squeezing,
62            entangling_strength: 1.0,
63            graph_structure,
64            finite_squeezing_compensation: true,
65        }
66    }
67
68    /// Create a square lattice cluster configuration
69    pub fn square_lattice(width: usize, height: usize, squeezing: f64) -> Self {
70        let num_modes = width * height;
71        let mut graph_structure = HashMap::new();
72
73        for i in 0..height {
74            for j in 0..width {
75                let node = i * width + j;
76                let mut neighbors = Vec::new();
77
78                // Add horizontal neighbors
79                if j > 0 {
80                    neighbors.push(i * width + (j - 1));
81                }
82                if j < width - 1 {
83                    neighbors.push(i * width + (j + 1));
84                }
85
86                // Add vertical neighbors
87                if i > 0 {
88                    neighbors.push((i - 1) * width + j);
89                }
90                if i < height - 1 {
91                    neighbors.push((i + 1) * width + j);
92                }
93
94                graph_structure.insert(node, neighbors);
95            }
96        }
97
98        Self {
99            cluster_type: ClusterStateType::Square,
100            num_modes,
101            squeezing_parameter: squeezing,
102            entangling_strength: 1.0,
103            graph_structure,
104            finite_squeezing_compensation: true,
105        }
106    }
107
108    /// Create a custom cluster configuration
109    pub fn custom(adjacency_matrix: Vec<Vec<bool>>, squeezing: f64) -> DeviceResult<Self> {
110        let num_modes = adjacency_matrix.len();
111
112        // Validate adjacency matrix
113        for row in &adjacency_matrix {
114            if row.len() != num_modes {
115                return Err(DeviceError::InvalidInput(
116                    "Adjacency matrix must be square".to_string(),
117                ));
118            }
119        }
120
121        // Build graph structure from adjacency matrix
122        let mut graph_structure = HashMap::new();
123        for i in 0..num_modes {
124            let mut neighbors = Vec::new();
125            for j in 0..num_modes {
126                if adjacency_matrix[i][j] {
127                    neighbors.push(j);
128                }
129            }
130            graph_structure.insert(i, neighbors);
131        }
132
133        Ok(Self {
134            cluster_type: ClusterStateType::Custom { adjacency_matrix },
135            num_modes,
136            squeezing_parameter: squeezing,
137            entangling_strength: 1.0,
138            graph_structure,
139            finite_squeezing_compensation: true,
140        })
141    }
142}
143
144/// Cluster state generator
145pub struct ClusterStateGenerator {
146    /// Configuration
147    config: ClusterStateConfig,
148    /// Current cluster state
149    cluster_state: Option<GaussianState>,
150    /// Generation statistics
151    generation_stats: GenerationStatistics,
152}
153
154/// Statistics for cluster state generation
155#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct GenerationStatistics {
157    /// Total entangling gates applied
158    pub total_entangling_gates: usize,
159    /// Average entanglement per mode
160    pub average_entanglement: f64,
161    /// Nullifier violations (finite squeezing effects)
162    pub nullifier_violations: f64,
163    /// Generation fidelity
164    pub generation_fidelity: f64,
165    /// Time taken for generation (ms)
166    pub generation_time_ms: f64,
167}
168
169impl Default for GenerationStatistics {
170    fn default() -> Self {
171        Self {
172            total_entangling_gates: 0,
173            average_entanglement: 0.0,
174            nullifier_violations: 0.0,
175            generation_fidelity: 0.0,
176            generation_time_ms: 0.0,
177        }
178    }
179}
180
181impl ClusterStateGenerator {
182    /// Create a new cluster state generator
183    pub fn new(config: ClusterStateConfig) -> Self {
184        Self {
185            config,
186            cluster_state: None,
187            generation_stats: GenerationStatistics::default(),
188        }
189    }
190
191    /// Generate the cluster state
192    pub async fn generate_cluster_state(&mut self) -> DeviceResult<GaussianState> {
193        let start_time = std::time::Instant::now();
194
195        println!(
196            "Generating {} cluster state with {} modes",
197            match self.config.cluster_type {
198                ClusterStateType::Linear => "linear",
199                ClusterStateType::Square => "square lattice",
200                ClusterStateType::Hexagonal => "hexagonal",
201                ClusterStateType::Custom { .. } => "custom",
202            },
203            self.config.num_modes
204        );
205
206        // Step 1: Initialize with squeezed vacuum states
207        let mut state = self.initialize_squeezed_modes().await?;
208
209        // Step 2: Apply entangling gates according to graph structure
210        self.apply_entangling_gates(&mut state).await?;
211
212        // Step 3: Apply finite squeezing compensation if enabled
213        if self.config.finite_squeezing_compensation {
214            self.apply_squeezing_compensation(&mut state).await?;
215        }
216
217        // Step 4: Calculate generation statistics
218        self.calculate_generation_statistics(&state);
219
220        let generation_time = start_time.elapsed();
221        self.generation_stats.generation_time_ms = generation_time.as_millis() as f64;
222
223        println!(
224            "Cluster state generated in {:.2} ms with fidelity {:.3}",
225            self.generation_stats.generation_time_ms, self.generation_stats.generation_fidelity
226        );
227
228        self.cluster_state = Some(state.clone());
229        Ok(state)
230    }
231
232    /// Initialize all modes with squeezed vacuum states
233    async fn initialize_squeezed_modes(&mut self) -> DeviceResult<GaussianState> {
234        let squeezing_params = vec![self.config.squeezing_parameter; self.config.num_modes];
235        let squeezing_phases = vec![0.0; self.config.num_modes]; // All in x-quadrature
236
237        GaussianState::squeezed_vacuum_state(
238            self.config.num_modes,
239            squeezing_params,
240            squeezing_phases,
241        )
242        .map_err(|e| DeviceError::InvalidInput(format!("Failed to create squeezed states: {e}")))
243    }
244
245    /// Apply entangling gates according to the graph structure
246    async fn apply_entangling_gates(&mut self, state: &mut GaussianState) -> DeviceResult<()> {
247        let mut gate_count = 0;
248
249        // Collect all edges to avoid double-counting
250        let mut edges = HashSet::new();
251        for (node, neighbors) in &self.config.graph_structure {
252            for neighbor in neighbors {
253                let edge = if node < neighbor {
254                    (*node, *neighbor)
255                } else {
256                    (*neighbor, *node)
257                };
258                edges.insert(edge);
259            }
260        }
261
262        println!("Applying {} entangling gates", edges.len());
263
264        // Apply controlled-Z gates for each edge
265        for (mode1, mode2) in edges {
266            self.apply_cv_cz_gate(state, mode1, mode2).await?;
267            gate_count += 1;
268
269            // Simulate some processing time
270            if gate_count % 10 == 0 {
271                tokio::time::sleep(std::time::Duration::from_millis(1)).await;
272            }
273        }
274
275        self.generation_stats.total_entangling_gates = gate_count;
276        Ok(())
277    }
278
279    /// Apply a continuous variable controlled-Z gate
280    async fn apply_cv_cz_gate(
281        &self,
282        state: &mut GaussianState,
283        mode1: usize,
284        mode2: usize,
285    ) -> DeviceResult<()> {
286        // CV controlled-Z gate is implemented via position-momentum coupling
287        // This creates correlation between x1 and p2, and p1 and x2
288
289        let strength = self.config.entangling_strength;
290
291        // Get current covariance matrix elements
292        let old_covar = state.covariancematrix.clone();
293
294        // Apply CZ transformation to covariance matrix
295        // CZ gate: exp(i*g*x1*x2) creates correlations
296
297        let i1_x = 2 * mode1; // x quadrature of mode 1
298        let i1_p = 2 * mode1 + 1; // p quadrature of mode 1
299        let i2_x = 2 * mode2; // x quadrature of mode 2
300        let i2_p = 2 * mode2 + 1; // p quadrature of mode 2
301
302        // CZ gate adds correlations between x1-p2 and p1-x2
303        state.covariancematrix[i1_x][i2_p] +=
304            strength * old_covar[i1_x][i1_x].sqrt() * old_covar[i2_p][i2_p].sqrt();
305        state.covariancematrix[i2_p][i1_x] +=
306            strength * old_covar[i1_x][i1_x].sqrt() * old_covar[i2_p][i2_p].sqrt();
307
308        state.covariancematrix[i1_p][i2_x] +=
309            strength * old_covar[i1_p][i1_p].sqrt() * old_covar[i2_x][i2_x].sqrt();
310        state.covariancematrix[i2_x][i1_p] +=
311            strength * old_covar[i1_p][i1_p].sqrt() * old_covar[i2_x][i2_x].sqrt();
312
313        Ok(())
314    }
315
316    /// Apply finite squeezing compensation
317    async fn apply_squeezing_compensation(
318        &mut self,
319        state: &mut GaussianState,
320    ) -> DeviceResult<()> {
321        println!("Applying finite squeezing compensation");
322
323        // For finite squeezing, we need to compensate for the fact that perfect
324        // cluster states require infinite squeezing. We apply additional local
325        // operations to improve the cluster state fidelity.
326
327        for mode in 0..self.config.num_modes {
328            // Calculate required compensation based on current variance
329            let var_x = state.covariancematrix[2 * mode][2 * mode];
330            let compensation_squeezing = if var_x > 0.1 {
331                -0.5 * var_x.ln() // Additional squeezing to reduce variance
332            } else {
333                0.0
334            };
335
336            if compensation_squeezing > 0.1 {
337                state.apply_squeezing(mode, compensation_squeezing, 0.0)?;
338            }
339        }
340
341        Ok(())
342    }
343
344    /// Calculate generation statistics
345    fn calculate_generation_statistics(&mut self, state: &GaussianState) {
346        // Calculate average entanglement
347        let entanglement_measures = state.calculate_entanglement_measures();
348        self.generation_stats.average_entanglement = entanglement_measures.logarithmic_negativity;
349
350        // Calculate nullifier violations (measure of finite squeezing effects)
351        let mut total_violation = 0.0;
352        for mode in 0..self.config.num_modes {
353            let var_x = state.covariancematrix[2 * mode][2 * mode];
354            // Ideal cluster state has zero x-variance
355            total_violation += var_x;
356        }
357        self.generation_stats.nullifier_violations = total_violation / self.config.num_modes as f64;
358
359        // Estimate generation fidelity
360        self.generation_stats.generation_fidelity = self.estimate_cluster_state_fidelity(state);
361    }
362
363    /// Estimate cluster state fidelity
364    fn estimate_cluster_state_fidelity(&self, state: &GaussianState) -> f64 {
365        // Simplified fidelity calculation based on nullifier violations
366        let ideal_variance = 0.0; // Perfect cluster state has zero x-variance
367        let actual_variance = self.generation_stats.nullifier_violations;
368
369        // Fidelity decreases with variance
370        let variance_penalty = (-actual_variance / 0.5).exp();
371
372        // Account for entanglement quality
373        let entanglement_bonus = (self.generation_stats.average_entanglement / 2.0).tanh();
374
375        (variance_penalty * 0.2f64.mul_add(entanglement_bonus, 0.8)).clamp(0.0, 1.0)
376    }
377
378    /// Perform measurement-based computation on the cluster state
379    pub async fn perform_mbqc_sequence(
380        &mut self,
381        measurement_sequence: Vec<MBQCMeasurement>,
382    ) -> DeviceResult<Vec<MBQCResult>> {
383        if self.cluster_state.is_none() {
384            return Err(DeviceError::InvalidInput(
385                "No cluster state generated".to_string(),
386            ));
387        }
388
389        let mut state = self
390            .cluster_state
391            .as_ref()
392            .expect("cluster state verified to exist above")
393            .clone();
394        let mut results = Vec::new();
395
396        println!(
397            "Performing MBQC sequence with {} measurements",
398            measurement_sequence.len()
399        );
400
401        for (i, measurement) in measurement_sequence.iter().enumerate() {
402            let result = self
403                .perform_single_mbqc_measurement(&mut state, measurement)
404                .await?;
405            results.push(result);
406
407            println!(
408                "Completed measurement {} of {}",
409                i + 1,
410                measurement_sequence.len()
411            );
412        }
413
414        Ok(results)
415    }
416
417    /// Perform a single MBQC measurement
418    async fn perform_single_mbqc_measurement(
419        &self,
420        state: &mut GaussianState,
421        measurement: &MBQCMeasurement,
422    ) -> DeviceResult<MBQCResult> {
423        match measurement.measurement_type {
424            MBQCMeasurementType::Homodyne { phase } => {
425                // Create a simplified measurement config
426                let config = CVDeviceConfig::default();
427                let measured_value =
428                    state.homodyne_measurement(measurement.mode, phase, &config)?;
429
430                Ok(MBQCResult {
431                    mode: measurement.mode,
432                    measurement_type: measurement.measurement_type.clone(),
433                    outcome: measured_value,
434                    feedforward_corrections: self
435                        .calculate_feedforward(measurement, measured_value),
436                    success_probability: 1.0, // Homodyne always succeeds
437                })
438            }
439
440            MBQCMeasurementType::Projection { target_value } => {
441                // Simplified projection measurement
442                let config = CVDeviceConfig::default();
443                let measured_value = state.homodyne_measurement(measurement.mode, 0.0, &config)?;
444                let success_prob =
445                    self.calculate_projection_success_probability(measured_value, target_value);
446
447                Ok(MBQCResult {
448                    mode: measurement.mode,
449                    measurement_type: measurement.measurement_type.clone(),
450                    outcome: measured_value,
451                    feedforward_corrections: Vec::new(),
452                    success_probability: success_prob,
453                })
454            }
455        }
456    }
457
458    /// Calculate feedforward corrections
459    fn calculate_feedforward(
460        &self,
461        measurement: &MBQCMeasurement,
462        outcome: f64,
463    ) -> Vec<FeedforwardCorrection> {
464        let mut corrections = Vec::new();
465
466        // Apply feedforward to neighboring modes
467        if let Some(neighbors) = self.config.graph_structure.get(&measurement.mode) {
468            for &neighbor in neighbors {
469                // Simplified feedforward: phase correction proportional to outcome
470                let correction_phase = outcome * 0.1; // Simplified calculation
471                corrections.push(FeedforwardCorrection {
472                    target_mode: neighbor,
473                    correction_type: CorrectionType::PhaseShift {
474                        phase: correction_phase,
475                    },
476                });
477            }
478        }
479
480        corrections
481    }
482
483    /// Calculate projection measurement success probability
484    fn calculate_projection_success_probability(&self, measured: f64, target: f64) -> f64 {
485        let tolerance = 0.5; // Tolerance for projection success
486        let deviation = (measured - target).abs();
487
488        if deviation <= tolerance {
489            1.0 - deviation / tolerance
490        } else {
491            0.0
492        }
493    }
494
495    /// Get current cluster state
496    pub const fn get_cluster_state(&self) -> Option<&GaussianState> {
497        self.cluster_state.as_ref()
498    }
499
500    /// Get generation statistics
501    pub const fn get_generation_statistics(&self) -> &GenerationStatistics {
502        &self.generation_stats
503    }
504
505    /// Validate cluster state properties
506    pub fn validate_cluster_state(&self) -> DeviceResult<ClusterStateValidation> {
507        if let Some(state) = &self.cluster_state {
508            let mut validation = ClusterStateValidation::default();
509
510            // Check nullifier properties
511            validation.nullifier_eigenvalues = self.calculate_nullifier_eigenvalues(state);
512            validation.max_nullifier_violation = validation
513                .nullifier_eigenvalues
514                .iter()
515                .fold(0.0, |acc, &x| acc.max(x));
516
517            // Check entanglement structure
518            validation.entanglement_spectrum = self.calculate_entanglement_spectrum(state);
519            validation.average_entanglement = validation.entanglement_spectrum.iter().sum::<f64>()
520                / validation.entanglement_spectrum.len() as f64;
521
522            // Overall validation
523            validation.is_valid =
524                validation.max_nullifier_violation < 0.1 && validation.average_entanglement > 0.5;
525
526            Ok(validation)
527        } else {
528            Err(DeviceError::InvalidInput(
529                "No cluster state to validate".to_string(),
530            ))
531        }
532    }
533
534    /// Calculate nullifier eigenvalues
535    fn calculate_nullifier_eigenvalues(&self, state: &GaussianState) -> Vec<f64> {
536        // Simplified calculation of nullifier operator eigenvalues
537        let mut eigenvalues = Vec::new();
538
539        for mode in 0..self.config.num_modes {
540            let var_x = state.covariancematrix[2 * mode][2 * mode];
541            eigenvalues.push(var_x);
542        }
543
544        eigenvalues
545    }
546
547    /// Calculate entanglement spectrum
548    fn calculate_entanglement_spectrum(&self, state: &GaussianState) -> Vec<f64> {
549        // Simplified entanglement spectrum calculation
550        let mut spectrum = Vec::new();
551
552        // Calculate bipartite entanglement for each possible bipartition
553        for i in 0..self.config.num_modes {
554            for j in (i + 1)..self.config.num_modes {
555                let cov_ij = state.covariancematrix[2 * i][2 * j];
556                let entanglement = cov_ij.abs(); // Simplified measure
557                spectrum.push(entanglement);
558            }
559        }
560
561        spectrum
562    }
563}
564
565/// MBQC measurement specification
566#[derive(Debug, Clone, Serialize, Deserialize)]
567pub struct MBQCMeasurement {
568    /// Mode to measure
569    pub mode: usize,
570    /// Type of measurement
571    pub measurement_type: MBQCMeasurementType,
572    /// Adaptive measurement (depends on previous results)
573    pub is_adaptive: bool,
574}
575
576/// Types of MBQC measurements
577#[derive(Debug, Clone, Serialize, Deserialize)]
578pub enum MBQCMeasurementType {
579    /// Homodyne measurement at specific phase
580    Homodyne { phase: f64 },
581    /// Projection onto specific value
582    Projection { target_value: f64 },
583}
584
585/// Result of an MBQC measurement
586#[derive(Debug, Clone, Serialize, Deserialize)]
587pub struct MBQCResult {
588    /// Measured mode
589    pub mode: usize,
590    /// Type of measurement performed
591    pub measurement_type: MBQCMeasurementType,
592    /// Measurement outcome
593    pub outcome: f64,
594    /// Required feedforward corrections
595    pub feedforward_corrections: Vec<FeedforwardCorrection>,
596    /// Success probability (for projection measurements)
597    pub success_probability: f64,
598}
599
600/// Feedforward correction specification
601#[derive(Debug, Clone, Serialize, Deserialize)]
602pub struct FeedforwardCorrection {
603    /// Target mode for correction
604    pub target_mode: usize,
605    /// Type of correction
606    pub correction_type: CorrectionType,
607}
608
609/// Types of feedforward corrections
610#[derive(Debug, Clone, Serialize, Deserialize)]
611pub enum CorrectionType {
612    /// Phase shift correction
613    PhaseShift { phase: f64 },
614    /// Displacement correction
615    Displacement { amplitude: Complex },
616    /// Squeezing correction
617    Squeezing { parameter: f64, phase: f64 },
618}
619
620/// Cluster state validation results
621#[derive(Debug, Clone, Serialize, Deserialize)]
622pub struct ClusterStateValidation {
623    /// Whether the cluster state is valid
624    pub is_valid: bool,
625    /// Nullifier operator eigenvalues
626    pub nullifier_eigenvalues: Vec<f64>,
627    /// Maximum nullifier violation
628    pub max_nullifier_violation: f64,
629    /// Entanglement spectrum
630    pub entanglement_spectrum: Vec<f64>,
631    /// Average entanglement
632    pub average_entanglement: f64,
633}
634
635impl Default for ClusterStateValidation {
636    fn default() -> Self {
637        Self {
638            is_valid: false,
639            nullifier_eigenvalues: Vec::new(),
640            max_nullifier_violation: 0.0,
641            entanglement_spectrum: Vec::new(),
642            average_entanglement: 0.0,
643        }
644    }
645}
646
647#[cfg(test)]
648mod tests {
649    use super::*;
650
651    #[test]
652    fn test_linear_cluster_config() {
653        let config = ClusterStateConfig::linear(5, 1.0);
654        assert_eq!(config.num_modes, 5);
655        assert_eq!(config.cluster_type, ClusterStateType::Linear);
656        assert_eq!(config.graph_structure.len(), 5);
657
658        // Check linear connectivity
659        assert_eq!(config.graph_structure[&0], vec![1]);
660        assert_eq!(config.graph_structure[&2], vec![1, 3]);
661        assert_eq!(config.graph_structure[&4], vec![3]);
662    }
663
664    #[test]
665    fn test_square_lattice_config() {
666        let config = ClusterStateConfig::square_lattice(3, 3, 1.0);
667        assert_eq!(config.num_modes, 9);
668        assert_eq!(config.cluster_type, ClusterStateType::Square);
669
670        // Check corner node (should have 2 neighbors)
671        assert_eq!(config.graph_structure[&0].len(), 2);
672        // Check center node (should have 4 neighbors)
673        assert_eq!(config.graph_structure[&4].len(), 4);
674    }
675
676    #[test]
677    fn test_custom_cluster_config() {
678        let adjacency = vec![
679            vec![false, true, false],
680            vec![true, false, true],
681            vec![false, true, false],
682        ];
683
684        let config =
685            ClusterStateConfig::custom(adjacency, 1.0).expect("Custom adjacency should be valid");
686        assert_eq!(config.num_modes, 3);
687
688        // Check custom connectivity
689        assert_eq!(config.graph_structure[&0], vec![1]);
690        assert_eq!(config.graph_structure[&1], vec![0, 2]);
691        assert_eq!(config.graph_structure[&2], vec![1]);
692    }
693
694    #[tokio::test]
695    async fn test_cluster_state_generation() {
696        let config = ClusterStateConfig::linear(3, 1.0);
697        let mut generator = ClusterStateGenerator::new(config);
698
699        let state = generator
700            .generate_cluster_state()
701            .await
702            .expect("Cluster state generation should succeed");
703        assert_eq!(state.num_modes, 3);
704
705        let stats = generator.get_generation_statistics();
706        assert!(stats.total_entangling_gates > 0);
707        assert!(stats.generation_fidelity > 0.0);
708    }
709
710    #[tokio::test]
711    async fn test_mbqc_measurement() {
712        let config = ClusterStateConfig::linear(3, 1.0);
713        let mut generator = ClusterStateGenerator::new(config);
714        generator
715            .generate_cluster_state()
716            .await
717            .expect("Cluster state generation should succeed");
718
719        let measurements = vec![MBQCMeasurement {
720            mode: 0,
721            measurement_type: MBQCMeasurementType::Homodyne { phase: 0.0 },
722            is_adaptive: false,
723        }];
724
725        let results = generator
726            .perform_mbqc_sequence(measurements)
727            .await
728            .expect("MBQC sequence should succeed");
729        assert_eq!(results.len(), 1);
730        assert_eq!(results[0].success_probability, 1.0);
731    }
732
733    #[test]
734    fn test_cluster_validation() {
735        let config = ClusterStateConfig::linear(2, 1.0);
736        let generator = ClusterStateGenerator::new(config);
737
738        // Should fail validation without generated state
739        assert!(generator.validate_cluster_state().is_err());
740    }
741
742    #[test]
743    fn test_feedforward_calculation() {
744        let config = ClusterStateConfig::linear(3, 1.0);
745        let generator = ClusterStateGenerator::new(config);
746
747        let measurement = MBQCMeasurement {
748            mode: 1,
749            measurement_type: MBQCMeasurementType::Homodyne { phase: 0.0 },
750            is_adaptive: false,
751        };
752
753        let corrections = generator.calculate_feedforward(&measurement, 1.0);
754        assert_eq!(corrections.len(), 2); // Mode 1 has 2 neighbors in linear chain
755    }
756}