Skip to main content

qec_code/
code.rs

1use crate::Pauli;
2use crate::binary::try_binary_rank;
3use crate::error::{QecError, Result};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct StabilizerCode {
7    n: usize,
8    stabilizers: Vec<Pauli>,
9    stabilizer_rank: usize,
10}
11
12impl StabilizerCode {
13    pub fn from_stabilizers(n: usize, stabilizers: Vec<Pauli>) -> Result<Self> {
14        for stabilizer in &stabilizers {
15            if stabilizer.n() != n {
16                return Err(QecError::InvalidPauliWidth {
17                    x_width: stabilizer.n(),
18                    z_width: n,
19                });
20            }
21        }
22
23        for i in 0..stabilizers.len() {
24            for j in (i + 1)..stabilizers.len() {
25                if !stabilizers[i].try_commutes_with(&stabilizers[j])? {
26                    return Err(QecError::NonCommutingStabilizers);
27                }
28            }
29        }
30
31        let symplectic_rows: Vec<Vec<u8>> =
32            stabilizers.iter().map(Pauli::to_symplectic_row).collect();
33        let stabilizer_rank = try_binary_rank(&symplectic_rows)?;
34
35        if stabilizer_rank != stabilizers.len() {
36            return Err(QecError::DependentStabilizers);
37        }
38
39        Ok(Self {
40            n,
41            stabilizers,
42            stabilizer_rank,
43        })
44    }
45
46    pub fn n(&self) -> usize {
47        self.n
48    }
49
50    pub fn stabilizers(&self) -> &[Pauli] {
51        &self.stabilizers
52    }
53
54    pub fn stabilizer_rows(&self) -> Vec<Vec<u8>> {
55        self.stabilizers
56            .iter()
57            .map(Pauli::to_symplectic_row)
58            .collect()
59    }
60
61    pub fn stabilizer_rank(&self) -> usize {
62        self.stabilizer_rank
63    }
64
65    pub fn num_logical_qubits(&self) -> usize {
66        self.n - self.stabilizer_rank
67    }
68
69    /// Returns a basis for the full stabilizer normalizer, including stabilizer generators.
70    pub fn normalizer_basis(&self) -> Result<Vec<Pauli>> {
71        crate::logical::compute_normalizer_basis(self)
72    }
73
74    pub fn logical_basis(&self) -> Result<crate::logical::LogicalBasis> {
75        crate::logical::compute_logical_basis(self)
76    }
77
78    pub fn canonical_logical_basis(&self) -> Result<crate::logical::LogicalBasis> {
79        crate::logical::compute_canonical_logical_basis(self)
80    }
81}