rustiq_core/structures/
isometry.rs

1use super::pauli_like::PauliLike;
2use super::pauli_set::PauliSet;
3use crate::routines::f2_linalg::{row_echelon, Matrix};
4use rand::Rng;
5use std::fmt;
6
7#[derive(Clone, Debug, PartialEq)]
8pub struct IsometryTableau {
9    pub n: usize,
10    pub k: usize,
11    pub logicals: PauliSet,
12    pub stabilizers: PauliSet,
13}
14
15impl IsometryTableau {
16    pub fn new(n: usize, k: usize) -> Self {
17        let mut logicals = PauliSet::new(n + k);
18        for i in 0..n {
19            let mut vecbool = vec![false; 2 * n + 2 * k];
20            vecbool[i] = true;
21            logicals.insert_vec_bool(&vecbool, false);
22        }
23        for i in 0..n {
24            let mut vecbool = vec![false; 2 * n + 2 * k];
25            vecbool[i + n + k] = true;
26            logicals.insert_vec_bool(&vecbool, false);
27        }
28        let mut stabilizers = PauliSet::new(n + k);
29        for i in 0..k {
30            let mut vecbool = vec![false; 2 * n + 2 * k];
31            vecbool[n + k + n + i] = true;
32            stabilizers.insert_vec_bool(&vecbool, false);
33        }
34        IsometryTableau {
35            n,
36            k,
37            logicals,
38            stabilizers,
39        }
40    }
41    pub fn random(n: usize, k: usize) -> Self {
42        let mut rng = rand::thread_rng();
43        let mut iso = Self::new(n, k);
44        for _ in 0..(n + k) * (n + k) {
45            let i = rng.gen::<usize>() % (n + k);
46            loop {
47                let j = rng.gen::<usize>() % (n + k);
48                if i == j {
49                    continue;
50                }
51                iso.cnot(i, j);
52                break;
53            }
54            for _ in 0..(n + k) {
55                let gate_i = rng.gen::<u8>() % 3;
56                if gate_i == 1 {
57                    let q = rng.gen::<usize>() % (n + k);
58                    iso.h(q);
59                }
60                if gate_i == 2 {
61                    let q = rng.gen::<usize>() % (n + k);
62                    iso.s(q);
63                }
64            }
65        }
66        iso
67    }
68    /// Put the full Tableau in column echelon form
69    /// Warning: this method scratches the phases
70    pub fn normalize_inplace(&mut self) {
71        let mut table: Matrix = Vec::new();
72        // The first k rows are the stabilizers
73        for i in 0..self.k {
74            let (_, vec) = self.stabilizers.get_as_vec_bool(i);
75            table.push(vec);
76        }
77        // The next 2n rows are the logical operators
78        for i in 0..2 * self.n {
79            let (_, vec) = self.logicals.get_as_vec_bool(i);
80            table.push(vec);
81        }
82        row_echelon(&mut table, self.k);
83        let mut stabs = PauliSet::new(self.n + self.k);
84        for row in table.iter().take(self.k) {
85            stabs.insert_vec_bool(row, false);
86        }
87        let mut logicals = PauliSet::new(self.n + self.k);
88        for i in 0..2 * self.n {
89            logicals.insert_vec_bool(&table[self.k + i], false);
90        }
91        self.logicals = logicals;
92        self.stabilizers = stabs;
93    }
94}
95
96impl PauliLike for IsometryTableau {
97    fn h(&mut self, i: usize) {
98        self.logicals.h(i);
99        self.stabilizers.h(i);
100    }
101
102    fn s(&mut self, i: usize) {
103        self.logicals.s(i);
104        self.stabilizers.s(i);
105    }
106
107    fn sd(&mut self, i: usize) {
108        self.logicals.sd(i);
109        self.stabilizers.sd(i);
110    }
111
112    fn sqrt_x(&mut self, i: usize) {
113        self.logicals.sqrt_x(i);
114        self.stabilizers.sqrt_x(i);
115    }
116
117    fn sqrt_xd(&mut self, i: usize) {
118        self.logicals.sqrt_xd(i);
119        self.stabilizers.sqrt_xd(i);
120    }
121
122    fn cnot(&mut self, i: usize, j: usize) {
123        self.logicals.cnot(i, j);
124        self.stabilizers.cnot(i, j);
125    }
126}
127
128impl fmt::Display for IsometryTableau {
129    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130        write!(
131            f,
132            "Logicals:\n{}Stabilizers:\n{}",
133            self.logicals, self.stabilizers
134        )?;
135        fmt::Result::Ok(())
136    }
137}