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}