1use crate::error::{QuantRS2Error, QuantRS2Result};
7use crate::gate::GateOp;
8use crate::qubit::QubitId;
9use num_complex::Complex64;
10use std::any::Any;
11use std::fmt::Debug;
12
13#[derive(Debug)]
15pub struct ControlledGate {
16 controls: Vec<QubitId>,
18 base_gate: Box<dyn GateOp>,
20 control_phase: Complex64,
22}
23
24impl ControlledGate {
25 pub fn new(controls: Vec<QubitId>, base_gate: Box<dyn GateOp>) -> Self {
27 Self {
28 controls,
29 base_gate,
30 control_phase: Complex64::new(1.0, 0.0),
31 }
32 }
33
34 pub fn with_phase(
36 controls: Vec<QubitId>,
37 base_gate: Box<dyn GateOp>,
38 phase: Complex64,
39 ) -> Self {
40 Self {
41 controls,
42 base_gate,
43 control_phase: phase,
44 }
45 }
46
47 pub fn controls(&self) -> &[QubitId] {
49 &self.controls
50 }
51
52 pub fn targets(&self) -> Vec<QubitId> {
54 self.base_gate.qubits()
55 }
56
57 pub fn is_control(&self, qubit: QubitId) -> bool {
59 self.controls.contains(&qubit)
60 }
61
62 pub fn is_target(&self, qubit: QubitId) -> bool {
64 self.base_gate.qubits().contains(&qubit)
65 }
66}
67
68impl GateOp for ControlledGate {
69 fn name(&self) -> &'static str {
70 match self.controls.len() {
71 1 => "C",
72 2 => "CC",
73 _ => "Multi-C",
74 }
75 }
76
77 fn qubits(&self) -> Vec<QubitId> {
78 let mut qubits = self.controls.clone();
79 qubits.extend(self.base_gate.qubits());
80 qubits
81 }
82
83 fn is_parameterized(&self) -> bool {
84 self.base_gate.is_parameterized()
85 }
86
87 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
88 let base_matrix = self.base_gate.matrix()?;
89 let base_dim = (base_matrix.len() as f64).sqrt() as usize;
90
91 if base_dim * base_dim != base_matrix.len() {
92 return Err(QuantRS2Error::InvalidInput(
93 "Base gate matrix is not square".to_string(),
94 ));
95 }
96
97 let num_controls = self.controls.len();
98 let control_dim = 1 << num_controls;
99 let total_dim = control_dim * base_dim;
100
101 let mut matrix = vec![Complex64::new(0.0, 0.0); total_dim * total_dim];
103 for i in 0..total_dim {
104 matrix[i * total_dim + i] = Complex64::new(1.0, 0.0);
105 }
106
107 let control_mask = control_dim - 1; for i in 0..base_dim {
111 for j in 0..base_dim {
112 let row = control_mask * base_dim + i;
113 let col = control_mask * base_dim + j;
114 matrix[row * total_dim + col] = self.control_phase * base_matrix[i * base_dim + j];
115 }
116 }
117
118 Ok(matrix)
119 }
120
121 fn as_any(&self) -> &dyn Any {
122 self
123 }
124
125 fn clone_gate(&self) -> Box<dyn GateOp> {
126 Box::new(Self {
127 controls: self.controls.clone(),
128 base_gate: self.base_gate.clone(),
129 control_phase: self.control_phase,
130 })
131 }
132}
133
134#[derive(Debug)]
136pub struct MultiControlledGate {
137 positive_controls: Vec<QubitId>,
139 negative_controls: Vec<QubitId>,
141 base_gate: Box<dyn GateOp>,
143}
144
145impl MultiControlledGate {
146 pub fn new(
148 positive_controls: Vec<QubitId>,
149 negative_controls: Vec<QubitId>,
150 base_gate: Box<dyn GateOp>,
151 ) -> Self {
152 Self {
153 positive_controls,
154 negative_controls,
155 base_gate,
156 }
157 }
158
159 pub fn positive(controls: Vec<QubitId>, base_gate: Box<dyn GateOp>) -> Self {
161 Self {
162 positive_controls: controls,
163 negative_controls: vec![],
164 base_gate,
165 }
166 }
167
168 pub fn num_controls(&self) -> usize {
170 self.positive_controls.len() + self.negative_controls.len()
171 }
172}
173
174impl GateOp for MultiControlledGate {
175 fn name(&self) -> &'static str {
176 match self.num_controls() {
177 1 => "C",
178 2 => "CC",
179 3 => "CCC",
180 _ => "Multi-C",
181 }
182 }
183
184 fn qubits(&self) -> Vec<QubitId> {
185 let mut qubits = self.positive_controls.clone();
186 qubits.extend(&self.negative_controls);
187 qubits.extend(self.base_gate.qubits());
188 qubits
189 }
190
191 fn is_parameterized(&self) -> bool {
192 self.base_gate.is_parameterized()
193 }
194
195 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
196 let base_matrix = self.base_gate.matrix()?;
197 let base_dim = (base_matrix.len() as f64).sqrt() as usize;
198
199 let num_controls = self.num_controls();
200 let control_dim = 1 << num_controls;
201 let total_dim = control_dim * base_dim;
202
203 let mut matrix = vec![Complex64::new(0.0, 0.0); total_dim * total_dim];
205 for i in 0..total_dim {
206 matrix[i * total_dim + i] = Complex64::new(1.0, 0.0);
207 }
208
209 let mut _control_pattern = 0usize;
211 for (i, _) in self.positive_controls.iter().enumerate() {
212 _control_pattern |= 1 << i;
213 }
214 let neg_offset = self.positive_controls.len();
216
217 for ctrl_state in 0..control_dim {
219 let mut matches = true;
220
221 for (i, _) in self.positive_controls.iter().enumerate() {
223 if (ctrl_state >> i) & 1 != 1 {
224 matches = false;
225 break;
226 }
227 }
228
229 if matches {
231 for (i, _) in self.negative_controls.iter().enumerate() {
232 if (ctrl_state >> (neg_offset + i)) & 1 != 0 {
233 matches = false;
234 break;
235 }
236 }
237 }
238
239 if matches {
240 for i in 0..base_dim {
242 for j in 0..base_dim {
243 let row = ctrl_state * base_dim + i;
244 let col = ctrl_state * base_dim + j;
245 matrix[row * total_dim + col] = base_matrix[i * base_dim + j];
246 }
247 }
248 }
249 }
250
251 Ok(matrix)
252 }
253
254 fn as_any(&self) -> &dyn Any {
255 self
256 }
257
258 fn clone_gate(&self) -> Box<dyn GateOp> {
259 Box::new(Self {
260 positive_controls: self.positive_controls.clone(),
261 negative_controls: self.negative_controls.clone(),
262 base_gate: self.base_gate.clone(),
263 })
264 }
265}
266
267#[derive(Debug, Clone, Copy)]
269pub struct ToffoliGate {
270 control1: QubitId,
271 control2: QubitId,
272 target: QubitId,
273}
274
275impl ToffoliGate {
276 pub fn new(control1: QubitId, control2: QubitId, target: QubitId) -> Self {
278 Self {
279 control1,
280 control2,
281 target,
282 }
283 }
284}
285
286impl GateOp for ToffoliGate {
287 fn name(&self) -> &'static str {
288 "Toffoli"
289 }
290
291 fn qubits(&self) -> Vec<QubitId> {
292 vec![self.control1, self.control2, self.target]
293 }
294
295 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
296 let mut matrix = vec![Complex64::new(0.0, 0.0); 64]; for i in 0..8 {
301 matrix[i * 8 + i] = Complex64::new(1.0, 0.0);
302 }
303
304 matrix[6 * 8 + 6] = Complex64::new(0.0, 0.0);
306 matrix[7 * 8 + 7] = Complex64::new(0.0, 0.0);
307 matrix[6 * 8 + 7] = Complex64::new(1.0, 0.0);
308 matrix[7 * 8 + 6] = Complex64::new(1.0, 0.0);
309
310 Ok(matrix)
311 }
312
313 fn as_any(&self) -> &dyn Any {
314 self
315 }
316
317 fn clone_gate(&self) -> Box<dyn GateOp> {
318 Box::new(self.clone())
319 }
320}
321
322#[derive(Debug, Clone, Copy)]
324pub struct FredkinGate {
325 control: QubitId,
326 target1: QubitId,
327 target2: QubitId,
328}
329
330impl FredkinGate {
331 pub fn new(control: QubitId, target1: QubitId, target2: QubitId) -> Self {
333 Self {
334 control,
335 target1,
336 target2,
337 }
338 }
339}
340
341impl GateOp for FredkinGate {
342 fn name(&self) -> &'static str {
343 "Fredkin"
344 }
345
346 fn qubits(&self) -> Vec<QubitId> {
347 vec![self.control, self.target1, self.target2]
348 }
349
350 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
351 let mut matrix = vec![Complex64::new(0.0, 0.0); 64]; for i in 0..8 {
356 matrix[i * 8 + i] = Complex64::new(1.0, 0.0);
357 }
358
359 matrix[5 * 8 + 5] = Complex64::new(0.0, 0.0);
362 matrix[6 * 8 + 6] = Complex64::new(0.0, 0.0);
363 matrix[5 * 8 + 6] = Complex64::new(1.0, 0.0);
364 matrix[6 * 8 + 5] = Complex64::new(1.0, 0.0);
365
366 Ok(matrix)
367 }
368
369 fn as_any(&self) -> &dyn Any {
370 self
371 }
372
373 fn clone_gate(&self) -> Box<dyn GateOp> {
374 Box::new(self.clone())
375 }
376}
377
378pub fn make_controlled<G: GateOp + 'static>(controls: Vec<QubitId>, gate: G) -> ControlledGate {
380 ControlledGate::new(controls, Box::new(gate))
381}
382
383pub fn make_multi_controlled<G: GateOp + 'static>(
385 positive_controls: Vec<QubitId>,
386 negative_controls: Vec<QubitId>,
387 gate: G,
388) -> MultiControlledGate {
389 MultiControlledGate::new(positive_controls, negative_controls, Box::new(gate))
390}
391
392#[cfg(test)]
393mod tests {
394 use super::*;
395 use crate::gate::single::PauliX;
396
397 #[test]
398 fn test_controlled_x_gate() {
399 let x = PauliX { target: QubitId(1) };
400 let cx = make_controlled(vec![QubitId(0)], x);
401
402 assert_eq!(cx.name(), "C");
403 assert_eq!(cx.qubits(), vec![QubitId(0), QubitId(1)]);
404
405 let matrix = cx.matrix().unwrap();
406 assert_eq!(matrix.len(), 16); assert_eq!(matrix[0], Complex64::new(1.0, 0.0)); assert_eq!(matrix[5], Complex64::new(1.0, 0.0)); assert_eq!(matrix[11], Complex64::new(1.0, 0.0)); assert_eq!(matrix[14], Complex64::new(1.0, 0.0)); }
414
415 #[test]
416 fn test_toffoli_gate() {
417 let toffoli = ToffoliGate::new(QubitId(0), QubitId(1), QubitId(2));
418
419 assert_eq!(toffoli.name(), "Toffoli");
420 assert_eq!(toffoli.qubits().len(), 3);
421
422 let matrix = toffoli.matrix().unwrap();
423 assert_eq!(matrix.len(), 64); }
425}