quantrs2_device/topological/
device.rs

1//! Device implementation for topological quantum computers
2//!
3//! This module provides the device interface for topological quantum computers,
4//! integrating anyon manipulation, braiding, and fusion operations.
5
6use super::{
7    anyons::AnyonFactory, braiding::BraidingOperationManager, fusion::FusionOperationExecutor,
8    Anyon, BraidingDirection, FusionRuleSet, NonAbelianAnyonType, TopologicalCapabilities,
9    TopologicalCharge, TopologicalDevice, TopologicalError, TopologicalQubit, TopologicalResult,
10    TopologicalSystemType,
11};
12use crate::{Circuit, CircuitExecutor, CircuitResult, DeviceError, DeviceResult, QuantumDevice};
13use scirs2_core::random::prelude::*;
14use serde::{Deserialize, Serialize};
15use std::collections::HashMap;
16use std::time::Duration;
17
18/// Enhanced topological quantum device with full anyon manipulation
19pub struct EnhancedTopologicalDevice {
20    /// Core topological device
21    pub core_device: TopologicalDevice,
22    /// Anyon factory for creating anyons
23    pub anyon_factory: AnyonFactory,
24    /// Braiding operation manager
25    pub braiding_manager: BraidingOperationManager,
26    /// Fusion operation executor
27    pub fusion_executor: FusionOperationExecutor,
28    /// Device configuration
29    pub config: TopologicalDeviceConfig,
30    /// Connection status
31    pub is_connected: bool,
32}
33
34/// Configuration for topological quantum devices
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct TopologicalDeviceConfig {
37    /// Maximum execution time for operations
38    pub max_execution_time: Duration,
39    /// Temperature of the system (mK)
40    pub operating_temperature: f64,
41    /// Topological gap energy scale (K)
42    pub topological_gap: f64,
43    /// Coherence length (μm)
44    pub coherence_length: f64,
45    /// Anyon manipulation precision
46    pub manipulation_precision: f64,
47    /// Braiding fidelity
48    pub braiding_fidelity: f64,
49    /// Fusion fidelity
50    pub fusion_fidelity: f64,
51    /// Measurement fidelity
52    pub measurement_fidelity: f64,
53    /// Enable advanced error correction
54    pub enable_error_correction: bool,
55    /// Hardware-specific parameters
56    pub hardware_params: HashMap<String, String>,
57}
58
59impl Default for TopologicalDeviceConfig {
60    fn default() -> Self {
61        Self {
62            max_execution_time: Duration::from_secs(300),
63            operating_temperature: 0.01, // 10 mK
64            topological_gap: 1.0,        // 1 K
65            coherence_length: 100.0,     // 100 μm
66            manipulation_precision: 0.99,
67            braiding_fidelity: 0.9999,
68            fusion_fidelity: 0.999,
69            measurement_fidelity: 0.999,
70            enable_error_correction: true,
71            hardware_params: HashMap::new(),
72        }
73    }
74}
75
76impl EnhancedTopologicalDevice {
77    /// Create a new enhanced topological device
78    pub fn new(
79        system_type: TopologicalSystemType,
80        fusion_rules: FusionRuleSet,
81        capabilities: TopologicalCapabilities,
82        config: TopologicalDeviceConfig,
83    ) -> TopologicalResult<Self> {
84        let core_device =
85            TopologicalDevice::new(system_type.clone(), fusion_rules.clone(), capabilities);
86
87        let anyon_type = match system_type {
88            TopologicalSystemType::NonAbelian { anyon_type, .. } => anyon_type,
89            _ => NonAbelianAnyonType::Fibonacci, // Default
90        };
91
92        let anyon_factory = AnyonFactory::new(anyon_type.clone(), fusion_rules.clone());
93        let braiding_manager = BraidingOperationManager::new(anyon_type.clone());
94        let fusion_executor = FusionOperationExecutor::new(anyon_type, fusion_rules);
95
96        Ok(Self {
97            core_device,
98            anyon_factory,
99            braiding_manager,
100            fusion_executor,
101            config,
102            is_connected: false,
103        })
104    }
105
106    /// Connect to the topological quantum hardware
107    pub async fn connect(&mut self) -> TopologicalResult<()> {
108        // Simulate hardware connection
109        tokio::time::sleep(Duration::from_millis(100)).await;
110
111        // Verify system integrity
112        self.verify_system_integrity().await?;
113
114        self.is_connected = true;
115        Ok(())
116    }
117
118    /// Disconnect from the hardware
119    pub async fn disconnect(&mut self) -> TopologicalResult<()> {
120        self.is_connected = false;
121        Ok(())
122    }
123
124    /// Verify system integrity
125    async fn verify_system_integrity(&self) -> TopologicalResult<()> {
126        // Check topological gap
127        if self.config.topological_gap < 0.1 {
128            return Err(TopologicalError::InvalidWorldline(
129                "Topological gap too small for reliable operation".to_string(),
130            ));
131        }
132
133        // Check coherence length
134        if self.config.coherence_length < 10.0 {
135            return Err(TopologicalError::InvalidWorldline(
136                "Coherence length too small".to_string(),
137            ));
138        }
139
140        Ok(())
141    }
142
143    /// Initialize topological qubits
144    pub async fn initialize_topological_qubits(
145        &mut self,
146        num_qubits: usize,
147    ) -> TopologicalResult<Vec<usize>> {
148        let mut qubit_ids = Vec::new();
149
150        for _ in 0..num_qubits {
151            // Create anyon pairs for each qubit
152            let charge = match self.core_device.system_type {
153                TopologicalSystemType::NonAbelian {
154                    anyon_type: NonAbelianAnyonType::Fibonacci,
155                    ..
156                } => TopologicalCharge::fibonacci_tau(),
157                TopologicalSystemType::NonAbelian {
158                    anyon_type: NonAbelianAnyonType::Ising,
159                    ..
160                } => TopologicalCharge::ising_sigma(),
161                _ => TopologicalCharge::identity(),
162            };
163
164            // Create anyon pairs at different positions
165            let positions = [
166                (qubit_ids.len() as f64 * 10.0, 0.0),
167                ((qubit_ids.len() as f64).mul_add(10.0, 5.0), 0.0),
168                (qubit_ids.len() as f64 * 10.0, 5.0),
169                ((qubit_ids.len() as f64).mul_add(10.0, 5.0), 5.0),
170            ];
171
172            let (anyon1_id, anyon2_id) = self
173                .core_device
174                .create_anyon_pair(charge.clone(), [positions[0], positions[1]])?;
175
176            let (anyon3_id, anyon4_id) = self
177                .core_device
178                .create_anyon_pair(charge, [positions[2], positions[3]])?;
179
180            // Create topological qubit from four anyons
181            let qubit_id = self
182                .core_device
183                .create_topological_qubit(vec![anyon1_id, anyon2_id, anyon3_id, anyon4_id])?;
184
185            qubit_ids.push(qubit_id);
186        }
187
188        Ok(qubit_ids)
189    }
190
191    /// Perform a topological X gate via braiding
192    pub async fn topological_x_gate(&mut self, qubit_id: usize) -> TopologicalResult<()> {
193        let qubit = self.core_device.qubits.get(&qubit_id).ok_or_else(|| {
194            TopologicalError::InvalidBraiding(format!("Qubit {qubit_id} not found"))
195        })?;
196
197        if qubit.anyons.len() < 4 {
198            return Err(TopologicalError::InsufficientAnyons {
199                needed: 4,
200                available: qubit.anyons.len(),
201            });
202        }
203
204        // Perform braiding sequence for X gate
205        let anyon1_id = qubit.anyons[0];
206        let anyon2_id = qubit.anyons[1];
207
208        // Single braid for X rotation
209        self.core_device
210            .braid_anyons(anyon1_id, anyon2_id, BraidingDirection::Clockwise, 1)?;
211
212        Ok(())
213    }
214
215    /// Perform a topological Z gate via braiding
216    pub async fn topological_z_gate(&mut self, qubit_id: usize) -> TopologicalResult<()> {
217        let qubit = self.core_device.qubits.get(&qubit_id).ok_or_else(|| {
218            TopologicalError::InvalidBraiding(format!("Qubit {qubit_id} not found"))
219        })?;
220
221        if qubit.anyons.len() < 4 {
222            return Err(TopologicalError::InsufficientAnyons {
223                needed: 4,
224                available: qubit.anyons.len(),
225            });
226        }
227
228        // Perform braiding sequence for Z gate
229        let anyon1_id = qubit.anyons[0];
230        let anyon3_id = qubit.anyons[2];
231
232        // Different braiding pattern for Z rotation
233        self.core_device.braid_anyons(
234            anyon1_id,
235            anyon3_id,
236            BraidingDirection::Counterclockwise,
237            1,
238        )?;
239
240        Ok(())
241    }
242
243    /// Perform a topological CNOT gate
244    pub async fn topological_cnot_gate(
245        &mut self,
246        control_qubit: usize,
247        target_qubit: usize,
248    ) -> TopologicalResult<()> {
249        // Get anyons from both qubits
250        let control_anyons = {
251            let qubit = self.core_device.qubits.get(&control_qubit).ok_or_else(|| {
252                TopologicalError::InvalidBraiding(format!(
253                    "Control qubit {control_qubit} not found"
254                ))
255            })?;
256            qubit.anyons.clone()
257        };
258
259        let target_anyons = {
260            let qubit = self.core_device.qubits.get(&target_qubit).ok_or_else(|| {
261                TopologicalError::InvalidBraiding(format!("Target qubit {target_qubit} not found"))
262            })?;
263            qubit.anyons.clone()
264        };
265
266        // Perform complex braiding sequence for CNOT
267        // This is simplified - actual implementation would be more complex
268        if !control_anyons.is_empty() && !target_anyons.is_empty() {
269            self.core_device.braid_anyons(
270                control_anyons[0],
271                target_anyons[0],
272                BraidingDirection::Clockwise,
273                2,
274            )?;
275        }
276
277        Ok(())
278    }
279
280    /// Measure a topological qubit
281    pub async fn measure_topological_qubit(&mut self, qubit_id: usize) -> TopologicalResult<bool> {
282        let result = self.core_device.measure_qubit(qubit_id)?;
283
284        // Apply measurement fidelity
285        let actual_fidelity = thread_rng().gen::<f64>();
286        if actual_fidelity < self.config.measurement_fidelity {
287            Ok(result)
288        } else {
289            Ok(!result) // Measurement error
290        }
291    }
292
293    /// Reset a topological qubit to |0⟩ state
294    pub async fn reset_topological_qubit(&mut self, qubit_id: usize) -> TopologicalResult<()> {
295        if let Some(qubit) = self.core_device.qubits.get_mut(&qubit_id) {
296            qubit.state = super::TopologicalQubitState::zero();
297            qubit.braiding_history.clear();
298            Ok(())
299        } else {
300            Err(TopologicalError::InvalidBraiding(format!(
301                "Qubit {qubit_id} not found for reset"
302            )))
303        }
304    }
305
306    /// Get device status and diagnostics
307    pub async fn get_diagnostics(&self) -> TopologicalDeviceDiagnostics {
308        let system_status = self.core_device.get_system_status();
309
310        TopologicalDeviceDiagnostics {
311            is_connected: self.is_connected,
312            system_status,
313            operating_temperature: self.config.operating_temperature,
314            topological_gap: self.config.topological_gap,
315            average_braiding_fidelity: self.config.braiding_fidelity,
316            total_operations: self.braiding_manager.get_operation_history().len(),
317            error_rate: 1.0 - self.config.braiding_fidelity,
318        }
319    }
320}
321
322/// Diagnostics information for topological devices
323#[derive(Debug, Clone, Serialize, Deserialize)]
324pub struct TopologicalDeviceDiagnostics {
325    pub is_connected: bool,
326    pub system_status: super::TopologicalSystemStatus,
327    pub operating_temperature: f64,
328    pub topological_gap: f64,
329    pub average_braiding_fidelity: f64,
330    pub total_operations: usize,
331    pub error_rate: f64,
332}
333
334#[cfg(feature = "ibm")]
335#[async_trait::async_trait]
336impl QuantumDevice for EnhancedTopologicalDevice {
337    async fn is_available(&self) -> DeviceResult<bool> {
338        Ok(self.is_connected && self.config.topological_gap > 0.1)
339    }
340
341    async fn qubit_count(&self) -> DeviceResult<usize> {
342        Ok(self.core_device.capabilities.max_qubits)
343    }
344
345    async fn properties(&self) -> DeviceResult<HashMap<String, String>> {
346        let mut props = HashMap::new();
347        props.insert("device_type".to_string(), "topological".to_string());
348        props.insert(
349            "anyon_type".to_string(),
350            format!("{:?}", self.core_device.system_type),
351        );
352        props.insert(
353            "max_anyons".to_string(),
354            self.core_device.capabilities.max_anyons.to_string(),
355        );
356        props.insert(
357            "max_qubits".to_string(),
358            self.core_device.capabilities.max_qubits.to_string(),
359        );
360        props.insert(
361            "braiding_fidelity".to_string(),
362            self.config.braiding_fidelity.to_string(),
363        );
364        props.insert(
365            "topological_gap".to_string(),
366            self.config.topological_gap.to_string(),
367        );
368        props.insert(
369            "coherence_length".to_string(),
370            self.config.coherence_length.to_string(),
371        );
372        Ok(props)
373    }
374
375    async fn is_simulator(&self) -> DeviceResult<bool> {
376        Ok(true) // This implementation is a simulator
377    }
378}
379
380#[cfg(not(feature = "ibm"))]
381impl QuantumDevice for EnhancedTopologicalDevice {
382    fn is_available(&self) -> DeviceResult<bool> {
383        Ok(self.is_connected && self.config.topological_gap > 0.1)
384    }
385
386    fn qubit_count(&self) -> DeviceResult<usize> {
387        Ok(self.core_device.capabilities.max_qubits)
388    }
389
390    fn properties(&self) -> DeviceResult<HashMap<String, String>> {
391        let mut props = HashMap::new();
392        props.insert("device_type".to_string(), "topological".to_string());
393        props.insert(
394            "anyon_type".to_string(),
395            format!("{:?}", self.core_device.system_type),
396        );
397        props.insert(
398            "max_anyons".to_string(),
399            self.core_device.capabilities.max_anyons.to_string(),
400        );
401        props.insert(
402            "max_qubits".to_string(),
403            self.core_device.capabilities.max_qubits.to_string(),
404        );
405        props.insert(
406            "braiding_fidelity".to_string(),
407            self.config.braiding_fidelity.to_string(),
408        );
409        props.insert(
410            "topological_gap".to_string(),
411            self.config.topological_gap.to_string(),
412        );
413        props.insert(
414            "coherence_length".to_string(),
415            self.config.coherence_length.to_string(),
416        );
417        Ok(props)
418    }
419
420    fn is_simulator(&self) -> DeviceResult<bool> {
421        Ok(true) // This implementation is a simulator
422    }
423}
424
425#[cfg(feature = "ibm")]
426#[async_trait::async_trait]
427impl CircuitExecutor for EnhancedTopologicalDevice {
428    async fn execute_circuit<const N: usize>(
429        &self,
430        circuit: &Circuit<N>,
431        shots: usize,
432    ) -> DeviceResult<CircuitResult> {
433        if !self.is_connected {
434            return Err(DeviceError::DeviceNotInitialized(
435                "Topological device not connected".to_string(),
436            ));
437        }
438
439        // Simplified circuit execution
440        // In practice, this would translate circuit gates to braiding operations
441        let mut counts = HashMap::new();
442
443        // Simulate perfect braiding for now
444        let all_zeros = "0".repeat(N);
445        counts.insert(all_zeros, shots);
446
447        let mut metadata = HashMap::new();
448        metadata.insert("device_type".to_string(), "topological".to_string());
449        metadata.insert(
450            "braiding_fidelity".to_string(),
451            self.config.braiding_fidelity.to_string(),
452        );
453        metadata.insert("execution_time_ms".to_string(), "100".to_string());
454
455        Ok(CircuitResult {
456            counts,
457            shots,
458            metadata,
459        })
460    }
461
462    async fn execute_circuits<const N: usize>(
463        &self,
464        circuits: Vec<&Circuit<N>>,
465        shots: usize,
466    ) -> DeviceResult<Vec<CircuitResult>> {
467        let mut results = Vec::new();
468
469        for circuit in circuits {
470            let result = self.execute_circuit(circuit, shots).await?;
471            results.push(result);
472        }
473
474        Ok(results)
475    }
476
477    async fn can_execute_circuit<const N: usize>(
478        &self,
479        _circuit: &Circuit<N>,
480    ) -> DeviceResult<bool> {
481        Ok(N <= self.core_device.capabilities.max_qubits)
482    }
483
484    async fn estimated_queue_time<const N: usize>(
485        &self,
486        _circuit: &Circuit<N>,
487    ) -> DeviceResult<Duration> {
488        // Topological quantum computers have very long coherence times
489        Ok(Duration::from_secs(10))
490    }
491}
492
493#[cfg(not(feature = "ibm"))]
494impl CircuitExecutor for EnhancedTopologicalDevice {
495    fn execute_circuit<const N: usize>(
496        &self,
497        _circuit: &Circuit<N>,
498        shots: usize,
499    ) -> DeviceResult<CircuitResult> {
500        if !self.is_connected {
501            return Err(DeviceError::DeviceNotInitialized(
502                "Topological device not connected".to_string(),
503            ));
504        }
505
506        // Simplified circuit execution
507        // In practice, this would translate circuit gates to braiding operations
508        let mut counts = HashMap::new();
509
510        // Simulate perfect braiding for now
511        let all_zeros = "0".repeat(N);
512        counts.insert(all_zeros, shots);
513
514        let mut metadata = HashMap::new();
515        metadata.insert("device_type".to_string(), "topological".to_string());
516        metadata.insert(
517            "braiding_fidelity".to_string(),
518            self.config.braiding_fidelity.to_string(),
519        );
520        metadata.insert("execution_time_ms".to_string(), "100".to_string());
521
522        Ok(CircuitResult {
523            counts,
524            shots,
525            metadata,
526        })
527    }
528
529    fn execute_circuits<const N: usize>(
530        &self,
531        circuits: Vec<&Circuit<N>>,
532        shots: usize,
533    ) -> DeviceResult<Vec<CircuitResult>> {
534        let mut results = Vec::new();
535
536        for circuit in circuits {
537            let result = self.execute_circuit(circuit, shots)?;
538            results.push(result);
539        }
540
541        Ok(results)
542    }
543
544    fn can_execute_circuit<const N: usize>(&self, _circuit: &Circuit<N>) -> DeviceResult<bool> {
545        Ok(N <= self.core_device.capabilities.max_qubits)
546    }
547
548    fn estimated_queue_time<const N: usize>(
549        &self,
550        _circuit: &Circuit<N>,
551    ) -> DeviceResult<Duration> {
552        // Topological quantum computers have very long coherence times
553        Ok(Duration::from_secs(10))
554    }
555}
556
557/// Create a Fibonacci anyon topological device
558pub fn create_fibonacci_device(
559    max_anyons: usize,
560    max_qubits: usize,
561) -> TopologicalResult<EnhancedTopologicalDevice> {
562    let system_type = TopologicalSystemType::NonAbelian {
563        anyon_type: NonAbelianAnyonType::Fibonacci,
564        fusion_rules: FusionRuleSet::fibonacci(),
565    };
566
567    let capabilities = TopologicalCapabilities {
568        max_anyons,
569        max_qubits,
570        supported_anyons: vec![
571            TopologicalCharge::identity(),
572            TopologicalCharge::fibonacci_tau(),
573        ],
574        available_operations: vec![
575            super::TopologicalOperation::AnyonCreation {
576                charge_type: "τ".to_string(),
577            },
578            super::TopologicalOperation::Braiding {
579                direction: BraidingDirection::Clockwise,
580            },
581            super::TopologicalOperation::Fusion,
582            super::TopologicalOperation::Measurement,
583        ],
584        braiding_fidelity: 0.9999,
585        fusion_fidelity: 0.999,
586        topological_gap: 1.0,
587        coherence_length: 100.0,
588    };
589
590    let config = TopologicalDeviceConfig::default();
591    let fusion_rules = FusionRuleSet::fibonacci();
592
593    EnhancedTopologicalDevice::new(system_type, fusion_rules, capabilities, config)
594}
595
596/// Create an Ising anyon topological device
597pub fn create_ising_device(
598    max_anyons: usize,
599    max_qubits: usize,
600) -> TopologicalResult<EnhancedTopologicalDevice> {
601    let system_type = TopologicalSystemType::NonAbelian {
602        anyon_type: NonAbelianAnyonType::Ising,
603        fusion_rules: FusionRuleSet::ising(),
604    };
605
606    let capabilities = TopologicalCapabilities {
607        max_anyons,
608        max_qubits,
609        supported_anyons: vec![
610            TopologicalCharge::identity(),
611            TopologicalCharge::ising_sigma(),
612            TopologicalCharge::ising_psi(),
613        ],
614        available_operations: vec![
615            super::TopologicalOperation::AnyonCreation {
616                charge_type: "σ".to_string(),
617            },
618            super::TopologicalOperation::Braiding {
619                direction: BraidingDirection::Clockwise,
620            },
621            super::TopologicalOperation::Fusion,
622            super::TopologicalOperation::Measurement,
623        ],
624        braiding_fidelity: 0.999,
625        fusion_fidelity: 0.998,
626        topological_gap: 0.5,
627        coherence_length: 50.0,
628    };
629
630    let config = TopologicalDeviceConfig::default();
631    let fusion_rules = FusionRuleSet::ising();
632
633    EnhancedTopologicalDevice::new(system_type, fusion_rules, capabilities, config)
634}
635
636#[cfg(test)]
637mod tests {
638    use super::*;
639
640    #[tokio::test]
641    async fn test_fibonacci_device_creation() {
642        let device = create_fibonacci_device(100, 10).expect("Failed to create Fibonacci device");
643        assert_eq!(device.core_device.capabilities.max_anyons, 100);
644        assert_eq!(device.core_device.capabilities.max_qubits, 10);
645    }
646
647    #[tokio::test]
648    async fn test_device_connection() {
649        let mut device = create_fibonacci_device(50, 5).expect("Failed to create Fibonacci device");
650        assert!(!device.is_connected);
651
652        device.connect().await.expect("Failed to connect to device");
653        assert!(device.is_connected);
654
655        device
656            .disconnect()
657            .await
658            .expect("Failed to disconnect from device");
659        assert!(!device.is_connected);
660    }
661
662    #[tokio::test]
663    async fn test_qubit_initialization() {
664        let mut device =
665            create_fibonacci_device(100, 10).expect("Failed to create Fibonacci device");
666        device.connect().await.expect("Failed to connect to device");
667
668        let qubit_ids = device
669            .initialize_topological_qubits(3)
670            .await
671            .expect("Failed to initialize topological qubits");
672        assert_eq!(qubit_ids.len(), 3);
673    }
674
675    #[tokio::test]
676    async fn test_topological_gates() {
677        let mut device =
678            create_fibonacci_device(100, 10).expect("Failed to create Fibonacci device");
679        device.connect().await.expect("Failed to connect to device");
680
681        let qubit_ids = device
682            .initialize_topological_qubits(2)
683            .await
684            .expect("Failed to initialize topological qubits");
685
686        // Test X gate
687        device
688            .topological_x_gate(qubit_ids[0])
689            .await
690            .expect("Failed to apply X gate");
691
692        // Test Z gate
693        device
694            .topological_z_gate(qubit_ids[0])
695            .await
696            .expect("Failed to apply Z gate");
697
698        // Test CNOT gate
699        device
700            .topological_cnot_gate(qubit_ids[0], qubit_ids[1])
701            .await
702            .expect("Failed to apply CNOT gate");
703    }
704
705    #[tokio::test]
706    async fn test_measurement() {
707        let mut device = create_fibonacci_device(50, 5).expect("Failed to create Fibonacci device");
708        device.connect().await.expect("Failed to connect to device");
709
710        let qubit_ids = device
711            .initialize_topological_qubits(1)
712            .await
713            .expect("Failed to initialize topological qubits");
714        let result = device
715            .measure_topological_qubit(qubit_ids[0])
716            .await
717            .expect("Failed to measure topological qubit");
718
719        // Result should be boolean
720        // result is bool, always true or false
721    }
722
723    #[tokio::test]
724    async fn test_device_diagnostics() {
725        let device = create_fibonacci_device(50, 5).expect("Failed to create Fibonacci device");
726        let diagnostics = device.get_diagnostics().await;
727
728        assert!(!diagnostics.is_connected);
729        assert!(diagnostics.topological_gap > 0.0);
730        assert!(diagnostics.average_braiding_fidelity > 0.0);
731    }
732
733    #[tokio::test]
734    async fn test_quantum_device_traits() {
735        let device = create_ising_device(30, 3).expect("Failed to create Ising device");
736
737        assert!(device
738            .is_simulator()
739            .await
740            .expect("Failed to check if device is simulator"));
741        assert_eq!(
742            device
743                .qubit_count()
744                .await
745                .expect("Failed to get qubit count"),
746            3
747        );
748
749        let properties = device
750            .properties()
751            .await
752            .expect("Failed to get device properties");
753        assert_eq!(
754            properties
755                .get("device_type")
756                .expect("device_type property not found"),
757            "topological"
758        );
759    }
760}