1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::fmt;
9
10use quantrs2_core::{
11 error::{QuantRS2Error, QuantRS2Result},
12 gate::GateOp,
13 qubit::QubitId,
14};
15
16use crate::translation::{DecomposedGate, HardwareBackend, NativeGateSet};
17
18pub trait HardwareGate: GateOp {
20 fn backend(&self) -> HardwareBackend;
22
23 fn metadata(&self) -> HashMap<String, String> {
25 HashMap::new()
26 }
27
28 fn requires_calibration(&self) -> bool {
30 true
31 }
32
33 fn calibration_params(&self) -> Vec<String> {
35 vec![]
36 }
37}
38
39pub mod ibm_gates {
41 use super::*;
42 use scirs2_core::Complex64;
43 use std::any::Any;
44
45 #[derive(Debug, Clone, Copy)]
47 pub struct SXGate {
48 pub target: QubitId,
49 }
50
51 impl GateOp for SXGate {
52 fn name(&self) -> &'static str {
53 "sx"
54 }
55
56 fn qubits(&self) -> Vec<QubitId> {
57 vec![self.target]
58 }
59
60 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
61 let half = 0.5;
62 let i_half = Complex64::new(0.0, 0.5);
63 Ok(vec![
64 Complex64::new(half, 0.0) + i_half,
65 Complex64::new(half, 0.0) - i_half,
66 Complex64::new(half, 0.0) - i_half,
67 Complex64::new(half, 0.0) + i_half,
68 ])
69 }
70
71 fn as_any(&self) -> &dyn Any {
72 self
73 }
74
75 fn clone_gate(&self) -> Box<dyn GateOp> {
76 Box::new(self.clone())
77 }
78 }
79
80 impl HardwareGate for SXGate {
81 fn backend(&self) -> HardwareBackend {
82 HardwareBackend::IBMQuantum
83 }
84
85 fn metadata(&self) -> HashMap<String, String> {
86 let mut meta = HashMap::new();
87 meta.insert("gate_type".to_string(), "basis".to_string());
88 meta.insert("duration_ns".to_string(), "35.5".to_string());
89 meta
90 }
91 }
92}
93
94pub mod google_gates {
96 use super::*;
97 use scirs2_core::Complex64;
98 use std::any::Any;
99 use std::f64::consts::PI;
100
101 #[derive(Debug, Clone, Copy)]
103 pub struct SycamoreGate {
104 pub qubit1: QubitId,
105 pub qubit2: QubitId,
106 }
107
108 impl GateOp for SycamoreGate {
109 fn name(&self) -> &'static str {
110 "syc"
111 }
112
113 fn qubits(&self) -> Vec<QubitId> {
114 vec![self.qubit1, self.qubit2]
115 }
116
117 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
118 let fsim_theta = PI / 2.0;
121 let fsim_phi = PI / 6.0;
122
123 let c = fsim_theta.cos();
125 let s = Complex64::new(0.0, -fsim_theta.sin());
126 let phase = Complex64::from_polar(1.0, -fsim_phi);
127
128 Ok(vec![
129 Complex64::new(1.0, 0.0),
130 Complex64::new(0.0, 0.0),
131 Complex64::new(0.0, 0.0),
132 Complex64::new(0.0, 0.0),
133 Complex64::new(0.0, 0.0),
134 Complex64::new(c, 0.0),
135 s,
136 Complex64::new(0.0, 0.0),
137 Complex64::new(0.0, 0.0),
138 s,
139 Complex64::new(c, 0.0),
140 Complex64::new(0.0, 0.0),
141 Complex64::new(0.0, 0.0),
142 Complex64::new(0.0, 0.0),
143 Complex64::new(0.0, 0.0),
144 phase,
145 ])
146 }
147
148 fn as_any(&self) -> &dyn Any {
149 self
150 }
151
152 fn clone_gate(&self) -> Box<dyn GateOp> {
153 Box::new(self.clone())
154 }
155 }
156
157 impl HardwareGate for SycamoreGate {
158 fn backend(&self) -> HardwareBackend {
159 HardwareBackend::GoogleSycamore
160 }
161
162 fn metadata(&self) -> HashMap<String, String> {
163 let mut meta = HashMap::new();
164 meta.insert("gate_type".to_string(), "entangling".to_string());
165 meta.insert("duration_ns".to_string(), "12".to_string());
166 meta.insert("fidelity".to_string(), "0.995".to_string());
167 meta
168 }
169 }
170
171 #[derive(Debug, Clone, Copy)]
173 pub struct PoweredGate {
174 pub target: QubitId,
175 pub axis: char, pub power: f64,
177 }
178
179 impl GateOp for PoweredGate {
180 fn name(&self) -> &'static str {
181 match self.axis {
182 'X' => "x_pow",
183 'Y' => "y_pow",
184 'Z' => "z_pow",
185 _ => "pow",
186 }
187 }
188
189 fn qubits(&self) -> Vec<QubitId> {
190 vec![self.target]
191 }
192
193 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
194 let angle = PI * self.power;
195 let cos_half = (angle / 2.0).cos();
196 let sin_half = (angle / 2.0).sin();
197
198 match self.axis {
199 'X' => Ok(vec![
200 Complex64::new(cos_half, 0.0),
201 Complex64::new(0.0, -sin_half),
202 Complex64::new(0.0, -sin_half),
203 Complex64::new(cos_half, 0.0),
204 ]),
205 'Y' => Ok(vec![
206 Complex64::new(cos_half, 0.0),
207 Complex64::new(-sin_half, 0.0),
208 Complex64::new(sin_half, 0.0),
209 Complex64::new(cos_half, 0.0),
210 ]),
211 'Z' => Ok(vec![
212 Complex64::from_polar(1.0, -angle / 2.0),
213 Complex64::new(0.0, 0.0),
214 Complex64::new(0.0, 0.0),
215 Complex64::from_polar(1.0, angle / 2.0),
216 ]),
217 _ => Err(QuantRS2Error::InvalidInput("Invalid axis".to_string())),
218 }
219 }
220
221 fn as_any(&self) -> &dyn Any {
222 self
223 }
224
225 fn clone_gate(&self) -> Box<dyn GateOp> {
226 Box::new(self.clone())
227 }
228 }
229}
230
231pub mod ionq_gates {
233 use super::*;
234 use scirs2_core::Complex64;
235 use std::any::Any;
236
237 #[derive(Debug, Clone, Copy)]
239 pub struct XXGate {
240 pub qubit1: QubitId,
241 pub qubit2: QubitId,
242 pub angle: f64,
243 }
244
245 impl GateOp for XXGate {
246 fn name(&self) -> &'static str {
247 "xx"
248 }
249
250 fn qubits(&self) -> Vec<QubitId> {
251 vec![self.qubit1, self.qubit2]
252 }
253
254 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
255 let c = self.angle.cos();
256 let s = Complex64::new(0.0, -self.angle.sin());
257
258 Ok(vec![
259 Complex64::new(c, 0.0),
260 Complex64::new(0.0, 0.0),
261 Complex64::new(0.0, 0.0),
262 s,
263 Complex64::new(0.0, 0.0),
264 Complex64::new(c, 0.0),
265 s,
266 Complex64::new(0.0, 0.0),
267 Complex64::new(0.0, 0.0),
268 s,
269 Complex64::new(c, 0.0),
270 Complex64::new(0.0, 0.0),
271 s,
272 Complex64::new(0.0, 0.0),
273 Complex64::new(0.0, 0.0),
274 Complex64::new(c, 0.0),
275 ])
276 }
277
278 fn as_any(&self) -> &dyn Any {
279 self
280 }
281
282 fn clone_gate(&self) -> Box<dyn GateOp> {
283 Box::new(self.clone())
284 }
285 }
286
287 impl HardwareGate for XXGate {
288 fn backend(&self) -> HardwareBackend {
289 HardwareBackend::IonQ
290 }
291
292 fn metadata(&self) -> HashMap<String, String> {
293 let mut meta = HashMap::new();
294 meta.insert("gate_type".to_string(), "ms".to_string());
295 meta.insert("interaction".to_string(), "all-to-all".to_string());
296 meta
297 }
298
299 fn calibration_params(&self) -> Vec<String> {
300 vec!["ms_amplitude".to_string(), "ms_phase".to_string()]
301 }
302 }
303}
304
305pub mod rigetti_gates {
307 use super::*;
308 use scirs2_core::Complex64;
309 use std::any::Any;
310
311 #[derive(Debug, Clone, Copy)]
313 pub struct XYGate {
314 pub qubit1: QubitId,
315 pub qubit2: QubitId,
316 pub angle: f64,
317 }
318
319 impl GateOp for XYGate {
320 fn name(&self) -> &'static str {
321 "xy"
322 }
323
324 fn qubits(&self) -> Vec<QubitId> {
325 vec![self.qubit1, self.qubit2]
326 }
327
328 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
329 let c = (self.angle / 2.0).cos();
330 let s = Complex64::new(0.0, (self.angle / 2.0).sin());
331
332 Ok(vec![
333 Complex64::new(1.0, 0.0),
334 Complex64::new(0.0, 0.0),
335 Complex64::new(0.0, 0.0),
336 Complex64::new(0.0, 0.0),
337 Complex64::new(0.0, 0.0),
338 Complex64::new(c, 0.0),
339 s,
340 Complex64::new(0.0, 0.0),
341 Complex64::new(0.0, 0.0),
342 s,
343 Complex64::new(c, 0.0),
344 Complex64::new(0.0, 0.0),
345 Complex64::new(0.0, 0.0),
346 Complex64::new(0.0, 0.0),
347 Complex64::new(0.0, 0.0),
348 Complex64::new(1.0, 0.0),
349 ])
350 }
351
352 fn as_any(&self) -> &dyn Any {
353 self
354 }
355
356 fn clone_gate(&self) -> Box<dyn GateOp> {
357 Box::new(self.clone())
358 }
359 }
360}
361
362pub mod honeywell_gates {
364 use super::*;
365 use scirs2_core::Complex64;
366 use std::any::Any;
367
368 #[derive(Debug, Clone, Copy)]
370 pub struct ZZGate {
371 pub qubit1: QubitId,
372 pub qubit2: QubitId,
373 pub angle: f64,
374 }
375
376 impl GateOp for ZZGate {
377 fn name(&self) -> &'static str {
378 "zz"
379 }
380
381 fn qubits(&self) -> Vec<QubitId> {
382 vec![self.qubit1, self.qubit2]
383 }
384
385 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
386 let phase_p = Complex64::from_polar(1.0, self.angle / 2.0);
387 let phase_m = Complex64::from_polar(1.0, -self.angle / 2.0);
388
389 Ok(vec![
390 phase_m,
391 Complex64::new(0.0, 0.0),
392 Complex64::new(0.0, 0.0),
393 Complex64::new(0.0, 0.0),
394 Complex64::new(0.0, 0.0),
395 phase_p,
396 Complex64::new(0.0, 0.0),
397 Complex64::new(0.0, 0.0),
398 Complex64::new(0.0, 0.0),
399 Complex64::new(0.0, 0.0),
400 phase_p,
401 Complex64::new(0.0, 0.0),
402 Complex64::new(0.0, 0.0),
403 Complex64::new(0.0, 0.0),
404 Complex64::new(0.0, 0.0),
405 phase_m,
406 ])
407 }
408
409 fn as_any(&self) -> &dyn Any {
410 self
411 }
412
413 fn clone_gate(&self) -> Box<dyn GateOp> {
414 Box::new(self.clone())
415 }
416 }
417
418 impl HardwareGate for ZZGate {
419 fn backend(&self) -> HardwareBackend {
420 HardwareBackend::Honeywell
421 }
422
423 fn metadata(&self) -> HashMap<String, String> {
424 let mut meta = HashMap::new();
425 meta.insert("gate_type".to_string(), "native".to_string());
426 meta.insert("fidelity".to_string(), "0.999".to_string());
427 meta
428 }
429 }
430
431 #[derive(Debug, Clone, Copy)]
433 pub struct U3Gate {
434 pub target: QubitId,
435 pub theta: f64,
436 pub phi: f64,
437 pub lambda: f64,
438 }
439
440 impl GateOp for U3Gate {
441 fn name(&self) -> &'static str {
442 "u3"
443 }
444
445 fn qubits(&self) -> Vec<QubitId> {
446 vec![self.target]
447 }
448
449 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
450 let cos_half = (self.theta / 2.0).cos();
451 let sin_half = (self.theta / 2.0).sin();
452
453 Ok(vec![
454 Complex64::new(cos_half, 0.0),
455 -Complex64::from_polar(sin_half, self.lambda),
456 Complex64::from_polar(sin_half, self.phi),
457 Complex64::from_polar(cos_half, self.phi + self.lambda),
458 ])
459 }
460
461 fn as_any(&self) -> &dyn Any {
462 self
463 }
464
465 fn clone_gate(&self) -> Box<dyn GateOp> {
466 Box::new(self.clone())
467 }
468 }
469}
470
471pub struct DecompositionValidator {
473 tolerance: f64,
475}
476
477impl DecompositionValidator {
478 pub fn new(tolerance: f64) -> Self {
480 Self { tolerance }
481 }
482
483 pub fn validate(
485 &self,
486 original: &dyn GateOp,
487 decomposed: &[DecomposedGate],
488 ) -> QuantRS2Result<bool> {
489 Ok(true)
492 }
493
494 pub fn calculate_fidelity(
496 &self,
497 original: &dyn GateOp,
498 decomposed: &[DecomposedGate],
499 ) -> QuantRS2Result<f64> {
500 Ok(0.999)
503 }
504}
505
506#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
508pub struct BackendCapabilities {
509 pub backend: HardwareBackend,
511 pub native_gates: NativeGateSet,
513 pub features: BackendFeatures,
515 pub performance: BackendPerformance,
517}
518
519impl Default for BackendCapabilities {
520 fn default() -> Self {
521 Self {
522 backend: HardwareBackend::Custom(0),
523 native_gates: NativeGateSet::default(),
524 features: BackendFeatures::default(),
525 performance: BackendPerformance::default(),
526 }
527 }
528}
529
530#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
532pub struct BackendFeatures {
533 pub mid_circuit_measurement: bool,
535 pub conditional_gates: bool,
537 pub parametric_compilation: bool,
539 pub pulse_control: bool,
541 pub max_qubits: usize,
543 pub max_depth: Option<usize>,
545 pub max_mid_circuit_measurements: Option<usize>,
547 pub classical_register_size: usize,
549 pub supports_real_time_feedback: bool,
551 pub supports_parallel_execution: bool,
553 pub supports_reset: bool,
555 pub supports_barriers: bool,
557 pub supported_measurement_bases: Vec<String>,
559}
560
561impl Default for BackendFeatures {
562 fn default() -> Self {
563 Self {
564 mid_circuit_measurement: false,
565 conditional_gates: false,
566 parametric_compilation: true,
567 pulse_control: false,
568 max_qubits: 64,
569 max_depth: None,
570 max_mid_circuit_measurements: None,
571 classical_register_size: 64,
572 supports_real_time_feedback: false,
573 supports_parallel_execution: false,
574 supports_reset: true,
575 supports_barriers: true,
576 supported_measurement_bases: vec!["Z".to_string()],
577 }
578 }
579}
580
581#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
583pub struct BackendPerformance {
584 pub single_qubit_gate_time: f64,
586 pub two_qubit_gate_time: f64,
588 pub measurement_time: f64,
590 pub t1_time: f64,
592 pub t2_time: f64,
594 pub single_qubit_fidelity: f64,
596 pub two_qubit_fidelity: f64,
598}
599
600impl Default for BackendPerformance {
601 fn default() -> Self {
602 Self {
603 single_qubit_gate_time: 50.0, two_qubit_gate_time: 500.0, measurement_time: 1000.0, t1_time: 100.0, t2_time: 50.0, single_qubit_fidelity: 0.999,
609 two_qubit_fidelity: 0.99,
610 }
611 }
612}
613
614pub fn query_backend_capabilities(backend: HardwareBackend) -> BackendCapabilities {
616 match backend {
617 HardwareBackend::IBMQuantum => BackendCapabilities {
618 backend,
619 native_gates: NativeGateSet {
620 backend,
621 single_qubit_gates: vec!["id", "rz", "sx", "x"]
622 .iter()
623 .map(|s| s.to_string())
624 .collect(),
625 two_qubit_gates: vec!["cx".to_string()],
626 multi_qubit_gates: vec![],
627 arbitrary_single_qubit: false,
628 rotation_axes: vec![crate::translation::RotationAxis::Z],
629 constraints: crate::translation::BackendConstraints {
630 max_depth: None,
631 discrete_angles: None,
632 virtual_z: true,
633 coupling_map: None,
634 timing_constraints: None,
635 },
636 },
637 features: BackendFeatures {
638 mid_circuit_measurement: true,
639 conditional_gates: true,
640 parametric_compilation: true,
641 pulse_control: true,
642 max_qubits: 127,
643 max_depth: Some(10000),
644 max_mid_circuit_measurements: Some(127), classical_register_size: 128,
646 supports_real_time_feedback: true,
647 supports_parallel_execution: false, supports_reset: true,
649 supports_barriers: true,
650 supported_measurement_bases: vec![
651 "Z".to_string(),
652 "X".to_string(),
653 "Y".to_string(),
654 ],
655 },
656 performance: BackendPerformance {
657 single_qubit_gate_time: 35.0,
658 two_qubit_gate_time: 300.0,
659 measurement_time: 3000.0,
660 t1_time: 100.0,
661 t2_time: 100.0,
662 single_qubit_fidelity: 0.9999,
663 two_qubit_fidelity: 0.99,
664 },
665 },
666 HardwareBackend::IonQ => BackendCapabilities {
667 backend,
668 native_gates: NativeGateSet {
669 backend,
670 single_qubit_gates: vec!["rx", "ry", "rz"]
671 .iter()
672 .map(|s| s.to_string())
673 .collect(),
674 two_qubit_gates: vec!["xx".to_string()],
675 multi_qubit_gates: vec![],
676 arbitrary_single_qubit: true,
677 rotation_axes: vec![
678 crate::translation::RotationAxis::X,
679 crate::translation::RotationAxis::Y,
680 crate::translation::RotationAxis::Z,
681 ],
682 constraints: crate::translation::BackendConstraints {
683 max_depth: None,
684 discrete_angles: None,
685 virtual_z: false,
686 coupling_map: None, timing_constraints: None,
688 },
689 },
690 features: BackendFeatures {
691 mid_circuit_measurement: false,
692 conditional_gates: false,
693 parametric_compilation: true,
694 pulse_control: false,
695 max_qubits: 32,
696 max_depth: None,
697 max_mid_circuit_measurements: None, classical_register_size: 0, supports_real_time_feedback: false,
700 supports_parallel_execution: true, supports_reset: false,
702 supports_barriers: false,
703 supported_measurement_bases: vec!["Z".to_string()],
704 },
705 performance: BackendPerformance {
706 single_qubit_gate_time: 135.0,
707 two_qubit_gate_time: 600.0,
708 measurement_time: 100.0,
709 t1_time: 10000.0, t2_time: 1000.0, single_qubit_fidelity: 0.9995,
712 two_qubit_fidelity: 0.97,
713 },
714 },
715 _ => {
716 BackendCapabilities {
718 backend,
719 native_gates: NativeGateSet {
720 backend,
721 single_qubit_gates: vec![],
722 two_qubit_gates: vec![],
723 multi_qubit_gates: vec![],
724 arbitrary_single_qubit: true,
725 rotation_axes: vec![],
726 constraints: crate::translation::BackendConstraints {
727 max_depth: None,
728 discrete_angles: None,
729 virtual_z: false,
730 coupling_map: None,
731 timing_constraints: None,
732 },
733 },
734 features: BackendFeatures {
735 mid_circuit_measurement: false,
736 conditional_gates: false,
737 parametric_compilation: false,
738 pulse_control: false,
739 max_qubits: 20,
740 max_depth: None,
741 max_mid_circuit_measurements: None,
742 classical_register_size: 0,
743 supports_real_time_feedback: false,
744 supports_parallel_execution: false,
745 supports_reset: false,
746 supports_barriers: false,
747 supported_measurement_bases: vec!["Z".to_string()],
748 },
749 performance: BackendPerformance {
750 single_qubit_gate_time: 50.0,
751 two_qubit_gate_time: 500.0,
752 measurement_time: 1000.0,
753 t1_time: 50.0,
754 t2_time: 50.0,
755 single_qubit_fidelity: 0.999,
756 two_qubit_fidelity: 0.99,
757 },
758 }
759 }
760 }
761}
762
763#[cfg(test)]
764mod tests {
765 use super::*;
766
767 #[test]
768 fn test_hardware_gate_implementations() {
769 let sx = ibm_gates::SXGate { target: QubitId(0) };
771 assert_eq!(sx.name(), "sx");
772 assert_eq!(sx.backend(), HardwareBackend::IBMQuantum);
773
774 let syc = google_gates::SycamoreGate {
776 qubit1: QubitId(0),
777 qubit2: QubitId(1),
778 };
779 assert_eq!(syc.name(), "syc");
780 assert_eq!(syc.backend(), HardwareBackend::GoogleSycamore);
781
782 let xx = ionq_gates::XXGate {
784 qubit1: QubitId(0),
785 qubit2: QubitId(1),
786 angle: std::f64::consts::PI / 2.0,
787 };
788 assert_eq!(xx.name(), "xx");
789 assert_eq!(xx.backend(), HardwareBackend::IonQ);
790 }
791
792 #[test]
793 fn test_backend_capabilities() {
794 let ibm_caps = query_backend_capabilities(HardwareBackend::IBMQuantum);
795 assert!(ibm_caps.features.pulse_control);
796 assert!(ibm_caps.features.mid_circuit_measurement);
797 assert_eq!(ibm_caps.performance.single_qubit_gate_time, 35.0);
798
799 let ionq_caps = query_backend_capabilities(HardwareBackend::IonQ);
800 assert!(!ionq_caps.features.pulse_control);
801 assert!(ionq_caps.performance.t1_time > ibm_caps.performance.t1_time);
802 }
803}