1use crate::operations::single_qubit_gate_operations::*;
14use crate::prelude::*;
15use crate::Circuit;
16use crate::RoqoqoError;
17use ndarray::{array, Array2};
18use num_complex::Complex64;
19use qoqo_calculator::{CalculatorComplex, CalculatorFloat};
20#[cfg(feature = "overrotate")]
21use rand_distr::{Distribution, Normal};
22use std::convert::TryFrom;
23use std::f64::consts::PI;
24
25use super::SupportedVersion;
26
27#[derive(Debug, Clone, PartialEq)]
38pub struct KakDecomposition {
39 pub global_phase: CalculatorFloat,
41 pub k_vector: [CalculatorFloat; 3],
43 pub circuit_before: Option<Circuit>,
45 pub circuit_after: Option<Circuit>,
47}
48
49#[allow(clippy::upper_case_acronyms)]
53#[derive(
54 Debug,
55 Clone,
56 PartialEq,
57 Eq,
58 roqoqo_derive::InvolveQubits,
59 roqoqo_derive::SupportedVersion,
60 roqoqo_derive::Operate,
61 roqoqo_derive::Substitute,
62 roqoqo_derive::OperateTwoQubit,
63)]
64#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
65#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
66pub struct CNOT {
67 control: usize,
69 target: usize,
71}
72
73#[allow(non_upper_case_globals)]
74const TAGS_CNOT: &[&str; 4] = &[
75 "Operation",
76 "GateOperation",
77 "TwoQubitGateOperation",
78 "CNOT",
79];
80
81impl OperateGate for CNOT {
83 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
90 Ok(array![
91 [
92 Complex64::new(1.0, 0.0),
93 Complex64::new(0.0, 0.0),
94 Complex64::new(0.0, 0.0),
95 Complex64::new(0.0, 0.0)
96 ],
97 [
98 Complex64::new(0.0, 0.0),
99 Complex64::new(1.0, 0.0),
100 Complex64::new(0.0, 0.0),
101 Complex64::new(0.0, 0.0)
102 ],
103 [
104 Complex64::new(0.0, 0.0),
105 Complex64::new(0.0, 0.0),
106 Complex64::new(0.0, 0.0),
107 Complex64::new(1.0, 0.0)
108 ],
109 [
110 Complex64::new(0.0, 0.0),
111 Complex64::new(0.0, 0.0),
112 Complex64::new(1.0, 0.0),
113 Complex64::new(0.0, 0.0)
114 ],
115 ])
116 }
117}
118
119impl OperateTwoQubitGate for CNOT {
121 fn kak_decomposition(&self) -> KakDecomposition {
127 let mut circuit_b = Circuit::new();
128 circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2);
129 circuit_b += RotateY::new(self.control, CalculatorFloat::FRAC_PI_2);
130 circuit_b += RotateX::new(self.target, CalculatorFloat::FRAC_PI_2);
131
132 let mut circuit_a = Circuit::new();
133 circuit_a += RotateY::new(self.control, CalculatorFloat::FRAC_PI_2 * (-1.0));
134
135 KakDecomposition {
136 global_phase: CalculatorFloat::FRAC_PI_4,
137 k_vector: [
138 CalculatorFloat::FRAC_PI_4,
139 CalculatorFloat::ZERO,
140 CalculatorFloat::ZERO,
141 ],
142 circuit_before: Some(circuit_b),
143 circuit_after: Some(circuit_a),
144 }
145 }
146}
147
148#[allow(clippy::upper_case_acronyms)]
152#[derive(
153 Debug,
154 Clone,
155 PartialEq,
156 Eq,
157 roqoqo_derive::InvolveQubits,
158 roqoqo_derive::SupportedVersion,
159 roqoqo_derive::Operate,
160 roqoqo_derive::Substitute,
161 roqoqo_derive::OperateTwoQubit,
162)]
163#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
164#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
165pub struct SWAP {
166 control: usize,
168 target: usize,
170}
171
172#[allow(non_upper_case_globals)]
173const TAGS_SWAP: &[&str; 4] = &[
174 "Operation",
175 "GateOperation",
176 "TwoQubitGateOperation",
177 "SWAP",
178];
179
180impl OperateGate for SWAP {
182 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
189 Ok(array![
190 [
191 Complex64::new(1.0, 0.0),
192 Complex64::new(0.0, 0.0),
193 Complex64::new(0.0, 0.0),
194 Complex64::new(0.0, 0.0)
195 ],
196 [
197 Complex64::new(0.0, 0.0),
198 Complex64::new(0.0, 0.0),
199 Complex64::new(1.0, 0.0),
200 Complex64::new(0.0, 0.0)
201 ],
202 [
203 Complex64::new(0.0, 0.0),
204 Complex64::new(1.0, 0.0),
205 Complex64::new(0.0, 0.0),
206 Complex64::new(0.0, 0.0)
207 ],
208 [
209 Complex64::new(0.0, 0.0),
210 Complex64::new(0.0, 0.0),
211 Complex64::new(0.0, 0.0),
212 Complex64::new(1.0, 0.0)
213 ],
214 ])
215 }
216}
217
218impl OperateTwoQubitGate for SWAP {
220 fn kak_decomposition(&self) -> KakDecomposition {
226 KakDecomposition {
227 global_phase: CalculatorFloat::from(-PI / 4.0),
228 k_vector: [
229 CalculatorFloat::FRAC_PI_4,
230 CalculatorFloat::FRAC_PI_4,
231 CalculatorFloat::FRAC_PI_4,
232 ],
233 circuit_before: None,
234 circuit_after: None,
235 }
236 }
237}
238
239#[allow(clippy::upper_case_acronyms)]
244#[derive(
245 Debug,
246 Clone,
247 PartialEq,
248 Eq,
249 roqoqo_derive::InvolveQubits,
250 roqoqo_derive::SupportedVersion,
251 roqoqo_derive::Operate,
252 roqoqo_derive::Substitute,
253 roqoqo_derive::OperateTwoQubit,
254)]
255#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
256#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
257pub struct ISwap {
258 control: usize,
260 target: usize,
262}
263
264#[allow(non_upper_case_globals)]
265const TAGS_ISwap: &[&str; 4] = &[
266 "Operation",
267 "GateOperation",
268 "TwoQubitGateOperation",
269 "ISwap",
270];
271
272impl OperateGate for ISwap {
274 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
281 Ok(array![
282 [
283 Complex64::new(1.0, 0.0),
284 Complex64::new(0.0, 0.0),
285 Complex64::new(0.0, 0.0),
286 Complex64::new(0.0, 0.0)
287 ],
288 [
289 Complex64::new(0.0, 0.0),
290 Complex64::new(0.0, 0.0),
291 Complex64::new(0.0, 1.0),
292 Complex64::new(0.0, 0.0)
293 ],
294 [
295 Complex64::new(0.0, 0.0),
296 Complex64::new(0.0, 1.0),
297 Complex64::new(0.0, 0.0),
298 Complex64::new(0.0, 0.0)
299 ],
300 [
301 Complex64::new(0.0, 0.0),
302 Complex64::new(0.0, 0.0),
303 Complex64::new(0.0, 0.0),
304 Complex64::new(1.0, 0.0)
305 ],
306 ])
307 }
308}
309
310impl OperateTwoQubitGate for ISwap {
312 fn kak_decomposition(&self) -> KakDecomposition {
318 KakDecomposition {
319 global_phase: CalculatorFloat::ZERO,
320 k_vector: [
321 CalculatorFloat::FRAC_PI_4,
322 CalculatorFloat::FRAC_PI_4,
323 CalculatorFloat::ZERO,
324 ],
325 circuit_before: None,
326 circuit_after: None,
327 }
328 }
329}
330
331#[allow(clippy::upper_case_acronyms)]
337#[derive(
338 Debug,
339 Clone,
340 PartialEq,
341 Eq,
342 roqoqo_derive::InvolveQubits,
343 roqoqo_derive::SupportedVersion,
344 roqoqo_derive::Operate,
345 roqoqo_derive::Substitute,
346 roqoqo_derive::OperateTwoQubit,
347)]
348#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
349#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
350pub struct FSwap {
351 control: usize,
353 target: usize,
355}
356
357#[allow(non_upper_case_globals)]
358const TAGS_FSwap: &[&str; 4] = &[
359 "Operation",
360 "GateOperation",
361 "TwoQubitGateOperation",
362 "FSwap",
363];
364
365impl OperateGate for FSwap {
367 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
374 Ok(array![
375 [
376 Complex64::new(1.0, 0.0),
377 Complex64::new(0.0, 0.0),
378 Complex64::new(0.0, 0.0),
379 Complex64::new(0.0, 0.0)
380 ],
381 [
382 Complex64::new(0.0, 0.0),
383 Complex64::new(0.0, 0.0),
384 Complex64::new(1.0, 0.0),
385 Complex64::new(0.0, 0.0)
386 ],
387 [
388 Complex64::new(0.0, 0.0),
389 Complex64::new(1.0, 0.0),
390 Complex64::new(0.0, 0.0),
391 Complex64::new(0.0, 0.0)
392 ],
393 [
394 Complex64::new(0.0, 0.0),
395 Complex64::new(0.0, 0.0),
396 Complex64::new(0.0, 0.0),
397 Complex64::new(-1.0, 0.0)
398 ],
399 ])
400 }
401}
402
403impl OperateTwoQubitGate for FSwap {
405 fn kak_decomposition(&self) -> KakDecomposition {
411 let mut circuit_b = Circuit::new();
412 circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2 * (-1.0));
413 circuit_b += RotateZ::new(self.target, CalculatorFloat::FRAC_PI_2 * (-1.0));
414
415 KakDecomposition {
416 global_phase: CalculatorFloat::FRAC_PI_2 * (-1.0),
417 k_vector: [
418 CalculatorFloat::FRAC_PI_4,
419 CalculatorFloat::FRAC_PI_4,
420 CalculatorFloat::ZERO,
421 ],
422 circuit_before: Some(circuit_b),
423 circuit_after: None,
424 }
425 }
426}
427
428#[allow(clippy::upper_case_acronyms)]
433#[derive(
434 Debug,
435 Clone,
436 PartialEq,
437 Eq,
438 roqoqo_derive::InvolveQubits,
439 roqoqo_derive::SupportedVersion,
440 roqoqo_derive::Operate,
441 roqoqo_derive::Substitute,
442 roqoqo_derive::OperateTwoQubit,
443)]
444#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
445#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
446pub struct SqrtISwap {
447 control: usize,
449 target: usize,
451}
452
453#[allow(non_upper_case_globals)]
454const TAGS_SqrtISwap: &[&str; 4] = &[
455 "Operation",
456 "GateOperation",
457 "TwoQubitGateOperation",
458 "SqrtISwap",
459];
460
461impl OperateGate for SqrtISwap {
463 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
470 let f: f64 = 1.0 / ((2.0_f64).sqrt());
471 Ok(array![
472 [
473 Complex64::new(1.0, 0.0),
474 Complex64::new(0.0, 0.0),
475 Complex64::new(0.0, 0.0),
476 Complex64::new(0.0, 0.0)
477 ],
478 [
479 Complex64::new(0.0, 0.0),
480 Complex64::new(f, 0.0),
481 Complex64::new(0.0, f),
482 Complex64::new(0.0, 0.0)
483 ],
484 [
485 Complex64::new(0.0, 0.0),
486 Complex64::new(0.0, f),
487 Complex64::new(f, 0.0),
488 Complex64::new(0.0, 0.0)
489 ],
490 [
491 Complex64::new(0.0, 0.0),
492 Complex64::new(0.0, 0.0),
493 Complex64::new(0.0, 0.0),
494 Complex64::new(1.0, 0.0)
495 ],
496 ])
497 }
498}
499
500impl OperateTwoQubitGate for SqrtISwap {
502 fn kak_decomposition(&self) -> KakDecomposition {
508 KakDecomposition {
509 global_phase: CalculatorFloat::ZERO,
510 k_vector: [
511 CalculatorFloat::from(PI / 8.0),
512 CalculatorFloat::from(PI / 8.0),
513 CalculatorFloat::ZERO,
514 ],
515 circuit_before: None,
516 circuit_after: None,
517 }
518 }
519}
520
521#[allow(clippy::upper_case_acronyms)]
525#[derive(
526 Debug,
527 Clone,
528 PartialEq,
529 Eq,
530 roqoqo_derive::InvolveQubits,
531 roqoqo_derive::SupportedVersion,
532 roqoqo_derive::Operate,
533 roqoqo_derive::Substitute,
534 roqoqo_derive::OperateTwoQubit,
535)]
536#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
537#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
538pub struct InvSqrtISwap {
539 control: usize,
541 target: usize,
543}
544
545#[allow(non_upper_case_globals)]
546const TAGS_InvSqrtISwap: &[&str; 4] = &[
547 "Operation",
548 "GateOperation",
549 "TwoQubitGateOperation",
550 "InvSqrtISwap",
551];
552
553impl OperateGate for InvSqrtISwap {
555 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
562 let f: f64 = 1.0 / ((2.0_f64).sqrt());
563 Ok(array![
564 [
565 Complex64::new(1.0, 0.0),
566 Complex64::new(0.0, 0.0),
567 Complex64::new(0.0, 0.0),
568 Complex64::new(0.0, 0.0)
569 ],
570 [
571 Complex64::new(0.0, 0.0),
572 Complex64::new(f, 0.0),
573 Complex64::new(0.0, -f),
574 Complex64::new(0.0, 0.0)
575 ],
576 [
577 Complex64::new(0.0, 0.0),
578 Complex64::new(0.0, -f),
579 Complex64::new(f, 0.0),
580 Complex64::new(0.0, 0.0)
581 ],
582 [
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 ],
588 ])
589 }
590}
591
592impl OperateTwoQubitGate for InvSqrtISwap {
594 fn kak_decomposition(&self) -> KakDecomposition {
600 KakDecomposition {
601 global_phase: CalculatorFloat::ZERO,
602 k_vector: [
603 CalculatorFloat::from(-PI / 8.0),
604 CalculatorFloat::from(-PI / 8.0),
605 CalculatorFloat::ZERO,
606 ],
607 circuit_before: None,
608 circuit_after: None,
609 }
610 }
611}
612
613#[allow(clippy::upper_case_acronyms)]
619#[derive(
620 Debug,
621 Clone,
622 PartialEq,
623 roqoqo_derive::InvolveQubits,
624 roqoqo_derive::SupportedVersion,
625 roqoqo_derive::Operate,
626 roqoqo_derive::Substitute,
627 roqoqo_derive::OperateTwoQubit,
628 roqoqo_derive::Rotate,
629)]
630#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
631#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
632pub struct XY {
633 control: usize,
635 target: usize,
637 theta: CalculatorFloat,
639}
640
641#[allow(non_upper_case_globals)]
642const TAGS_XY: &[&str; 5] = &[
643 "Operation",
644 "GateOperation",
645 "TwoQubitGateOperation",
646 "Rotation",
647 "XY",
648];
649
650impl OperateGate for XY {
652 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
659 let c: f64 = (f64::try_from(self.theta.clone())? / 2.0).cos();
660 let s: f64 = (f64::try_from(self.theta.clone())? / 2.0).sin();
661 Ok(array![
662 [
663 Complex64::new(1.0, 0.0),
664 Complex64::new(0.0, 0.0),
665 Complex64::new(0.0, 0.0),
666 Complex64::new(0.0, 0.0)
667 ],
668 [
669 Complex64::new(0.0, 0.0),
670 Complex64::new(c, 0.0),
671 Complex64::new(0.0, s),
672 Complex64::new(0.0, 0.0)
673 ],
674 [
675 Complex64::new(0.0, 0.0),
676 Complex64::new(0.0, s),
677 Complex64::new(c, 0.0),
678 Complex64::new(0.0, 0.0)
679 ],
680 [
681 Complex64::new(0.0, 0.0),
682 Complex64::new(0.0, 0.0),
683 Complex64::new(0.0, 0.0),
684 Complex64::new(1.0, 0.0)
685 ],
686 ])
687 }
688}
689
690impl OperateTwoQubitGate for XY {
692 fn kak_decomposition(&self) -> KakDecomposition {
698 KakDecomposition {
699 global_phase: CalculatorFloat::ZERO,
700 k_vector: [
701 self.theta.clone() / 4.0,
702 self.theta.clone() / 4.0,
703 CalculatorFloat::ZERO,
704 ],
705 circuit_before: None,
706 circuit_after: None,
707 }
708 }
709}
710
711#[allow(clippy::upper_case_acronyms)]
717#[derive(
718 Debug,
719 Clone,
720 PartialEq,
721 roqoqo_derive::InvolveQubits,
722 roqoqo_derive::SupportedVersion,
723 roqoqo_derive::Operate,
724 roqoqo_derive::Substitute,
725 roqoqo_derive::OperateTwoQubit,
726 roqoqo_derive::Rotate,
727)]
728#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
729#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
730pub struct ControlledPhaseShift {
731 control: usize,
733 target: usize,
735 theta: CalculatorFloat,
737}
738
739#[allow(non_upper_case_globals)]
740const TAGS_ControlledPhaseShift: &[&str; 5] = &[
741 "Operation",
742 "GateOperation",
743 "TwoQubitGateOperation",
744 "Rotation",
745 "ControlledPhaseShift",
746];
747
748impl OperateGate for ControlledPhaseShift {
750 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
757 let c: f64 = (f64::try_from(self.theta.clone())?).cos();
759 let s: f64 = (f64::try_from(self.theta.clone())?).sin();
760 Ok(array![
761 [
762 Complex64::new(1.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 ],
767 [
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 ],
773 [
774 Complex64::new(0.0, 0.0),
775 Complex64::new(0.0, 0.0),
776 Complex64::new(1.0, 0.0),
777 Complex64::new(0.0, 0.0)
778 ],
779 [
780 Complex64::new(0.0, 0.0),
781 Complex64::new(0.0, 0.0),
782 Complex64::new(0.0, 0.0),
783 Complex64::new(c, s)
784 ],
785 ])
786 }
787}
788
789impl OperateTwoQubitGate for ControlledPhaseShift {
791 fn kak_decomposition(&self) -> KakDecomposition {
797 let mut circuit_b = Circuit::new();
798 circuit_b += RotateZ::new(self.control, self.theta.clone() / 2.0);
799 circuit_b += RotateZ::new(self.target, self.theta.clone() / 2.0);
800
801 KakDecomposition {
802 global_phase: self.theta.clone() / 4.0,
803 k_vector: [
804 CalculatorFloat::ZERO,
805 CalculatorFloat::ZERO,
806 self.theta.clone() / 4.0,
807 ],
808 circuit_before: Some(circuit_b),
809 circuit_after: None,
810 }
811 }
812}
813
814#[allow(clippy::upper_case_acronyms)]
818#[derive(
819 Debug,
820 Clone,
821 PartialEq,
822 Eq,
823 roqoqo_derive::InvolveQubits,
824 roqoqo_derive::SupportedVersion,
825 roqoqo_derive::Operate,
826 roqoqo_derive::Substitute,
827 roqoqo_derive::OperateTwoQubit,
828)]
829#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
830#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
831pub struct ControlledPauliY {
832 control: usize,
834 target: usize,
836}
837
838#[allow(non_upper_case_globals)]
839const TAGS_ControlledPauliY: &[&str; 4] = &[
840 "Operation",
841 "GateOperation",
842 "TwoQubitGateOperation",
843 "ControlledPauliY",
844];
845
846impl OperateGate for ControlledPauliY {
848 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
855 Ok(array![
856 [
857 Complex64::new(1.0, 0.0),
858 Complex64::new(0.0, 0.0),
859 Complex64::new(0.0, 0.0),
860 Complex64::new(0.0, 0.0)
861 ],
862 [
863 Complex64::new(0.0, 0.0),
864 Complex64::new(1.0, 0.0),
865 Complex64::new(0.0, 0.0),
866 Complex64::new(0.0, 0.0)
867 ],
868 [
869 Complex64::new(0.0, 0.0),
870 Complex64::new(0.0, 0.0),
871 Complex64::new(0.0, 0.0),
872 Complex64::new(0.0, -1.0)
873 ],
874 [
875 Complex64::new(0.0, 0.0),
876 Complex64::new(0.0, 0.0),
877 Complex64::new(0.0, 1.0),
878 Complex64::new(0.0, 0.0)
879 ],
880 ])
881 }
882}
883
884impl OperateTwoQubitGate for ControlledPauliY {
886 fn kak_decomposition(&self) -> KakDecomposition {
892 let mut circuit_b = Circuit::new();
893 circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2);
894 circuit_b += RotateY::new(self.target, CalculatorFloat::FRAC_PI_2);
895 circuit_b += RotateX::new(self.target, CalculatorFloat::FRAC_PI_2);
896
897 let mut circuit_a = Circuit::new();
898 circuit_a += RotateX::new(self.target, CalculatorFloat::FRAC_PI_2 * (-1.0));
899
900 KakDecomposition {
901 global_phase: CalculatorFloat::FRAC_PI_4,
902 k_vector: [
903 CalculatorFloat::ZERO,
904 CalculatorFloat::ZERO,
905 CalculatorFloat::FRAC_PI_4,
906 ],
907 circuit_before: Some(circuit_b),
908 circuit_after: Some(circuit_a),
909 }
910 }
911}
912
913#[allow(clippy::upper_case_acronyms)]
917#[derive(
918 Debug,
919 Clone,
920 PartialEq,
921 Eq,
922 roqoqo_derive::InvolveQubits,
923 roqoqo_derive::SupportedVersion,
924 roqoqo_derive::Operate,
925 roqoqo_derive::Substitute,
926 roqoqo_derive::OperateTwoQubit,
927)]
928#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
929#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
930pub struct ControlledPauliZ {
931 control: usize,
933 target: usize,
935}
936
937#[allow(non_upper_case_globals)]
938const TAGS_ControlledPauliZ: &[&str; 4] = &[
939 "Operation",
940 "GateOperation",
941 "TwoQubitGateOperation",
942 "ControlledPauliZ",
943];
944
945impl OperateGate for ControlledPauliZ {
947 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
954 Ok(array![
955 [
956 Complex64::new(1.0, 0.0),
957 Complex64::new(0.0, 0.0),
958 Complex64::new(0.0, 0.0),
959 Complex64::new(0.0, 0.0)
960 ],
961 [
962 Complex64::new(0.0, 0.0),
963 Complex64::new(1.0, 0.0),
964 Complex64::new(0.0, 0.0),
965 Complex64::new(0.0, 0.0)
966 ],
967 [
968 Complex64::new(0.0, 0.0),
969 Complex64::new(0.0, 0.0),
970 Complex64::new(1.0, 0.0),
971 Complex64::new(0.0, 0.0)
972 ],
973 [
974 Complex64::new(0.0, 0.0),
975 Complex64::new(0.0, 0.0),
976 Complex64::new(0.0, 0.0),
977 Complex64::new(-1.0, 0.0)
978 ],
979 ])
980 }
981}
982
983impl OperateTwoQubitGate for ControlledPauliZ {
985 fn kak_decomposition(&self) -> KakDecomposition {
991 let mut circuit_b = Circuit::new();
992 circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2);
993 circuit_b += RotateZ::new(self.target, CalculatorFloat::FRAC_PI_2);
994
995 KakDecomposition {
996 global_phase: CalculatorFloat::FRAC_PI_4,
997 k_vector: [
998 CalculatorFloat::ZERO,
999 CalculatorFloat::ZERO,
1000 CalculatorFloat::FRAC_PI_4,
1001 ],
1002 circuit_before: Some(circuit_b),
1003 circuit_after: None,
1004 }
1005 }
1006}
1007
1008#[allow(clippy::upper_case_acronyms)]
1012#[derive(
1013 Debug,
1014 Clone,
1015 PartialEq,
1016 Eq,
1017 roqoqo_derive::InvolveQubits,
1018 roqoqo_derive::SupportedVersion,
1019 roqoqo_derive::Operate,
1020 roqoqo_derive::Substitute,
1021 roqoqo_derive::OperateTwoQubit,
1022)]
1023#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1024#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
1025pub struct MolmerSorensenXX {
1026 control: usize,
1028 target: usize,
1030}
1031
1032#[allow(non_upper_case_globals)]
1033const TAGS_MolmerSorensenXX: &[&str; 4] = &[
1034 "Operation",
1035 "GateOperation",
1036 "TwoQubitGateOperation",
1037 "MolmerSorensenXX",
1038];
1039
1040impl OperateGate for MolmerSorensenXX {
1042 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
1049 let f: f64 = 1.0 / ((2.0_f64).sqrt());
1050 Ok(array![
1051 [
1052 Complex64::new(f, 0.0),
1053 Complex64::new(0.0, 0.0),
1054 Complex64::new(0.0, 0.0),
1055 Complex64::new(0.0, -f)
1056 ],
1057 [
1058 Complex64::new(0.0, 0.0),
1059 Complex64::new(f, 0.0),
1060 Complex64::new(0.0, -f),
1061 Complex64::new(0.0, 0.0)
1062 ],
1063 [
1064 Complex64::new(0.0, 0.0),
1065 Complex64::new(0.0, -f),
1066 Complex64::new(f, 0.0),
1067 Complex64::new(0.0, 0.0)
1068 ],
1069 [
1070 Complex64::new(0.0, -f),
1071 Complex64::new(0.0, 0.0),
1072 Complex64::new(0.0, 0.0),
1073 Complex64::new(f, 0.0)
1074 ],
1075 ])
1076 }
1077}
1078
1079impl OperateTwoQubitGate for MolmerSorensenXX {
1081 fn kak_decomposition(&self) -> KakDecomposition {
1087 KakDecomposition {
1088 global_phase: CalculatorFloat::ZERO,
1089 k_vector: [
1090 CalculatorFloat::from(-PI / 4.0),
1091 CalculatorFloat::ZERO,
1092 CalculatorFloat::ZERO,
1093 ],
1094 circuit_before: None,
1095 circuit_after: None,
1096 }
1097 }
1098}
1099
1100#[allow(clippy::upper_case_acronyms)]
1104#[derive(
1105 Debug,
1106 Clone,
1107 PartialEq,
1108 roqoqo_derive::InvolveQubits,
1109 roqoqo_derive::SupportedVersion,
1110 roqoqo_derive::Operate,
1111 roqoqo_derive::Substitute,
1112 roqoqo_derive::OperateTwoQubit,
1113 roqoqo_derive::Rotate,
1114)]
1115#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1116#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
1117pub struct VariableMSXX {
1118 control: usize,
1120 target: usize,
1122 theta: CalculatorFloat,
1124}
1125
1126#[allow(non_upper_case_globals)]
1127const TAGS_VariableMSXX: &[&str; 5] = &[
1128 "Operation",
1129 "GateOperation",
1130 "TwoQubitGateOperation",
1131 "Rotation",
1132 "VariableMSXX",
1133];
1134
1135impl OperateGate for VariableMSXX {
1137 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
1144 let c: f64 = (f64::try_from(self.theta.clone())? / 2.0).cos();
1145 let s: f64 = (f64::try_from(self.theta.clone())? / 2.0).sin();
1146 Ok(array![
1147 [
1148 Complex64::new(c, 0.0),
1149 Complex64::new(0.0, 0.0),
1150 Complex64::new(0.0, 0.0),
1151 Complex64::new(0.0, -s)
1152 ],
1153 [
1154 Complex64::new(0.0, 0.0),
1155 Complex64::new(c, 0.0),
1156 Complex64::new(0.0, -s),
1157 Complex64::new(0.0, 0.0)
1158 ],
1159 [
1160 Complex64::new(0.0, 0.0),
1161 Complex64::new(0.0, -s),
1162 Complex64::new(c, 0.0),
1163 Complex64::new(0.0, 0.0)
1164 ],
1165 [
1166 Complex64::new(0.0, -s),
1167 Complex64::new(0.0, 0.0),
1168 Complex64::new(0.0, 0.0),
1169 Complex64::new(c, 0.0)
1170 ],
1171 ])
1172 }
1173}
1174
1175impl OperateTwoQubitGate for VariableMSXX {
1177 fn kak_decomposition(&self) -> KakDecomposition {
1183 KakDecomposition {
1184 global_phase: CalculatorFloat::ZERO,
1185 k_vector: [
1186 self.theta.clone() * (-1.0 / 2.0),
1187 CalculatorFloat::ZERO,
1188 CalculatorFloat::ZERO,
1189 ],
1190 circuit_before: None,
1191 circuit_after: None,
1192 }
1193 }
1194}
1195
1196#[allow(clippy::upper_case_acronyms)]
1202#[derive(
1203 Debug,
1204 Clone,
1205 PartialEq,
1206 roqoqo_derive::InvolveQubits,
1207 roqoqo_derive::SupportedVersion,
1208 roqoqo_derive::Operate,
1209 roqoqo_derive::Substitute,
1210 roqoqo_derive::OperateTwoQubit,
1211 roqoqo_derive::Rotate,
1212)]
1213#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1214#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
1215pub struct GivensRotation {
1216 control: usize,
1218 target: usize,
1220 theta: CalculatorFloat,
1222 phi: CalculatorFloat,
1224}
1225
1226#[allow(non_upper_case_globals)]
1227const TAGS_GivensRotation: &[&str; 5] = &[
1228 "Operation",
1229 "GateOperation",
1230 "TwoQubitGateOperation",
1231 "Rotation",
1232 "GivensRotation",
1233];
1234
1235impl OperateGate for GivensRotation {
1237 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
1244 let ct: f64 = (f64::try_from(self.theta.clone())?).cos();
1245 let st: f64 = (f64::try_from(self.theta.clone())?).sin();
1246 let cp: f64 = (f64::try_from(self.phi.clone())?).cos();
1248 let sp: f64 = (f64::try_from(self.phi.clone())?).sin();
1249 Ok(array![
1250 [
1251 Complex64::new(1.0, 0.0),
1252 Complex64::new(0.0, 0.0),
1253 Complex64::new(0.0, 0.0),
1254 Complex64::new(0.0, 0.0)
1255 ],
1256 [
1257 Complex64::new(0.0, 0.0),
1258 Complex64::new(ct * cp, ct * sp),
1259 Complex64::new(st, 0.0),
1260 Complex64::new(0.0, 0.0)
1261 ],
1262 [
1263 Complex64::new(0.0, 0.0),
1264 Complex64::new(-st * cp, -st * sp),
1265 Complex64::new(ct, 0.0),
1266 Complex64::new(0.0, 0.0)
1267 ],
1268 [
1269 Complex64::new(0.0, 0.0),
1270 Complex64::new(0.0, 0.0),
1271 Complex64::new(0.0, 0.0),
1272 Complex64::new(cp, sp)
1273 ],
1274 ])
1275 }
1276}
1277
1278impl OperateTwoQubitGate for GivensRotation {
1280 fn kak_decomposition(&self) -> KakDecomposition {
1286 let mut circuit_b = Circuit::new();
1287 circuit_b += RotateZ::new(self.target, self.phi.clone() + (PI / 2.0));
1288
1289 let mut circuit_a = Circuit::new();
1290 circuit_a += RotateZ::new(self.target, CalculatorFloat::FRAC_PI_2 * (-1.0));
1291
1292 KakDecomposition {
1293 global_phase: self.phi.clone() / 2.0,
1294 k_vector: [
1295 self.theta.clone() / 2.0,
1296 self.theta.clone() / 2.0,
1297 CalculatorFloat::ZERO,
1298 ],
1299 circuit_before: Some(circuit_b),
1300 circuit_after: Some(circuit_a),
1301 }
1302 }
1303}
1304
1305#[allow(clippy::upper_case_acronyms)]
1311#[derive(
1312 Debug,
1313 Clone,
1314 PartialEq,
1315 roqoqo_derive::InvolveQubits,
1316 roqoqo_derive::SupportedVersion,
1317 roqoqo_derive::Operate,
1318 roqoqo_derive::Substitute,
1319 roqoqo_derive::OperateTwoQubit,
1320 roqoqo_derive::Rotate,
1321)]
1322#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1323#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
1324pub struct GivensRotationLittleEndian {
1325 control: usize,
1327 target: usize,
1329 theta: CalculatorFloat,
1331 phi: CalculatorFloat,
1333}
1334
1335#[allow(non_upper_case_globals)]
1336const TAGS_GivensRotationLittleEndian: &[&str; 5] = &[
1337 "Operation",
1338 "GateOperation",
1339 "TwoQubitGateOperation",
1340 "Rotation",
1341 "GivensRotationLittleEndian",
1342];
1343
1344impl OperateGate for GivensRotationLittleEndian {
1346 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
1353 let ct: f64 = (f64::try_from(self.theta.clone())?).cos();
1354 let st: f64 = (f64::try_from(self.theta.clone())?).sin();
1355 let cp: f64 = (f64::try_from(self.phi.clone())?).cos();
1357 let sp: f64 = (f64::try_from(self.phi.clone())?).sin();
1358 Ok(array![
1359 [
1360 Complex64::new(1.0, 0.0),
1361 Complex64::new(0.0, 0.0),
1362 Complex64::new(0.0, 0.0),
1363 Complex64::new(0.0, 0.0)
1364 ],
1365 [
1366 Complex64::new(0.0, 0.0),
1367 Complex64::new(ct, 0.0),
1368 Complex64::new(st, 0.0),
1369 Complex64::new(0.0, 0.0)
1370 ],
1371 [
1372 Complex64::new(0.0, 0.0),
1373 Complex64::new(-st * cp, -st * sp),
1374 Complex64::new(ct * cp, ct * sp),
1375 Complex64::new(0.0, 0.0)
1376 ],
1377 [
1378 Complex64::new(0.0, 0.0),
1379 Complex64::new(0.0, 0.0),
1380 Complex64::new(0.0, 0.0),
1381 Complex64::new(cp, sp)
1382 ],
1383 ])
1384 }
1385}
1386
1387impl OperateTwoQubitGate for GivensRotationLittleEndian {
1389 fn kak_decomposition(&self) -> KakDecomposition {
1395 let mut circuit_b = Circuit::new();
1396 circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2 * (-1.0));
1397
1398 let mut circuit_a = Circuit::new();
1399 circuit_a += RotateZ::new(self.control, self.phi.clone() + (PI / 2.0));
1400
1401 KakDecomposition {
1402 global_phase: self.phi.clone() / 2.0,
1403 k_vector: [
1404 self.theta.clone() / 2.0,
1405 self.theta.clone() / 2.0,
1406 CalculatorFloat::ZERO,
1407 ],
1408 circuit_before: Some(circuit_b),
1409 circuit_after: Some(circuit_a),
1410 }
1411 }
1412}
1413
1414#[allow(clippy::upper_case_acronyms)]
1421#[derive(
1422 Debug,
1423 Clone,
1424 PartialEq,
1425 roqoqo_derive::InvolveQubits,
1426 roqoqo_derive::SupportedVersion,
1427 roqoqo_derive::Operate,
1428 roqoqo_derive::Substitute,
1429 roqoqo_derive::OperateTwoQubit,
1430)]
1431#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1432#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
1433pub struct Qsim {
1434 control: usize,
1436 target: usize,
1438 x: CalculatorFloat,
1440 y: CalculatorFloat,
1442 z: CalculatorFloat,
1444}
1445
1446#[allow(non_upper_case_globals)]
1447const TAGS_Qsim: &[&str; 4] = &[
1448 "Operation",
1449 "GateOperation",
1450 "TwoQubitGateOperation",
1451 "Qsim",
1452];
1453
1454impl OperateGate for Qsim {
1456 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
1463 let x: f64 = f64::try_from(self.x.clone())?;
1464 let y: f64 = f64::try_from(self.y.clone())?;
1465 let z: f64 = f64::try_from(self.z.clone())?;
1466
1467 let cm: f64 = (x - y).cos();
1468 let cp: f64 = (x + y).cos();
1469 let sm: f64 = (x - y).sin();
1470 let sp: f64 = (x + y).sin();
1471
1472 let cz: f64 = z.cos();
1475 let sz: f64 = z.sin();
1476
1477 Ok(array![
1478 [
1479 Complex64::new(cm * cz, -cm * sz),
1480 Complex64::new(0.0, 0.0),
1481 Complex64::new(0.0, 0.0),
1482 Complex64::new(-sm * sz, -sm * cz)
1483 ],
1484 [
1485 Complex64::new(0.0, 0.0),
1486 Complex64::new(sp * sz, -sp * cz),
1487 Complex64::new(cp * cz, cp * sz),
1488 Complex64::new(0.0, 0.0)
1489 ],
1490 [
1491 Complex64::new(0.0, 0.0),
1492 Complex64::new(cp * cz, cp * sz),
1493 Complex64::new(sp * sz, -sp * cz),
1494 Complex64::new(0.0, 0.0)
1495 ],
1496 [
1497 Complex64::new(-sm * sz, -sm * cz),
1498 Complex64::new(0.0, 0.0),
1499 Complex64::new(0.0, 0.0),
1500 Complex64::new(cm * cz, -cm * sz)
1501 ],
1502 ])
1503 }
1504}
1505
1506impl OperateTwoQubitGate for Qsim {
1508 fn kak_decomposition(&self) -> KakDecomposition {
1514 KakDecomposition {
1515 global_phase: CalculatorFloat::from(-PI / 4.0),
1516 k_vector: [
1517 self.x.clone() * (-1.0) + PI / 4.0,
1518 self.y.clone() * (-1.0) + PI / 4.0,
1519 self.z.clone() * (-1.0) + PI / 4.0,
1520 ],
1521 circuit_before: None,
1522 circuit_after: None,
1523 }
1524 }
1525}
1526
1527#[allow(clippy::upper_case_acronyms)]
1538#[derive(
1539 Debug,
1540 Clone,
1541 PartialEq,
1542 roqoqo_derive::InvolveQubits,
1543 roqoqo_derive::SupportedVersion,
1544 roqoqo_derive::Operate,
1545 roqoqo_derive::Substitute,
1546 roqoqo_derive::OperateTwoQubit,
1547)]
1548#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1549#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
1550pub struct Fsim {
1551 control: usize,
1553 target: usize,
1555 t: CalculatorFloat,
1557 u: CalculatorFloat,
1559 delta: CalculatorFloat,
1561}
1562
1563#[allow(non_upper_case_globals)]
1564const TAGS_Fsim: &[&str; 4] = &[
1565 "Operation",
1566 "GateOperation",
1567 "TwoQubitGateOperation",
1568 "Fsim",
1569];
1570
1571impl OperateGate for Fsim {
1573 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
1580 let t: f64 = f64::try_from(self.t.clone())?;
1581 let u: f64 = f64::try_from(self.u.clone())?;
1582 let d: f64 = f64::try_from(self.delta.clone())?;
1583
1584 Ok(array![
1585 [
1586 Complex64::new(d.cos(), 0.0),
1587 Complex64::new(0.0, 0.0),
1588 Complex64::new(0.0, 0.0),
1589 Complex64::new(0.0, d.sin())
1590 ],
1591 [
1592 Complex64::new(0.0, 0.0),
1593 Complex64::new(0.0, -t.sin()),
1594 Complex64::new(t.cos(), 0.0),
1595 Complex64::new(0.0, 0.0)
1596 ],
1597 [
1598 Complex64::new(0.0, 0.0),
1599 Complex64::new(t.cos(), 0.0),
1600 Complex64::new(0.0, -t.sin()),
1601 Complex64::new(0.0, 0.0)
1602 ],
1603 [
1604 Complex64::new(-d.sin() * u.sin(), -d.sin() * u.cos()),
1605 Complex64::new(0.0, 0.0),
1606 Complex64::new(0.0, 0.0),
1607 Complex64::new(-d.cos() * u.cos(), d.cos() * u.sin())
1608 ],
1609 ])
1610 }
1611}
1612
1613impl OperateTwoQubitGate for Fsim {
1615 fn kak_decomposition(&self) -> KakDecomposition {
1621 let theta = self.u.clone() / (-2.0) - PI / 2.0;
1622 let mut circuit_a = Circuit::new();
1623 circuit_a += RotateZ::new(self.control, theta.clone());
1624 circuit_a += RotateZ::new(self.target, theta);
1625
1626 KakDecomposition {
1627 global_phase: self.u.clone() / (-4.0) - PI / 2.0,
1628 k_vector: [
1629 (self.t.clone() / (-2.0) + self.delta.clone() / 2.0 + PI / 4.0),
1630 (self.t.clone() / (-2.0) - self.delta.clone() / 2.0 + PI / 4.0),
1631 self.u.clone() / (-4.0),
1632 ],
1633 circuit_before: None,
1634 circuit_after: Some(circuit_a),
1635 }
1636 }
1637}
1638
1639#[allow(clippy::upper_case_acronyms)]
1644#[derive(
1645 Debug,
1646 Clone,
1647 PartialEq,
1648 roqoqo_derive::InvolveQubits,
1649 roqoqo_derive::SupportedVersion,
1650 roqoqo_derive::Operate,
1651 roqoqo_derive::Substitute,
1652 roqoqo_derive::OperateTwoQubit,
1653)]
1654#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1655#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
1656pub struct SpinInteraction {
1657 control: usize,
1659 target: usize,
1661 x: CalculatorFloat,
1663 y: CalculatorFloat,
1665 z: CalculatorFloat,
1667}
1668
1669#[allow(non_upper_case_globals)]
1670const TAGS_SpinInteraction: &[&str; 4] = &[
1671 "Operation",
1672 "GateOperation",
1673 "TwoQubitGateOperation",
1674 "SpinInteraction",
1675];
1676
1677impl OperateGate for SpinInteraction {
1679 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
1686 let x: f64 = f64::try_from(self.x.clone())?;
1687 let y: f64 = f64::try_from(self.y.clone())?;
1688 let z: f64 = f64::try_from(self.z.clone())?;
1689
1690 let cm: f64 = (x - y).cos();
1691 let cp: f64 = (x + y).cos();
1692 let sm: f64 = (x - y).sin();
1693 let sp: f64 = (x + y).sin();
1694
1695 let cz: f64 = z.cos();
1698 let sz: f64 = z.sin();
1699
1700 Ok(array![
1701 [
1702 Complex64::new(cm * cz, -cm * sz),
1703 Complex64::new(0.0, 0.0),
1704 Complex64::new(0.0, 0.0),
1705 Complex64::new(-sm * sz, -sm * cz)
1706 ],
1707 [
1708 Complex64::new(0.0, 0.0),
1709 Complex64::new(cp * cz, cp * sz),
1710 Complex64::new(sp * sz, -sp * cz),
1711 Complex64::new(0.0, 0.0)
1712 ],
1713 [
1714 Complex64::new(0.0, 0.0),
1715 Complex64::new(sp * sz, -sp * cz),
1716 Complex64::new(cp * cz, cp * sz),
1717 Complex64::new(0.0, 0.0)
1718 ],
1719 [
1720 Complex64::new(-sm * sz, -sm * cz),
1721 Complex64::new(0.0, 0.0),
1722 Complex64::new(0.0, 0.0),
1723 Complex64::new(cm * cz, -cm * sz)
1724 ],
1725 ])
1726 }
1727}
1728
1729impl OperateTwoQubitGate for SpinInteraction {
1731 fn kak_decomposition(&self) -> KakDecomposition {
1737 KakDecomposition {
1738 global_phase: CalculatorFloat::ZERO,
1739 k_vector: [
1740 self.x.clone() * (-1.0),
1741 self.y.clone() * (-1.0),
1742 self.z.clone() * (-1.0),
1743 ],
1744 circuit_before: None,
1745 circuit_after: None,
1746 }
1747 }
1748}
1749
1750#[allow(clippy::upper_case_acronyms)]
1757#[derive(
1758 Debug,
1759 Clone,
1760 PartialEq,
1761 roqoqo_derive::InvolveQubits,
1762 roqoqo_derive::SupportedVersion,
1763 roqoqo_derive::Operate,
1764 roqoqo_derive::Substitute,
1765 roqoqo_derive::OperateTwoQubit,
1766)]
1767#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1768#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
1769pub struct Bogoliubov {
1770 control: usize,
1772 target: usize,
1774 delta_real: CalculatorFloat,
1776 delta_imag: CalculatorFloat,
1778}
1779
1780#[allow(non_upper_case_globals)]
1781const TAGS_Bogoliubov: &[&str; 4] = &[
1782 "Operation",
1783 "GateOperation",
1784 "TwoQubitGateOperation",
1785 "Bogoliubov",
1786];
1787
1788impl OperateGate for Bogoliubov {
1790 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
1797 let dr: f64 = f64::try_from(self.delta_real.clone())?;
1798 let di: f64 = f64::try_from(self.delta_imag.clone())?;
1799 let delta: Complex64 = Complex64::new(dr, di);
1800 let da: f64 = delta.norm(); let dp: f64 = delta.arg(); Ok(array![
1803 [
1804 Complex64::new(da.cos(), 0.0),
1805 Complex64::new(0.0, 0.0),
1806 Complex64::new(0.0, 0.0),
1807 Complex64::new(-da.sin() * dp.sin(), da.sin() * dp.cos())
1808 ],
1809 [
1810 Complex64::new(0.0, 0.0),
1811 Complex64::new(1.0, 0.0),
1812 Complex64::new(0.0, 0.0),
1813 Complex64::new(0.0, 0.0)
1814 ],
1815 [
1816 Complex64::new(0.0, 0.0),
1817 Complex64::new(0.0, 0.0),
1818 Complex64::new(1.0, 0.0),
1819 Complex64::new(0.0, 0.0)
1820 ],
1821 [
1822 Complex64::new(da.sin() * dp.sin(), da.sin() * dp.cos()),
1823 Complex64::new(0.0, 0.0),
1824 Complex64::new(0.0, 0.0),
1825 Complex64::new(da.cos(), 0.0)
1826 ],
1827 ])
1828 }
1829}
1830
1831impl OperateTwoQubitGate for Bogoliubov {
1833 fn kak_decomposition(&self) -> KakDecomposition {
1839 let dr = self.delta_real.clone();
1840 let di = self.delta_imag.clone();
1841 let delta: CalculatorComplex = CalculatorComplex::new(dr, di);
1842
1843 let mut circuit_b = Circuit::new();
1844 circuit_b += RotateZ::new(self.target, delta.arg());
1845
1846 let mut circuit_a = Circuit::new();
1847 circuit_a += RotateZ::new(self.target, delta.arg() * (-1.0));
1848
1849 KakDecomposition {
1850 global_phase: CalculatorFloat::ZERO,
1851 k_vector: [
1852 delta.norm() / (2.0),
1853 delta.norm() / (-2.0),
1854 CalculatorFloat::ZERO,
1855 ],
1856 circuit_before: Some(circuit_b),
1857 circuit_after: Some(circuit_a),
1858 }
1859 }
1860}
1861
1862#[allow(clippy::upper_case_acronyms)]
1869#[derive(
1870 Debug,
1871 Clone,
1872 PartialEq,
1873 roqoqo_derive::InvolveQubits,
1874 roqoqo_derive::SupportedVersion,
1875 roqoqo_derive::Operate,
1876 roqoqo_derive::Substitute,
1877 roqoqo_derive::OperateTwoQubit,
1878)]
1879#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1880#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
1881pub struct PMInteraction {
1882 control: usize,
1884 target: usize,
1886 t: CalculatorFloat,
1888}
1889
1890#[allow(non_upper_case_globals)]
1891const TAGS_PMInteraction: &[&str; 4] = &[
1892 "Operation",
1893 "GateOperation",
1894 "TwoQubitGateOperation",
1895 "PMInteraction",
1896];
1897
1898impl OperateGate for PMInteraction {
1900 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
1907 let c: f64 = (f64::try_from(self.t.clone())?).cos();
1908 let s: f64 = (f64::try_from(self.t.clone())?).sin();
1909 Ok(array![
1910 [
1911 Complex64::new(1.0, 0.0),
1912 Complex64::new(0.0, 0.0),
1913 Complex64::new(0.0, 0.0),
1914 Complex64::new(0.0, 0.0)
1915 ],
1916 [
1917 Complex64::new(0.0, 0.0),
1918 Complex64::new(c, 0.0),
1919 Complex64::new(0.0, -s),
1920 Complex64::new(0.0, 0.0)
1921 ],
1922 [
1923 Complex64::new(0.0, 0.0),
1924 Complex64::new(0.0, -s),
1925 Complex64::new(c, 0.0),
1926 Complex64::new(0.0, 0.0)
1927 ],
1928 [
1929 Complex64::new(0.0, 0.0),
1930 Complex64::new(0.0, 0.0),
1931 Complex64::new(0.0, 0.0),
1932 Complex64::new(1.0, 0.0)
1933 ],
1934 ])
1935 }
1936}
1937
1938impl OperateTwoQubitGate for PMInteraction {
1940 fn kak_decomposition(&self) -> KakDecomposition {
1946 KakDecomposition {
1947 global_phase: CalculatorFloat::ZERO,
1948 k_vector: [
1949 self.t.clone() / (-2.0),
1950 self.t.clone() / (-2.0),
1951 CalculatorFloat::ZERO,
1952 ],
1953 circuit_before: None,
1954 circuit_after: None,
1955 }
1956 }
1957}
1958
1959#[allow(clippy::upper_case_acronyms)]
1966#[derive(
1967 Debug,
1968 Clone,
1969 PartialEq,
1970 roqoqo_derive::InvolveQubits,
1971 roqoqo_derive::SupportedVersion,
1972 roqoqo_derive::Operate,
1973 roqoqo_derive::Substitute,
1974 roqoqo_derive::OperateTwoQubit,
1975)]
1976#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1977#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
1978pub struct ComplexPMInteraction {
1979 control: usize,
1981 target: usize,
1983 t_real: CalculatorFloat,
1985 t_imag: CalculatorFloat,
1987}
1988
1989#[allow(non_upper_case_globals)]
1990const TAGS_ComplexPMInteraction: &[&str; 4] = &[
1991 "Operation",
1992 "GateOperation",
1993 "TwoQubitGateOperation",
1994 "ComplexPMInteraction",
1995];
1996
1997impl OperateGate for ComplexPMInteraction {
1999 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
2006 let tr: f64 = f64::try_from(self.t_real.clone())?;
2007 let ti: f64 = f64::try_from(self.t_imag.clone())?;
2008 let t: Complex64 = Complex64::new(tr, ti);
2009 let tn: f64 = t.norm(); let ta: f64 = t.arg(); Ok(array![
2012 [
2013 Complex64::new(1.0, 0.0),
2014 Complex64::new(0.0, 0.0),
2015 Complex64::new(0.0, 0.0),
2016 Complex64::new(0.0, 0.0)
2017 ],
2018 [
2019 Complex64::new(0.0, 0.0),
2020 Complex64::new(tn.cos(), 0.0),
2021 Complex64::new(-tn.sin() * ta.sin(), -tn.sin() * ta.cos()),
2022 Complex64::new(0.0, 0.0)
2023 ],
2024 [
2025 Complex64::new(0.0, 0.0),
2026 Complex64::new(tn.sin() * ta.sin(), -tn.sin() * ta.cos()),
2027 Complex64::new(tn.cos(), 0.0),
2028 Complex64::new(0.0, 0.0)
2029 ],
2030 [
2031 Complex64::new(0.0, 0.0),
2032 Complex64::new(0.0, 0.0),
2033 Complex64::new(0.0, 0.0),
2034 Complex64::new(1.0, 0.0)
2035 ],
2036 ])
2037 }
2038}
2039
2040impl OperateTwoQubitGate for ComplexPMInteraction {
2042 fn kak_decomposition(&self) -> KakDecomposition {
2048 let tr = self.t_real.clone();
2049 let ti = self.t_imag.clone();
2050 let t: CalculatorComplex = CalculatorComplex::new(tr, ti);
2051
2052 let mut circuit_b = Circuit::new();
2053 circuit_b += RotateZ::new(self.target, t.arg());
2054
2055 let mut circuit_a = Circuit::new();
2056 circuit_a += RotateZ::new(self.target, t.arg() * (-1.0));
2057
2058 KakDecomposition {
2059 global_phase: CalculatorFloat::ZERO,
2060 k_vector: [t.norm() / (-2.0), t.norm() / (-2.0), CalculatorFloat::ZERO],
2061 circuit_before: Some(circuit_b),
2062 circuit_after: Some(circuit_a),
2063 }
2064 }
2065}
2066
2067#[allow(clippy::upper_case_acronyms)]
2072#[derive(
2073 Debug,
2074 Clone,
2075 PartialEq,
2076 roqoqo_derive::InvolveQubits,
2077 roqoqo_derive::SupportedVersion,
2078 roqoqo_derive::Operate,
2079 roqoqo_derive::Substitute,
2080 roqoqo_derive::OperateTwoQubit,
2081)]
2082#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
2083#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
2084pub struct PhaseShiftedControlledZ {
2085 control: usize,
2087 target: usize,
2089 phi: CalculatorFloat,
2091}
2092
2093#[allow(non_upper_case_globals)]
2094const TAGS_PhaseShiftedControlledZ: &[&str; 4] = &[
2095 "Operation",
2096 "GateOperation",
2097 "TwoQubitGateOperation",
2098 "PhaseShiftedControlledZ",
2099];
2100
2101impl OperateGate for PhaseShiftedControlledZ {
2103 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
2110 let phi: f64 = f64::try_from(self.phi.clone())?;
2112 let cos: f64 = phi.cos();
2113 let sin: f64 = phi.sin();
2114 let cos2: f64 = (2.0 * phi + PI).cos();
2115 let sin2: f64 = (2.0 * phi + PI).sin();
2116 Ok(array![
2117 [
2118 Complex64::new(1.0, 0.0),
2119 Complex64::new(0.0, 0.0),
2120 Complex64::new(0.0, 0.0),
2121 Complex64::new(0.0, 0.0)
2122 ],
2123 [
2124 Complex64::new(0.0, 0.0),
2125 Complex64::new(cos, sin),
2126 Complex64::new(0.0, 0.0),
2127 Complex64::new(0.0, 0.0)
2128 ],
2129 [
2130 Complex64::new(0.0, 0.0),
2131 Complex64::new(0.0, 0.0),
2132 Complex64::new(cos, sin),
2133 Complex64::new(0.0, 0.0)
2134 ],
2135 [
2136 Complex64::new(0.0, 0.0),
2137 Complex64::new(0.0, 0.0),
2138 Complex64::new(0.0, 0.0),
2139 Complex64::new(cos2, sin2)
2140 ],
2141 ])
2142 }
2143}
2144
2145impl OperateTwoQubitGate for PhaseShiftedControlledZ {
2147 fn kak_decomposition(&self) -> KakDecomposition {
2153 let mut circuit_b = Circuit::new();
2154 circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2);
2155 circuit_b += RotateZ::new(self.target, CalculatorFloat::FRAC_PI_2);
2156
2157 let mut circuit_a = Circuit::new();
2158 circuit_a += RotateZ::new(self.control, self.phi.clone());
2159 circuit_a += RotateZ::new(self.target, self.phi.clone());
2160
2161 let g: CalculatorFloat = CalculatorFloat::FRAC_PI_4 + self.phi.clone();
2162 KakDecomposition {
2163 global_phase: g,
2164 k_vector: [
2165 CalculatorFloat::ZERO,
2166 CalculatorFloat::ZERO,
2167 CalculatorFloat::FRAC_PI_4,
2168 ],
2169 circuit_before: Some(circuit_b),
2170 circuit_after: Some(circuit_a),
2171 }
2172 }
2173}
2174
2175#[allow(clippy::upper_case_acronyms)]
2178#[derive(
2179 Debug,
2180 Clone,
2181 PartialEq,
2182 roqoqo_derive::InvolveQubits,
2183 roqoqo_derive::Operate,
2184 roqoqo_derive::Substitute,
2185 roqoqo_derive::OperateTwoQubit,
2186 roqoqo_derive::Rotate,
2187)]
2188#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
2189#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
2190pub struct PhaseShiftedControlledPhase {
2191 control: usize,
2193 target: usize,
2195 theta: CalculatorFloat,
2197 phi: CalculatorFloat,
2199}
2200
2201impl SupportedVersion for PhaseShiftedControlledPhase {
2202 fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
2203 (1, 2, 0)
2204 }
2205}
2206
2207impl super::ImplementedIn1point2 for PhaseShiftedControlledPhase {}
2208
2209#[allow(non_upper_case_globals)]
2210const TAGS_PhaseShiftedControlledPhase: &[&str; 4] = &[
2211 "Operation",
2212 "GateOperation",
2213 "TwoQubitGateOperation",
2214 "PhaseShiftedControlledPhase",
2215];
2216
2217impl OperateGate for PhaseShiftedControlledPhase {
2219 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
2226 let phi: f64 = f64::try_from(self.phi.clone())?;
2228 let theta: f64 = f64::try_from(self.theta.clone())?;
2229 let cos: f64 = phi.cos();
2230 let sin: f64 = phi.sin();
2231 let cos2: f64 = (2.0 * phi + theta).cos();
2232 let sin2: f64 = (2.0 * phi + theta).sin();
2233 Ok(array![
2234 [
2235 Complex64::new(1.0, 0.0),
2236 Complex64::new(0.0, 0.0),
2237 Complex64::new(0.0, 0.0),
2238 Complex64::new(0.0, 0.0)
2239 ],
2240 [
2241 Complex64::new(0.0, 0.0),
2242 Complex64::new(cos, sin),
2243 Complex64::new(0.0, 0.0),
2244 Complex64::new(0.0, 0.0)
2245 ],
2246 [
2247 Complex64::new(0.0, 0.0),
2248 Complex64::new(0.0, 0.0),
2249 Complex64::new(cos, sin),
2250 Complex64::new(0.0, 0.0)
2251 ],
2252 [
2253 Complex64::new(0.0, 0.0),
2254 Complex64::new(0.0, 0.0),
2255 Complex64::new(0.0, 0.0),
2256 Complex64::new(cos2, sin2)
2257 ],
2258 ])
2259 }
2260}
2261
2262impl OperateTwoQubitGate for PhaseShiftedControlledPhase {
2264 fn kak_decomposition(&self) -> KakDecomposition {
2270 let mut circuit_b = Circuit::new();
2271 circuit_b += RotateZ::new(self.control, self.theta.clone() / 2.0);
2272 circuit_b += RotateZ::new(self.target, self.theta.clone() / 2.0);
2273
2274 let mut circuit_a = Circuit::new();
2275 circuit_a += RotateZ::new(self.control, self.phi.clone());
2276 circuit_a += RotateZ::new(self.target, self.phi.clone());
2277
2278 let g: CalculatorFloat = self.theta.clone() / 4.0 + self.phi.clone();
2279 KakDecomposition {
2280 global_phase: g,
2281 k_vector: [
2282 CalculatorFloat::ZERO,
2283 CalculatorFloat::ZERO,
2284 self.theta.clone() / 4.0,
2285 ],
2286 circuit_before: Some(circuit_b),
2287 circuit_after: Some(circuit_a),
2288 }
2289 }
2290}
2291
2292#[allow(clippy::upper_case_acronyms)]
2294#[derive(
2295 Debug,
2296 Clone,
2297 PartialEq,
2298 roqoqo_derive::InvolveQubits,
2299 roqoqo_derive::Operate,
2300 roqoqo_derive::Substitute,
2301 roqoqo_derive::OperateTwoQubit,
2302 roqoqo_derive::Rotate,
2303)]
2304#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
2305#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
2306pub struct ControlledRotateX {
2307 control: usize,
2309 target: usize,
2311 theta: CalculatorFloat,
2313}
2314
2315impl SupportedVersion for ControlledRotateX {
2316 fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
2317 (1, 3, 0)
2318 }
2319}
2320
2321impl super::ImplementedIn1point3 for ControlledRotateX {}
2322
2323#[allow(non_upper_case_globals)]
2324const TAGS_ControlledRotateX: &[&str; 5] = &[
2325 "Operation",
2326 "GateOperation",
2327 "TwoQubitGateOperation",
2328 "Rotation",
2329 "ControlledRotateX",
2330];
2331
2332impl OperateGate for ControlledRotateX {
2334 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
2341 let c: f64 = (f64::try_from(self.theta.clone())? / 2.0).cos();
2342 let s: f64 = (f64::try_from(self.theta.clone())? / 2.0).sin();
2343 Ok(array![
2344 [
2345 Complex64::new(1.0, 0.0),
2346 Complex64::new(0.0, 0.0),
2347 Complex64::new(0.0, 0.0),
2348 Complex64::new(0.0, 0.0)
2349 ],
2350 [
2351 Complex64::new(0.0, 0.0),
2352 Complex64::new(1.0, 0.0),
2353 Complex64::new(0.0, 0.0),
2354 Complex64::new(0.0, 0.0)
2355 ],
2356 [
2357 Complex64::new(0.0, 0.0),
2358 Complex64::new(0.0, 0.0),
2359 Complex64::new(c, 0.0),
2360 Complex64::new(0.0, -s)
2361 ],
2362 [
2363 Complex64::new(0.0, 0.0),
2364 Complex64::new(0.0, 0.0),
2365 Complex64::new(0.0, -s),
2366 Complex64::new(c, 0.0)
2367 ]
2368 ])
2369 }
2370}
2371
2372impl OperateTwoQubitGate for ControlledRotateX {
2374 fn kak_decomposition(&self) -> KakDecomposition {
2380 let mut circuit_b = Circuit::new();
2381 circuit_b += Hadamard::new(self.target);
2382 circuit_b += RotateZ::new(self.target, self.theta.clone() / 2.0);
2383
2384 let mut circuit_a = Circuit::new();
2385 circuit_a += Hadamard::new(self.target);
2386
2387 KakDecomposition {
2388 global_phase: CalculatorFloat::ZERO,
2389 k_vector: [
2390 CalculatorFloat::ZERO,
2391 CalculatorFloat::ZERO,
2392 self.theta.clone() / 4.0,
2393 ],
2394 circuit_before: Some(circuit_b),
2395 circuit_after: Some(circuit_a),
2396 }
2397 }
2398}
2399
2400#[allow(clippy::upper_case_acronyms)]
2402#[derive(
2403 Debug,
2404 Clone,
2405 PartialEq,
2406 roqoqo_derive::InvolveQubits,
2407 roqoqo_derive::Operate,
2408 roqoqo_derive::Substitute,
2409 roqoqo_derive::OperateTwoQubit,
2410 roqoqo_derive::Rotate,
2411)]
2412#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
2413#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
2414pub struct ControlledRotateXY {
2415 control: usize,
2417 target: usize,
2419 theta: CalculatorFloat,
2421 phi: CalculatorFloat,
2423}
2424impl SupportedVersion for ControlledRotateXY {
2425 fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
2426 (1, 3, 0)
2427 }
2428}
2429
2430impl super::ImplementedIn1point3 for ControlledRotateXY {}
2431
2432#[allow(non_upper_case_globals)]
2433const TAGS_ControlledRotateXY: &[&str; 5] = &[
2434 "Operation",
2435 "GateOperation",
2436 "TwoQubitGateOperation",
2437 "Rotation",
2438 "ControlledRotateXY",
2439];
2440
2441impl OperateGate for ControlledRotateXY {
2443 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
2450 let c: f64 = (f64::try_from(self.theta.clone())? / 2.0).cos();
2451 let s: f64 = (f64::try_from(self.theta.clone())? / 2.0).sin();
2452 let vx: f64 = (f64::try_from(self.phi.clone())?).cos();
2453 let vy: f64 = (f64::try_from(self.phi.clone())?).sin();
2454 Ok(array![
2455 [
2456 Complex64::new(1.0, 0.0),
2457 Complex64::new(0.0, 0.0),
2458 Complex64::new(0.0, 0.0),
2459 Complex64::new(0.0, 0.0)
2460 ],
2461 [
2462 Complex64::new(0.0, 0.0),
2463 Complex64::new(1.0, 0.0),
2464 Complex64::new(0.0, 0.0),
2465 Complex64::new(0.0, 0.0)
2466 ],
2467 [
2468 Complex64::new(0.0, 0.0),
2469 Complex64::new(0.0, 0.0),
2470 Complex64::new(c, 0.0),
2471 Complex64::new(-s * vy, -s * vx)
2472 ],
2473 [
2474 Complex64::new(0.0, 0.0),
2475 Complex64::new(0.0, 0.0),
2476 Complex64::new(s * vy, -s * vx),
2477 Complex64::new(c, 0.0)
2478 ]
2479 ])
2480 }
2481}
2482
2483impl OperateTwoQubitGate for ControlledRotateXY {
2485 fn kak_decomposition(&self) -> KakDecomposition {
2491 let mut circuit_b = Circuit::new();
2492 circuit_b += RotateZ::new(self.target, -self.phi.clone());
2493 circuit_b += Hadamard::new(self.target);
2494 circuit_b += RotateZ::new(self.target, self.theta.clone() / 2.0);
2495
2496 let mut circuit_a = Circuit::new();
2497 circuit_a += Hadamard::new(self.target);
2498 circuit_a += RotateZ::new(self.target, self.phi.clone());
2499
2500 KakDecomposition {
2501 global_phase: CalculatorFloat::ZERO,
2502 k_vector: [
2503 CalculatorFloat::ZERO,
2504 CalculatorFloat::ZERO,
2505 self.theta.clone() / 4.0,
2506 ],
2507 circuit_before: Some(circuit_b),
2508 circuit_after: Some(circuit_a),
2509 }
2510 }
2511}
2512
2513#[allow(clippy::upper_case_acronyms)]
2515#[derive(
2516 Debug,
2517 Clone,
2518 PartialEq,
2519 roqoqo_derive::InvolveQubits,
2520 roqoqo_derive::Operate,
2521 roqoqo_derive::Substitute,
2522 roqoqo_derive::OperateTwoQubit,
2523)]
2524#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
2525#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
2526pub struct EchoCrossResonance {
2527 control: usize,
2529 target: usize,
2531}
2532impl SupportedVersion for EchoCrossResonance {
2533 fn minimum_supported_roqoqo_version(&self) -> (u32, u32, u32) {
2534 (1, 8, 0)
2535 }
2536}
2537
2538impl super::ImplementedIn1point8 for EchoCrossResonance {}
2539
2540#[allow(non_upper_case_globals)]
2541const TAGS_EchoCrossResonance: &[&str; 4] = &[
2542 "Operation",
2543 "GateOperation",
2544 "TwoQubitGateOperation",
2545 "EchoCrossResonance",
2546];
2547
2548impl OperateGate for EchoCrossResonance {
2550 fn unitary_matrix(&self) -> Result<Array2<Complex64>, RoqoqoError> {
2557 let matrix: Array2<Complex64> = array![
2558 [
2559 Complex64::new(0.0, 0.0),
2560 Complex64::new(0.0, 0.0),
2561 Complex64::new(1.0, 0.0),
2562 Complex64::new(0.0, 1.0)
2563 ],
2564 [
2565 Complex64::new(0.0, 0.0),
2566 Complex64::new(0.0, 0.0),
2567 Complex64::new(0.0, 1.0),
2568 Complex64::new(1.0, 0.0)
2569 ],
2570 [
2571 Complex64::new(1.0, 0.0),
2572 Complex64::new(0.0, -1.0),
2573 Complex64::new(0.0, 0.0),
2574 Complex64::new(0.0, 0.0)
2575 ],
2576 [
2577 Complex64::new(0.0, -1.0),
2578 Complex64::new(1.0, 0.0),
2579 Complex64::new(0.0, 0.0),
2580 Complex64::new(0.0, 0.0)
2581 ]
2582 ];
2583 Ok(matrix / 2.0_f64.sqrt())
2584 }
2585}
2586
2587impl OperateTwoQubitGate for EchoCrossResonance {
2589 fn kak_decomposition(&self) -> KakDecomposition {
2595 let mut circuit_b = Circuit::new();
2596 circuit_b += SGate::new(self.control);
2597 circuit_b += RotateZ::new(self.control, CalculatorFloat::FRAC_PI_2);
2598 circuit_b += RotateY::new(self.control, CalculatorFloat::FRAC_PI_2);
2599 circuit_b += RotateX::new(self.target, CalculatorFloat::PI);
2600
2601 let mut circuit_a = Circuit::new();
2602 circuit_a += RotateY::new(self.control, CalculatorFloat::FRAC_PI_2 * (-1.0));
2603 circuit_a += PauliX::new(self.control);
2604
2605 KakDecomposition {
2606 global_phase: CalculatorFloat::FRAC_PI_4,
2607 k_vector: [
2608 CalculatorFloat::FRAC_PI_4,
2609 CalculatorFloat::ZERO,
2610 CalculatorFloat::ZERO,
2611 ],
2612 circuit_before: Some(circuit_b),
2613 circuit_after: Some(circuit_a),
2614 }
2615 }
2616}