1use crate::UnitaryExpression;
2use crate::UnitarySystemExpression;
3#[cfg(feature = "python")]
4use pyo3_stub_gen::derive::gen_stub_pyfunction;
5use qudit_core::QuditSystem;
6use qudit_core::Radices;
7
8#[cfg_attr(
10 feature = "python",
11 gen_stub_pyfunction(module = "openqudit.expressions")
12)]
13#[cfg_attr(feature = "python", pyo3::pyfunction)]
14#[cfg_attr(feature = "python", pyo3(signature = (radix = 2)))]
15pub fn IGate(radix: usize) -> UnitaryExpression {
16 let proto = format!("I<{}>()", radix);
17 let mut body = "".to_string();
18 body += "[";
19 for i in 0..radix {
20 body += "[";
21 for j in 0..radix {
22 if i == j {
23 body += "1,";
24 } else {
25 body += "0,";
26 }
27 }
28 body += "],";
29 }
30 body += "]";
31
32 UnitaryExpression::new(proto + "{" + &body + "}")
33}
34
35#[cfg_attr(
66 feature = "python",
67 gen_stub_pyfunction(module = "openqudit.expressions")
68)]
69#[cfg_attr(feature = "python", pyo3::pyfunction)]
70#[cfg_attr(feature = "python", pyo3(signature = (radix = 2)))]
71pub fn HGate(radix: usize) -> UnitaryExpression {
72 let proto = format!("H<{}>()", radix);
73 let mut body = "".to_string();
74 if radix == 2 {
75 body += "[[sqrt(2)/2, sqrt(2)/2], [sqrt(2)/2, ~sqrt(2)/2]]";
76 return UnitaryExpression::new(proto + "{" + &body + "}");
77 }
78 let invsqrt = format!("1/sqrt({})", radix);
79 body += invsqrt.as_str();
80 body += " * ";
81 body += "[";
82 for i in 0..radix {
83 body += "[";
84 for j in 0..radix {
85 body += &format!("e^(2*π*i*{}*{}/{}), ", i, j, radix);
90 }
91 body += "],";
92 }
93 body += "]";
94
95 UnitaryExpression::new(proto + "{" + &body + "}")
96}
97
98#[cfg_attr(
141 feature = "python",
142 gen_stub_pyfunction(module = "openqudit.expressions")
143)]
144#[cfg_attr(feature = "python", pyo3::pyfunction)]
145#[cfg_attr(feature = "python", pyo3(signature = (radix = 2)))]
146pub fn SwapGate(radix: usize) -> UnitaryExpression {
147 let proto = format!("Swap<{}, {}>()", radix, radix);
148 let dim = radix * radix;
149 let mut body = "".to_string();
150 body += "[";
151 for i in 0..dim {
152 body += "[";
153 let a_i = i / radix;
154 let b_i = i % radix;
155 for j in 0..dim {
156 let a_j = j / radix;
157 let b_j = j % radix;
158 if a_i == b_j && b_i == a_j {
159 body += "1,";
160 } else {
161 body += "0,";
162 }
163 }
164 body += "],";
165 }
166 body += "]";
167
168 UnitaryExpression::new(proto + "{" + &body + "}")
169}
170
171#[cfg_attr(
199 feature = "python",
200 gen_stub_pyfunction(module = "openqudit.expressions")
201)]
202#[cfg_attr(feature = "python", pyo3::pyfunction)]
203#[cfg_attr(feature = "python", pyo3(signature = (radix = 2)))]
204pub fn XGate(radix: usize) -> UnitaryExpression {
205 let proto = format!("X<{}>()", radix);
206 let mut body = "[".to_string();
207 for i in 0..radix {
208 body += "[";
209 for j in 0..radix {
210 if (j + 1) % radix == i {
211 body += "1, ";
212 } else {
213 body += "0, ";
214 }
215 }
216 body += "],";
217 }
218 body += "]";
219
220 UnitaryExpression::new(proto + "{" + &body + "}")
221}
222
223#[cfg_attr(
251 feature = "python",
252 gen_stub_pyfunction(module = "openqudit.expressions")
253)]
254#[cfg_attr(feature = "python", pyo3::pyfunction)]
255#[cfg_attr(feature = "python", pyo3(signature = (radix = 2)))]
256pub fn ZGate(radix: usize) -> UnitaryExpression {
257 let proto = format!("Z<{}>()", radix);
258 let mut body = "[".to_string();
259 for i in 0..radix {
260 body += "[";
261 for j in 0..radix {
262 if i == j {
263 if i == 0 {
264 body += "1, ";
265 } else {
266 body += &format!("e^((2*{}*π*i)/{}), ", j, radix);
267 }
268 } else {
269 body += "0, ";
270 }
271 }
272 body += "],";
273 }
274 body += "]";
275
276 UnitaryExpression::new(proto + "{" + &body + "}")
277}
278
279#[cfg_attr(
298 feature = "python",
299 gen_stub_pyfunction(module = "openqudit.expressions")
300)]
301#[cfg_attr(feature = "python", pyo3::pyfunction)]
302#[cfg_attr(feature = "python", pyo3(signature = (radix = 2)))]
303pub fn YGate(radix: usize) -> UnitaryExpression {
304 let proto = format!("Y<{}>()", radix);
305 let mut body = "[".to_string();
306 for i in 0..radix {
307 body += "[";
308 for j in 0..radix {
309 if (j + 1) % radix == i {
310 body += &format!("e^(2*π*i*(2*{}+{}-1)/(2*{})), ", j, radix, radix);
312 } else {
313 body += "0, ";
314 }
315 }
316 body += "],";
317 }
318 body += "]";
319 UnitaryExpression::new(proto + "{" + &body + "}")
320}
321
322#[cfg_attr(
345 feature = "python",
346 gen_stub_pyfunction(module = "openqudit.expressions")
347)]
348#[cfg_attr(feature = "python", pyo3::pyfunction)]
349#[cfg_attr(feature = "python", pyo3(signature = (radix = 2)))]
350pub fn SGate(radix: usize) -> UnitaryExpression {
351 let proto = format!("S<{}>()", radix);
352 let mut body = "[".to_string();
353 for i in 0..radix {
354 body += "[";
355 for j in 0..radix {
356 if i == j {
357 if i == 0 {
358 body += "1, ";
359 } else {
360 body += &format!("e^(π*i*{}*{}/{}), ", i, i, radix);
362 }
363 } else {
364 body += "0, ";
365 }
366 }
367 body += "],";
368 }
369 body += "]";
370 UnitaryExpression::new(proto + "{" + &body + "}")
371}
372
373#[cfg_attr(
398 feature = "python",
399 gen_stub_pyfunction(module = "openqudit.expressions")
400)]
401#[cfg_attr(feature = "python", pyo3::pyfunction)]
402#[cfg_attr(feature = "python", pyo3(signature = (radix = 2)))]
403pub fn TGate(radix: usize) -> UnitaryExpression {
404 let proto = format!("T<{}>()", radix);
405 let mut body = "[".to_string();
406 for i in 0..radix {
407 body += "[";
408 for j in 0..radix {
409 if i == j {
410 if i == 0 {
411 body += "1, ";
412 } else {
413 body += &format!("e^(π*i*{}*{}/(2*{})), ", i, i, radix);
415 }
416 } else {
417 body += "0, ";
418 }
419 }
420 body += "],";
421 }
422 body += "]";
423 UnitaryExpression::new(proto + "{" + &body + "}")
424}
425
426#[cfg_attr(
455 feature = "python",
456 gen_stub_pyfunction(module = "openqudit.expressions")
457)]
458#[cfg_attr(feature = "python", pyo3::pyfunction)]
459#[cfg_attr(feature = "python", pyo3(signature = (radix = 2)))]
460pub fn PGate(radix: usize) -> UnitaryExpression {
461 let mut proto = format!("P<{}>(", radix);
462 for i in 0..radix - 1 {
463 proto += "θ";
464 proto += &i.to_string();
465 proto += ", ";
466 }
467 proto += ")";
468
469 let mut body = "".to_string();
470 body += "[";
471 for i in 0..radix {
472 body += "[";
473 for j in 0..radix {
474 if i == j {
475 if i == 0 {
476 body += "1, ";
477 } else {
478 body += &format!("e^(i*θ{}), ", i - 1);
479 }
480 } else {
481 body += "0, ";
482 }
483 }
484 body += "],";
485 }
486 body += "]";
487
488 UnitaryExpression::new(proto + "{" + &body + "}")
489}
490
491#[cfg_attr(
492 feature = "python",
493 gen_stub_pyfunction(module = "openqudit.expressions")
494)]
495#[cfg_attr(feature = "python", pyo3::pyfunction)]
496pub fn U3Gate() -> UnitaryExpression {
497 let proto = "U(θ0, θ1, θ2)";
498 let body = "[
499 [cos(θ0/2), ~e^(i*θ2)*sin(θ0/2)],
500 [e^(i*θ1)*sin(θ0/2), e^(i*(θ1+θ2))*cos(θ0/2)]
501 ]";
502 UnitaryExpression::new(proto.to_owned() + "{" + body + "}")
503}
504
505#[cfg_attr(
511 feature = "python",
512 gen_stub_pyfunction(module = "openqudit.expressions")
513)]
514#[cfg_attr(feature = "python", pyo3::pyfunction)]
515pub fn U1Gate() -> UnitaryExpression {
516 let proto = "U1(θ0)";
517 let body = "[[1, 0], [0, e^(i*θ0)]]";
518 UnitaryExpression::new(proto.to_owned() + "{" + body + "}")
519}
520
521#[cfg_attr(
528 feature = "python",
529 gen_stub_pyfunction(module = "openqudit.expressions")
530)]
531#[cfg_attr(feature = "python", pyo3::pyfunction)]
532pub fn U2Gate() -> UnitaryExpression {
533 let proto = "U2(θ0, θ1)";
534 let body = "1/sqrt(2) * [[1, ~e^(i*θ1)], [e^(i*θ0), e^(i*(θ0+θ1))]]";
535 UnitaryExpression::new(proto.to_owned() + "{" + body + "}")
536}
537
538#[cfg_attr(
548 feature = "python",
549 gen_stub_pyfunction(module = "openqudit.expressions")
550)]
551#[cfg_attr(feature = "python", pyo3::pyfunction)]
552pub fn SXGate() -> UnitaryExpression {
553 let proto = "SX()";
554 let body = "1/2 * [[1+i, 1-i], [1-i, 1+i]]";
555 UnitaryExpression::new(proto.to_owned() + "{" + body + "}")
556}
557
558#[cfg_attr(
564 feature = "python",
565 gen_stub_pyfunction(module = "openqudit.expressions")
566)]
567#[cfg_attr(feature = "python", pyo3::pyfunction)]
568pub fn RXGate() -> UnitaryExpression {
569 let proto = "RX(θ0)";
570 let body = "[[cos(θ0/2), ~i*sin(θ0/2)], [~i*sin(θ0/2), cos(θ0/2)]]";
571 UnitaryExpression::new(proto.to_owned() + "{" + body + "}")
572}
573
574#[cfg_attr(
580 feature = "python",
581 gen_stub_pyfunction(module = "openqudit.expressions")
582)]
583#[cfg_attr(feature = "python", pyo3::pyfunction)]
584pub fn RYGate() -> UnitaryExpression {
585 let proto = "RY(θ0)";
586 let body = "[[cos(θ0/2), ~sin(θ0/2)], [sin(θ0/2), cos(θ0/2)]]";
587 UnitaryExpression::new(proto.to_owned() + "{" + body + "}")
588}
589
590#[cfg_attr(
596 feature = "python",
597 gen_stub_pyfunction(module = "openqudit.expressions")
598)]
599#[cfg_attr(feature = "python", pyo3::pyfunction)]
600pub fn RZGate() -> UnitaryExpression {
601 let proto = "RZ(θ0)";
602 let body = "[[e^(~i*θ0/2), 0], [0, e^(i*θ0/2)]]";
603 UnitaryExpression::new(proto.to_owned() + "{" + body + "}")
604}
605
606fn generate_embedded_two_param_su2(dimension: usize, i: usize, j: usize) -> UnitaryExpression {
607 let proto = format!("U<{dimension}>(θ0, θ1)");
608 let mut body = String::from("[");
609 for row in 0..dimension {
610 body += "[";
611 for col in 0..dimension {
612 if row == i && col == i {
613 body += "e^(i*θ1)*cos(θ0/2)";
614 } else if row == i && col == j {
615 body += "~sin(θ0/2)";
616 } else if row == j && col == i {
617 body += "sin(θ0/2)";
618 } else if row == j && col == j {
619 body += "e^(i*(~θ1))*cos(θ0/2)";
620 } else if row == col {
621 body += "1";
622 } else {
623 body += "0";
624 }
625 body += ",";
626 }
627 body += "]";
628 }
629 body += "]";
630 UnitaryExpression::new(proto.to_owned() + "{" + &body + "}")
631}
632
633fn generate_embedded_su2(dimension: usize, i: usize, j: usize) -> UnitaryExpression {
634 let proto = format!("U<{dimension}>(θ0, θ1, θ2)");
635 let mut body = String::from("[");
636 for row in 0..dimension {
637 body += "[";
638 for col in 0..dimension {
639 if row == i && col == i {
640 body += "cos(θ0/2)";
641 } else if row == i && col == j {
642 body += "~e^(i*θ2)*sin(θ0/2)";
643 } else if row == j && col == i {
644 body += "e^(i*θ1)*sin(θ0/2)";
645 } else if row == j && col == j {
646 body += "e^(i*(θ1+θ2))*cos(θ0/2)";
647 } else if row == col {
648 body += "1";
649 } else {
650 body += "0";
651 }
652 body += ",";
653 }
654 body += "]";
655 }
656 body += "]";
657 UnitaryExpression::new(proto.to_owned() + "{" + &body + "}")
658}
659
660#[cfg_attr(
672 feature = "python",
673 gen_stub_pyfunction(module = "openqudit.expressions")
674)]
675#[cfg_attr(feature = "python", pyo3::pyfunction)]
676pub fn RXXGate() -> UnitaryExpression {
677 let proto = "RXX<2, 2>(θ0)";
678 let body = "[\
679 [cos(θ0/2), 0, 0, ~i*sin(θ0/2)],\
680 [0, cos(θ0/2), ~i*sin(θ0/2), 0],\
681 [0, ~i*sin(θ0/2), cos(θ0/2), 0],\
682 [~i*sin(θ0/2), 0, 0, cos(θ0/2)]\
683 ]";
684 UnitaryExpression::new(proto.to_owned() + "{" + body + "}")
685}
686
687#[cfg_attr(
699 feature = "python",
700 gen_stub_pyfunction(module = "openqudit.expressions")
701)]
702#[cfg_attr(feature = "python", pyo3::pyfunction)]
703pub fn RYYGate() -> UnitaryExpression {
704 let proto = "RYY<2, 2>(θ0)";
705 let body = "[\
706 [cos(θ0/2), 0, 0, i*sin(θ0/2)],\
707 [0, cos(θ0/2), ~i*sin(θ0/2), 0],\
708 [0, ~i*sin(θ0/2), cos(θ0/2), 0],\
709 [i*sin(θ0/2), 0, 0, cos(θ0/2)]\
710 ]";
711 UnitaryExpression::new(proto.to_owned() + "{" + body + "}")
712}
713
714#[cfg_attr(
726 feature = "python",
727 gen_stub_pyfunction(module = "openqudit.expressions")
728)]
729#[cfg_attr(feature = "python", pyo3::pyfunction)]
730pub fn RZZGate() -> UnitaryExpression {
731 let proto = "RZZ<2, 2>(θ0)";
732 let body = "[\
733 [e^(~i*θ0/2), 0, 0, 0],\
734 [0, e^(i*θ0/2), 0, 0],\
735 [0, 0, e^(i*θ0/2), 0],\
736 [0, 0, 0, e^(~i*θ0/2)]\
737 ]";
738 UnitaryExpression::new(proto.to_owned() + "{" + body + "}")
739}
740
741fn embed_one_larger(unitary: UnitaryExpression) -> UnitaryExpression {
742 let dimension = unitary.dimension() + 1;
743 let mut one_larger = UnitaryExpression::identity(unitary.name(), [dimension]);
744 one_larger.embed(unitary, 1, 1);
745 one_larger
746}
747
748#[cfg_attr(
755 feature = "python",
756 gen_stub_pyfunction(module = "openqudit.expressions")
757)]
758#[cfg_attr(feature = "python", pyo3::pyfunction)]
759#[cfg_attr(feature = "python", pyo3(signature = (radices = Radices::new([2]))))]
760pub fn ParameterizedUnitary(radices: Radices) -> UnitaryExpression {
761 let dimension = radices.dimension();
762
763 if dimension < 2 {
764 panic!("Cannot generate parameterized unitary for dimension 1 or less");
765 }
766
767 if dimension == 2 {
768 return U3Gate();
769 }
770
771 let right = {
772 let one_smaller = ParameterizedUnitary(Radices::new([dimension - 1]));
773 embed_one_larger(one_smaller)
774 };
775
776 let left = {
777 let mut acm = generate_embedded_su2(dimension, dimension - 2, dimension - 1);
778 for i in (0..=(dimension - 3)).rev() {
779 let j = i + 1;
780 let two = generate_embedded_two_param_su2(dimension, i, j);
781 acm = acm.dot(two)
782 }
783 acm
784 };
785
786 let mut expression = left.dot(right);
787 expression.set_radices(radices);
788 expression
789}
790
791#[cfg_attr(
793 feature = "python",
794 gen_stub_pyfunction(module = "openqudit.expressions")
795)]
796#[cfg_attr(feature = "python", pyo3::pyfunction)]
797pub fn Invert(mut expr: UnitaryExpression) -> UnitaryExpression {
798 expr.dagger();
799 expr
800}
801
802#[cfg_attr(
809 feature = "python",
810 gen_stub_pyfunction(module = "openqudit.expressions")
811)]
812#[cfg_attr(feature = "python", pyo3::pyfunction)]
813pub fn Dagger(mut expr: UnitaryExpression) -> UnitaryExpression {
814 let new_name = format!("Dagger({})", expr.name());
815 expr.dagger();
816 expr.set_name(new_name);
817 expr
818}
819
820fn cartesian_product(control_levels: Vec<Vec<usize>>) -> Vec<Vec<usize>> {
835 let mut prod = vec![];
836 for level in control_levels.into_iter() {
837 if prod.is_empty() {
838 for l in level.into_iter() {
839 prod.push(vec![l]);
840 }
841 } else {
842 let mut new_prod = vec![];
843 for l in level.into_iter() {
844 for v in prod.iter() {
845 let mut v_new = v.clone();
846 v_new.push(l);
847 new_prod.push(v_new);
848 }
849 }
850 prod = new_prod;
851 }
852 }
853 prod
854}
855
856#[cfg_attr(
991 feature = "python",
992 gen_stub_pyfunction(module = "openqudit.expressions")
993)]
994#[cfg_attr(feature = "python", pyo3::pyfunction)]
995#[cfg_attr(feature = "python", pyo3(signature = (expr, control_radices = Radices::new([2]), control_levels = None)))]
996pub fn Controlled(
997 expr: UnitaryExpression,
998 control_radices: Radices,
999 control_levels: Option<Vec<Vec<usize>>>,
1000) -> UnitaryExpression {
1001 let control_levels = match control_levels {
1002 Some(levels) => levels,
1003 None => {
1004 control_radices
1006 .iter()
1007 .map(|&radix| vec![(usize::from(radix) - 1)])
1008 .collect()
1009 }
1010 };
1011
1012 if control_radices.len() != control_levels.len() {
1013 panic!("control_radices and control_levels must have the same length");
1014 }
1015
1016 if control_levels.iter().any(|levels| levels.is_empty()) {
1017 panic!("control_levels must not contain empty levels");
1018 }
1019
1020 if control_levels
1021 .iter()
1022 .map(|levels| levels.iter().copied())
1023 .zip(control_radices.iter())
1024 .any(|(mut levels, radix)| levels.any(|level| level >= usize::from(*radix)))
1025 {
1026 panic!("Expected control levels to be less than the number of levels.");
1027 }
1028
1029 let mut control_level_sets = control_levels.clone();
1031 for level in control_level_sets.iter_mut() {
1032 level.sort();
1033 level.dedup();
1034 }
1035 if control_level_sets
1036 .iter()
1037 .zip(control_levels.iter())
1038 .any(|(level_dedup, level)| level.len() != level_dedup.len())
1039 {
1040 panic!("Expected control levels to be unique.");
1041 }
1042
1043 let gate_expr = expr;
1044 let gate_dim = gate_expr.dimension();
1045
1046 let name = format!("Controlled({})", gate_expr.name());
1048 let radices = control_radices.concat(&gate_expr.radices());
1049 let mut expr = UnitaryExpression::identity(&name, radices);
1050
1051 let diagonal_indices: Vec<usize> = cartesian_product(control_levels)
1053 .into_iter()
1054 .map(|block_idx_expansion| control_radices.compress(&block_idx_expansion))
1055 .map(|block_diag_idx| block_diag_idx * gate_dim)
1056 .collect();
1057
1058 for diagonal_idx in diagonal_indices.iter() {
1059 expr.embed(gate_expr.clone(), *diagonal_idx, *diagonal_idx);
1060 }
1061
1062 expr
1063}
1064
1065#[cfg_attr(
1066 feature = "python",
1067 gen_stub_pyfunction(module = "openqudit.expressions")
1068)]
1069#[cfg_attr(feature = "python", pyo3::pyfunction)]
1070#[cfg_attr(feature = "python", pyo3(signature = (expr, control_radices = Radices::new([2]), control_levels = None)))]
1071pub fn ClassicallyControlled(
1072 expr: UnitaryExpression,
1073 control_radices: Radices,
1074 control_levels: Option<Vec<Vec<usize>>>,
1075) -> UnitarySystemExpression {
1076 let control_levels = match control_levels {
1077 Some(levels) => levels,
1078 None => {
1079 control_radices
1081 .iter()
1082 .map(|&radix| vec![(usize::from(radix) - 1)])
1083 .collect()
1084 }
1085 };
1086
1087 if control_radices.len() != control_levels.len() {
1088 panic!("control_radices and control_levels must have the same length");
1089 }
1090
1091 if control_levels.iter().any(|levels| levels.is_empty()) {
1092 panic!("control_levels must not contain empty levels");
1093 }
1094
1095 if control_levels
1096 .iter()
1097 .map(|levels| levels.iter().copied())
1098 .zip(control_radices.iter())
1099 .any(|(mut levels, radix)| levels.any(|level| level >= usize::from(*radix)))
1100 {
1101 panic!("Expected control levels to be less than the number of levels.");
1102 }
1103
1104 let mut control_level_sets = control_levels.clone();
1106 for level in control_level_sets.iter_mut() {
1107 level.sort();
1108 level.dedup();
1109 }
1110 if control_level_sets
1111 .iter()
1112 .zip(control_levels.iter())
1113 .any(|(level_dedup, level)| level.len() != level_dedup.len())
1114 {
1115 panic!("Expected control levels to be unique.");
1116 }
1117
1118 let diagonal_indices: Vec<usize> = cartesian_product(control_levels)
1119 .into_iter()
1120 .map(|block_idx_expansion| control_radices.compress(&block_idx_expansion))
1121 .collect();
1122
1123 let new_radices = control_radices
1124 .iter()
1125 .map(|&r| r.into())
1126 .collect::<Vec<_>>();
1127 expr.classically_control(&diagonal_indices, &new_radices)
1128}
1129
1130#[cfg(feature = "python")]
1131mod python {
1132 use crate::python::PyExpressionRegistrar;
1133 use pyo3::prelude::*;
1134
1135 fn register(parent_module: &Bound<'_, PyModule>) -> PyResult<()> {
1137 parent_module.add_function(wrap_pyfunction!(super::IGate, parent_module)?)?;
1138 parent_module.add_function(wrap_pyfunction!(super::HGate, parent_module)?)?;
1139 parent_module.add_function(wrap_pyfunction!(super::SwapGate, parent_module)?)?;
1140 parent_module.add_function(wrap_pyfunction!(super::XGate, parent_module)?)?;
1141 parent_module.add_function(wrap_pyfunction!(super::ZGate, parent_module)?)?;
1142 parent_module.add_function(wrap_pyfunction!(super::YGate, parent_module)?)?;
1143 parent_module.add_function(wrap_pyfunction!(super::SGate, parent_module)?)?;
1144 parent_module.add_function(wrap_pyfunction!(super::TGate, parent_module)?)?;
1145 parent_module.add_function(wrap_pyfunction!(super::PGate, parent_module)?)?;
1146 parent_module.add_function(wrap_pyfunction!(super::U3Gate, parent_module)?)?;
1147 parent_module.add_function(wrap_pyfunction!(super::U1Gate, parent_module)?)?;
1148 parent_module.add_function(wrap_pyfunction!(super::U2Gate, parent_module)?)?;
1149 parent_module.add_function(wrap_pyfunction!(super::SXGate, parent_module)?)?;
1150 parent_module.add_function(wrap_pyfunction!(super::RXGate, parent_module)?)?;
1151 parent_module.add_function(wrap_pyfunction!(super::RYGate, parent_module)?)?;
1152 parent_module.add_function(wrap_pyfunction!(super::RZGate, parent_module)?)?;
1153 parent_module.add_function(wrap_pyfunction!(super::RXXGate, parent_module)?)?;
1154 parent_module.add_function(wrap_pyfunction!(super::RYYGate, parent_module)?)?;
1155 parent_module.add_function(wrap_pyfunction!(super::RZZGate, parent_module)?)?;
1156 parent_module.add_function(wrap_pyfunction!(
1157 super::ParameterizedUnitary,
1158 parent_module
1159 )?)?;
1160 parent_module.add_function(wrap_pyfunction!(super::Invert, parent_module)?)?;
1161 parent_module.add_function(wrap_pyfunction!(super::Dagger, parent_module)?)?;
1162 parent_module.add_function(wrap_pyfunction!(super::Controlled, parent_module)?)?;
1163 parent_module.add_function(wrap_pyfunction!(
1164 super::ClassicallyControlled,
1165 parent_module
1166 )?)?;
1167 Ok(())
1168 }
1169 inventory::submit!(PyExpressionRegistrar { func: register });
1170}
1171
1172#[cfg(test)]
1173mod tests {
1174 use super::*;
1175
1176 #[test]
1177 fn dagger_renames_s() {
1178 let dg = Dagger(SGate(2));
1179 assert_eq!(dg.name(), "Dagger(S)");
1180 }
1181
1182 #[test]
1183 fn dagger_renames_t() {
1184 let dg = Dagger(TGate(2));
1185 assert_eq!(dg.name(), "Dagger(T)");
1186 }
1187}