1use scirs2_core::Complex64;
2use std::any::Any;
3use std::f64::consts::PI;
4use std::fmt::Debug;
5
6use crate::error::QuantRS2Result;
7use crate::qubit::QubitId;
8
9macro_rules! impl_clone_gate {
11 () => {
12 fn clone_gate(&self) -> Box<dyn GateOp> {
13 Box::new(self.clone())
14 }
15 };
16}
17
18pub trait GateOp: Debug + Send + Sync {
20 fn name(&self) -> &'static str;
22
23 fn qubits(&self) -> Vec<QubitId>;
25
26 fn num_qubits(&self) -> usize {
28 self.qubits().len()
29 }
30
31 fn is_parameterized(&self) -> bool {
33 false
34 }
35
36 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>>;
38
39 fn as_any(&self) -> &dyn Any;
41
42 fn clone_gate(&self) -> Box<dyn GateOp>;
44}
45
46impl Clone for Box<dyn GateOp> {
48 fn clone(&self) -> Self {
49 self.clone_gate()
50 }
51}
52
53pub mod single {
55 use super::*;
56 use std::any::Any;
57
58 #[derive(Debug, Clone, Copy)]
60 pub struct Hadamard {
61 pub target: QubitId,
63 }
64
65 impl GateOp for Hadamard {
66 fn name(&self) -> &'static str {
67 "H"
68 }
69
70 fn qubits(&self) -> Vec<QubitId> {
71 vec![self.target]
72 }
73
74 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
75 let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
76 Ok(vec![
77 Complex64::new(sqrt2_inv, 0.0),
78 Complex64::new(sqrt2_inv, 0.0),
79 Complex64::new(sqrt2_inv, 0.0),
80 Complex64::new(-sqrt2_inv, 0.0),
81 ])
82 }
83
84 fn as_any(&self) -> &dyn Any {
85 self
86 }
87
88 impl_clone_gate!();
89 }
90
91 #[derive(Debug, Clone, Copy)]
93 pub struct PauliX {
94 pub target: QubitId,
96 }
97
98 impl GateOp for PauliX {
99 fn name(&self) -> &'static str {
100 "X"
101 }
102
103 fn qubits(&self) -> Vec<QubitId> {
104 vec![self.target]
105 }
106
107 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
108 Ok(vec![
109 Complex64::new(0.0, 0.0),
110 Complex64::new(1.0, 0.0),
111 Complex64::new(1.0, 0.0),
112 Complex64::new(0.0, 0.0),
113 ])
114 }
115
116 fn as_any(&self) -> &dyn Any {
117 self
118 }
119
120 impl_clone_gate!();
121 }
122
123 #[derive(Debug, Clone, Copy)]
125 pub struct PauliY {
126 pub target: QubitId,
128 }
129
130 impl GateOp for PauliY {
131 fn name(&self) -> &'static str {
132 "Y"
133 }
134
135 fn qubits(&self) -> Vec<QubitId> {
136 vec![self.target]
137 }
138
139 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
140 Ok(vec![
141 Complex64::new(0.0, 0.0),
142 Complex64::new(0.0, -1.0),
143 Complex64::new(0.0, 1.0),
144 Complex64::new(0.0, 0.0),
145 ])
146 }
147
148 fn as_any(&self) -> &dyn Any {
149 self
150 }
151
152 impl_clone_gate!();
153 }
154
155 #[derive(Debug, Clone, Copy)]
157 pub struct PauliZ {
158 pub target: QubitId,
160 }
161
162 impl GateOp for PauliZ {
163 fn name(&self) -> &'static str {
164 "Z"
165 }
166
167 fn qubits(&self) -> Vec<QubitId> {
168 vec![self.target]
169 }
170
171 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
172 Ok(vec![
173 Complex64::new(1.0, 0.0),
174 Complex64::new(0.0, 0.0),
175 Complex64::new(0.0, 0.0),
176 Complex64::new(-1.0, 0.0),
177 ])
178 }
179
180 fn as_any(&self) -> &dyn Any {
181 self
182 }
183
184 impl_clone_gate!();
185 }
186
187 #[derive(Debug, Clone, Copy)]
189 pub struct RotationX {
190 pub target: QubitId,
192
193 pub theta: f64,
195 }
196
197 impl GateOp for RotationX {
198 fn name(&self) -> &'static str {
199 "RX"
200 }
201
202 fn qubits(&self) -> Vec<QubitId> {
203 vec![self.target]
204 }
205
206 fn is_parameterized(&self) -> bool {
207 true
208 }
209
210 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
211 let cos = (self.theta / 2.0).cos();
212 let sin = (self.theta / 2.0).sin();
213 Ok(vec![
214 Complex64::new(cos, 0.0),
215 Complex64::new(0.0, -sin),
216 Complex64::new(0.0, -sin),
217 Complex64::new(cos, 0.0),
218 ])
219 }
220
221 fn as_any(&self) -> &dyn Any {
222 self
223 }
224
225 impl_clone_gate!();
226 }
227
228 #[derive(Debug, Clone, Copy)]
230 pub struct RotationY {
231 pub target: QubitId,
233
234 pub theta: f64,
236 }
237
238 impl GateOp for RotationY {
239 fn name(&self) -> &'static str {
240 "RY"
241 }
242
243 fn qubits(&self) -> Vec<QubitId> {
244 vec![self.target]
245 }
246
247 fn is_parameterized(&self) -> bool {
248 true
249 }
250
251 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
252 let cos = (self.theta / 2.0).cos();
253 let sin = (self.theta / 2.0).sin();
254 Ok(vec![
255 Complex64::new(cos, 0.0),
256 Complex64::new(-sin, 0.0),
257 Complex64::new(sin, 0.0),
258 Complex64::new(cos, 0.0),
259 ])
260 }
261
262 fn as_any(&self) -> &dyn Any {
263 self
264 }
265
266 impl_clone_gate!();
267 }
268
269 #[derive(Debug, Clone, Copy)]
271 pub struct RotationZ {
272 pub target: QubitId,
274
275 pub theta: f64,
277 }
278
279 impl GateOp for RotationZ {
280 fn name(&self) -> &'static str {
281 "RZ"
282 }
283
284 fn qubits(&self) -> Vec<QubitId> {
285 vec![self.target]
286 }
287
288 fn is_parameterized(&self) -> bool {
289 true
290 }
291
292 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
293 let phase = Complex64::new(0.0, -self.theta / 2.0).exp();
294 let phase_conj = Complex64::new(0.0, self.theta / 2.0).exp();
295 Ok(vec![
296 phase_conj,
297 Complex64::new(0.0, 0.0),
298 Complex64::new(0.0, 0.0),
299 phase,
300 ])
301 }
302
303 fn as_any(&self) -> &dyn Any {
304 self
305 }
306
307 impl_clone_gate!();
308 }
309
310 #[derive(Debug, Clone, Copy)]
312 pub struct Phase {
313 pub target: QubitId,
315 }
316
317 impl GateOp for Phase {
318 fn name(&self) -> &'static str {
319 "S"
320 }
321
322 fn qubits(&self) -> Vec<QubitId> {
323 vec![self.target]
324 }
325
326 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
327 Ok(vec![
328 Complex64::new(1.0, 0.0),
329 Complex64::new(0.0, 0.0),
330 Complex64::new(0.0, 0.0),
331 Complex64::new(0.0, 1.0),
332 ])
333 }
334
335 fn as_any(&self) -> &dyn Any {
336 self
337 }
338
339 impl_clone_gate!();
340 }
341
342 #[derive(Debug, Clone, Copy)]
344 pub struct T {
345 pub target: QubitId,
347 }
348
349 impl GateOp for T {
350 fn name(&self) -> &'static str {
351 "T"
352 }
353
354 fn qubits(&self) -> Vec<QubitId> {
355 vec![self.target]
356 }
357
358 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
359 let phase = Complex64::new((PI / 4.0).cos(), (PI / 4.0).sin());
360 Ok(vec![
361 Complex64::new(1.0, 0.0),
362 Complex64::new(0.0, 0.0),
363 Complex64::new(0.0, 0.0),
364 phase,
365 ])
366 }
367
368 fn as_any(&self) -> &dyn Any {
369 self
370 }
371
372 impl_clone_gate!();
373 }
374
375 #[derive(Debug, Clone, Copy)]
377 pub struct TDagger {
378 pub target: QubitId,
380 }
381
382 impl GateOp for TDagger {
383 fn name(&self) -> &'static str {
384 "T†"
385 }
386
387 fn qubits(&self) -> Vec<QubitId> {
388 vec![self.target]
389 }
390
391 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
392 let phase = Complex64::new((PI / 4.0).cos(), -(PI / 4.0).sin());
393 Ok(vec![
394 Complex64::new(1.0, 0.0),
395 Complex64::new(0.0, 0.0),
396 Complex64::new(0.0, 0.0),
397 phase,
398 ])
399 }
400
401 fn as_any(&self) -> &dyn Any {
402 self
403 }
404
405 impl_clone_gate!();
406 }
407
408 #[derive(Debug, Clone, Copy)]
410 pub struct PhaseDagger {
411 pub target: QubitId,
413 }
414
415 impl GateOp for PhaseDagger {
416 fn name(&self) -> &'static str {
417 "S†"
418 }
419
420 fn qubits(&self) -> Vec<QubitId> {
421 vec![self.target]
422 }
423
424 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
425 Ok(vec![
426 Complex64::new(1.0, 0.0),
427 Complex64::new(0.0, 0.0),
428 Complex64::new(0.0, 0.0),
429 Complex64::new(0.0, -1.0),
430 ])
431 }
432
433 fn as_any(&self) -> &dyn Any {
434 self
435 }
436
437 impl_clone_gate!();
438 }
439
440 #[derive(Debug, Clone, Copy)]
442 pub struct SqrtX {
443 pub target: QubitId,
445 }
446
447 impl GateOp for SqrtX {
448 fn name(&self) -> &'static str {
449 "√X"
450 }
451
452 fn qubits(&self) -> Vec<QubitId> {
453 vec![self.target]
454 }
455
456 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
457 let half_plus_i_half = Complex64::new(0.5, 0.5);
459 let half_minus_i_half = Complex64::new(0.5, -0.5);
460
461 Ok(vec![
462 half_plus_i_half,
463 half_minus_i_half,
464 half_minus_i_half,
465 half_plus_i_half,
466 ])
467 }
468
469 fn as_any(&self) -> &dyn Any {
470 self
471 }
472
473 impl_clone_gate!();
474 }
475
476 #[derive(Debug, Clone, Copy)]
478 pub struct SqrtXDagger {
479 pub target: QubitId,
481 }
482
483 impl GateOp for SqrtXDagger {
484 fn name(&self) -> &'static str {
485 "√X†"
486 }
487
488 fn qubits(&self) -> Vec<QubitId> {
489 vec![self.target]
490 }
491
492 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
493 let half_minus_i_half = Complex64::new(0.5, -0.5);
495 let half_plus_i_half = Complex64::new(0.5, 0.5);
496
497 Ok(vec![
498 half_minus_i_half,
499 half_plus_i_half,
500 half_plus_i_half,
501 half_minus_i_half,
502 ])
503 }
504
505 fn as_any(&self) -> &dyn Any {
506 self
507 }
508
509 impl_clone_gate!();
510 }
511
512 #[derive(Debug, Clone, Copy)]
517 pub struct UGate {
518 pub target: QubitId,
520 pub theta: f64,
522 pub phi: f64,
524 pub lambda: f64,
526 }
527
528 impl GateOp for UGate {
529 fn name(&self) -> &'static str {
530 "U"
531 }
532
533 fn qubits(&self) -> Vec<QubitId> {
534 vec![self.target]
535 }
536
537 fn is_parameterized(&self) -> bool {
538 true
539 }
540
541 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
542 let cos = (self.theta / 2.0).cos();
543 let sin = (self.theta / 2.0).sin();
544 let exp_i_lambda = Complex64::new(0.0, self.lambda).exp();
545 let exp_i_phi = Complex64::new(0.0, self.phi).exp();
546 let exp_i_phi_lambda = Complex64::new(0.0, self.phi + self.lambda).exp();
547
548 Ok(vec![
549 Complex64::new(cos, 0.0),
550 -exp_i_lambda * sin,
551 exp_i_phi * sin,
552 exp_i_phi_lambda * cos,
553 ])
554 }
555
556 fn as_any(&self) -> &dyn Any {
557 self
558 }
559
560 impl_clone_gate!();
561 }
562
563 #[derive(Debug, Clone, Copy)]
567 pub struct PGate {
568 pub target: QubitId,
570 pub lambda: f64,
572 }
573
574 impl GateOp for PGate {
575 fn name(&self) -> &'static str {
576 "P"
577 }
578
579 fn qubits(&self) -> Vec<QubitId> {
580 vec![self.target]
581 }
582
583 fn is_parameterized(&self) -> bool {
584 true
585 }
586
587 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
588 let exp_i_lambda = Complex64::new(0.0, self.lambda).exp();
589 Ok(vec![
590 Complex64::new(1.0, 0.0),
591 Complex64::new(0.0, 0.0),
592 Complex64::new(0.0, 0.0),
593 exp_i_lambda,
594 ])
595 }
596
597 fn as_any(&self) -> &dyn Any {
598 self
599 }
600
601 impl_clone_gate!();
602 }
603
604 #[derive(Debug, Clone, Copy)]
606 pub struct Identity {
607 pub target: QubitId,
609 }
610
611 impl GateOp for Identity {
612 fn name(&self) -> &'static str {
613 "I"
614 }
615
616 fn qubits(&self) -> Vec<QubitId> {
617 vec![self.target]
618 }
619
620 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
621 Ok(vec![
622 Complex64::new(1.0, 0.0),
623 Complex64::new(0.0, 0.0),
624 Complex64::new(0.0, 0.0),
625 Complex64::new(1.0, 0.0),
626 ])
627 }
628
629 fn as_any(&self) -> &dyn Any {
630 self
631 }
632
633 impl_clone_gate!();
634 }
635}
636
637pub mod multi {
639 use super::*;
640 use std::any::Any;
641
642 #[derive(Debug, Clone, Copy)]
644 pub struct CNOT {
645 pub control: QubitId,
647
648 pub target: QubitId,
650 }
651
652 impl GateOp for CNOT {
653 fn name(&self) -> &'static str {
654 "CNOT"
655 }
656
657 fn qubits(&self) -> Vec<QubitId> {
658 vec![self.control, self.target]
659 }
660
661 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
662 Ok(vec![
664 Complex64::new(1.0, 0.0),
665 Complex64::new(0.0, 0.0),
666 Complex64::new(0.0, 0.0),
667 Complex64::new(0.0, 0.0),
668 Complex64::new(0.0, 0.0),
669 Complex64::new(1.0, 0.0),
670 Complex64::new(0.0, 0.0),
671 Complex64::new(0.0, 0.0),
672 Complex64::new(0.0, 0.0),
673 Complex64::new(0.0, 0.0),
674 Complex64::new(0.0, 0.0),
675 Complex64::new(1.0, 0.0),
676 Complex64::new(0.0, 0.0),
677 Complex64::new(0.0, 0.0),
678 Complex64::new(1.0, 0.0),
679 Complex64::new(0.0, 0.0),
680 ])
681 }
682
683 fn as_any(&self) -> &dyn Any {
684 self
685 }
686
687 impl_clone_gate!();
688 }
689
690 #[derive(Debug, Clone, Copy)]
692 pub struct CZ {
693 pub control: QubitId,
695
696 pub target: QubitId,
698 }
699
700 impl GateOp for CZ {
701 fn name(&self) -> &'static str {
702 "CZ"
703 }
704
705 fn qubits(&self) -> Vec<QubitId> {
706 vec![self.control, self.target]
707 }
708
709 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
710 Ok(vec![
712 Complex64::new(1.0, 0.0),
713 Complex64::new(0.0, 0.0),
714 Complex64::new(0.0, 0.0),
715 Complex64::new(0.0, 0.0),
716 Complex64::new(0.0, 0.0),
717 Complex64::new(1.0, 0.0),
718 Complex64::new(0.0, 0.0),
719 Complex64::new(0.0, 0.0),
720 Complex64::new(0.0, 0.0),
721 Complex64::new(0.0, 0.0),
722 Complex64::new(1.0, 0.0),
723 Complex64::new(0.0, 0.0),
724 Complex64::new(0.0, 0.0),
725 Complex64::new(0.0, 0.0),
726 Complex64::new(0.0, 0.0),
727 Complex64::new(-1.0, 0.0),
728 ])
729 }
730
731 fn as_any(&self) -> &dyn Any {
732 self
733 }
734
735 impl_clone_gate!();
736 }
737
738 #[derive(Debug, Clone, Copy)]
740 pub struct SWAP {
741 pub qubit1: QubitId,
743
744 pub qubit2: QubitId,
746 }
747
748 impl GateOp for SWAP {
749 fn name(&self) -> &'static str {
750 "SWAP"
751 }
752
753 fn qubits(&self) -> Vec<QubitId> {
754 vec![self.qubit1, self.qubit2]
755 }
756
757 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
758 Ok(vec![
760 Complex64::new(1.0, 0.0),
761 Complex64::new(0.0, 0.0),
762 Complex64::new(0.0, 0.0),
763 Complex64::new(0.0, 0.0),
764 Complex64::new(0.0, 0.0),
765 Complex64::new(0.0, 0.0),
766 Complex64::new(1.0, 0.0),
767 Complex64::new(0.0, 0.0),
768 Complex64::new(0.0, 0.0),
769 Complex64::new(1.0, 0.0),
770 Complex64::new(0.0, 0.0),
771 Complex64::new(0.0, 0.0),
772 Complex64::new(0.0, 0.0),
773 Complex64::new(0.0, 0.0),
774 Complex64::new(0.0, 0.0),
775 Complex64::new(1.0, 0.0),
776 ])
777 }
778
779 fn as_any(&self) -> &dyn Any {
780 self
781 }
782
783 impl_clone_gate!();
784 }
785
786 #[derive(Debug, Clone, Copy)]
788 pub struct CY {
789 pub control: QubitId,
791
792 pub target: QubitId,
794 }
795
796 impl GateOp for CY {
797 fn name(&self) -> &'static str {
798 "CY"
799 }
800
801 fn qubits(&self) -> Vec<QubitId> {
802 vec![self.control, self.target]
803 }
804
805 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
806 Ok(vec![
812 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, -1.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 1.0), Complex64::new(0.0, 0.0), ])
829 }
830
831 fn as_any(&self) -> &dyn Any {
832 self
833 }
834
835 impl_clone_gate!();
836 }
837
838 #[derive(Debug, Clone, Copy)]
840 pub struct CH {
841 pub control: QubitId,
843
844 pub target: QubitId,
846 }
847
848 impl GateOp for CH {
849 fn name(&self) -> &'static str {
850 "CH"
851 }
852
853 fn qubits(&self) -> Vec<QubitId> {
854 vec![self.control, self.target]
855 }
856
857 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
858 let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
864
865 Ok(vec![
866 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(sqrt2_inv, 0.0), Complex64::new(sqrt2_inv, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(sqrt2_inv, 0.0), Complex64::new(-sqrt2_inv, 0.0), ])
883 }
884
885 fn as_any(&self) -> &dyn Any {
886 self
887 }
888
889 impl_clone_gate!();
890 }
891
892 #[derive(Debug, Clone, Copy)]
894 pub struct CS {
895 pub control: QubitId,
897
898 pub target: QubitId,
900 }
901
902 impl GateOp for CS {
903 fn name(&self) -> &'static str {
904 "CS"
905 }
906
907 fn qubits(&self) -> Vec<QubitId> {
908 vec![self.control, self.target]
909 }
910
911 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
912 Ok(vec![
918 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 1.0), ])
935 }
936
937 fn as_any(&self) -> &dyn Any {
938 self
939 }
940
941 impl_clone_gate!();
942 }
943
944 #[derive(Debug, Clone, Copy)]
946 pub struct Toffoli {
947 pub control1: QubitId,
949
950 pub control2: QubitId,
952
953 pub target: QubitId,
955 }
956
957 impl GateOp for Toffoli {
958 fn name(&self) -> &'static str {
959 "Toffoli"
960 }
961
962 fn qubits(&self) -> Vec<QubitId> {
963 vec![self.control1, self.control2, self.target]
964 }
965
966 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
967 Err(crate::error::QuantRS2Error::UnsupportedOperation(
971 "Direct matrix representation of Toffoli gate not supported. \
972 Use gate decomposition."
973 .into(),
974 ))
975 }
976
977 fn as_any(&self) -> &dyn Any {
978 self
979 }
980
981 impl_clone_gate!();
982 }
983
984 #[derive(Debug, Clone, Copy)]
986 pub struct Fredkin {
987 pub control: QubitId,
989
990 pub target1: QubitId,
992
993 pub target2: QubitId,
995 }
996
997 impl GateOp for Fredkin {
998 fn name(&self) -> &'static str {
999 "Fredkin"
1000 }
1001
1002 fn qubits(&self) -> Vec<QubitId> {
1003 vec![self.control, self.target1, self.target2]
1004 }
1005
1006 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1007 Err(crate::error::QuantRS2Error::UnsupportedOperation(
1011 "Direct matrix representation of Fredkin gate not supported. \
1012 Use gate decomposition."
1013 .into(),
1014 ))
1015 }
1016
1017 fn as_any(&self) -> &dyn Any {
1018 self
1019 }
1020
1021 impl_clone_gate!();
1022 }
1023
1024 #[derive(Debug, Clone, Copy)]
1026 pub struct CRX {
1027 pub control: QubitId,
1029
1030 pub target: QubitId,
1032
1033 pub theta: f64,
1035 }
1036
1037 impl GateOp for CRX {
1038 fn name(&self) -> &'static str {
1039 "CRX"
1040 }
1041
1042 fn qubits(&self) -> Vec<QubitId> {
1043 vec![self.control, self.target]
1044 }
1045
1046 fn is_parameterized(&self) -> bool {
1047 true
1048 }
1049
1050 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1051 let cos = (self.theta / 2.0).cos();
1057 let sin = (self.theta / 2.0).sin();
1058
1059 Ok(vec![
1060 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(cos, 0.0), Complex64::new(0.0, -sin), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, -sin), Complex64::new(cos, 0.0), ])
1077 }
1078
1079 fn as_any(&self) -> &dyn Any {
1080 self
1081 }
1082
1083 impl_clone_gate!();
1084 }
1085
1086 #[derive(Debug, Clone, Copy)]
1088 pub struct CRY {
1089 pub control: QubitId,
1091
1092 pub target: QubitId,
1094
1095 pub theta: f64,
1097 }
1098
1099 impl GateOp for CRY {
1100 fn name(&self) -> &'static str {
1101 "CRY"
1102 }
1103
1104 fn qubits(&self) -> Vec<QubitId> {
1105 vec![self.control, self.target]
1106 }
1107
1108 fn is_parameterized(&self) -> bool {
1109 true
1110 }
1111
1112 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1113 let cos = (self.theta / 2.0).cos();
1119 let sin = (self.theta / 2.0).sin();
1120
1121 Ok(vec![
1122 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(cos, 0.0), Complex64::new(-sin, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(sin, 0.0), Complex64::new(cos, 0.0), ])
1139 }
1140
1141 fn as_any(&self) -> &dyn Any {
1142 self
1143 }
1144
1145 impl_clone_gate!();
1146 }
1147
1148 #[derive(Debug, Clone, Copy)]
1150 pub struct CRZ {
1151 pub control: QubitId,
1153
1154 pub target: QubitId,
1156
1157 pub theta: f64,
1159 }
1160
1161 impl GateOp for CRZ {
1162 fn name(&self) -> &'static str {
1163 "CRZ"
1164 }
1165
1166 fn qubits(&self) -> Vec<QubitId> {
1167 vec![self.control, self.target]
1168 }
1169
1170 fn is_parameterized(&self) -> bool {
1171 true
1172 }
1173
1174 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1175 let phase = Complex64::new(0.0, -self.theta / 2.0).exp();
1181 let phase_conj = Complex64::new(0.0, self.theta / 2.0).exp();
1182
1183 Ok(vec![
1184 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), phase_conj, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), phase, ])
1201 }
1202
1203 fn as_any(&self) -> &dyn Any {
1204 self
1205 }
1206
1207 impl_clone_gate!();
1208 }
1209
1210 #[derive(Debug, Clone, Copy)]
1217 pub struct ISwap {
1218 pub qubit1: QubitId,
1220 pub qubit2: QubitId,
1222 }
1223
1224 impl GateOp for ISwap {
1225 fn name(&self) -> &'static str {
1226 "iSWAP"
1227 }
1228
1229 fn qubits(&self) -> Vec<QubitId> {
1230 vec![self.qubit1, self.qubit2]
1231 }
1232
1233 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1234 Ok(vec![
1235 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 1.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 1.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), ])
1252 }
1253
1254 fn as_any(&self) -> &dyn Any {
1255 self
1256 }
1257
1258 impl_clone_gate!();
1259 }
1260
1261 #[derive(Debug, Clone, Copy)]
1268 pub struct ECR {
1269 pub control: QubitId,
1271 pub target: QubitId,
1273 }
1274
1275 impl GateOp for ECR {
1276 fn name(&self) -> &'static str {
1277 "ECR"
1278 }
1279
1280 fn qubits(&self) -> Vec<QubitId> {
1281 vec![self.control, self.target]
1282 }
1283
1284 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1285 let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
1286 Ok(vec![
1287 Complex64::new(0.0, 0.0), Complex64::new(sqrt2_inv, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, sqrt2_inv), Complex64::new(sqrt2_inv, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, -sqrt2_inv), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, sqrt2_inv), Complex64::new(0.0, 0.0), Complex64::new(sqrt2_inv, 0.0), Complex64::new(0.0, -sqrt2_inv), Complex64::new(0.0, 0.0), Complex64::new(sqrt2_inv, 0.0), Complex64::new(0.0, 0.0), ])
1304 }
1305
1306 fn as_any(&self) -> &dyn Any {
1307 self
1308 }
1309
1310 impl_clone_gate!();
1311 }
1312
1313 #[derive(Debug, Clone, Copy)]
1317 pub struct RXX {
1318 pub qubit1: QubitId,
1320 pub qubit2: QubitId,
1322 pub theta: f64,
1324 }
1325
1326 impl GateOp for RXX {
1327 fn name(&self) -> &'static str {
1328 "RXX"
1329 }
1330
1331 fn qubits(&self) -> Vec<QubitId> {
1332 vec![self.qubit1, self.qubit2]
1333 }
1334
1335 fn is_parameterized(&self) -> bool {
1336 true
1337 }
1338
1339 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1340 let cos = (self.theta / 2.0).cos();
1341 let sin = (self.theta / 2.0).sin();
1342 let mi_sin = Complex64::new(0.0, -sin);
1343
1344 Ok(vec![
1345 Complex64::new(cos, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), mi_sin, Complex64::new(0.0, 0.0), Complex64::new(cos, 0.0), mi_sin, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), mi_sin, Complex64::new(cos, 0.0), Complex64::new(0.0, 0.0), mi_sin, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(cos, 0.0), ])
1362 }
1363
1364 fn as_any(&self) -> &dyn Any {
1365 self
1366 }
1367
1368 impl_clone_gate!();
1369 }
1370
1371 #[derive(Debug, Clone, Copy)]
1375 pub struct RYY {
1376 pub qubit1: QubitId,
1378 pub qubit2: QubitId,
1380 pub theta: f64,
1382 }
1383
1384 impl GateOp for RYY {
1385 fn name(&self) -> &'static str {
1386 "RYY"
1387 }
1388
1389 fn qubits(&self) -> Vec<QubitId> {
1390 vec![self.qubit1, self.qubit2]
1391 }
1392
1393 fn is_parameterized(&self) -> bool {
1394 true
1395 }
1396
1397 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1398 let cos = (self.theta / 2.0).cos();
1399 let sin = (self.theta / 2.0).sin();
1400 let i_sin = Complex64::new(0.0, sin);
1401 let mi_sin = Complex64::new(0.0, -sin);
1402
1403 Ok(vec![
1404 Complex64::new(cos, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), i_sin, Complex64::new(0.0, 0.0), Complex64::new(cos, 0.0), mi_sin, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), mi_sin, Complex64::new(cos, 0.0), Complex64::new(0.0, 0.0), i_sin, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(cos, 0.0), ])
1421 }
1422
1423 fn as_any(&self) -> &dyn Any {
1424 self
1425 }
1426
1427 impl_clone_gate!();
1428 }
1429
1430 #[derive(Debug, Clone, Copy)]
1434 pub struct RZZ {
1435 pub qubit1: QubitId,
1437 pub qubit2: QubitId,
1439 pub theta: f64,
1441 }
1442
1443 impl GateOp for RZZ {
1444 fn name(&self) -> &'static str {
1445 "RZZ"
1446 }
1447
1448 fn qubits(&self) -> Vec<QubitId> {
1449 vec![self.qubit1, self.qubit2]
1450 }
1451
1452 fn is_parameterized(&self) -> bool {
1453 true
1454 }
1455
1456 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1457 let phase_neg = Complex64::new(0.0, -self.theta / 2.0).exp();
1458 let phase_pos = Complex64::new(0.0, self.theta / 2.0).exp();
1459
1460 Ok(vec![
1461 phase_neg, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), phase_pos, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), phase_pos, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), phase_neg, ])
1478 }
1479
1480 fn as_any(&self) -> &dyn Any {
1481 self
1482 }
1483
1484 impl_clone_gate!();
1485 }
1486
1487 #[derive(Debug, Clone, Copy)]
1491 pub struct RZX {
1492 pub control: QubitId,
1494 pub target: QubitId,
1496 pub theta: f64,
1498 }
1499
1500 impl GateOp for RZX {
1501 fn name(&self) -> &'static str {
1502 "RZX"
1503 }
1504
1505 fn qubits(&self) -> Vec<QubitId> {
1506 vec![self.control, self.target]
1507 }
1508
1509 fn is_parameterized(&self) -> bool {
1510 true
1511 }
1512
1513 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1514 let cos = (self.theta / 2.0).cos();
1515 let sin = (self.theta / 2.0).sin();
1516 let mi_sin = Complex64::new(0.0, -sin);
1517 let i_sin = Complex64::new(0.0, sin);
1518
1519 Ok(vec![
1520 Complex64::new(cos, 0.0), mi_sin, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), mi_sin, Complex64::new(cos, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(cos, 0.0), i_sin, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), i_sin, Complex64::new(cos, 0.0), ])
1537 }
1538
1539 fn as_any(&self) -> &dyn Any {
1540 self
1541 }
1542
1543 impl_clone_gate!();
1544 }
1545
1546 #[derive(Debug, Clone, Copy)]
1550 pub struct DCX {
1551 pub qubit1: QubitId,
1553 pub qubit2: QubitId,
1555 }
1556
1557 impl GateOp for DCX {
1558 fn name(&self) -> &'static str {
1559 "DCX"
1560 }
1561
1562 fn qubits(&self) -> Vec<QubitId> {
1563 vec![self.qubit1, self.qubit2]
1564 }
1565
1566 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1567 Ok(vec![
1572 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), ])
1589 }
1590
1591 fn as_any(&self) -> &dyn Any {
1592 self
1593 }
1594
1595 impl_clone_gate!();
1596 }
1597
1598 #[derive(Debug, Clone, Copy)]
1602 pub struct XXPlusYY {
1603 pub qubit1: QubitId,
1605 pub qubit2: QubitId,
1607 pub theta: f64,
1609 pub beta: f64,
1611 }
1612
1613 impl GateOp for XXPlusYY {
1614 fn name(&self) -> &'static str {
1615 "XXPlusYY"
1616 }
1617
1618 fn qubits(&self) -> Vec<QubitId> {
1619 vec![self.qubit1, self.qubit2]
1620 }
1621
1622 fn is_parameterized(&self) -> bool {
1623 true
1624 }
1625
1626 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1627 let cos = (self.theta / 2.0).cos();
1628 let sin = (self.theta / 2.0).sin();
1629 let exp_neg_i_beta = Complex64::new(0.0, -self.beta).exp();
1630 let exp_i_beta = Complex64::new(0.0, self.beta).exp();
1631 let mi_sin_neg = Complex64::new(0.0, -sin) * exp_neg_i_beta;
1632 let mi_sin_pos = Complex64::new(0.0, -sin) * exp_i_beta;
1633
1634 Ok(vec![
1635 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(cos, 0.0), mi_sin_neg, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), mi_sin_pos, Complex64::new(cos, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), ])
1652 }
1653
1654 fn as_any(&self) -> &dyn Any {
1655 self
1656 }
1657
1658 impl_clone_gate!();
1659 }
1660
1661 #[derive(Debug, Clone, Copy)]
1665 pub struct XXMinusYY {
1666 pub qubit1: QubitId,
1668 pub qubit2: QubitId,
1670 pub theta: f64,
1672 pub beta: f64,
1674 }
1675
1676 impl GateOp for XXMinusYY {
1677 fn name(&self) -> &'static str {
1678 "XXMinusYY"
1679 }
1680
1681 fn qubits(&self) -> Vec<QubitId> {
1682 vec![self.qubit1, self.qubit2]
1683 }
1684
1685 fn is_parameterized(&self) -> bool {
1686 true
1687 }
1688
1689 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1690 let cos = (self.theta / 2.0).cos();
1691 let sin = (self.theta / 2.0).sin();
1692 let exp_neg_i_beta = Complex64::new(0.0, -self.beta).exp();
1693 let exp_i_beta = Complex64::new(0.0, self.beta).exp();
1694 let mi_sin_neg = Complex64::new(0.0, -sin) * exp_neg_i_beta;
1695 let mi_sin_pos = Complex64::new(0.0, -sin) * exp_i_beta;
1696
1697 Ok(vec![
1698 Complex64::new(cos, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), mi_sin_pos, Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), mi_sin_neg, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(cos, 0.0), ])
1715 }
1716
1717 fn as_any(&self) -> &dyn Any {
1718 self
1719 }
1720
1721 impl_clone_gate!();
1722 }
1723
1724 #[derive(Debug, Clone, Copy)]
1726 pub struct CSX {
1727 pub control: QubitId,
1729 pub target: QubitId,
1731 }
1732
1733 impl GateOp for CSX {
1734 fn name(&self) -> &'static str {
1735 "CSX"
1736 }
1737
1738 fn qubits(&self) -> Vec<QubitId> {
1739 vec![self.control, self.target]
1740 }
1741
1742 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1743 let half_plus_i_half = Complex64::new(0.5, 0.5);
1744 let half_minus_i_half = Complex64::new(0.5, -0.5);
1745
1746 Ok(vec![
1747 Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(1.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), half_plus_i_half, half_minus_i_half, Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0), half_minus_i_half, half_plus_i_half, ])
1764 }
1765
1766 fn as_any(&self) -> &dyn Any {
1767 self
1768 }
1769
1770 impl_clone_gate!();
1771 }
1772}
1773
1774pub mod global {
1776 use super::*;
1777 use std::any::Any;
1778
1779 #[derive(Debug, Clone, Copy)]
1783 pub struct GlobalPhase {
1784 pub phase: f64,
1786 }
1787
1788 impl GateOp for GlobalPhase {
1789 fn name(&self) -> &'static str {
1790 "GlobalPhase"
1791 }
1792
1793 fn qubits(&self) -> Vec<QubitId> {
1794 vec![] }
1796
1797 fn is_parameterized(&self) -> bool {
1798 true
1799 }
1800
1801 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1802 let phase = Complex64::new(0.0, self.phase).exp();
1803 Ok(vec![phase])
1804 }
1805
1806 fn as_any(&self) -> &dyn Any {
1807 self
1808 }
1809
1810 impl_clone_gate!();
1811 }
1812
1813 #[derive(Debug, Clone, Copy)]
1817 pub struct RGate {
1818 pub target: QubitId,
1820 pub theta: f64,
1822 pub phi: f64,
1824 }
1825
1826 impl GateOp for RGate {
1827 fn name(&self) -> &'static str {
1828 "R"
1829 }
1830
1831 fn qubits(&self) -> Vec<QubitId> {
1832 vec![self.target]
1833 }
1834
1835 fn is_parameterized(&self) -> bool {
1836 true
1837 }
1838
1839 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1840 let cos = (self.theta / 2.0).cos();
1841 let sin = (self.theta / 2.0).sin();
1842 let exp_neg_i_phi = Complex64::new(0.0, -self.phi).exp();
1843 let exp_i_phi = Complex64::new(0.0, self.phi).exp();
1844
1845 Ok(vec![
1846 Complex64::new(cos, 0.0),
1847 Complex64::new(0.0, -sin) * exp_neg_i_phi,
1848 Complex64::new(0.0, -sin) * exp_i_phi,
1849 Complex64::new(cos, 0.0),
1850 ])
1851 }
1852
1853 fn as_any(&self) -> &dyn Any {
1854 self
1855 }
1856
1857 impl_clone_gate!();
1858 }
1859}