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