stabilizer_ch_form_rust/form/
gate_application.rs

1use crate::{
2    StabilizerCHForm,
3    circuit::{CliffordCircuit, CliffordGate},
4    error::Result,
5    types::pauli::{Pauli, PauliString},
6};
7
8impl StabilizerCHForm {
9    /// Applies the Hadamard gate to the qubit at index `qarg`.
10    ///     
11    /// Time complexity: O(n^2)
12    ///
13    /// ## Arguments
14    /// * `qarg` - The index of the qubit to which the Hadamard gate is applied.
15    ///
16    /// ## Returns
17    /// A [`Result`] indicating success or failure.
18    pub fn apply_h(&mut self, qarg: usize) -> Result<()> {
19        self.left_multiply_h(qarg)
20    }
21
22    /// Applies the Pauli-X gate to the qubit at index `qarg`.
23    ///
24    /// Time complexity: O(n)
25    ///
26    /// ## Arguments
27    /// * `qarg` - The index of the qubit to which the Pauli-X gate is applied.
28    ///
29    /// ## Returns
30    /// A [`Result`] indicating success or failure.
31    pub fn apply_x(&mut self, qarg: usize) -> Result<()> {
32        self.left_multiply_x(qarg)
33    }
34
35    /// Applies the Pauli-Y gate to the qubit at index `qarg`.
36    ///
37    /// Time complexity: O(n)
38    ///
39    /// ## Arguments
40    /// * `qarg` - The index of the qubit to which the Pauli-Y gate is applied.
41    ///
42    /// ## Returns
43    /// A [`Result`] indicating success or failure.
44    pub fn apply_y(&mut self, qarg: usize) -> Result<()> {
45        self.left_multiply_y(qarg)
46    }
47
48    /// Applies the Pauli-Z gate to the qubit at index `qarg`.
49    ///
50    /// Time complexity: O(1)
51    ///
52    /// ## Arguments
53    /// * `qarg` - The index of the qubit to which the Pauli-Z gate is applied.
54    ///
55    /// ## Returns
56    /// A [`Result`] indicating success or failure.
57    pub fn apply_z(&mut self, qarg: usize) -> Result<()> {
58        self.left_multiply_z(qarg)
59    }
60
61    /// Applies the Phase (S) gate to the qubit at index `qarg`.
62    ///     
63    /// Time complexity: O(n)
64    ///
65    /// ## Arguments
66    /// * `qarg` - The index of the qubit to which the Phase (S) gate is applied.
67    ///
68    /// ## Returns
69    /// A [`Result`] indicating success or failure.
70    pub fn apply_s(&mut self, qarg: usize) -> Result<()> {
71        self.left_multiply_s(qarg)
72    }
73
74    /// Applies the adjoint Phase (S†) gate to the qubit at index `qarg`.
75    ///
76    /// Time complexity: O(n)
77    ///
78    /// ## Arguments
79    /// * `qarg` - The index of the qubit to which the adjoint Phase (S†) gate is applied.
80    ///
81    /// ## Returns
82    /// A [`Result`] indicating success or failure.
83    pub fn apply_sdg(&mut self, qarg: usize) -> Result<()> {
84        self.left_multiply_sdg(qarg)
85    }
86
87    /// Applies the √X gate to the qubit at index `qarg`.
88    ///
89    /// Time complexity: O(n^2)
90    ///
91    /// ## Arguments
92    /// * `qarg` - The index of the qubit to which the √X gate is applied.
93    ///
94    /// ## Returns
95    /// A [`Result`] indicating success or failure.
96    pub fn apply_sqrt_x(&mut self, qarg: usize) -> Result<()> {
97        self.left_multiply_sqrt_x(qarg)
98    }
99
100    /// Applies the adjoint of the √X gate to the qubit at index `qarg`.
101    ///
102    /// Time complexity: O(n^2)
103    ///
104    /// ## Arguments
105    /// * `qarg` - The index of the qubit to which the adjoint of the √X gate is applied.
106    ///
107    /// ## Returns
108    /// A [`Result`] indicating success or failure.
109    pub fn apply_sqrt_xdg(&mut self, qarg: usize) -> Result<()> {
110        self.left_multiply_sqrt_xdg(qarg)
111    }
112
113    /// Applies the CNOT (CX) gate with control qubit at index `control` and target qubit at index `target`.
114    ///
115    /// Time complexity: O(n)
116    ///
117    /// ## Arguments
118    /// * `control` - The index of the control qubit.
119    /// * `target` - The index of the target qubit.
120    ///
121    /// ## Returns
122    /// A [`Result`] indicating success or failure.
123    pub fn apply_cx(&mut self, control: usize, target: usize) -> Result<()> {
124        self.left_multiply_cx(control, target)
125    }
126
127    /// Applies the CZ gate between qubits at indices `qarg1` and `qarg2`.
128    ///
129    /// Time complexity: O(n)
130    ///
131    /// ## Arguments
132    /// * `qarg1` - The index of the first qubit.
133    /// * `qarg2` - The index of the second qubit.
134    ///
135    /// ## Returns
136    /// A [`Result`] indicating success or failure.
137    pub fn apply_cz(&mut self, qarg1: usize, qarg2: usize) -> Result<()> {
138        self.left_multiply_cz(qarg1, qarg2)
139    }
140
141    /// Applies the SWAP gate between the qubits at indices `qarg1` and `qarg2`.
142    ///
143    /// Time complexity: O(n)
144    ///
145    /// ## Arguments
146    /// * `qarg1` - The index of the first qubit.
147    /// * `qarg2` - The index of the second qubit.
148    ///
149    /// ## Returns
150    /// A [`Result`] indicating success or failure.
151    pub fn apply_swap(&mut self, qarg1: usize, qarg2: usize) -> Result<()> {
152        self.left_multiply_swap(qarg1, qarg2)
153    }
154
155    /// Applies a Clifford gate to the stabilizer state.
156    ////
157    /// ## Arguments
158    /// * `gate` - The Clifford gate to apply.
159    ///
160    /// ## Returns
161    /// A [`Result`] indicating success or failure.
162    pub fn apply_gate(&mut self, gate: &CliffordGate) -> Result<()> {
163        match gate {
164            CliffordGate::H(qarg) => self.apply_h(*qarg)?,
165            CliffordGate::X(qarg) => self.apply_x(*qarg)?,
166            CliffordGate::Y(qarg) => self.apply_y(*qarg)?,
167            CliffordGate::Z(qarg) => self.apply_z(*qarg)?,
168            CliffordGate::S(qarg) => self.apply_s(*qarg)?,
169            CliffordGate::Sdg(qarg) => self.apply_sdg(*qarg)?,
170            CliffordGate::SqrtX(qarg) => self.apply_sqrt_x(*qarg)?,
171            CliffordGate::SqrtXdg(qarg) => self.apply_sqrt_xdg(*qarg)?,
172            CliffordGate::CX(control, target) => self.apply_cx(*control, *target)?,
173            CliffordGate::CZ(control, target) => self.apply_cz(*control, *target)?,
174            CliffordGate::Swap(q1, q2) => self.apply_swap(*q1, *q2)?,
175        }
176        Ok(())
177    }
178
179    /// Applies a Pauli string to the stabilizer state.
180    ///
181    /// ## Arguments
182    /// * `pauli_string` - The Pauli string to apply.
183    ///
184    /// ## Returns
185    /// A [`Result`] indicating success or failure.
186    pub fn apply_pauli(&mut self, pauli_string: &PauliString) -> Result<()> {
187        match pauli_string {
188            PauliString::Dense(ops) => {
189                for (qubit, &op) in ops.iter().enumerate() {
190                    match op {
191                        Pauli::I => {}
192                        Pauli::X => self.apply_x(qubit)?,
193                        Pauli::Y => self.apply_y(qubit)?,
194                        Pauli::Z => self.apply_z(qubit)?,
195                    }
196                }
197            }
198            PauliString::Sparse(terms) => {
199                for term in terms {
200                    match term.op {
201                        Pauli::I => {}
202                        Pauli::X => self.apply_x(term.qubit)?,
203                        Pauli::Y => self.apply_y(term.qubit)?,
204                        Pauli::Z => self.apply_z(term.qubit)?,
205                    }
206                }
207            }
208        }
209        Ok(())
210    }
211
212    /// Applies a Clifford circuit to the stabilizer state.
213    ///
214    /// ## Arguments
215    /// * `circuit` - The Clifford circuit to apply.
216    ///
217    /// ## Returns
218    /// A [`Result`] indicating success or failure.
219    pub fn apply_circuit(&mut self, circuit: &CliffordCircuit) -> Result<()> {
220        for gate in &circuit.gates {
221            self.apply_gate(gate)?;
222        }
223        Ok(())
224    }
225}