rustiq_core/routines/
rotation_extraction.rs1use crate::structures::{PauliLike, Tableau};
4
5pub fn extract_rotations(
6 circuit: &[(String, Vec<usize>)],
7 nqubits: usize,
8) -> (Vec<(bool, String)>, Tableau) {
9 let mut clifford = Tableau::new(nqubits);
10 let mut rotations = Vec::new();
11 for (gate_name, qbits) in circuit.iter() {
12 match gate_name.as_str() {
13 "CX" => clifford.cnot(qbits[0], qbits[1]),
14 "CZ" => clifford.cz(qbits[0], qbits[1]),
15 "H" => clifford.h(qbits[0]),
16 "S" => clifford.s(qbits[0]),
17 "Sd" => clifford.sd(qbits[0]),
18 "SqrtX" => clifford.sqrt_x(qbits[0]),
19 "SqrtXd" => clifford.sqrt_xd(qbits[0]),
20 "X" => {
21 clifford.sqrt_x(qbits[0]);
22 clifford.sqrt_x(qbits[0])
23 }
24 "Z" => {
25 clifford.s(qbits[0]);
26 clifford.s(qbits[0])
27 }
28 "Y" => {
29 clifford.sqrt_x(qbits[0]);
30 clifford.s(qbits[0]);
31 clifford.s(qbits[0]);
32 clifford.sqrt_xd(qbits[0]);
33 }
34 "RZ" => {
35 rotations.push(clifford.get_inverse_z(qbits[0]));
36 }
37 _ => panic!("Unsupported gate {}", gate_name),
38 }
39 }
40 (rotations, clifford)
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 fn rotations_to_circuit(rotations: &[(&str, f64)], n: usize) -> Vec<(String, Vec<usize>)> {
48 let mut circuit = Vec::new();
49 for (axis, _) in rotations {
50 for q in 0..n {
51 match axis.chars().nth(q).unwrap() {
52 'X' => circuit.push(("H".to_string(), vec![q])),
53 'Y' => circuit.push(("SqrtX".to_string(), vec![q])),
54 _ => {}
55 }
56 }
57 let mut support: Vec<_> = (0..n)
58 .filter(|q| axis.chars().nth(*q).unwrap() != 'I')
59 .collect();
60 let control = support.pop().unwrap();
61 for q in support.iter() {
62 circuit.push(("CX".to_string(), vec![*q, control]));
63 }
64 circuit.push(("RZ".to_string(), vec![control]));
65 for q in support.iter() {
66 circuit.push(("CX".to_string(), vec![*q, control]));
67 }
68 for q in 0..n {
69 match axis.chars().nth(q).unwrap() {
70 'X' => circuit.push(("H".to_string(), vec![q])),
71 'Y' => circuit.push(("SqrtXd".to_string(), vec![q])),
72 _ => {}
73 }
74 }
75 }
76 circuit
77 }
78
79 #[test]
80 fn simple_rotation_extraction() {
81 let rotations = [
82 ("ZX", 4.512201785772802),
83 ("XX", 2.851130732235927),
84 ("YZ", 6.202871194609474),
85 ("ZY", 5.709017144348731),
86 ("XI", 5.20162260375333),
87 ("ZZ", 4.0981647318566905),
88 ("IX", 1.20103093057112),
89 ("XX", 3.748132932778756),
90 ("IX", 2.7013063221306455),
91 ("YI", 2.085429040429552),
92 ];
93 let circuit = rotations_to_circuit(&rotations, 2);
94 let (new_rotations, clifford) = extract_rotations(&circuit, 2);
95 println!("{:?}", new_rotations);
96 assert_eq!(clifford, Tableau::new(2));
97 for (r1, r2) in rotations.iter().zip(new_rotations.iter()) {
98 assert_eq!(r1.0, r2.1);
99 assert!(!r2.0);
100 }
101 println!("{}", clifford.logicals);
102 for i in 0..4 {
103 assert!(!clifford.logicals.get_phase(i));
104 }
105 }
106}