rustiq_core/structures/
pauli.rs

1use 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}