rustiq_core/structures/
pauli.rs1use super::pauli_like::PauliLike;
2use std::ops;
3
4pub struct Pauli {
5 pub n: usize,
6 pub data: Vec<bool>,
7 pub phase: u8,
8}
9
10impl Pauli {
11 pub fn new(n: usize) -> Self {
12 Pauli {
13 n,
14 data: vec![true; 2 * n],
15 phase: 0,
16 }
17 }
18 pub fn from_vec_bool(data: Vec<bool>, phase: u8) -> Self {
19 Pauli {
20 n: data.len() / 2,
21 data,
22 phase,
23 }
24 }
25 pub fn commutes(&self, other: &Pauli) -> bool {
26 if self.n != other.n {
27 panic!("Can't compare two Paulis on different number of qubits");
28 }
29 let (my_z, my_x) = self.data.split_at(self.n);
30 let (their_z, their_x) = other.data.split_at(self.n);
31 let p1 = my_z.iter().zip(their_x.iter()).map(|(a, b)| a & b);
32 let p2 = my_x.iter().zip(their_z.iter()).map(|(a, b)| a & b);
33 (p1.zip(p2).map(|(a, b)| a ^ b).filter(|a| *a).count() & 1) == 0
34 }
35}
36
37impl ops::Mul<Pauli> for Pauli {
38 type Output = Pauli;
39
40 fn mul(self, _rhs: Pauli) -> Pauli {
41 assert_eq!(self.n, _rhs.n);
42 let mut output = Pauli::new(self.n);
43 output.phase = self.phase + _rhs.phase;
44 for i in 0..self.n {
45 if self.data[i] && _rhs.data[i + self.n] {
46 output.phase += 2;
47 }
48 if self.data[i + self.n] && _rhs.data[i] {
49 output.phase += 2;
50 }
51 }
52 for i in 0..2 * self.n {
53 output.data[i] = self.data[i] ^ _rhs.data[i];
54 }
55 output.phase %= 4;
56 output
57 }
58}
59
60impl PauliLike for Pauli {
61 fn h(&mut self, i: usize) {
62 self.data.swap(i, i + self.n);
63 }
64
65 fn s(&mut self, i: usize) {
66 self.data[i + self.n] ^= self.data[i];
67 }
68
69 fn sd(&mut self, i: usize) {
70 self.data[i + self.n] ^= self.data[i];
71 }
72
73 fn sqrt_x(&mut self, i: usize) {
74 self.data[i] ^= self.data[i + self.n];
75 }
76
77 fn sqrt_xd(&mut self, i: usize) {
78 self.data[i] ^= self.data[i + self.n];
79 }
80
81 fn cnot(&mut self, i: usize, j: usize) {
82 self.data[i + self.n] ^= self.data[j + self.n];
83 self.data[j] ^= self.data[i];
84 }
85}