1use super::{
7 Anyon, BraidingDirection, BraidingOperation, BraidingResult, NonAbelianAnyonType,
8 TopologicalCharge, TopologicalError, TopologicalResult,
9};
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12use std::f64::consts::PI;
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct BraidGenerator {
17 pub index: usize,
19 pub anyon_indices: (usize, usize),
21 pub direction: BraidingDirection,
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct BraidGroupElement {
28 pub generators: Vec<BraidGenerator>,
30 pub anyon_count: usize,
32}
33
34impl BraidGroupElement {
35 pub const fn new(anyon_count: usize) -> Self {
37 Self {
38 generators: Vec::new(),
39 anyon_count,
40 }
41 }
42
43 pub fn add_generator(&mut self, generator: BraidGenerator) -> TopologicalResult<()> {
45 if generator.anyon_indices.0 >= self.anyon_count
46 || generator.anyon_indices.1 >= self.anyon_count
47 {
48 return Err(TopologicalError::InvalidBraiding(
49 "Anyon indices out of bounds for braid".to_string(),
50 ));
51 }
52 self.generators.push(generator);
53 Ok(())
54 }
55
56 pub fn compose(&self, other: &Self) -> TopologicalResult<Self> {
58 if self.anyon_count != other.anyon_count {
59 return Err(TopologicalError::InvalidBraiding(
60 "Cannot compose braids with different anyon counts".to_string(),
61 ));
62 }
63
64 let mut result = self.clone();
65 result.generators.extend(other.generators.clone());
66 Ok(result)
67 }
68
69 #[must_use]
71 pub fn inverse(&self) -> Self {
72 let mut inverse_generators = Vec::new();
73
74 for generator in self.generators.iter().rev() {
75 let inverse_direction = match generator.direction {
76 BraidingDirection::Clockwise => BraidingDirection::Counterclockwise,
77 BraidingDirection::Counterclockwise => BraidingDirection::Clockwise,
78 };
79
80 inverse_generators.push(BraidGenerator {
81 index: generator.index,
82 anyon_indices: generator.anyon_indices,
83 direction: inverse_direction,
84 });
85 }
86
87 Self {
88 generators: inverse_generators,
89 anyon_count: self.anyon_count,
90 }
91 }
92}
93
94pub struct BraidingMatrixCalculator {
96 anyon_type: NonAbelianAnyonType,
97}
98
99impl BraidingMatrixCalculator {
100 pub const fn new(anyon_type: NonAbelianAnyonType) -> Self {
102 Self { anyon_type }
103 }
104
105 pub fn calculate_r_matrix(
107 &self,
108 charge1: &TopologicalCharge,
109 charge2: &TopologicalCharge,
110 fusion_channel: &str,
111 ) -> TopologicalResult<Vec<Vec<f64>>> {
112 match self.anyon_type {
113 NonAbelianAnyonType::Fibonacci => {
114 self.fibonacci_r_matrix(charge1, charge2, fusion_channel)
115 }
116 NonAbelianAnyonType::Ising => self.ising_r_matrix(charge1, charge2, fusion_channel),
117 _ => {
118 Ok(vec![vec![1.0, 0.0], vec![0.0, 1.0]])
120 }
121 }
122 }
123
124 fn fibonacci_r_matrix(
126 &self,
127 charge1: &TopologicalCharge,
128 charge2: &TopologicalCharge,
129 fusion_channel: &str,
130 ) -> TopologicalResult<Vec<Vec<f64>>> {
131 let phi = f64::midpoint(1.0, 5.0_f64.sqrt()); match (
134 charge1.label.as_str(),
135 charge2.label.as_str(),
136 fusion_channel,
137 ) {
138 ("τ", "τ", "I") => {
139 let phase = (-4.0 * PI / 5.0).exp();
141 Ok(vec![vec![phase, 0.0], vec![0.0, phase]])
142 }
143 ("τ", "τ", "τ") => {
144 let r11 = (-4.0 * PI / 5.0).exp();
146 let r22 = (3.0 * PI / 5.0).exp();
147 let off_diagonal = (1.0 / phi).sqrt();
148
149 Ok(vec![vec![r11, off_diagonal], vec![off_diagonal, r22]])
150 }
151 ("I", _, _) | (_, "I", _) => {
152 Ok(vec![vec![1.0, 0.0], vec![0.0, 1.0]])
154 }
155 _ => Err(TopologicalError::InvalidBraiding(format!(
156 "Unknown Fibonacci braiding: {} × {} → {}",
157 charge1.label, charge2.label, fusion_channel
158 ))),
159 }
160 }
161
162 fn ising_r_matrix(
164 &self,
165 charge1: &TopologicalCharge,
166 charge2: &TopologicalCharge,
167 fusion_channel: &str,
168 ) -> TopologicalResult<Vec<Vec<f64>>> {
169 match (
170 charge1.label.as_str(),
171 charge2.label.as_str(),
172 fusion_channel,
173 ) {
174 ("σ", "σ", "I") => {
175 let phase = (PI / 8.0).exp();
177 Ok(vec![vec![phase, 0.0], vec![0.0, phase]])
178 }
179 ("σ", "σ", "ψ") => {
180 let phase = (PI / 8.0).exp();
182 Ok(vec![vec![phase, 0.0], vec![0.0, -phase]])
183 }
184 ("σ", "ψ", "σ") | ("ψ", "σ", "σ") => {
185 let phase = (-PI / 2.0).exp();
187 Ok(vec![vec![phase, 0.0], vec![0.0, phase]])
188 }
189 ("I", _, _) | (_, "I", _) => {
190 Ok(vec![vec![1.0, 0.0], vec![0.0, 1.0]])
192 }
193 ("ψ", "ψ", "I") => {
194 Ok(vec![vec![-1.0, 0.0], vec![0.0, -1.0]])
196 }
197 _ => Err(TopologicalError::InvalidBraiding(format!(
198 "Unknown Ising braiding: {} × {} → {}",
199 charge1.label, charge2.label, fusion_channel
200 ))),
201 }
202 }
203}
204
205pub struct BraidingOperationManager {
207 anyon_type: NonAbelianAnyonType,
208 matrix_calculator: BraidingMatrixCalculator,
209 operation_history: Vec<BraidingOperation>,
210}
211
212impl BraidingOperationManager {
213 pub fn new(anyon_type: NonAbelianAnyonType) -> Self {
215 Self {
216 anyon_type: anyon_type.clone(),
217 matrix_calculator: BraidingMatrixCalculator::new(anyon_type),
218 operation_history: Vec::new(),
219 }
220 }
221
222 pub fn perform_braiding(
224 &mut self,
225 anyon1: &Anyon,
226 anyon2: &Anyon,
227 direction: BraidingDirection,
228 braid_count: usize,
229 fusion_channel: Option<&str>,
230 ) -> TopologicalResult<BraidingResult> {
231 let result = self.calculate_braiding_result(
233 &anyon1.charge,
234 &anyon2.charge,
235 &direction,
236 braid_count,
237 fusion_channel,
238 )?;
239
240 let operation = BraidingOperation {
242 operation_id: self.operation_history.len(),
243 anyon1: anyon1.anyon_id,
244 anyon2: anyon2.anyon_id,
245 direction,
246 braid_count,
247 result: result.clone(),
248 timestamp: 0.0, };
250
251 self.operation_history.push(operation);
252 Ok(result)
253 }
254
255 fn calculate_braiding_result(
257 &self,
258 charge1: &TopologicalCharge,
259 charge2: &TopologicalCharge,
260 direction: &BraidingDirection,
261 braid_count: usize,
262 fusion_channel: Option<&str>,
263 ) -> TopologicalResult<BraidingResult> {
264 let channel = fusion_channel.unwrap_or("I");
265
266 let r_matrix = self
268 .matrix_calculator
269 .calculate_r_matrix(charge1, charge2, channel)?;
270
271 let final_matrix = self.matrix_power(&r_matrix, braid_count)?;
273
274 let result_matrix = match direction {
276 BraidingDirection::Clockwise => final_matrix,
277 BraidingDirection::Counterclockwise => self.matrix_inverse(&final_matrix)?,
278 };
279
280 if result_matrix.len() == 2 && result_matrix[0].len() == 2 {
282 if (result_matrix[0][0] - result_matrix[1][1]).abs() < 1e-10 {
284 let phase = 0.0; Ok(BraidingResult::Phase(phase))
286 } else {
287 Ok(BraidingResult::UnitaryMatrix(result_matrix))
288 }
289 } else {
290 Ok(BraidingResult::UnitaryMatrix(result_matrix))
291 }
292 }
293
294 fn matrix_power(&self, matrix: &[Vec<f64>], power: usize) -> TopologicalResult<Vec<Vec<f64>>> {
296 if power == 0 {
297 let size = matrix.len();
299 let mut identity = vec![vec![0.0; size]; size];
300 for i in 0..size {
301 identity[i][i] = 1.0;
302 }
303 return Ok(identity);
304 }
305
306 let mut result = matrix.to_vec();
307 for _ in 1..power {
308 result = self.matrix_multiply(&result, matrix)?;
309 }
310 Ok(result)
311 }
312
313 fn matrix_multiply(&self, a: &[Vec<f64>], b: &[Vec<f64>]) -> TopologicalResult<Vec<Vec<f64>>> {
315 if a[0].len() != b.len() {
316 return Err(TopologicalError::InvalidBraiding(
317 "Matrix dimensions incompatible for multiplication".to_string(),
318 ));
319 }
320
321 let rows = a.len();
322 let cols = b[0].len();
323 let inner = a[0].len();
324
325 let mut result = vec![vec![0.0; cols]; rows];
326 for i in 0..rows {
327 for j in 0..cols {
328 for k in 0..inner {
329 result[i][j] += a[i][k] * b[k][j];
330 }
331 }
332 }
333 Ok(result)
334 }
335
336 fn matrix_inverse(&self, matrix: &[Vec<f64>]) -> TopologicalResult<Vec<Vec<f64>>> {
338 if matrix.len() != 2 || matrix[0].len() != 2 {
339 return Err(TopologicalError::InvalidBraiding(
340 "Matrix inverse only implemented for 2x2 matrices".to_string(),
341 ));
342 }
343
344 let det = matrix[0][0].mul_add(matrix[1][1], -(matrix[0][1] * matrix[1][0]));
345 if det.abs() < 1e-10 {
346 return Err(TopologicalError::InvalidBraiding(
347 "Matrix is singular and cannot be inverted".to_string(),
348 ));
349 }
350
351 let inv_det = 1.0 / det;
352 Ok(vec![
353 vec![matrix[1][1] * inv_det, -matrix[0][1] * inv_det],
354 vec![-matrix[1][0] * inv_det, matrix[0][0] * inv_det],
355 ])
356 }
357
358 pub fn get_operation_history(&self) -> &[BraidingOperation] {
360 &self.operation_history
361 }
362
363 pub fn calculate_total_phase(&self) -> f64 {
365 self.operation_history
366 .iter()
367 .map(|op| match &op.result {
368 BraidingResult::Phase(phase) => *phase,
369 _ => 0.0,
370 })
371 .sum()
372 }
373}
374
375pub struct BraidWordOptimizer {
377 anyon_count: usize,
378}
379
380impl BraidWordOptimizer {
381 pub const fn new(anyon_count: usize) -> Self {
383 Self { anyon_count }
384 }
385
386 pub fn optimize(&self, braid: &BraidGroupElement) -> BraidGroupElement {
388 let mut optimized = braid.clone();
389
390 self.remove_inverse_pairs(&mut optimized);
392
393 self.apply_braid_relations(&mut optimized);
395
396 optimized
397 }
398
399 fn remove_inverse_pairs(&self, braid: &mut BraidGroupElement) {
401 let mut i = 0;
402 while i < braid.generators.len().saturating_sub(1) {
403 let current = &braid.generators[i];
404 let next = &braid.generators[i + 1];
405
406 if current.anyon_indices == next.anyon_indices && current.direction != next.direction {
407 braid.generators.remove(i);
409 braid.generators.remove(i);
410 i = i.saturating_sub(1);
411 } else {
412 i += 1;
413 }
414 }
415 }
416
417 fn apply_braid_relations(&self, braid: &mut BraidGroupElement) {
419 let mut changed = true;
422 while changed {
423 changed = false;
424
425 for i in 0..braid.generators.len().saturating_sub(2) {
426 if self.is_yang_baxter_pattern(&braid.generators[i..i + 3]) {
427 self.apply_yang_baxter_relation(braid, i);
429 changed = true;
430 break;
431 }
432 }
433 }
434 }
435
436 fn is_yang_baxter_pattern(&self, generators: &[BraidGenerator]) -> bool {
438 if generators.len() < 3 {
439 return false;
440 }
441
442 let g1 = &generators[0];
444 let g2 = &generators[1];
445 let g3 = &generators[2];
446
447 g1.anyon_indices == g3.anyon_indices
449 && g1.direction == g3.direction
450 && ((g2.anyon_indices.0 == g1.anyon_indices.1
451 && g2.anyon_indices.1 == g1.anyon_indices.1 + 1)
452 || (g2.anyon_indices.1 == g1.anyon_indices.0
453 && g2.anyon_indices.0 == g1.anyon_indices.0 - 1))
454 }
455
456 fn apply_yang_baxter_relation(&self, braid: &mut BraidGroupElement, start_index: usize) {
458 if start_index + 2 < braid.generators.len() {
463 let g1 = braid.generators[start_index].clone();
464 let g2 = braid.generators[start_index + 1].clone();
465 let g3 = braid.generators[start_index + 2].clone();
466
467 braid.generators[start_index] = g2.clone();
469 braid.generators[start_index + 1] = g1;
470 braid.generators[start_index + 2] = g2;
471 }
472 }
473}
474
475#[cfg(test)]
476mod tests {
477 use super::*;
478
479 #[test]
480 fn test_braid_group_element() {
481 let mut braid = BraidGroupElement::new(4);
482
483 let generator = BraidGenerator {
484 index: 0,
485 anyon_indices: (0, 1),
486 direction: BraidingDirection::Clockwise,
487 };
488
489 assert!(braid.add_generator(generator).is_ok());
490 assert_eq!(braid.generators.len(), 1);
491 }
492
493 #[test]
494 fn test_braid_inverse() {
495 let mut braid = BraidGroupElement::new(3);
496
497 let generator = BraidGenerator {
498 index: 0,
499 anyon_indices: (0, 1),
500 direction: BraidingDirection::Clockwise,
501 };
502
503 braid
504 .add_generator(generator)
505 .expect("Generator should be valid for 3-anyon braid");
506 let inverse = braid.inverse();
507
508 assert_eq!(inverse.generators.len(), 1);
509 assert_eq!(
510 inverse.generators[0].direction,
511 BraidingDirection::Counterclockwise
512 );
513 }
514
515 #[test]
516 fn test_fibonacci_r_matrix() {
517 let calculator = BraidingMatrixCalculator::new(NonAbelianAnyonType::Fibonacci);
518 let tau_charge = TopologicalCharge::fibonacci_tau();
519
520 let r_matrix = calculator
521 .calculate_r_matrix(&tau_charge, &tau_charge, "I")
522 .expect("Fibonacci tau x tau -> I R-matrix should be valid");
523 assert_eq!(r_matrix.len(), 2);
524 assert_eq!(r_matrix[0].len(), 2);
525 }
526
527 #[test]
528 fn test_braiding_operation_manager() {
529 let mut manager = BraidingOperationManager::new(NonAbelianAnyonType::Fibonacci);
530
531 let anyon1 = Anyon {
532 anyon_id: 0,
533 charge: TopologicalCharge::fibonacci_tau(),
534 position: (0.0, 0.0),
535 is_qubit_part: false,
536 qubit_id: None,
537 creation_time: 0.0,
538 };
539
540 let anyon2 = Anyon {
541 anyon_id: 1,
542 charge: TopologicalCharge::fibonacci_tau(),
543 position: (1.0, 0.0),
544 is_qubit_part: false,
545 qubit_id: None,
546 creation_time: 0.0,
547 };
548
549 let result =
550 manager.perform_braiding(&anyon1, &anyon2, BraidingDirection::Clockwise, 1, Some("I"));
551
552 assert!(result.is_ok());
553 assert_eq!(manager.get_operation_history().len(), 1);
554 }
555}