quantrs2_circuit/
topological.rs

1//! Topological quantum circuit support
2//!
3//! This module provides support for topological quantum computation,
4//! including anyonic braiding operations, fusion rules, and
5//! topologically protected quantum gates.
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, VecDeque};
15use std::f64::consts::PI;
16
17/// Types of anyons supported in topological quantum computation
18#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
19pub enum AnyonType {
20    /// Vacuum (trivial anyon)
21    Vacuum,
22    /// Ising anyons (σ)
23    Ising,
24    /// Fibonacci anyons (τ)
25    Fibonacci,
26    /// Majorana fermions
27    Majorana,
28    /// Non-Abelian SU(2) anyons
29    SU2 { level: usize },
30    /// Parafermions
31    Parafermion { n: usize },
32    /// Custom anyon type
33    Custom {
34        name: String,
35        quantum_dimension: f64,
36        fusion_rules: Vec<FusionRule>,
37    },
38}
39
40impl AnyonType {
41    /// Get the quantum dimension of the anyon
42    #[must_use]
43    pub fn quantum_dimension(&self) -> f64 {
44        match self {
45            Self::Vacuum => 1.0,
46            Self::Ising => (2.0_f64).sqrt(),
47            Self::Fibonacci => f64::midpoint(1.0, 5.0_f64.sqrt()), // Golden ratio
48            Self::Majorana => (2.0_f64).sqrt(),
49            Self::SU2 { level } => (*level as f64 + 1.0).sqrt(),
50            Self::Parafermion { n } => (2.0 * (*n as f64)).sqrt(),
51            Self::Custom {
52                quantum_dimension, ..
53            } => *quantum_dimension,
54        }
55    }
56
57    /// Check if this anyon type is Abelian
58    #[must_use]
59    pub const fn is_abelian(&self) -> bool {
60        matches!(self, Self::Vacuum)
61    }
62
63    /// Check if this anyon type supports universal quantum computation
64    #[must_use]
65    pub const fn is_universal(&self) -> bool {
66        match self {
67            Self::Fibonacci => true,
68            Self::SU2 { level } => *level >= 3,
69            Self::Parafermion { n } => *n >= 3,
70            _ => false,
71        }
72    }
73}
74
75/// Fusion rules for anyons
76#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
77pub struct FusionRule {
78    /// Input anyon types
79    pub inputs: Vec<AnyonType>,
80    /// Possible output anyon types with multiplicities
81    pub outputs: Vec<(AnyonType, usize)>,
82}
83
84/// Anyon representation in the topological circuit
85#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
86pub struct Anyon {
87    /// Unique identifier
88    pub id: usize,
89    /// Anyon type
90    pub anyon_type: AnyonType,
91    /// Position in 2D space (for braiding)
92    pub position: (f64, f64),
93    /// Current charge state
94    pub charge: Option<usize>,
95}
96
97impl Anyon {
98    /// Create a new anyon
99    #[must_use]
100    pub const fn new(id: usize, anyon_type: AnyonType, position: (f64, f64)) -> Self {
101        Self {
102            id,
103            anyon_type,
104            position,
105            charge: None,
106        }
107    }
108
109    /// Check if this anyon can fuse with another
110    #[must_use]
111    pub fn can_fuse_with(&self, other: &Self) -> bool {
112        // For now, allow fusion between same types or with vacuum
113        self.anyon_type == other.anyon_type
114            || self.anyon_type == AnyonType::Vacuum
115            || other.anyon_type == AnyonType::Vacuum
116    }
117}
118
119/// Braiding operation between anyons
120#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
121pub struct BraidingOperation {
122    /// Anyons involved in the braiding
123    pub anyons: Vec<usize>,
124    /// Braiding type (clockwise or counterclockwise)
125    pub braiding_type: BraidingType,
126    /// Number of braiding operations
127    pub braiding_count: usize,
128    /// Resulting phase or unitary matrix
129    pub phase: Option<f64>,
130}
131
132/// Types of braiding operations
133#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
134pub enum BraidingType {
135    /// Clockwise braiding
136    Clockwise,
137    /// Counterclockwise braiding
138    Counterclockwise,
139    /// Exchange (swap positions)
140    Exchange,
141    /// Yang-Baxter move
142    YangBaxter,
143}
144
145/// Topological gate operations
146#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
147pub enum TopologicalGate {
148    /// Braiding operation
149    Braiding {
150        anyon1: usize,
151        anyon2: usize,
152        braiding_type: BraidingType,
153    },
154    /// Fusion operation
155    Fusion {
156        input_anyons: Vec<usize>,
157        output_anyon: usize,
158        fusion_channel: usize,
159    },
160    /// Splitting operation (inverse of fusion)
161    Splitting {
162        input_anyon: usize,
163        output_anyons: Vec<usize>,
164        splitting_channel: usize,
165    },
166    /// Measurement in fusion basis
167    FusionMeasurement {
168        anyons: Vec<usize>,
169        measurement_basis: FusionBasis,
170    },
171    /// Anyon creation
172    Creation {
173        anyon_type: AnyonType,
174        position: (f64, f64),
175    },
176    /// Anyon annihilation
177    Annihilation { anyon: usize },
178}
179
180/// Fusion measurement basis
181#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
182pub enum FusionBasis {
183    /// Vacuum channel
184    Vacuum,
185    /// Non-trivial channel for non-Abelian anyons
186    NonTrivial { channel: usize },
187}
188
189/// Topological quantum circuit
190#[derive(Debug, Clone)]
191pub struct TopologicalCircuit {
192    /// Anyons in the circuit
193    pub anyons: HashMap<usize, Anyon>,
194    /// Topological gates
195    pub gates: Vec<TopologicalGate>,
196    /// Braiding sequence
197    pub braiding_sequence: Vec<BraidingOperation>,
198    /// Fusion rules for the anyon model
199    pub fusion_rules: Vec<(AnyonType, Vec<FusionRule>)>,
200    /// 2D layout for anyon positions
201    pub layout: TopologicalLayout,
202}
203
204/// 2D layout for topological computation
205#[derive(Debug, Clone)]
206pub struct TopologicalLayout {
207    /// Width of the 2D region
208    pub width: f64,
209    /// Height of the 2D region
210    pub height: f64,
211    /// Forbidden regions (holes or obstacles)
212    pub forbidden_regions: Vec<Region>,
213    /// Braiding paths
214    pub braiding_paths: Vec<Path>,
215}
216
217/// 2D region
218#[derive(Debug, Clone)]
219pub struct Region {
220    /// Center position
221    pub center: (f64, f64),
222    /// Radius (for circular regions)
223    pub radius: f64,
224    /// Shape type
225    pub shape: RegionShape,
226}
227
228/// Shape types for regions
229#[derive(Debug, Clone, PartialEq)]
230pub enum RegionShape {
231    Circle,
232    Rectangle { width: f64, height: f64 },
233    Polygon { vertices: Vec<(f64, f64)> },
234}
235
236/// Path for braiding operations
237#[derive(Debug, Clone)]
238pub struct Path {
239    /// Waypoints along the path
240    pub waypoints: Vec<(f64, f64)>,
241    /// Path type
242    pub path_type: PathType,
243}
244
245/// Types of braiding paths
246#[derive(Debug, Clone, PartialEq, Eq)]
247pub enum PathType {
248    /// Straight line
249    Straight,
250    /// Curved path
251    Curved,
252    /// Optimized path avoiding obstacles
253    Optimized,
254}
255
256/// Topological circuit compiler
257pub struct TopologicalCompiler {
258    /// Default anyon model
259    default_anyon_model: AnyonModel,
260    /// Braiding optimizer
261    braiding_optimizer: BraidingOptimizer,
262    /// Layout optimizer
263    layout_optimizer: LayoutOptimizer,
264}
265
266/// Anyon model configuration
267#[derive(Debug, Clone)]
268pub struct AnyonModel {
269    /// Primary anyon type
270    pub primary_anyon: AnyonType,
271    /// Supported anyon types
272    pub supported_anyons: Vec<AnyonType>,
273    /// Fusion rules
274    pub fusion_rules: Vec<(AnyonType, Vec<FusionRule>)>,
275    /// Braiding phases
276    pub braiding_phases: Vec<((AnyonType, AnyonType), f64)>,
277}
278
279impl AnyonModel {
280    /// Create Fibonacci anyon model
281    #[must_use]
282    pub fn fibonacci() -> Self {
283        let fusion_rules = vec![(
284            AnyonType::Fibonacci,
285            vec![FusionRule {
286                inputs: vec![AnyonType::Fibonacci, AnyonType::Fibonacci],
287                outputs: vec![(AnyonType::Vacuum, 1), (AnyonType::Fibonacci, 1)],
288            }],
289        )];
290
291        let braiding_phases = vec![(
292            (AnyonType::Fibonacci, AnyonType::Fibonacci),
293            2.0 * PI / 5.0, // e^(2πi/5)
294        )];
295
296        Self {
297            primary_anyon: AnyonType::Fibonacci,
298            supported_anyons: vec![AnyonType::Vacuum, AnyonType::Fibonacci],
299            fusion_rules,
300            braiding_phases,
301        }
302    }
303
304    /// Create Ising anyon model
305    #[must_use]
306    pub fn ising() -> Self {
307        let fusion_rules = vec![(
308            AnyonType::Ising,
309            vec![FusionRule {
310                inputs: vec![AnyonType::Ising, AnyonType::Ising],
311                outputs: vec![
312                    (AnyonType::Vacuum, 1),
313                    (AnyonType::Majorana, 1), // Using Majorana as fermion
314                ],
315            }],
316        )];
317
318        let braiding_phases = vec![(
319            (AnyonType::Ising, AnyonType::Ising),
320            PI / 4.0, // e^(πi/4)
321        )];
322
323        Self {
324            primary_anyon: AnyonType::Ising,
325            supported_anyons: vec![AnyonType::Vacuum, AnyonType::Ising, AnyonType::Majorana],
326            fusion_rules,
327            braiding_phases,
328        }
329    }
330}
331
332/// Braiding optimizer for efficient gate sequences
333#[derive(Debug, Clone)]
334pub struct BraidingOptimizer {
335    /// Optimization strategy
336    pub strategy: OptimizationStrategy,
337    /// Maximum braiding distance
338    pub max_braiding_distance: f64,
339    /// Enable path optimization
340    pub optimize_paths: bool,
341}
342
343/// Optimization strategies for braiding
344#[derive(Debug, Clone, PartialEq, Eq)]
345pub enum OptimizationStrategy {
346    /// Minimize total braiding length
347    MinimizeLength,
348    /// Minimize number of crossings
349    MinimizeCrossings,
350    /// Minimize execution time
351    MinimizeTime,
352    /// Balanced optimization
353    Balanced,
354}
355
356/// Layout optimizer for anyon placement
357#[derive(Debug, Clone)]
358pub struct LayoutOptimizer {
359    /// Target layout density
360    pub target_density: f64,
361    /// Enable automatic spacing
362    pub auto_spacing: bool,
363    /// Minimum distance between anyons
364    pub min_distance: f64,
365}
366
367impl TopologicalCompiler {
368    /// Create a new topological compiler
369    #[must_use]
370    pub const fn new(anyon_model: AnyonModel) -> Self {
371        Self {
372            default_anyon_model: anyon_model,
373            braiding_optimizer: BraidingOptimizer {
374                strategy: OptimizationStrategy::Balanced,
375                max_braiding_distance: 10.0,
376                optimize_paths: true,
377            },
378            layout_optimizer: LayoutOptimizer {
379                target_density: 0.5,
380                auto_spacing: true,
381                min_distance: 1.0,
382            },
383        }
384    }
385
386    /// Compile a standard quantum circuit to topological representation
387    pub fn compile_quantum_circuit<const N: usize>(
388        &self,
389        circuit: &Circuit<N>,
390    ) -> QuantRS2Result<TopologicalCircuit> {
391        // Create initial anyons for each logical qubit
392        let mut anyons = HashMap::new();
393        let mut next_anyon_id = 0;
394
395        // Create anyon pairs for each qubit (encoding in anyon pairs)
396        for qubit_id in 0..N {
397            let pos_x = qubit_id as f64 * 2.0;
398
399            // Create anyon pair
400            let anyon1 = Anyon::new(
401                next_anyon_id,
402                self.default_anyon_model.primary_anyon.clone(),
403                (pos_x, 0.0),
404            );
405            let anyon2 = Anyon::new(
406                next_anyon_id + 1,
407                self.default_anyon_model.primary_anyon.clone(),
408                (pos_x + 1.0, 0.0),
409            );
410
411            anyons.insert(next_anyon_id, anyon1);
412            anyons.insert(next_anyon_id + 1, anyon2);
413            next_anyon_id += 2;
414        }
415
416        // Compile gates to topological operations
417        let mut topological_gates = Vec::new();
418        let mut braiding_sequence = Vec::new();
419
420        for gate in circuit.gates() {
421            let (topo_gates, braidings) = self.compile_gate(gate.as_ref(), &anyons)?;
422            topological_gates.extend(topo_gates);
423            braiding_sequence.extend(braidings);
424        }
425
426        // Create layout
427        let layout = self.create_layout(N)?;
428
429        Ok(TopologicalCircuit {
430            anyons,
431            gates: topological_gates,
432            braiding_sequence,
433            fusion_rules: self.default_anyon_model.fusion_rules.clone(),
434            layout,
435        })
436    }
437
438    /// Compile a single quantum gate to topological operations
439    fn compile_gate(
440        &self,
441        gate: &dyn GateOp,
442        anyons: &HashMap<usize, Anyon>,
443    ) -> QuantRS2Result<(Vec<TopologicalGate>, Vec<BraidingOperation>)> {
444        let gate_name = gate.name();
445        let qubits = gate.qubits();
446
447        match gate_name {
448            "H" => self.compile_hadamard_gate(&qubits, anyons),
449            "X" => self.compile_pauli_x_gate(&qubits, anyons),
450            "Z" => self.compile_pauli_z_gate(&qubits, anyons),
451            "CNOT" => self.compile_cnot_gate(&qubits, anyons),
452            "T" => self.compile_t_gate(&qubits, anyons),
453            _ => Err(QuantRS2Error::InvalidInput(format!(
454                "Gate {gate_name} not supported in topological compilation"
455            ))),
456        }
457    }
458
459    /// Compile Hadamard gate using braiding
460    fn compile_hadamard_gate(
461        &self,
462        qubits: &[QubitId],
463        anyons: &HashMap<usize, Anyon>,
464    ) -> QuantRS2Result<(Vec<TopologicalGate>, Vec<BraidingOperation>)> {
465        if qubits.len() != 1 {
466            return Err(QuantRS2Error::InvalidInput(
467                "Hadamard requires one qubit".to_string(),
468            ));
469        }
470
471        let qubit_id = qubits[0].id() as usize;
472        let anyon1_id = qubit_id * 2;
473        let anyon2_id = qubit_id * 2 + 1;
474
475        // Hadamard implemented as specific braiding sequence
476        let braiding = BraidingOperation {
477            anyons: vec![anyon1_id, anyon2_id],
478            braiding_type: BraidingType::Clockwise,
479            braiding_count: 1,
480            phase: Some(PI / 2.0),
481        };
482
483        let topo_gate = TopologicalGate::Braiding {
484            anyon1: anyon1_id,
485            anyon2: anyon2_id,
486            braiding_type: BraidingType::Clockwise,
487        };
488
489        Ok((vec![topo_gate], vec![braiding]))
490    }
491
492    /// Compile Pauli-X gate
493    fn compile_pauli_x_gate(
494        &self,
495        qubits: &[QubitId],
496        anyons: &HashMap<usize, Anyon>,
497    ) -> QuantRS2Result<(Vec<TopologicalGate>, Vec<BraidingOperation>)> {
498        if qubits.len() != 1 {
499            return Err(QuantRS2Error::InvalidInput(
500                "Pauli-X requires one qubit".to_string(),
501            ));
502        }
503
504        let qubit_id = qubits[0].id() as usize;
505        let anyon1_id = qubit_id * 2;
506        let anyon2_id = qubit_id * 2 + 1;
507
508        // Pauli-X as double braiding (full exchange)
509        let braiding = BraidingOperation {
510            anyons: vec![anyon1_id, anyon2_id],
511            braiding_type: BraidingType::Exchange,
512            braiding_count: 2,
513            phase: Some(PI),
514        };
515
516        let topo_gate = TopologicalGate::Braiding {
517            anyon1: anyon1_id,
518            anyon2: anyon2_id,
519            braiding_type: BraidingType::Exchange,
520        };
521
522        Ok((vec![topo_gate], vec![braiding]))
523    }
524
525    /// Compile Pauli-Z gate
526    fn compile_pauli_z_gate(
527        &self,
528        qubits: &[QubitId],
529        anyons: &HashMap<usize, Anyon>,
530    ) -> QuantRS2Result<(Vec<TopologicalGate>, Vec<BraidingOperation>)> {
531        // For many anyon models, Z gates are trivial or require measurement
532        let qubit_id = qubits[0].id() as usize;
533        let anyon1_id = qubit_id * 2;
534        let anyon2_id = qubit_id * 2 + 1;
535
536        // Z gate might be implemented via measurement and feedback
537        let topo_gate = TopologicalGate::FusionMeasurement {
538            anyons: vec![anyon1_id, anyon2_id],
539            measurement_basis: FusionBasis::Vacuum,
540        };
541
542        Ok((vec![topo_gate], vec![]))
543    }
544
545    /// Compile CNOT gate using braiding
546    fn compile_cnot_gate(
547        &self,
548        qubits: &[QubitId],
549        anyons: &HashMap<usize, Anyon>,
550    ) -> QuantRS2Result<(Vec<TopologicalGate>, Vec<BraidingOperation>)> {
551        if qubits.len() != 2 {
552            return Err(QuantRS2Error::InvalidInput(
553                "CNOT requires two qubits".to_string(),
554            ));
555        }
556
557        let control_id = qubits[0].id() as usize;
558        let target_id = qubits[1].id() as usize;
559
560        let control_anyon1 = control_id * 2;
561        let control_anyon2 = control_id * 2 + 1;
562        let target_anyon1 = target_id * 2;
563        let target_anyon2 = target_id * 2 + 1;
564
565        // CNOT requires complex braiding between control and target
566        let mut braidings = Vec::new();
567        let mut topo_gates = Vec::new();
568
569        // Braiding sequence for CNOT (simplified)
570        braidings.push(BraidingOperation {
571            anyons: vec![control_anyon1, target_anyon1],
572            braiding_type: BraidingType::Clockwise,
573            braiding_count: 1,
574            phase: Some(PI / 4.0),
575        });
576
577        braidings.push(BraidingOperation {
578            anyons: vec![control_anyon2, target_anyon2],
579            braiding_type: BraidingType::Counterclockwise,
580            braiding_count: 1,
581            phase: Some(-PI / 4.0),
582        });
583
584        // Corresponding topological gates
585        topo_gates.push(TopologicalGate::Braiding {
586            anyon1: control_anyon1,
587            anyon2: target_anyon1,
588            braiding_type: BraidingType::Clockwise,
589        });
590
591        topo_gates.push(TopologicalGate::Braiding {
592            anyon1: control_anyon2,
593            anyon2: target_anyon2,
594            braiding_type: BraidingType::Counterclockwise,
595        });
596
597        Ok((topo_gates, braidings))
598    }
599
600    /// Compile T gate (non-Clifford gate requiring special treatment)
601    fn compile_t_gate(
602        &self,
603        qubits: &[QubitId],
604        anyons: &HashMap<usize, Anyon>,
605    ) -> QuantRS2Result<(Vec<TopologicalGate>, Vec<BraidingOperation>)> {
606        if !self.default_anyon_model.primary_anyon.is_universal() {
607            return Err(QuantRS2Error::InvalidInput(
608                "T gate requires universal anyon model".to_string(),
609            ));
610        }
611
612        let qubit_id = qubits[0].id() as usize;
613        let anyon1_id = qubit_id * 2;
614        let anyon2_id = qubit_id * 2 + 1;
615
616        // T gate requires specific braiding sequence for universal models
617        let braiding = BraidingOperation {
618            anyons: vec![anyon1_id, anyon2_id],
619            braiding_type: BraidingType::YangBaxter,
620            braiding_count: 1,
621            phase: Some(PI / 4.0),
622        };
623
624        let topo_gate = TopologicalGate::Braiding {
625            anyon1: anyon1_id,
626            anyon2: anyon2_id,
627            braiding_type: BraidingType::YangBaxter,
628        };
629
630        Ok((vec![topo_gate], vec![braiding]))
631    }
632
633    /// Create layout for the topological circuit
634    fn create_layout(&self, num_qubits: usize) -> QuantRS2Result<TopologicalLayout> {
635        let width = (num_qubits as f64).mul_add(2.0, 2.0).max(10.0);
636        let height = 10.0;
637
638        Ok(TopologicalLayout {
639            width,
640            height,
641            forbidden_regions: Vec::new(),
642            braiding_paths: Vec::new(),
643        })
644    }
645
646    /// Optimize braiding sequence
647    pub fn optimize_braiding_sequence(
648        &self,
649        circuit: &mut TopologicalCircuit,
650    ) -> QuantRS2Result<OptimizationStats> {
651        let initial_length = self.calculate_total_braiding_length(&circuit.braiding_sequence);
652        let initial_crossings = self.count_braiding_crossings(&circuit.braiding_sequence);
653
654        // Apply optimization based on strategy
655        match self.braiding_optimizer.strategy {
656            OptimizationStrategy::MinimizeLength => {
657                self.optimize_for_length(&circuit.braiding_sequence)?;
658            }
659            OptimizationStrategy::MinimizeCrossings => {
660                self.optimize_for_crossings(&circuit.braiding_sequence)?;
661            }
662            OptimizationStrategy::MinimizeTime => {
663                self.optimize_for_time(&circuit.braiding_sequence)?;
664            }
665            OptimizationStrategy::Balanced => {
666                self.optimize_balanced(&circuit.braiding_sequence)?;
667            }
668        }
669
670        let final_length = self.calculate_total_braiding_length(&circuit.braiding_sequence);
671        let final_crossings = self.count_braiding_crossings(&circuit.braiding_sequence);
672
673        Ok(OptimizationStats {
674            initial_length,
675            final_length,
676            initial_crossings,
677            final_crossings,
678            length_improvement: (initial_length - final_length) / initial_length,
679            crossings_improvement: (initial_crossings as f64 - final_crossings as f64)
680                / initial_crossings as f64,
681        })
682    }
683
684    /// Calculate total braiding length
685    fn calculate_total_braiding_length(&self, braidings: &[BraidingOperation]) -> f64 {
686        braidings.iter().map(|b| b.braiding_count as f64).sum()
687    }
688
689    /// Count braiding crossings
690    const fn count_braiding_crossings(&self, braidings: &[BraidingOperation]) -> usize {
691        // Simplified crossing count
692        braidings.len()
693    }
694
695    /// Optimize for minimum length
696    const fn optimize_for_length(&self, braidings: &[BraidingOperation]) -> QuantRS2Result<()> {
697        // Implement length optimization
698        Ok(())
699    }
700
701    /// Optimize for minimum crossings
702    const fn optimize_for_crossings(&self, braidings: &[BraidingOperation]) -> QuantRS2Result<()> {
703        // Implement crossing optimization
704        Ok(())
705    }
706
707    /// Optimize for minimum time
708    const fn optimize_for_time(&self, braidings: &[BraidingOperation]) -> QuantRS2Result<()> {
709        // Implement time optimization
710        Ok(())
711    }
712
713    /// Balanced optimization
714    const fn optimize_balanced(&self, braidings: &[BraidingOperation]) -> QuantRS2Result<()> {
715        // Implement balanced optimization
716        Ok(())
717    }
718}
719
720/// Optimization statistics
721#[derive(Debug, Clone)]
722pub struct OptimizationStats {
723    pub initial_length: f64,
724    pub final_length: f64,
725    pub initial_crossings: usize,
726    pub final_crossings: usize,
727    pub length_improvement: f64,
728    pub crossings_improvement: f64,
729}
730
731impl TopologicalCircuit {
732    /// Calculate the total number of braiding operations
733    #[must_use]
734    pub fn total_braiding_operations(&self) -> usize {
735        self.braiding_sequence
736            .iter()
737            .map(|b| b.braiding_count)
738            .sum()
739    }
740
741    /// Get the number of anyons
742    #[must_use]
743    pub fn anyon_count(&self) -> usize {
744        self.anyons.len()
745    }
746
747    /// Check if the circuit uses universal anyons
748    #[must_use]
749    pub fn is_universal(&self) -> bool {
750        self.anyons
751            .values()
752            .any(|anyon| anyon.anyon_type.is_universal())
753    }
754
755    /// Calculate circuit depth in terms of braiding layers
756    #[must_use]
757    pub fn braiding_depth(&self) -> usize {
758        // Simplified depth calculation
759        self.braiding_sequence.len()
760    }
761}
762
763#[cfg(test)]
764mod tests {
765    use super::*;
766    use quantrs2_core::gate::multi::CNOT;
767    use quantrs2_core::gate::single::Hadamard;
768
769    #[test]
770    fn test_anyon_types() {
771        let fibonacci = AnyonType::Fibonacci;
772        assert!(fibonacci.is_universal());
773        assert!(!fibonacci.is_abelian());
774        assert!((fibonacci.quantum_dimension() - 1.618).abs() < 0.01);
775
776        let ising = AnyonType::Ising;
777        assert!(!ising.is_universal());
778        assert!(!ising.is_abelian());
779        assert!((ising.quantum_dimension() - 1.414).abs() < 0.01);
780    }
781
782    #[test]
783    fn test_anyon_creation() {
784        let anyon = Anyon::new(0, AnyonType::Fibonacci, (1.0, 2.0));
785        assert_eq!(anyon.id, 0);
786        assert_eq!(anyon.position, (1.0, 2.0));
787        assert_eq!(anyon.anyon_type, AnyonType::Fibonacci);
788    }
789
790    #[test]
791    fn test_anyon_model_creation() {
792        let fibonacci_model = AnyonModel::fibonacci();
793        assert_eq!(fibonacci_model.primary_anyon, AnyonType::Fibonacci);
794        assert!(fibonacci_model
795            .fusion_rules
796            .iter()
797            .any(|(anyon_type, _)| *anyon_type == AnyonType::Fibonacci));
798
799        let ising_model = AnyonModel::ising();
800        assert_eq!(ising_model.primary_anyon, AnyonType::Ising);
801        assert!(ising_model
802            .braiding_phases
803            .iter()
804            .any(|((a1, a2), _)| *a1 == AnyonType::Ising && *a2 == AnyonType::Ising));
805    }
806
807    #[test]
808    fn test_topological_compiler() {
809        let model = AnyonModel::fibonacci();
810        let compiler = TopologicalCompiler::new(model);
811
812        assert_eq!(
813            compiler.default_anyon_model.primary_anyon,
814            AnyonType::Fibonacci
815        );
816        assert_eq!(
817            compiler.braiding_optimizer.strategy,
818            OptimizationStrategy::Balanced
819        );
820    }
821
822    #[test]
823    fn test_braiding_operation() {
824        let braiding = BraidingOperation {
825            anyons: vec![0, 1],
826            braiding_type: BraidingType::Clockwise,
827            braiding_count: 2,
828            phase: Some(PI / 4.0),
829        };
830
831        assert_eq!(braiding.anyons.len(), 2);
832        assert_eq!(braiding.braiding_count, 2);
833        assert_eq!(braiding.braiding_type, BraidingType::Clockwise);
834    }
835
836    #[test]
837    fn test_topological_gates() {
838        let fusion_gate = TopologicalGate::Fusion {
839            input_anyons: vec![0, 1],
840            output_anyon: 2,
841            fusion_channel: 0,
842        };
843
844        let braiding_gate = TopologicalGate::Braiding {
845            anyon1: 0,
846            anyon2: 1,
847            braiding_type: BraidingType::Exchange,
848        };
849
850        assert!(matches!(fusion_gate, TopologicalGate::Fusion { .. }));
851        assert!(matches!(braiding_gate, TopologicalGate::Braiding { .. }));
852    }
853
854    #[test]
855    fn test_layout_creation() {
856        let layout = TopologicalLayout {
857            width: 10.0,
858            height: 8.0,
859            forbidden_regions: vec![],
860            braiding_paths: vec![],
861        };
862
863        assert_eq!(layout.width, 10.0);
864        assert_eq!(layout.height, 8.0);
865        assert!(layout.forbidden_regions.is_empty());
866    }
867
868    #[test]
869    fn test_circuit_properties() {
870        let mut anyons = HashMap::new();
871        anyons.insert(0, Anyon::new(0, AnyonType::Fibonacci, (0.0, 0.0)));
872        anyons.insert(1, Anyon::new(1, AnyonType::Fibonacci, (1.0, 0.0)));
873
874        let circuit = TopologicalCircuit {
875            anyons,
876            gates: vec![],
877            braiding_sequence: vec![BraidingOperation {
878                anyons: vec![0, 1],
879                braiding_type: BraidingType::Clockwise,
880                braiding_count: 3,
881                phase: Some(PI / 4.0),
882            }],
883            fusion_rules: Vec::new(),
884            layout: TopologicalLayout {
885                width: 5.0,
886                height: 5.0,
887                forbidden_regions: vec![],
888                braiding_paths: vec![],
889            },
890        };
891
892        assert_eq!(circuit.anyon_count(), 2);
893        assert_eq!(circuit.total_braiding_operations(), 3);
894        assert!(circuit.is_universal());
895        assert_eq!(circuit.braiding_depth(), 1);
896    }
897}