1use super::{
7 Anyon, FusionRuleSet, NonAbelianAnyonType, TopologicalCharge, TopologicalError,
8 TopologicalResult,
9};
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12
13pub struct AnyonFactory {
15 anyon_type: NonAbelianAnyonType,
16 fusion_rules: FusionRuleSet,
17 next_id: usize,
18}
19
20impl AnyonFactory {
21 pub const fn new(anyon_type: NonAbelianAnyonType, fusion_rules: FusionRuleSet) -> Self {
23 Self {
24 anyon_type,
25 fusion_rules,
26 next_id: 0,
27 }
28 }
29
30 pub const fn create_anyon(
32 &mut self,
33 charge: TopologicalCharge,
34 position: (f64, f64),
35 creation_time: f64,
36 ) -> Anyon {
37 let anyon = Anyon {
38 anyon_id: self.next_id,
39 charge,
40 position,
41 is_qubit_part: false,
42 qubit_id: None,
43 creation_time,
44 };
45 self.next_id += 1;
46 anyon
47 }
48
49 pub fn create_anyon_pair(
51 &mut self,
52 charge: TopologicalCharge,
53 positions: [(f64, f64); 2],
54 creation_time: f64,
55 ) -> TopologicalResult<(Anyon, Anyon)> {
56 let anyon1 = self.create_anyon(charge.clone(), positions[0], creation_time);
57 let anyon2 = self.create_anyon(charge, positions[1], creation_time);
58 Ok((anyon1, anyon2))
59 }
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct AnyonWorldline {
65 pub anyon_id: usize,
66 pub positions: Vec<(f64, f64, f64)>, pub charge_history: Vec<TopologicalCharge>,
68 pub interaction_history: Vec<AnyonInteraction>,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct AnyonInteraction {
74 pub interaction_id: usize,
75 pub anyon1_id: usize,
76 pub anyon2_id: usize,
77 pub interaction_type: AnyonInteractionType,
78 pub timestamp: f64,
79 pub result: InteractionResult,
80}
81
82#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
84pub enum AnyonInteractionType {
85 Braiding,
87 Fusion,
89 Correlation,
91 Measurement,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub enum InteractionResult {
98 PhaseChange(f64),
100 FusionProduct(TopologicalCharge),
102 Correlation(f64),
104 MeasurementOutcome(bool),
106}
107
108pub struct AnyonTracker {
110 worldlines: HashMap<usize, AnyonWorldline>,
111 interactions: Vec<AnyonInteraction>,
112 next_interaction_id: usize,
113}
114
115impl AnyonTracker {
116 pub fn new() -> Self {
118 Self {
119 worldlines: HashMap::new(),
120 interactions: Vec::new(),
121 next_interaction_id: 0,
122 }
123 }
124
125 pub fn track_anyon(&mut self, anyon: &Anyon) {
127 let worldline = AnyonWorldline {
128 anyon_id: anyon.anyon_id,
129 positions: vec![(anyon.position.0, anyon.position.1, anyon.creation_time)],
130 charge_history: vec![anyon.charge.clone()],
131 interaction_history: Vec::new(),
132 };
133 self.worldlines.insert(anyon.anyon_id, worldline);
134 }
135
136 pub fn update_position(
138 &mut self,
139 anyon_id: usize,
140 new_position: (f64, f64),
141 timestamp: f64,
142 ) -> TopologicalResult<()> {
143 let worldline = self.worldlines.get_mut(&anyon_id).ok_or_else(|| {
144 TopologicalError::AnyonCreationFailed(format!(
145 "Anyon {anyon_id} not found for position update"
146 ))
147 })?;
148 worldline
149 .positions
150 .push((new_position.0, new_position.1, timestamp));
151 Ok(())
152 }
153
154 pub fn record_interaction(
156 &mut self,
157 anyon1_id: usize,
158 anyon2_id: usize,
159 interaction_type: AnyonInteractionType,
160 result: InteractionResult,
161 timestamp: f64,
162 ) -> TopologicalResult<()> {
163 let interaction = AnyonInteraction {
164 interaction_id: self.next_interaction_id,
165 anyon1_id,
166 anyon2_id,
167 interaction_type,
168 timestamp,
169 result,
170 };
171
172 self.interactions.push(interaction.clone());
174
175 self.worldlines
177 .entry(anyon1_id)
178 .or_insert_with(|| AnyonWorldline {
179 anyon_id: anyon1_id,
180 positions: vec![(0.0, 0.0, timestamp)],
181 charge_history: vec![TopologicalCharge {
182 label: "I".to_string(),
183 quantum_dimension: "1".to_string(),
184 scaling_dimension: 0.0,
185 }],
186 interaction_history: vec![],
187 });
188 self.worldlines
189 .entry(anyon2_id)
190 .or_insert_with(|| AnyonWorldline {
191 anyon_id: anyon2_id,
192 positions: vec![(0.0, 0.0, timestamp)],
193 charge_history: vec![TopologicalCharge {
194 label: "I".to_string(),
195 quantum_dimension: "1".to_string(),
196 scaling_dimension: 0.0,
197 }],
198 interaction_history: vec![],
199 });
200
201 if let Some(worldline1) = self.worldlines.get_mut(&anyon1_id) {
202 worldline1.interaction_history.push(interaction.clone());
203 }
204 if let Some(worldline2) = self.worldlines.get_mut(&anyon2_id) {
205 worldline2.interaction_history.push(interaction);
206 }
207
208 self.next_interaction_id += 1;
209 Ok(())
210 }
211
212 pub fn get_worldline(&self, anyon_id: usize) -> Option<&AnyonWorldline> {
214 self.worldlines.get(&anyon_id)
215 }
216
217 pub fn calculate_total_phase(&self, anyon_id: usize) -> f64 {
219 self.worldlines.get(&anyon_id).map_or(0.0, |worldline| {
220 worldline
221 .interaction_history
222 .iter()
223 .filter(|i| i.interaction_type == AnyonInteractionType::Braiding)
224 .map(|i| match &i.result {
225 InteractionResult::PhaseChange(phase) => *phase,
226 _ => 0.0,
227 })
228 .sum()
229 })
230 }
231}
232
233pub struct ChargeAlgebra {
235 anyon_type: NonAbelianAnyonType,
236 fusion_rules: FusionRuleSet,
237}
238
239impl ChargeAlgebra {
240 pub const fn new(anyon_type: NonAbelianAnyonType, fusion_rules: FusionRuleSet) -> Self {
242 Self {
243 anyon_type,
244 fusion_rules,
245 }
246 }
247
248 pub fn is_valid_charge(&self, charge: &TopologicalCharge) -> bool {
250 match self.anyon_type {
251 NonAbelianAnyonType::Fibonacci => {
252 matches!(charge.label.as_str(), "I" | "τ")
253 }
254 NonAbelianAnyonType::Ising => {
255 matches!(charge.label.as_str(), "I" | "σ" | "ψ")
256 }
257 _ => true, }
259 }
260
261 pub fn fusion_products(
263 &self,
264 charge1: &TopologicalCharge,
265 charge2: &TopologicalCharge,
266 ) -> TopologicalResult<Vec<String>> {
267 let fusion_key = (charge1.label.clone(), charge2.label.clone());
268 self.fusion_rules
269 .rules
270 .get(&fusion_key)
271 .cloned()
272 .ok_or_else(|| {
273 TopologicalError::FusionFailed(format!("No fusion rule found for {fusion_key:?}"))
274 })
275 }
276
277 pub fn quantum_dimension(&self, charge: &TopologicalCharge) -> f64 {
279 match (&self.anyon_type, charge.label.as_str()) {
280 (&NonAbelianAnyonType::Fibonacci, "τ") => f64::midpoint(1.0, 5.0_f64.sqrt()), (&NonAbelianAnyonType::Ising, "σ") => 2.0_f64.sqrt(),
282 (&NonAbelianAnyonType::Fibonacci, "I")
283 | (&NonAbelianAnyonType::Ising, "I")
284 | (&NonAbelianAnyonType::Ising, "ψ")
285 | _ => 1.0, }
287 }
288
289 pub fn total_quantum_dimension(&self, charges: &[TopologicalCharge]) -> f64 {
291 charges
292 .iter()
293 .map(|charge| self.quantum_dimension(charge))
294 .product()
295 }
296}
297
298#[cfg(test)]
299mod tests {
300 use super::*;
301
302 #[test]
303 fn test_anyon_factory() {
304 let fusion_rules = FusionRuleSet::fibonacci();
305 let mut factory = AnyonFactory::new(NonAbelianAnyonType::Fibonacci, fusion_rules);
306
307 let charge = TopologicalCharge::fibonacci_tau();
308 let anyon = factory.create_anyon(charge, (0.0, 0.0), 0.0);
309
310 assert_eq!(anyon.anyon_id, 0);
311 assert_eq!(anyon.charge.label, "τ");
312 assert_eq!(anyon.position, (0.0, 0.0));
313 }
314
315 #[test]
316 fn test_anyon_tracker() {
317 let mut tracker = AnyonTracker::new();
318 let charge = TopologicalCharge::fibonacci_tau();
319 let anyon = Anyon {
320 anyon_id: 0,
321 charge,
322 position: (0.0, 0.0),
323 is_qubit_part: false,
324 qubit_id: None,
325 creation_time: 0.0,
326 };
327
328 tracker.track_anyon(&anyon);
329 assert!(tracker.get_worldline(0).is_some());
330
331 tracker
332 .update_position(0, (1.0, 1.0), 1.0)
333 .expect("Position update should succeed for tracked anyon");
334 let worldline = tracker
335 .get_worldline(0)
336 .expect("Worldline should exist for tracked anyon");
337 assert_eq!(worldline.positions.len(), 2);
338 }
339
340 #[test]
341 fn test_charge_algebra() {
342 let fusion_rules = FusionRuleSet::fibonacci();
343 let algebra = ChargeAlgebra::new(NonAbelianAnyonType::Fibonacci, fusion_rules);
344
345 let tau_charge = TopologicalCharge::fibonacci_tau();
346 assert!(algebra.is_valid_charge(&tau_charge));
347
348 let quantum_dim = algebra.quantum_dimension(&tau_charge);
349 assert!((quantum_dim - (1.0 + 5.0_f64.sqrt()) / 2.0).abs() < 1e-10);
350 }
351
352 #[test]
353 fn test_interaction_recording() {
354 let mut tracker = AnyonTracker::new();
355
356 tracker
357 .record_interaction(
358 0,
359 1,
360 AnyonInteractionType::Braiding,
361 InteractionResult::PhaseChange(std::f64::consts::PI / 4.0),
362 1.0,
363 )
364 .expect("Recording braiding interaction should succeed");
365
366 assert_eq!(tracker.interactions.len(), 1);
367 assert_eq!(tracker.calculate_total_phase(0), std::f64::consts::PI / 4.0);
368 }
369}