stabilizer_ch_form_rust/form/
mod.rs

1use ndarray::{Array1, Array2};
2use num_complex::Complex64;
3
4use crate::{
5    circuit::{CliffordCircuit, CliffordGate},
6    error::{Error, Result},
7};
8
9use types::PhaseFactor;
10
11#[derive(Debug, Clone)]
12pub struct StabilizerCHForm {
13    pub(crate) n: usize,
14    pub(crate) mat_g: Array2<bool>,
15    pub(crate) mat_f: Array2<bool>,
16    pub(crate) mat_m: Array2<bool>,
17    pub(crate) gamma: Array1<PhaseFactor>,
18    pub(crate) vec_v: Array1<bool>,
19    pub(crate) vec_s: Array1<bool>,
20    pub(crate) omega: Complex64,
21    pub(crate) phase_factor: PhaseFactor,
22}
23
24mod amplitude;
25mod discard;
26mod gate_application;
27mod get_qubit_state;
28mod inner_product;
29mod kron;
30mod left_multiplication;
31mod matrix_operations;
32mod measure;
33mod permute;
34mod project;
35mod resolve_superposition;
36mod right_multiplication;
37mod statevector;
38mod types;
39
40impl StabilizerCHForm {
41    /// Creates a new StabilizerCHForm representing the |0...0> state for `n` qubits.
42    /// ## Arguments
43    /// * `n` - The number of qubits.
44    pub fn new(n: usize) -> Result<Self> {
45        if n == 0 {
46            return Err(Error::InvalidNumQubits(n));
47        }
48
49        Ok(Self {
50            n,
51            // Initialize G, F as identity matrices, M as zero matrix
52            mat_g: Array2::from_shape_fn((n, n), |(i, j)| i == j),
53            mat_f: Array2::from_shape_fn((n, n), |(i, j)| i == j),
54            mat_m: Array2::from_elem((n, n), false),
55            // Initialize gamma as [+1, +1, ..., +1]
56            gamma: Array1::from_elem(n, PhaseFactor::PLUS_ONE),
57            // Initialize v, s as zero vectors
58            vec_v: Array1::from_elem(n, false),
59            vec_s: Array1::from_elem(n, false),
60            // Initialize omega as 1 + 0i
61            omega: Complex64::new(1.0, 0.0),
62            // Initialize overall phase factor as +1
63            phase_factor: PhaseFactor::PLUS_ONE,
64        })
65    }
66
67    /// Returns the number of qubits in the stabilizer state.
68    pub fn num_qubits(&self) -> usize {
69        self.n
70    }
71
72    /// Sets the global phase of the stabilizer state.
73    ///
74    /// ## Arguments
75    /// * `phase` - A unit complex number representing the desired global phase.
76    pub fn set_global_phase(&mut self, phase: Complex64) {
77        if (phase.norm_sqr() - 1.0).abs() > 1e-8 {
78            panic!("Global phase must be a unit complex number.");
79        }
80        self.omega = phase;
81    }
82
83    /// Returns the global phase of the stabilizer state.
84    ///
85    /// ## Returns
86    /// A unit complex number representing the global phase.
87    pub fn global_phase(&self) -> Complex64 {
88        self.omega
89    }
90
91    /// Constructs a [`StabilizerCHForm`] from a [`CliffordCircuit`].
92    ///
93    /// ## Arguments
94    /// * `circuit` - The [`CliffordCircuit`] to convert.
95    ///
96    /// ## Returns
97    /// A [`Result`] containing the resulting [`StabilizerCHForm`].
98    pub fn from_clifford_circuit(circuit: &CliffordCircuit) -> Result<Self> {
99        let mut ch_form = StabilizerCHForm::new(circuit.num_qubits)?;
100
101        for gate in &circuit.gates {
102            match gate {
103                CliffordGate::H(q) => ch_form.left_multiply_h(*q)?,
104                CliffordGate::S(q) => ch_form.left_multiply_s(*q)?,
105                CliffordGate::Sdg(q) => ch_form.left_multiply_sdg(*q)?,
106                CliffordGate::X(q) => ch_form.left_multiply_x(*q)?,
107                CliffordGate::Y(q) => ch_form.left_multiply_y(*q)?,
108                CliffordGate::Z(q) => ch_form.left_multiply_z(*q)?,
109                CliffordGate::SqrtX(q) => ch_form.left_multiply_sqrt_x(*q)?,
110                CliffordGate::SqrtXdg(q) => ch_form.left_multiply_sqrt_xdg(*q)?,
111                CliffordGate::CX(control, target) => ch_form.left_multiply_cx(*control, *target)?,
112                CliffordGate::CZ(control, target) => ch_form.left_multiply_cz(*control, *target)?,
113                CliffordGate::Swap(q1, q2) => ch_form.left_multiply_swap(*q1, *q2)?,
114            }
115        }
116        Ok(ch_form)
117    }
118}