1use crate::error::QuantRS2Result;
6use crate::qubit::QubitId;
7use scirs2_core::Complex64;
8use std::any::Any;
9use std::f64::consts::PI;
10use std::fmt::Debug;
11
12macro_rules! impl_clone_gate {
14 () => {
15 fn clone_gate(&self) -> Box<dyn GateOp> {
16 Box::new(self.clone())
17 }
18 };
19}
20pub trait GateOp: Debug + Send + Sync {
22 fn name(&self) -> &'static str;
24 fn qubits(&self) -> Vec<QubitId>;
26 fn num_qubits(&self) -> usize {
28 self.qubits().len()
29 }
30 fn is_parameterized(&self) -> bool {
32 false
33 }
34 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>>;
36 fn as_any(&self) -> &dyn Any;
38 fn clone_gate(&self) -> Box<dyn GateOp>;
40}
41impl Clone for Box<dyn GateOp> {
43 fn clone(&self) -> Self {
44 self.clone_gate()
45 }
46}
47pub mod single {
49 use super::*;
50 use super::*;
51 #[derive(Debug, Clone, Copy)]
53 pub struct Hadamard {
54 pub target: QubitId,
56 }
57 impl GateOp for Hadamard {
58 fn name(&self) -> &'static str {
59 "H"
60 }
61 fn qubits(&self) -> Vec<QubitId> {
62 vec![self.target]
63 }
64 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
65 let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
66 Ok(vec![
67 Complex64::new(sqrt2_inv, 0.0),
68 Complex64::new(sqrt2_inv, 0.0),
69 Complex64::new(sqrt2_inv, 0.0),
70 Complex64::new(-sqrt2_inv, 0.0),
71 ])
72 }
73 fn as_any(&self) -> &dyn Any {
74 self
75 }
76 impl_clone_gate!();
77 }
78 #[derive(Debug, Clone, Copy)]
80 pub struct PauliX {
81 pub target: QubitId,
83 }
84 impl GateOp for PauliX {
85 fn name(&self) -> &'static str {
86 "X"
87 }
88 fn qubits(&self) -> Vec<QubitId> {
89 vec![self.target]
90 }
91 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
92 Ok(vec![
93 Complex64::new(0.0, 0.0),
94 Complex64::new(1.0, 0.0),
95 Complex64::new(1.0, 0.0),
96 Complex64::new(0.0, 0.0),
97 ])
98 }
99 fn as_any(&self) -> &dyn Any {
100 self
101 }
102 impl_clone_gate!();
103 }
104 #[derive(Debug, Clone, Copy)]
106 pub struct PauliY {
107 pub target: QubitId,
109 }
110 impl GateOp for PauliY {
111 fn name(&self) -> &'static str {
112 "Y"
113 }
114 fn qubits(&self) -> Vec<QubitId> {
115 vec![self.target]
116 }
117 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
118 Ok(vec![
119 Complex64::new(0.0, 0.0),
120 Complex64::new(0.0, -1.0),
121 Complex64::new(0.0, 1.0),
122 Complex64::new(0.0, 0.0),
123 ])
124 }
125 fn as_any(&self) -> &dyn Any {
126 self
127 }
128 impl_clone_gate!();
129 }
130 #[derive(Debug, Clone, Copy)]
132 pub struct PauliZ {
133 pub target: QubitId,
135 }
136 impl GateOp for PauliZ {
137 fn name(&self) -> &'static str {
138 "Z"
139 }
140 fn qubits(&self) -> Vec<QubitId> {
141 vec![self.target]
142 }
143 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
144 Ok(vec![
145 Complex64::new(1.0, 0.0),
146 Complex64::new(0.0, 0.0),
147 Complex64::new(0.0, 0.0),
148 Complex64::new(-1.0, 0.0),
149 ])
150 }
151 fn as_any(&self) -> &dyn Any {
152 self
153 }
154 impl_clone_gate!();
155 }
156 #[derive(Debug, Clone, Copy)]
158 pub struct RotationX {
159 pub target: QubitId,
161 pub theta: f64,
163 }
164 impl GateOp for RotationX {
165 fn name(&self) -> &'static str {
166 "RX"
167 }
168 fn qubits(&self) -> Vec<QubitId> {
169 vec![self.target]
170 }
171 fn is_parameterized(&self) -> bool {
172 true
173 }
174 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
175 let cos = (self.theta / 2.0).cos();
176 let sin = (self.theta / 2.0).sin();
177 Ok(vec![
178 Complex64::new(cos, 0.0),
179 Complex64::new(0.0, -sin),
180 Complex64::new(0.0, -sin),
181 Complex64::new(cos, 0.0),
182 ])
183 }
184 fn as_any(&self) -> &dyn Any {
185 self
186 }
187 impl_clone_gate!();
188 }
189 #[derive(Debug, Clone, Copy)]
191 pub struct RotationY {
192 pub target: QubitId,
194 pub theta: f64,
196 }
197 impl GateOp for RotationY {
198 fn name(&self) -> &'static str {
199 "RY"
200 }
201 fn qubits(&self) -> Vec<QubitId> {
202 vec![self.target]
203 }
204 fn is_parameterized(&self) -> bool {
205 true
206 }
207 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
208 let cos = (self.theta / 2.0).cos();
209 let sin = (self.theta / 2.0).sin();
210 Ok(vec![
211 Complex64::new(cos, 0.0),
212 Complex64::new(-sin, 0.0),
213 Complex64::new(sin, 0.0),
214 Complex64::new(cos, 0.0),
215 ])
216 }
217 fn as_any(&self) -> &dyn Any {
218 self
219 }
220 impl_clone_gate!();
221 }
222 #[derive(Debug, Clone, Copy)]
224 pub struct RotationZ {
225 pub target: QubitId,
227 pub theta: f64,
229 }
230 impl GateOp for RotationZ {
231 fn name(&self) -> &'static str {
232 "RZ"
233 }
234 fn qubits(&self) -> Vec<QubitId> {
235 vec![self.target]
236 }
237 fn is_parameterized(&self) -> bool {
238 true
239 }
240 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
241 let phase = Complex64::new(0.0, -self.theta / 2.0).exp();
242 let phase_conj = Complex64::new(0.0, self.theta / 2.0).exp();
243 Ok(vec![
244 phase_conj,
245 Complex64::new(0.0, 0.0),
246 Complex64::new(0.0, 0.0),
247 phase,
248 ])
249 }
250 fn as_any(&self) -> &dyn Any {
251 self
252 }
253 impl_clone_gate!();
254 }
255 #[derive(Debug, Clone, Copy)]
257 pub struct Phase {
258 pub target: QubitId,
260 }
261 impl GateOp for Phase {
262 fn name(&self) -> &'static str {
263 "S"
264 }
265 fn qubits(&self) -> Vec<QubitId> {
266 vec![self.target]
267 }
268 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
269 Ok(vec![
270 Complex64::new(1.0, 0.0),
271 Complex64::new(0.0, 0.0),
272 Complex64::new(0.0, 0.0),
273 Complex64::new(0.0, 1.0),
274 ])
275 }
276 fn as_any(&self) -> &dyn Any {
277 self
278 }
279 impl_clone_gate!();
280 }
281 #[derive(Debug, Clone, Copy)]
283 pub struct T {
284 pub target: QubitId,
286 }
287 impl GateOp for T {
288 fn name(&self) -> &'static str {
289 "T"
290 }
291 fn qubits(&self) -> Vec<QubitId> {
292 vec![self.target]
293 }
294 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
295 let phase = Complex64::new((PI / 4.0).cos(), (PI / 4.0).sin());
296 Ok(vec![
297 Complex64::new(1.0, 0.0),
298 Complex64::new(0.0, 0.0),
299 Complex64::new(0.0, 0.0),
300 phase,
301 ])
302 }
303 fn as_any(&self) -> &dyn Any {
304 self
305 }
306 impl_clone_gate!();
307 }
308 #[derive(Debug, Clone, Copy)]
310 pub struct TDagger {
311 pub target: QubitId,
313 }
314 impl GateOp for TDagger {
315 fn name(&self) -> &'static str {
316 "T†"
317 }
318 fn qubits(&self) -> Vec<QubitId> {
319 vec![self.target]
320 }
321 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
322 let phase = Complex64::new((PI / 4.0).cos(), -(PI / 4.0).sin());
323 Ok(vec![
324 Complex64::new(1.0, 0.0),
325 Complex64::new(0.0, 0.0),
326 Complex64::new(0.0, 0.0),
327 phase,
328 ])
329 }
330 fn as_any(&self) -> &dyn Any {
331 self
332 }
333 impl_clone_gate!();
334 }
335 #[derive(Debug, Clone, Copy)]
337 pub struct PhaseDagger {
338 pub target: QubitId,
340 }
341 impl GateOp for PhaseDagger {
342 fn name(&self) -> &'static str {
343 "S†"
344 }
345 fn qubits(&self) -> Vec<QubitId> {
346 vec![self.target]
347 }
348 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
349 Ok(vec![
350 Complex64::new(1.0, 0.0),
351 Complex64::new(0.0, 0.0),
352 Complex64::new(0.0, 0.0),
353 Complex64::new(0.0, -1.0),
354 ])
355 }
356 fn as_any(&self) -> &dyn Any {
357 self
358 }
359 impl_clone_gate!();
360 }
361 #[derive(Debug, Clone, Copy)]
363 pub struct SqrtX {
364 pub target: QubitId,
366 }
367 impl GateOp for SqrtX {
368 fn name(&self) -> &'static str {
369 "√X"
370 }
371 fn qubits(&self) -> Vec<QubitId> {
372 vec![self.target]
373 }
374 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
375 let half_plus_i_half = Complex64::new(0.5, 0.5);
376 let half_minus_i_half = Complex64::new(0.5, -0.5);
377 Ok(vec![
378 half_plus_i_half,
379 half_minus_i_half,
380 half_minus_i_half,
381 half_plus_i_half,
382 ])
383 }
384 fn as_any(&self) -> &dyn Any {
385 self
386 }
387 impl_clone_gate!();
388 }
389 #[derive(Debug, Clone, Copy)]
391 pub struct SqrtXDagger {
392 pub target: QubitId,
394 }
395 impl GateOp for SqrtXDagger {
396 fn name(&self) -> &'static str {
397 "√X†"
398 }
399 fn qubits(&self) -> Vec<QubitId> {
400 vec![self.target]
401 }
402 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
403 let half_minus_i_half = Complex64::new(0.5, -0.5);
404 let half_plus_i_half = Complex64::new(0.5, 0.5);
405 Ok(vec![
406 half_minus_i_half,
407 half_plus_i_half,
408 half_plus_i_half,
409 half_minus_i_half,
410 ])
411 }
412 fn as_any(&self) -> &dyn Any {
413 self
414 }
415 impl_clone_gate!();
416 }
417 #[derive(Debug, Clone, Copy)]
422 pub struct UGate {
423 pub target: QubitId,
425 pub theta: f64,
427 pub phi: f64,
429 pub lambda: f64,
431 }
432 impl GateOp for UGate {
433 fn name(&self) -> &'static str {
434 "U"
435 }
436 fn qubits(&self) -> Vec<QubitId> {
437 vec![self.target]
438 }
439 fn is_parameterized(&self) -> bool {
440 true
441 }
442 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
443 let cos = (self.theta / 2.0).cos();
444 let sin = (self.theta / 2.0).sin();
445 let exp_i_lambda = Complex64::new(0.0, self.lambda).exp();
446 let exp_i_phi = Complex64::new(0.0, self.phi).exp();
447 let exp_i_phi_lambda = Complex64::new(0.0, self.phi + self.lambda).exp();
448 Ok(vec![
449 Complex64::new(cos, 0.0),
450 -exp_i_lambda * sin,
451 exp_i_phi * sin,
452 exp_i_phi_lambda * cos,
453 ])
454 }
455 fn as_any(&self) -> &dyn Any {
456 self
457 }
458 impl_clone_gate!();
459 }
460 #[derive(Debug, Clone, Copy)]
464 pub struct PGate {
465 pub target: QubitId,
467 pub lambda: f64,
469 }
470 impl GateOp for PGate {
471 fn name(&self) -> &'static str {
472 "P"
473 }
474 fn qubits(&self) -> Vec<QubitId> {
475 vec![self.target]
476 }
477 fn is_parameterized(&self) -> bool {
478 true
479 }
480 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
481 let exp_i_lambda = Complex64::new(0.0, self.lambda).exp();
482 Ok(vec![
483 Complex64::new(1.0, 0.0),
484 Complex64::new(0.0, 0.0),
485 Complex64::new(0.0, 0.0),
486 exp_i_lambda,
487 ])
488 }
489 fn as_any(&self) -> &dyn Any {
490 self
491 }
492 impl_clone_gate!();
493 }
494 #[derive(Debug, Clone, Copy)]
496 pub struct Identity {
497 pub target: QubitId,
499 }
500 impl GateOp for Identity {
501 fn name(&self) -> &'static str {
502 "I"
503 }
504 fn qubits(&self) -> Vec<QubitId> {
505 vec![self.target]
506 }
507 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
508 Ok(vec![
509 Complex64::new(1.0, 0.0),
510 Complex64::new(0.0, 0.0),
511 Complex64::new(0.0, 0.0),
512 Complex64::new(1.0, 0.0),
513 ])
514 }
515 fn as_any(&self) -> &dyn Any {
516 self
517 }
518 impl_clone_gate!();
519 }
520}
521pub mod multi {
523 use super::*;
524 #[derive(Debug, Clone, Copy)]
526 pub struct CNOT {
527 pub control: QubitId,
529 pub target: QubitId,
531 }
532 impl GateOp for CNOT {
533 fn name(&self) -> &'static str {
534 "CNOT"
535 }
536 fn qubits(&self) -> Vec<QubitId> {
537 vec![self.control, self.target]
538 }
539 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
540 Ok(vec![
541 Complex64::new(1.0, 0.0),
542 Complex64::new(0.0, 0.0),
543 Complex64::new(0.0, 0.0),
544 Complex64::new(0.0, 0.0),
545 Complex64::new(0.0, 0.0),
546 Complex64::new(1.0, 0.0),
547 Complex64::new(0.0, 0.0),
548 Complex64::new(0.0, 0.0),
549 Complex64::new(0.0, 0.0),
550 Complex64::new(0.0, 0.0),
551 Complex64::new(0.0, 0.0),
552 Complex64::new(1.0, 0.0),
553 Complex64::new(0.0, 0.0),
554 Complex64::new(0.0, 0.0),
555 Complex64::new(1.0, 0.0),
556 Complex64::new(0.0, 0.0),
557 ])
558 }
559 fn as_any(&self) -> &dyn Any {
560 self
561 }
562 impl_clone_gate!();
563 }
564 #[derive(Debug, Clone, Copy)]
566 pub struct CZ {
567 pub control: QubitId,
569 pub target: QubitId,
571 }
572 impl GateOp for CZ {
573 fn name(&self) -> &'static str {
574 "CZ"
575 }
576 fn qubits(&self) -> Vec<QubitId> {
577 vec![self.control, self.target]
578 }
579 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
580 Ok(vec![
581 Complex64::new(1.0, 0.0),
582 Complex64::new(0.0, 0.0),
583 Complex64::new(0.0, 0.0),
584 Complex64::new(0.0, 0.0),
585 Complex64::new(0.0, 0.0),
586 Complex64::new(1.0, 0.0),
587 Complex64::new(0.0, 0.0),
588 Complex64::new(0.0, 0.0),
589 Complex64::new(0.0, 0.0),
590 Complex64::new(0.0, 0.0),
591 Complex64::new(1.0, 0.0),
592 Complex64::new(0.0, 0.0),
593 Complex64::new(0.0, 0.0),
594 Complex64::new(0.0, 0.0),
595 Complex64::new(0.0, 0.0),
596 Complex64::new(-1.0, 0.0),
597 ])
598 }
599 fn as_any(&self) -> &dyn Any {
600 self
601 }
602 impl_clone_gate!();
603 }
604 #[derive(Debug, Clone, Copy)]
606 pub struct SWAP {
607 pub qubit1: QubitId,
609 pub qubit2: QubitId,
611 }
612 impl GateOp for SWAP {
613 fn name(&self) -> &'static str {
614 "SWAP"
615 }
616 fn qubits(&self) -> Vec<QubitId> {
617 vec![self.qubit1, self.qubit2]
618 }
619 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
620 Ok(vec![
621 Complex64::new(1.0, 0.0),
622 Complex64::new(0.0, 0.0),
623 Complex64::new(0.0, 0.0),
624 Complex64::new(0.0, 0.0),
625 Complex64::new(0.0, 0.0),
626 Complex64::new(0.0, 0.0),
627 Complex64::new(1.0, 0.0),
628 Complex64::new(0.0, 0.0),
629 Complex64::new(0.0, 0.0),
630 Complex64::new(1.0, 0.0),
631 Complex64::new(0.0, 0.0),
632 Complex64::new(0.0, 0.0),
633 Complex64::new(0.0, 0.0),
634 Complex64::new(0.0, 0.0),
635 Complex64::new(0.0, 0.0),
636 Complex64::new(1.0, 0.0),
637 ])
638 }
639 fn as_any(&self) -> &dyn Any {
640 self
641 }
642 impl_clone_gate!();
643 }
644 #[derive(Debug, Clone, Copy)]
646 pub struct CY {
647 pub control: QubitId,
649 pub target: QubitId,
651 }
652 impl GateOp for CY {
653 fn name(&self) -> &'static str {
654 "CY"
655 }
656 fn qubits(&self) -> Vec<QubitId> {
657 vec![self.control, self.target]
658 }
659 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
660 Ok(vec![
661 Complex64::new(1.0, 0.0),
662 Complex64::new(0.0, 0.0),
663 Complex64::new(0.0, 0.0),
664 Complex64::new(0.0, 0.0),
665 Complex64::new(0.0, 0.0),
666 Complex64::new(1.0, 0.0),
667 Complex64::new(0.0, 0.0),
668 Complex64::new(0.0, 0.0),
669 Complex64::new(0.0, 0.0),
670 Complex64::new(0.0, 0.0),
671 Complex64::new(0.0, 0.0),
672 Complex64::new(0.0, -1.0),
673 Complex64::new(0.0, 0.0),
674 Complex64::new(0.0, 0.0),
675 Complex64::new(0.0, 1.0),
676 Complex64::new(0.0, 0.0),
677 ])
678 }
679 fn as_any(&self) -> &dyn Any {
680 self
681 }
682 impl_clone_gate!();
683 }
684 #[derive(Debug, Clone, Copy)]
686 pub struct CH {
687 pub control: QubitId,
689 pub target: QubitId,
691 }
692 impl GateOp for CH {
693 fn name(&self) -> &'static str {
694 "CH"
695 }
696 fn qubits(&self) -> Vec<QubitId> {
697 vec![self.control, self.target]
698 }
699 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
700 let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
701 Ok(vec![
702 Complex64::new(1.0, 0.0),
703 Complex64::new(0.0, 0.0),
704 Complex64::new(0.0, 0.0),
705 Complex64::new(0.0, 0.0),
706 Complex64::new(0.0, 0.0),
707 Complex64::new(1.0, 0.0),
708 Complex64::new(0.0, 0.0),
709 Complex64::new(0.0, 0.0),
710 Complex64::new(0.0, 0.0),
711 Complex64::new(0.0, 0.0),
712 Complex64::new(sqrt2_inv, 0.0),
713 Complex64::new(sqrt2_inv, 0.0),
714 Complex64::new(0.0, 0.0),
715 Complex64::new(0.0, 0.0),
716 Complex64::new(sqrt2_inv, 0.0),
717 Complex64::new(-sqrt2_inv, 0.0),
718 ])
719 }
720 fn as_any(&self) -> &dyn Any {
721 self
722 }
723 impl_clone_gate!();
724 }
725 #[derive(Debug, Clone, Copy)]
727 pub struct CS {
728 pub control: QubitId,
730 pub target: QubitId,
732 }
733 impl GateOp for CS {
734 fn name(&self) -> &'static str {
735 "CS"
736 }
737 fn qubits(&self) -> Vec<QubitId> {
738 vec![self.control, self.target]
739 }
740 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
741 Ok(vec![
742 Complex64::new(1.0, 0.0),
743 Complex64::new(0.0, 0.0),
744 Complex64::new(0.0, 0.0),
745 Complex64::new(0.0, 0.0),
746 Complex64::new(0.0, 0.0),
747 Complex64::new(1.0, 0.0),
748 Complex64::new(0.0, 0.0),
749 Complex64::new(0.0, 0.0),
750 Complex64::new(0.0, 0.0),
751 Complex64::new(0.0, 0.0),
752 Complex64::new(1.0, 0.0),
753 Complex64::new(0.0, 0.0),
754 Complex64::new(0.0, 0.0),
755 Complex64::new(0.0, 0.0),
756 Complex64::new(0.0, 0.0),
757 Complex64::new(0.0, 1.0),
758 ])
759 }
760 fn as_any(&self) -> &dyn Any {
761 self
762 }
763 impl_clone_gate!();
764 }
765 #[derive(Debug, Clone, Copy)]
767 pub struct Toffoli {
768 pub control1: QubitId,
770 pub control2: QubitId,
772 pub target: QubitId,
774 }
775 impl GateOp for Toffoli {
776 fn name(&self) -> &'static str {
777 "Toffoli"
778 }
779 fn qubits(&self) -> Vec<QubitId> {
780 vec![self.control1, self.control2, self.target]
781 }
782 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
783 Err(crate::error::QuantRS2Error::UnsupportedOperation(
784 "Direct matrix representation of Toffoli gate not supported. \
785 Use gate decomposition."
786 .into(),
787 ))
788 }
789 fn as_any(&self) -> &dyn Any {
790 self
791 }
792 impl_clone_gate!();
793 }
794 #[derive(Debug, Clone, Copy)]
796 pub struct Fredkin {
797 pub control: QubitId,
799 pub target1: QubitId,
801 pub target2: QubitId,
803 }
804 impl GateOp for Fredkin {
805 fn name(&self) -> &'static str {
806 "Fredkin"
807 }
808 fn qubits(&self) -> Vec<QubitId> {
809 vec![self.control, self.target1, self.target2]
810 }
811 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
812 Err(crate::error::QuantRS2Error::UnsupportedOperation(
813 "Direct matrix representation of Fredkin gate not supported. \
814 Use gate decomposition."
815 .into(),
816 ))
817 }
818 fn as_any(&self) -> &dyn Any {
819 self
820 }
821 impl_clone_gate!();
822 }
823 #[derive(Debug, Clone, Copy)]
825 pub struct CRX {
826 pub control: QubitId,
828 pub target: QubitId,
830 pub theta: f64,
832 }
833 impl GateOp for CRX {
834 fn name(&self) -> &'static str {
835 "CRX"
836 }
837 fn qubits(&self) -> Vec<QubitId> {
838 vec![self.control, self.target]
839 }
840 fn is_parameterized(&self) -> bool {
841 true
842 }
843 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
844 let cos = (self.theta / 2.0).cos();
845 let sin = (self.theta / 2.0).sin();
846 Ok(vec![
847 Complex64::new(1.0, 0.0),
848 Complex64::new(0.0, 0.0),
849 Complex64::new(0.0, 0.0),
850 Complex64::new(0.0, 0.0),
851 Complex64::new(0.0, 0.0),
852 Complex64::new(1.0, 0.0),
853 Complex64::new(0.0, 0.0),
854 Complex64::new(0.0, 0.0),
855 Complex64::new(0.0, 0.0),
856 Complex64::new(0.0, 0.0),
857 Complex64::new(cos, 0.0),
858 Complex64::new(0.0, -sin),
859 Complex64::new(0.0, 0.0),
860 Complex64::new(0.0, 0.0),
861 Complex64::new(0.0, -sin),
862 Complex64::new(cos, 0.0),
863 ])
864 }
865 fn as_any(&self) -> &dyn Any {
866 self
867 }
868 impl_clone_gate!();
869 }
870 #[derive(Debug, Clone, Copy)]
872 pub struct CRY {
873 pub control: QubitId,
875 pub target: QubitId,
877 pub theta: f64,
879 }
880 impl GateOp for CRY {
881 fn name(&self) -> &'static str {
882 "CRY"
883 }
884 fn qubits(&self) -> Vec<QubitId> {
885 vec![self.control, self.target]
886 }
887 fn is_parameterized(&self) -> bool {
888 true
889 }
890 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
891 let cos = (self.theta / 2.0).cos();
892 let sin = (self.theta / 2.0).sin();
893 Ok(vec![
894 Complex64::new(1.0, 0.0),
895 Complex64::new(0.0, 0.0),
896 Complex64::new(0.0, 0.0),
897 Complex64::new(0.0, 0.0),
898 Complex64::new(0.0, 0.0),
899 Complex64::new(1.0, 0.0),
900 Complex64::new(0.0, 0.0),
901 Complex64::new(0.0, 0.0),
902 Complex64::new(0.0, 0.0),
903 Complex64::new(0.0, 0.0),
904 Complex64::new(cos, 0.0),
905 Complex64::new(-sin, 0.0),
906 Complex64::new(0.0, 0.0),
907 Complex64::new(0.0, 0.0),
908 Complex64::new(sin, 0.0),
909 Complex64::new(cos, 0.0),
910 ])
911 }
912 fn as_any(&self) -> &dyn Any {
913 self
914 }
915 impl_clone_gate!();
916 }
917 #[derive(Debug, Clone, Copy)]
919 pub struct CRZ {
920 pub control: QubitId,
922 pub target: QubitId,
924 pub theta: f64,
926 }
927 impl GateOp for CRZ {
928 fn name(&self) -> &'static str {
929 "CRZ"
930 }
931 fn qubits(&self) -> Vec<QubitId> {
932 vec![self.control, self.target]
933 }
934 fn is_parameterized(&self) -> bool {
935 true
936 }
937 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
938 let phase = Complex64::new(0.0, -self.theta / 2.0).exp();
939 let phase_conj = Complex64::new(0.0, self.theta / 2.0).exp();
940 Ok(vec![
941 Complex64::new(1.0, 0.0),
942 Complex64::new(0.0, 0.0),
943 Complex64::new(0.0, 0.0),
944 Complex64::new(0.0, 0.0),
945 Complex64::new(0.0, 0.0),
946 Complex64::new(1.0, 0.0),
947 Complex64::new(0.0, 0.0),
948 Complex64::new(0.0, 0.0),
949 Complex64::new(0.0, 0.0),
950 Complex64::new(0.0, 0.0),
951 phase_conj,
952 Complex64::new(0.0, 0.0),
953 Complex64::new(0.0, 0.0),
954 Complex64::new(0.0, 0.0),
955 Complex64::new(0.0, 0.0),
956 phase,
957 ])
958 }
959 fn as_any(&self) -> &dyn Any {
960 self
961 }
962 impl_clone_gate!();
963 }
964 #[derive(Debug, Clone, Copy)]
971 pub struct ISwap {
972 pub qubit1: QubitId,
974 pub qubit2: QubitId,
976 }
977 impl GateOp for ISwap {
978 fn name(&self) -> &'static str {
979 "iSWAP"
980 }
981 fn qubits(&self) -> Vec<QubitId> {
982 vec![self.qubit1, self.qubit2]
983 }
984 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
985 Ok(vec![
986 Complex64::new(1.0, 0.0),
987 Complex64::new(0.0, 0.0),
988 Complex64::new(0.0, 0.0),
989 Complex64::new(0.0, 0.0),
990 Complex64::new(0.0, 0.0),
991 Complex64::new(0.0, 0.0),
992 Complex64::new(0.0, 1.0),
993 Complex64::new(0.0, 0.0),
994 Complex64::new(0.0, 0.0),
995 Complex64::new(0.0, 1.0),
996 Complex64::new(0.0, 0.0),
997 Complex64::new(0.0, 0.0),
998 Complex64::new(0.0, 0.0),
999 Complex64::new(0.0, 0.0),
1000 Complex64::new(0.0, 0.0),
1001 Complex64::new(1.0, 0.0),
1002 ])
1003 }
1004 fn as_any(&self) -> &dyn Any {
1005 self
1006 }
1007 impl_clone_gate!();
1008 }
1009 #[derive(Debug, Clone, Copy)]
1016 pub struct ECR {
1017 pub control: QubitId,
1019 pub target: QubitId,
1021 }
1022 impl GateOp for ECR {
1023 fn name(&self) -> &'static str {
1024 "ECR"
1025 }
1026 fn qubits(&self) -> Vec<QubitId> {
1027 vec![self.control, self.target]
1028 }
1029 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1030 let sqrt2_inv = 1.0 / 2.0_f64.sqrt();
1031 Ok(vec![
1032 Complex64::new(0.0, 0.0),
1033 Complex64::new(sqrt2_inv, 0.0),
1034 Complex64::new(0.0, 0.0),
1035 Complex64::new(0.0, sqrt2_inv),
1036 Complex64::new(sqrt2_inv, 0.0),
1037 Complex64::new(0.0, 0.0),
1038 Complex64::new(0.0, -sqrt2_inv),
1039 Complex64::new(0.0, 0.0),
1040 Complex64::new(0.0, 0.0),
1041 Complex64::new(0.0, sqrt2_inv),
1042 Complex64::new(0.0, 0.0),
1043 Complex64::new(sqrt2_inv, 0.0),
1044 Complex64::new(0.0, -sqrt2_inv),
1045 Complex64::new(0.0, 0.0),
1046 Complex64::new(sqrt2_inv, 0.0),
1047 Complex64::new(0.0, 0.0),
1048 ])
1049 }
1050 fn as_any(&self) -> &dyn Any {
1051 self
1052 }
1053 impl_clone_gate!();
1054 }
1055 #[derive(Debug, Clone, Copy)]
1059 pub struct RXX {
1060 pub qubit1: QubitId,
1062 pub qubit2: QubitId,
1064 pub theta: f64,
1066 }
1067 impl GateOp for RXX {
1068 fn name(&self) -> &'static str {
1069 "RXX"
1070 }
1071 fn qubits(&self) -> Vec<QubitId> {
1072 vec![self.qubit1, self.qubit2]
1073 }
1074 fn is_parameterized(&self) -> bool {
1075 true
1076 }
1077 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1078 let cos = (self.theta / 2.0).cos();
1079 let sin = (self.theta / 2.0).sin();
1080 let mi_sin = Complex64::new(0.0, -sin);
1081 Ok(vec![
1082 Complex64::new(cos, 0.0),
1083 Complex64::new(0.0, 0.0),
1084 Complex64::new(0.0, 0.0),
1085 mi_sin,
1086 Complex64::new(0.0, 0.0),
1087 Complex64::new(cos, 0.0),
1088 mi_sin,
1089 Complex64::new(0.0, 0.0),
1090 Complex64::new(0.0, 0.0),
1091 mi_sin,
1092 Complex64::new(cos, 0.0),
1093 Complex64::new(0.0, 0.0),
1094 mi_sin,
1095 Complex64::new(0.0, 0.0),
1096 Complex64::new(0.0, 0.0),
1097 Complex64::new(cos, 0.0),
1098 ])
1099 }
1100 fn as_any(&self) -> &dyn Any {
1101 self
1102 }
1103 impl_clone_gate!();
1104 }
1105 #[derive(Debug, Clone, Copy)]
1109 pub struct RYY {
1110 pub qubit1: QubitId,
1112 pub qubit2: QubitId,
1114 pub theta: f64,
1116 }
1117 impl GateOp for RYY {
1118 fn name(&self) -> &'static str {
1119 "RYY"
1120 }
1121 fn qubits(&self) -> Vec<QubitId> {
1122 vec![self.qubit1, self.qubit2]
1123 }
1124 fn is_parameterized(&self) -> bool {
1125 true
1126 }
1127 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1128 let cos = (self.theta / 2.0).cos();
1129 let sin = (self.theta / 2.0).sin();
1130 let i_sin = Complex64::new(0.0, sin);
1131 let mi_sin = Complex64::new(0.0, -sin);
1132 Ok(vec![
1133 Complex64::new(cos, 0.0),
1134 Complex64::new(0.0, 0.0),
1135 Complex64::new(0.0, 0.0),
1136 i_sin,
1137 Complex64::new(0.0, 0.0),
1138 Complex64::new(cos, 0.0),
1139 mi_sin,
1140 Complex64::new(0.0, 0.0),
1141 Complex64::new(0.0, 0.0),
1142 mi_sin,
1143 Complex64::new(cos, 0.0),
1144 Complex64::new(0.0, 0.0),
1145 i_sin,
1146 Complex64::new(0.0, 0.0),
1147 Complex64::new(0.0, 0.0),
1148 Complex64::new(cos, 0.0),
1149 ])
1150 }
1151 fn as_any(&self) -> &dyn Any {
1152 self
1153 }
1154 impl_clone_gate!();
1155 }
1156 #[derive(Debug, Clone, Copy)]
1160 pub struct RZZ {
1161 pub qubit1: QubitId,
1163 pub qubit2: QubitId,
1165 pub theta: f64,
1167 }
1168 impl GateOp for RZZ {
1169 fn name(&self) -> &'static str {
1170 "RZZ"
1171 }
1172 fn qubits(&self) -> Vec<QubitId> {
1173 vec![self.qubit1, self.qubit2]
1174 }
1175 fn is_parameterized(&self) -> bool {
1176 true
1177 }
1178 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1179 let phase_neg = Complex64::new(0.0, -self.theta / 2.0).exp();
1180 let phase_pos = Complex64::new(0.0, self.theta / 2.0).exp();
1181 Ok(vec![
1182 phase_neg,
1183 Complex64::new(0.0, 0.0),
1184 Complex64::new(0.0, 0.0),
1185 Complex64::new(0.0, 0.0),
1186 Complex64::new(0.0, 0.0),
1187 phase_pos,
1188 Complex64::new(0.0, 0.0),
1189 Complex64::new(0.0, 0.0),
1190 Complex64::new(0.0, 0.0),
1191 Complex64::new(0.0, 0.0),
1192 phase_pos,
1193 Complex64::new(0.0, 0.0),
1194 Complex64::new(0.0, 0.0),
1195 Complex64::new(0.0, 0.0),
1196 Complex64::new(0.0, 0.0),
1197 phase_neg,
1198 ])
1199 }
1200 fn as_any(&self) -> &dyn Any {
1201 self
1202 }
1203 impl_clone_gate!();
1204 }
1205 #[derive(Debug, Clone, Copy)]
1209 pub struct RZX {
1210 pub control: QubitId,
1212 pub target: QubitId,
1214 pub theta: f64,
1216 }
1217 impl GateOp for RZX {
1218 fn name(&self) -> &'static str {
1219 "RZX"
1220 }
1221 fn qubits(&self) -> Vec<QubitId> {
1222 vec![self.control, self.target]
1223 }
1224 fn is_parameterized(&self) -> bool {
1225 true
1226 }
1227 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1228 let cos = (self.theta / 2.0).cos();
1229 let sin = (self.theta / 2.0).sin();
1230 let mi_sin = Complex64::new(0.0, -sin);
1231 let i_sin = Complex64::new(0.0, sin);
1232 Ok(vec![
1233 Complex64::new(cos, 0.0),
1234 mi_sin,
1235 Complex64::new(0.0, 0.0),
1236 Complex64::new(0.0, 0.0),
1237 mi_sin,
1238 Complex64::new(cos, 0.0),
1239 Complex64::new(0.0, 0.0),
1240 Complex64::new(0.0, 0.0),
1241 Complex64::new(0.0, 0.0),
1242 Complex64::new(0.0, 0.0),
1243 Complex64::new(cos, 0.0),
1244 i_sin,
1245 Complex64::new(0.0, 0.0),
1246 Complex64::new(0.0, 0.0),
1247 i_sin,
1248 Complex64::new(cos, 0.0),
1249 ])
1250 }
1251 fn as_any(&self) -> &dyn Any {
1252 self
1253 }
1254 impl_clone_gate!();
1255 }
1256 #[derive(Debug, Clone, Copy)]
1260 pub struct DCX {
1261 pub qubit1: QubitId,
1263 pub qubit2: QubitId,
1265 }
1266 impl GateOp for DCX {
1267 fn name(&self) -> &'static str {
1268 "DCX"
1269 }
1270 fn qubits(&self) -> Vec<QubitId> {
1271 vec![self.qubit1, self.qubit2]
1272 }
1273 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1274 Ok(vec![
1275 Complex64::new(1.0, 0.0),
1276 Complex64::new(0.0, 0.0),
1277 Complex64::new(0.0, 0.0),
1278 Complex64::new(0.0, 0.0),
1279 Complex64::new(0.0, 0.0),
1280 Complex64::new(0.0, 0.0),
1281 Complex64::new(0.0, 0.0),
1282 Complex64::new(1.0, 0.0),
1283 Complex64::new(0.0, 0.0),
1284 Complex64::new(1.0, 0.0),
1285 Complex64::new(0.0, 0.0),
1286 Complex64::new(0.0, 0.0),
1287 Complex64::new(0.0, 0.0),
1288 Complex64::new(0.0, 0.0),
1289 Complex64::new(1.0, 0.0),
1290 Complex64::new(0.0, 0.0),
1291 ])
1292 }
1293 fn as_any(&self) -> &dyn Any {
1294 self
1295 }
1296 impl_clone_gate!();
1297 }
1298 #[derive(Debug, Clone, Copy)]
1302 pub struct XXPlusYY {
1303 pub qubit1: QubitId,
1305 pub qubit2: QubitId,
1307 pub theta: f64,
1309 pub beta: f64,
1311 }
1312 impl GateOp for XXPlusYY {
1313 fn name(&self) -> &'static str {
1314 "XXPlusYY"
1315 }
1316 fn qubits(&self) -> Vec<QubitId> {
1317 vec![self.qubit1, self.qubit2]
1318 }
1319 fn is_parameterized(&self) -> bool {
1320 true
1321 }
1322 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1323 let cos = (self.theta / 2.0).cos();
1324 let sin = (self.theta / 2.0).sin();
1325 let exp_neg_i_beta = Complex64::new(0.0, -self.beta).exp();
1326 let exp_i_beta = Complex64::new(0.0, self.beta).exp();
1327 let mi_sin_neg = Complex64::new(0.0, -sin) * exp_neg_i_beta;
1328 let mi_sin_pos = Complex64::new(0.0, -sin) * exp_i_beta;
1329 Ok(vec![
1330 Complex64::new(1.0, 0.0),
1331 Complex64::new(0.0, 0.0),
1332 Complex64::new(0.0, 0.0),
1333 Complex64::new(0.0, 0.0),
1334 Complex64::new(0.0, 0.0),
1335 Complex64::new(cos, 0.0),
1336 mi_sin_neg,
1337 Complex64::new(0.0, 0.0),
1338 Complex64::new(0.0, 0.0),
1339 mi_sin_pos,
1340 Complex64::new(cos, 0.0),
1341 Complex64::new(0.0, 0.0),
1342 Complex64::new(0.0, 0.0),
1343 Complex64::new(0.0, 0.0),
1344 Complex64::new(0.0, 0.0),
1345 Complex64::new(1.0, 0.0),
1346 ])
1347 }
1348 fn as_any(&self) -> &dyn Any {
1349 self
1350 }
1351 impl_clone_gate!();
1352 }
1353 #[derive(Debug, Clone, Copy)]
1357 pub struct XXMinusYY {
1358 pub qubit1: QubitId,
1360 pub qubit2: QubitId,
1362 pub theta: f64,
1364 pub beta: f64,
1366 }
1367 impl GateOp for XXMinusYY {
1368 fn name(&self) -> &'static str {
1369 "XXMinusYY"
1370 }
1371 fn qubits(&self) -> Vec<QubitId> {
1372 vec![self.qubit1, self.qubit2]
1373 }
1374 fn is_parameterized(&self) -> bool {
1375 true
1376 }
1377 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1378 let cos = (self.theta / 2.0).cos();
1379 let sin = (self.theta / 2.0).sin();
1380 let exp_neg_i_beta = Complex64::new(0.0, -self.beta).exp();
1381 let exp_i_beta = Complex64::new(0.0, self.beta).exp();
1382 let mi_sin_neg = Complex64::new(0.0, -sin) * exp_neg_i_beta;
1383 let mi_sin_pos = Complex64::new(0.0, -sin) * exp_i_beta;
1384 Ok(vec![
1385 Complex64::new(cos, 0.0),
1386 Complex64::new(0.0, 0.0),
1387 Complex64::new(0.0, 0.0),
1388 mi_sin_pos,
1389 Complex64::new(0.0, 0.0),
1390 Complex64::new(1.0, 0.0),
1391 Complex64::new(0.0, 0.0),
1392 Complex64::new(0.0, 0.0),
1393 Complex64::new(0.0, 0.0),
1394 Complex64::new(0.0, 0.0),
1395 Complex64::new(1.0, 0.0),
1396 Complex64::new(0.0, 0.0),
1397 mi_sin_neg,
1398 Complex64::new(0.0, 0.0),
1399 Complex64::new(0.0, 0.0),
1400 Complex64::new(cos, 0.0),
1401 ])
1402 }
1403 fn as_any(&self) -> &dyn Any {
1404 self
1405 }
1406 impl_clone_gate!();
1407 }
1408 #[derive(Debug, Clone, Copy)]
1410 pub struct CSX {
1411 pub control: QubitId,
1413 pub target: QubitId,
1415 }
1416 impl GateOp for CSX {
1417 fn name(&self) -> &'static str {
1418 "CSX"
1419 }
1420 fn qubits(&self) -> Vec<QubitId> {
1421 vec![self.control, self.target]
1422 }
1423 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1424 let half_plus_i_half = Complex64::new(0.5, 0.5);
1425 let half_minus_i_half = Complex64::new(0.5, -0.5);
1426 Ok(vec![
1427 Complex64::new(1.0, 0.0),
1428 Complex64::new(0.0, 0.0),
1429 Complex64::new(0.0, 0.0),
1430 Complex64::new(0.0, 0.0),
1431 Complex64::new(0.0, 0.0),
1432 Complex64::new(1.0, 0.0),
1433 Complex64::new(0.0, 0.0),
1434 Complex64::new(0.0, 0.0),
1435 Complex64::new(0.0, 0.0),
1436 Complex64::new(0.0, 0.0),
1437 half_plus_i_half,
1438 half_minus_i_half,
1439 Complex64::new(0.0, 0.0),
1440 Complex64::new(0.0, 0.0),
1441 half_minus_i_half,
1442 half_plus_i_half,
1443 ])
1444 }
1445 fn as_any(&self) -> &dyn Any {
1446 self
1447 }
1448 impl_clone_gate!();
1449 }
1450}
1451pub mod global {
1453 use super::*;
1454 #[derive(Debug, Clone, Copy)]
1458 pub struct GlobalPhase {
1459 pub phase: f64,
1461 }
1462 impl GateOp for GlobalPhase {
1463 fn name(&self) -> &'static str {
1464 "GlobalPhase"
1465 }
1466 fn qubits(&self) -> Vec<QubitId> {
1467 vec![]
1468 }
1469 fn is_parameterized(&self) -> bool {
1470 true
1471 }
1472 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1473 let phase = Complex64::new(0.0, self.phase).exp();
1474 Ok(vec![phase])
1475 }
1476 fn as_any(&self) -> &dyn Any {
1477 self
1478 }
1479 impl_clone_gate!();
1480 }
1481 #[derive(Debug, Clone, Copy)]
1485 pub struct RGate {
1486 pub target: QubitId,
1488 pub theta: f64,
1490 pub phi: f64,
1492 }
1493 impl GateOp for RGate {
1494 fn name(&self) -> &'static str {
1495 "R"
1496 }
1497 fn qubits(&self) -> Vec<QubitId> {
1498 vec![self.target]
1499 }
1500 fn is_parameterized(&self) -> bool {
1501 true
1502 }
1503 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
1504 let cos = (self.theta / 2.0).cos();
1505 let sin = (self.theta / 2.0).sin();
1506 let exp_neg_i_phi = Complex64::new(0.0, -self.phi).exp();
1507 let exp_i_phi = Complex64::new(0.0, self.phi).exp();
1508 Ok(vec![
1509 Complex64::new(cos, 0.0),
1510 Complex64::new(0.0, -sin) * exp_neg_i_phi,
1511 Complex64::new(0.0, -sin) * exp_i_phi,
1512 Complex64::new(cos, 0.0),
1513 ])
1514 }
1515 fn as_any(&self) -> &dyn Any {
1516 self
1517 }
1518 impl_clone_gate!();
1519 }
1520}