1use 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#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
19pub enum AnyonType {
20 Vacuum,
22 Ising,
24 Fibonacci,
26 Majorana,
28 SU2 { level: usize },
30 Parafermion { n: usize },
32 Custom {
34 name: String,
35 quantum_dimension: f64,
36 fusion_rules: Vec<FusionRule>,
37 },
38}
39
40impl AnyonType {
41 #[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()), 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 #[must_use]
59 pub const fn is_abelian(&self) -> bool {
60 matches!(self, Self::Vacuum)
61 }
62
63 #[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#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
77pub struct FusionRule {
78 pub inputs: Vec<AnyonType>,
80 pub outputs: Vec<(AnyonType, usize)>,
82}
83
84#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
86pub struct Anyon {
87 pub id: usize,
89 pub anyon_type: AnyonType,
91 pub position: (f64, f64),
93 pub charge: Option<usize>,
95}
96
97impl Anyon {
98 #[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 #[must_use]
111 pub fn can_fuse_with(&self, other: &Self) -> bool {
112 self.anyon_type == other.anyon_type
114 || self.anyon_type == AnyonType::Vacuum
115 || other.anyon_type == AnyonType::Vacuum
116 }
117}
118
119#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
121pub struct BraidingOperation {
122 pub anyons: Vec<usize>,
124 pub braiding_type: BraidingType,
126 pub braiding_count: usize,
128 pub phase: Option<f64>,
130}
131
132#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
134pub enum BraidingType {
135 Clockwise,
137 Counterclockwise,
139 Exchange,
141 YangBaxter,
143}
144
145#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
147pub enum TopologicalGate {
148 Braiding {
150 anyon1: usize,
151 anyon2: usize,
152 braiding_type: BraidingType,
153 },
154 Fusion {
156 input_anyons: Vec<usize>,
157 output_anyon: usize,
158 fusion_channel: usize,
159 },
160 Splitting {
162 input_anyon: usize,
163 output_anyons: Vec<usize>,
164 splitting_channel: usize,
165 },
166 FusionMeasurement {
168 anyons: Vec<usize>,
169 measurement_basis: FusionBasis,
170 },
171 Creation {
173 anyon_type: AnyonType,
174 position: (f64, f64),
175 },
176 Annihilation { anyon: usize },
178}
179
180#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
182pub enum FusionBasis {
183 Vacuum,
185 NonTrivial { channel: usize },
187}
188
189#[derive(Debug, Clone)]
191pub struct TopologicalCircuit {
192 pub anyons: HashMap<usize, Anyon>,
194 pub gates: Vec<TopologicalGate>,
196 pub braiding_sequence: Vec<BraidingOperation>,
198 pub fusion_rules: Vec<(AnyonType, Vec<FusionRule>)>,
200 pub layout: TopologicalLayout,
202}
203
204#[derive(Debug, Clone)]
206pub struct TopologicalLayout {
207 pub width: f64,
209 pub height: f64,
211 pub forbidden_regions: Vec<Region>,
213 pub braiding_paths: Vec<Path>,
215}
216
217#[derive(Debug, Clone)]
219pub struct Region {
220 pub center: (f64, f64),
222 pub radius: f64,
224 pub shape: RegionShape,
226}
227
228#[derive(Debug, Clone, PartialEq)]
230pub enum RegionShape {
231 Circle,
232 Rectangle { width: f64, height: f64 },
233 Polygon { vertices: Vec<(f64, f64)> },
234}
235
236#[derive(Debug, Clone)]
238pub struct Path {
239 pub waypoints: Vec<(f64, f64)>,
241 pub path_type: PathType,
243}
244
245#[derive(Debug, Clone, PartialEq, Eq)]
247pub enum PathType {
248 Straight,
250 Curved,
252 Optimized,
254}
255
256pub struct TopologicalCompiler {
258 default_anyon_model: AnyonModel,
260 braiding_optimizer: BraidingOptimizer,
262 layout_optimizer: LayoutOptimizer,
264}
265
266#[derive(Debug, Clone)]
268pub struct AnyonModel {
269 pub primary_anyon: AnyonType,
271 pub supported_anyons: Vec<AnyonType>,
273 pub fusion_rules: Vec<(AnyonType, Vec<FusionRule>)>,
275 pub braiding_phases: Vec<((AnyonType, AnyonType), f64)>,
277}
278
279impl AnyonModel {
280 #[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, )];
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 #[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), ],
315 }],
316 )];
317
318 let braiding_phases = vec![(
319 (AnyonType::Ising, AnyonType::Ising),
320 PI / 4.0, )];
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#[derive(Debug, Clone)]
334pub struct BraidingOptimizer {
335 pub strategy: OptimizationStrategy,
337 pub max_braiding_distance: f64,
339 pub optimize_paths: bool,
341}
342
343#[derive(Debug, Clone, PartialEq, Eq)]
345pub enum OptimizationStrategy {
346 MinimizeLength,
348 MinimizeCrossings,
350 MinimizeTime,
352 Balanced,
354}
355
356#[derive(Debug, Clone)]
358pub struct LayoutOptimizer {
359 pub target_density: f64,
361 pub auto_spacing: bool,
363 pub min_distance: f64,
365}
366
367impl TopologicalCompiler {
368 #[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 pub fn compile_quantum_circuit<const N: usize>(
388 &self,
389 circuit: &Circuit<N>,
390 ) -> QuantRS2Result<TopologicalCircuit> {
391 let mut anyons = HashMap::new();
393 let mut next_anyon_id = 0;
394
395 for qubit_id in 0..N {
397 let pos_x = qubit_id as f64 * 2.0;
398
399 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 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 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 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 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 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 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 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 fn compile_pauli_z_gate(
527 &self,
528 qubits: &[QubitId],
529 anyons: &HashMap<usize, Anyon>,
530 ) -> QuantRS2Result<(Vec<TopologicalGate>, Vec<BraidingOperation>)> {
531 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 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 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 let mut braidings = Vec::new();
567 let mut topo_gates = Vec::new();
568
569 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 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 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 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 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 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 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 fn calculate_total_braiding_length(&self, braidings: &[BraidingOperation]) -> f64 {
686 braidings.iter().map(|b| b.braiding_count as f64).sum()
687 }
688
689 const fn count_braiding_crossings(&self, braidings: &[BraidingOperation]) -> usize {
691 braidings.len()
693 }
694
695 const fn optimize_for_length(&self, braidings: &[BraidingOperation]) -> QuantRS2Result<()> {
697 Ok(())
699 }
700
701 const fn optimize_for_crossings(&self, braidings: &[BraidingOperation]) -> QuantRS2Result<()> {
703 Ok(())
705 }
706
707 const fn optimize_for_time(&self, braidings: &[BraidingOperation]) -> QuantRS2Result<()> {
709 Ok(())
711 }
712
713 const fn optimize_balanced(&self, braidings: &[BraidingOperation]) -> QuantRS2Result<()> {
715 Ok(())
717 }
718}
719
720#[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 #[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 #[must_use]
743 pub fn anyon_count(&self) -> usize {
744 self.anyons.len()
745 }
746
747 #[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 #[must_use]
757 pub fn braiding_depth(&self) -> usize {
758 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}