quant_iron/components/gate.rs
1use crate::{
2 components::{
3 measurement::MeasurementBasis,
4 operator::{
5 CNOT, Hadamard, Identity, Operator, Pauli, PhaseS, PhaseSdag, PhaseShift, PhaseT,
6 PhaseTdag, RotateX, RotateY, RotateZ, SWAP, Toffoli, Unitary2
7 },
8 state::State,
9 },
10 errors::Error,
11};
12
13use num_complex::Complex;
14
15/// Represents a quantum gate as part of a quantum circuit.
16pub enum Gate {
17 /// Represents an operator gate.
18 ///
19 /// # Fields
20 ///
21 /// * `operator` - A boxed dynamic operator trait object.
22 ///
23 /// * `target_indices` - The indices of the qubits on which the operator acts.
24 ///
25 /// * `control_indices` - Optional control qubit indices for controlled gates. If empty, the gate is applied unconditionally.
26 Operator(Box<dyn Operator>, Vec<usize>, Vec<usize>),
27
28 /// Represents a measurement gate.
29 ///
30 /// # Fields
31 ///
32 /// * `MeasurementBasis` - The basis of measurement (e.g., computational basis).
33 /// * `indices` - The indices of the measured qubits.
34 Measurement(MeasurementBasis, Vec<usize>),
35}
36
37impl Gate {
38 /// Creates a new measurement gate for the specified qubit indices.
39 ///
40 /// # Arguments
41 ///
42 /// * `qubit_indices` - The indices of the qubits to be measured.
43 /// * `basis` - The basis of measurement (e.g., computational basis).
44 ///
45 /// # Returns
46 ///
47 /// * `Gate` - A new instance of the Gate struct representing a measurement gate.
48 pub fn new_measurement(qubit_indices: Vec<usize>, basis: MeasurementBasis) -> Self {
49 Gate::Measurement(basis, qubit_indices)
50 }
51
52 /// Creates a new operator gate for the specified qubit indices.
53 ///
54 /// # Arguments
55 ///
56 /// * `operator` - A boxed dynamic operator trait object.
57 ///
58 /// * `target_indices` - The indices of the qubits on which the operator acts.
59 ///
60 /// * `control_indices` - Optional control qubit indices for controlled gates.
61 ///
62 /// # Returns
63 ///
64 /// * `Gate` - A new instance of the Gate struct representing an operator gate.
65 pub fn new_operator(
66 operator: Box<dyn Operator>,
67 target_indices: Vec<usize>,
68 control_indices: Vec<usize>,
69 ) -> Self {
70 Gate::Operator(operator, target_indices, control_indices)
71 }
72
73 /// Applies the gate to the given state and returns the new state.
74 ///
75 /// # Arguments
76 ///
77 /// * `state` - The quantum state to which the gate will be applied.
78 ///
79 /// # Returns
80 ///
81 /// * `State` - The new quantum state after applying the gate.
82 pub fn apply(&self, state: &State) -> Result<State, Error> {
83 match self {
84 Gate::Operator(operator, target_indices, control_indices) => {
85 operator.apply(state, target_indices, control_indices.as_slice())
86 }
87 Gate::Measurement(basis, indices) => state
88 .measure(*basis, indices.as_slice())
89 .map(|measurementresult| measurementresult.get_new_state().clone()),
90 }
91 }
92
93 /// Returns the indices of the qubits on which the gate acts.
94 ///
95 /// # Returns
96 ///
97 /// * `&Vec<usize>` - A vector of indices of the qubits on which the gate acts.
98 pub fn get_target_qubits(&self) -> &Vec<usize> {
99 match self {
100 Gate::Operator(_, target_indices, _) => target_indices,
101 Gate::Measurement(_, indices) => indices,
102 }
103 }
104
105 /// Returns the control indices of the gate if it has any.
106 ///
107 /// # Returns
108 ///
109 /// * `Option<&Vec<usize>>` - An optional vector of control indices.
110 pub fn get_control_qubits(&self) -> Option<&Vec<usize>> {
111 match self {
112 Gate::Operator(_, _, control_indices) => Some(control_indices),
113 Gate::Measurement(_, _) => None,
114 }
115 }
116
117 // -- SINGLE-QUBIT GATES --
118
119 /// Creates a new Hadamard gate for the specified qubit index.
120 ///
121 /// # Arguments
122 ///
123 /// * `qubit_index` - The index of the qubit on which the Hadamard gate acts.
124 ///
125 /// # Returns
126 ///
127 /// * `Gate` - A new instance of the Gate struct representing a Hadamard gate.
128 pub fn h_gate(qubit_index: usize) -> Self {
129 Gate::Operator(Box::new(Hadamard), vec![qubit_index], vec![])
130 }
131
132 /// Creates new Hadamard gates for the specified qubit indices.
133 ///
134 /// # Arguments
135 ///
136 /// * `qubit_indices` - The indices of the qubits on which the Hadamard gate acts.
137 ///
138 /// # Returns
139 ///
140 /// * `Gates` - A vector of Gate structs representing Hadamard gates for each qubit index.
141 pub fn h_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
142 qubit_indices
143 .into_iter()
144 .map(|qubit_index| Gate::h_gate(qubit_index))
145 .collect()
146 }
147
148 /// Creates new controlled Hadamard gates for the specified qubit indices.
149 ///
150 /// # Arguments
151 ///
152 /// * `target_indices` - The indices of the target qubits.
153 /// * `control_indices` - The indices of the control qubits.
154 ///
155 /// # Returns
156 ///
157 /// * `Gates` - A vector of Gate structs representing controlled Hadamard gates for each target qubit index.
158 pub fn h_controlled_gates(
159 target_indices: Vec<usize>,
160 control_indices: Vec<usize>,
161 ) -> Vec<Self> {
162 target_indices
163 .into_iter()
164 .map(|target_index| Gate::Operator(
165 Box::new(Hadamard),
166 vec![target_index],
167 control_indices.clone(),
168 ))
169 .collect()
170 }
171
172 /// Creates a new Pauli-X gate for the specified qubit index.
173 ///
174 /// # Arguments
175 ///
176 /// * `qubit_index` - The index of the qubit on which the Pauli-X gate acts.
177 ///
178 /// # Returns
179 ///
180 /// * `Gate` - A new instance of the Gate struct representing a Pauli-X gate.
181 pub fn x_gate(qubit_index: usize) -> Self {
182 Gate::Operator(Box::new(Pauli::X), vec![qubit_index], vec![])
183 }
184
185 /// Creates new controlled Pauli-X gates for the specified qubit indices.
186 ///
187 /// # Arguments
188 ///
189 /// * `qubit_indices` - The indices of the qubits on which the Pauli-X gates act.
190 ///
191 /// # Returns
192 ///
193 /// * `Vec<Gate>` - A vector of Gate structs representing Pauli-X gates for each qubit index.
194 pub fn x_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
195 qubit_indices
196 .into_iter()
197 .map(|qubit_index| Gate::x_gate(qubit_index))
198 .collect()
199 }
200
201 /// Creates new Pauli-X gates for the specified qubit indices with control qubits.
202 ///
203 /// # Arguments
204 ///
205 /// * `target_indices` - The indices of the target qubits.
206 ///
207 /// * `control_indices` - The indices of the control qubits.
208 ///
209 /// # Returns
210 ///
211 /// * `Gates` - A vector of Gate structs representing controlled Pauli-X gates for each target qubit index.
212 pub fn x_controlled_gates(
213 target_indices: Vec<usize>,
214 control_indices: Vec<usize>,
215 ) -> Vec<Self> {
216 target_indices
217 .into_iter()
218 .map(|target_index| Gate::Operator(
219 Box::new(Pauli::X),
220 vec![target_index],
221 control_indices.clone(),
222 ))
223 .collect()
224 }
225
226 /// Creates a new Pauli-Y gate for the specified qubit index.
227 ///
228 /// # Arguments
229 ///
230 /// * `qubit_index` - The index of the qubit on which the Pauli-Y gate acts.
231 ///
232 /// # Returns
233 ///
234 /// * `Gate` - A new instance of the Gate struct representing a Pauli-Y gate.
235 pub fn y_gate(qubit_index: usize) -> Self {
236 Gate::Operator(Box::new(Pauli::Y), vec![qubit_index], vec![])
237 }
238
239 /// Creates new Pauli-Y gates for the specified qubit indices.
240 ///
241 /// # Arguments
242 ///
243 /// * `qubit_indices` - The indices of the qubits on which the Pauli-Y gates act.
244 ///
245 /// # Returns
246 ///
247 /// * `Vec<Gate>` - A vector of Gate structs representing Pauli-Y gates for each qubit index.
248 pub fn y_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
249 qubit_indices
250 .into_iter()
251 .map(|qubit_index| Gate::y_gate(qubit_index))
252 .collect()
253 }
254
255 /// Creates new controlled Pauli-Y gates for the specified qubit indices.
256 ///
257 /// # Arguments
258 ///
259 /// * `target_indices` - The indices of the target qubits.
260 ///
261 /// * `control_indices` - The indices of the control qubits.
262 ///
263 /// # Returns
264 ///
265 /// * `Gates` - A vector of Gate structs representing controlled Pauli-Y gates for each target qubit index.
266 pub fn y_controlled_gates(
267 target_indices: Vec<usize>,
268 control_indices: Vec<usize>,
269 ) -> Vec<Self> {
270 target_indices
271 .into_iter()
272 .map(|target_index| Gate::Operator(
273 Box::new(Pauli::Y),
274 vec![target_index],
275 control_indices.clone(),
276 ))
277 .collect()
278 }
279
280 /// Creates a new Pauli-Z gate for the specified qubit index.
281 ///
282 /// # Arguments
283 ///
284 /// * `qubit_index` - The index of the qubit on which the Pauli-Z gate acts.
285 ///
286 /// # Returns
287 ///
288 /// * `Gate` - A new instance of the Gate struct representing a Pauli-Z gate.
289 pub fn z_gate(qubit_index: usize) -> Self {
290 Gate::Operator(Box::new(Pauli::Z), vec![qubit_index], vec![])
291 }
292
293 /// Creates new Pauli-Z gates for the specified qubit indices.
294 ///
295 /// # Arguments
296 ///
297 /// * `qubit_indices` - The indices of the qubits on which the Pauli-Z gates act.
298 ///
299 /// # Returns
300 ///
301 /// * `Vec<Gate>` - A vector of Gate structs representing Pauli-Z gates for each qubit index.
302 pub fn z_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
303 qubit_indices
304 .into_iter()
305 .map(|qubit_index| Gate::z_gate(qubit_index))
306 .collect()
307 }
308
309 /// Creates new controlled Pauli-Z gates for the specified qubit indices.
310 ///
311 /// # Arguments
312 ///
313 /// * `target_indices` - The indices of the target qubits.
314 ///
315 /// * `control_indices` - The indices of the control qubits.
316 ///
317 /// # Returns
318 ///
319 /// * `Gates` - A vector of Gate structs representing controlled Pauli-Z gates for each target qubit index.
320 pub fn z_controlled_gates(
321 target_indices: Vec<usize>,
322 control_indices: Vec<usize>,
323 ) -> Vec<Self> {
324 target_indices
325 .into_iter()
326 .map(|target_index| Gate::Operator(
327 Box::new(Pauli::Z),
328 vec![target_index],
329 control_indices.clone(),
330 ))
331 .collect()
332 }
333
334 /// Creates a new Identity gate for the specified qubit index.
335 ///
336 /// # Arguments
337 ///
338 /// * `qubit_index` - The index of the qubit on which the Identity gate acts.
339 ///
340 /// # Returns
341 ///
342 /// * `Gate` - A new instance of the Gate struct representing an Identity gate.
343 pub fn i_gate(qubit_index: usize) -> Self {
344 Gate::Operator(Box::new(Identity), vec![qubit_index], vec![])
345 }
346
347 /// Creates new Identity gates for the specified qubit indices.
348 ///
349 /// # Arguments
350 ///
351 /// * `qubit_indices` - The indices of the qubits on which the Identity gates act.
352 ///
353 /// # Returns
354 ///
355 /// * `Vec<Gate>` - A vector of Gate structs representing Identity gates for each qubit index.
356 pub fn i_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
357 qubit_indices
358 .into_iter()
359 .map(|qubit_index| Gate::i_gate(qubit_index))
360 .collect()
361 }
362
363 /// Creates new controlled Identity gates for the specified qubit indices.
364 ///
365 /// # Arguments
366 ///
367 /// * `target_indices` - The indices of the target qubits.
368 ///
369 /// * `control_indices` - The indices of the control qubits.
370 ///
371 /// # Returns
372 ///
373 /// * `Gates` - A vector of Gate structs representing controlled Identity gates for each target qubit index.
374 pub fn i_controlled_gates(
375 target_indices: Vec<usize>,
376 control_indices: Vec<usize>,
377 ) -> Vec<Self> {
378 target_indices
379 .into_iter()
380 .map(|target_index| Gate::Operator(
381 Box::new(Identity),
382 vec![target_index],
383 control_indices.clone(),
384 ))
385 .collect()
386 }
387
388 /// Creates a new Phase-S gate for the specified qubit index.
389 ///
390 /// # Arguments
391 ///
392 /// * `qubit_index` - The index of the qubit on which the Phase-S gate acts.
393 ///
394 /// # Returns
395 ///
396 /// * `Gate` - A new instance of the Gate struct representing a Phase-S gate.
397 pub fn s_gate(qubit_index: usize) -> Self {
398 Gate::Operator(Box::new(PhaseS), vec![qubit_index], vec![])
399 }
400
401 /// Creates new Phase-S gates for the specified qubit indices.
402 ///
403 /// # Arguments
404 ///
405 /// * `qubit_indices` - The indices of the qubits on which the Phase-S gates act.
406 ///
407 /// # Returns
408 ///
409 /// * `Vec<Gate>` - A vector of Gate structs representing Phase-S gates for each qubit index.
410 pub fn s_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
411 qubit_indices
412 .into_iter()
413 .map(|qubit_index| Gate::s_gate(qubit_index))
414 .collect()
415 }
416
417 /// Creates new controlled Phase-S gates for the specified qubit indices.
418 ///
419 /// # Arguments
420 ///
421 /// * `target_indices` - The indices of the target qubits.
422 ///
423 /// * `control_indices` - The indices of the control qubits.
424 ///
425 /// # Returns
426 ///
427 /// * `Gates` - A vector of Gate structs representing controlled Phase-S gates for each target qubit index.
428 pub fn s_controlled_gates(
429 target_indices: Vec<usize>,
430 control_indices: Vec<usize>,
431 ) -> Vec<Self> {
432 target_indices
433 .into_iter()
434 .map(|target_index| Gate::Operator(
435 Box::new(PhaseS),
436 vec![target_index],
437 control_indices.clone(),
438 ))
439 .collect()
440 }
441
442 /// Creates a new Phase-S dagger gate for the specified qubit index.
443 ///
444 /// # Arguments
445 ///
446 /// * `qubit_index` - The index of the qubit on which the Phase-S dagger gate acts.
447 ///
448 /// # Returns
449 ///
450 /// * `Gate` - A new instance of the Gate struct representing a Phase-S dagger gate.
451 pub fn s_dag_gate(qubit_index: usize) -> Self {
452 Gate::Operator(Box::new(PhaseSdag), vec![qubit_index], vec![])
453 }
454
455 /// Creates new Phase-S dagger gates for the specified qubit indices.
456 ///
457 /// # Arguments
458 ///
459 /// * `qubit_indices` - The indices of the qubits on which the Phase-S dagger gates act.
460 ///
461 /// # Returns
462 ///
463 /// * `Vec<Gate>` - A vector of Gate structs representing Phase-S dagger gates for each qubit index.
464 pub fn s_dag_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
465 qubit_indices
466 .into_iter()
467 .map(|qubit_index| Gate::s_dag_gate(qubit_index))
468 .collect()
469 }
470
471 /// Creates new controlled Phase-S dagger gates for the specified qubit indices.
472 ///
473 /// # Arguments
474 ///
475 /// * `target_indices` - The indices of the target qubits.
476 ///
477 /// * `control_indices` - The indices of the control qubits.
478 ///
479 /// # Returns
480 ///
481 /// * `Gates` - A vector of Gate structs representing controlled Phase-S dagger gates for each target qubit index.
482 pub fn s_dag_controlled_gates(
483 target_indices: Vec<usize>,
484 control_indices: Vec<usize>,
485 ) -> Vec<Self> {
486 target_indices
487 .into_iter()
488 .map(|target_index| Gate::Operator(
489 Box::new(PhaseSdag),
490 vec![target_index],
491 control_indices.clone(),
492 ))
493 .collect()
494 }
495
496 /// Creates a new Phase-T gate for the specified qubit index.
497 ///
498 /// # Arguments
499 ///
500 /// * `qubit_index` - The index of the qubit on which the Phase-T gate acts.
501 ///
502 /// # Returns
503 ///
504 /// * `Gate` - A new instance of the Gate struct representing a Phase-T gate.
505 pub fn t_gate(qubit_index: usize) -> Self {
506 Gate::Operator(Box::new(PhaseT), vec![qubit_index], vec![])
507 }
508
509 /// Creates new Phase-T gates for the specified qubit indices.
510 ///
511 /// # Arguments
512 ///
513 /// * `qubit_indices` - The indices of the qubits on which the Phase-T gates act.
514 ///
515 /// # Returns
516 ///
517 /// * `Vec<Gate>` - A vector of Gate structs representing Phase-T gates for each qubit index.
518 pub fn t_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
519 qubit_indices
520 .into_iter()
521 .map(|qubit_index| Gate::t_gate(qubit_index))
522 .collect()
523 }
524
525 /// Creates new controlled Phase-T gates for the specified qubit indices.
526 ///
527 /// # Arguments
528 ///
529 /// * `target_indices` - The indices of the target qubits.
530 ///
531 /// * `control_indices` - The indices of the control qubits.
532 ///
533 /// # Returns
534 ///
535 /// * `Gates` - A vector of Gate structs representing controlled Phase-T gates for each target qubit index.
536 pub fn t_controlled_gates(
537 target_indices: Vec<usize>,
538 control_indices: Vec<usize>,
539 ) -> Vec<Self> {
540 target_indices
541 .into_iter()
542 .map(|target_index| Gate::Operator(
543 Box::new(PhaseT),
544 vec![target_index],
545 control_indices.clone(),
546 ))
547 .collect()
548 }
549
550 /// Creates a new Phase-T dagger gate for the specified qubit index.
551 ///
552 /// # Arguments
553 ///
554 /// * `qubit_index` - The index of the qubit on which the Phase-T dagger gate acts.
555 ///
556 /// # Returns
557 ///
558 /// * `Gate` - A new instance of the Gate struct representing a Phase-T dagger gate.
559 pub fn t_dag_gate(qubit_index: usize) -> Self {
560 Gate::Operator(Box::new(PhaseTdag), vec![qubit_index], vec![])
561 }
562
563 /// Creates new Phase-T dagger gates for the specified qubit indices.
564 ///
565 /// # Arguments
566 ///
567 /// * `qubit_indices` - The indices of the qubits on which the Phase-T dagger gates act.
568 ///
569 /// # Returns
570 ///
571 /// * `Vec<Gate>` - A vector of Gate structs representing Phase-T dagger gates for each qubit index.
572 pub fn t_dag_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
573 qubit_indices
574 .into_iter()
575 .map(|qubit_index| Gate::t_dag_gate(qubit_index))
576 .collect()
577 }
578
579 /// Creates new controlled Phase-T dagger gates for the specified qubit indices.
580 ///
581 /// # Arguments
582 ///
583 /// * `target_indices` - The indices of the target qubits.
584 ///
585 /// * `control_indices` - The indices of the control qubits.
586 ///
587 /// # Returns
588 ///
589 /// * `Gates` - A vector of Gate structs representing controlled Phase-T dagger gates for each target qubit index.
590 pub fn t_dag_controlled_gates(
591 target_indices: Vec<usize>,
592 control_indices: Vec<usize>,
593 ) -> Vec<Self> {
594 target_indices
595 .into_iter()
596 .map(|target_index| Gate::Operator(
597 Box::new(PhaseTdag),
598 vec![target_index],
599 control_indices.clone(),
600 ))
601 .collect()
602 }
603
604 /// Creates a new Phase Shift (P) gate for the specified qubit index and angle.
605 ///
606 /// # Arguments
607 ///
608 /// * `qubit_index` - The index of the qubit on which the Phase Shift gate acts.
609 /// * `angle` - The phase shift angle in radians.
610 ///
611 /// # Returns
612 ///
613 /// * `Gate` - A new instance of the Gate struct representing a Phase Shift gate.
614 pub fn p_gate(qubit_index: usize, angle: f64) -> Self {
615 Gate::Operator(Box::new(PhaseShift::new(angle)), vec![qubit_index], vec![])
616 }
617
618 /// Creates new Phase Shift (P) gates for the specified qubit indices and angle.
619 ///
620 /// # Arguments
621 ///
622 /// * `qubit_indices` - The indices of the qubits on which the Phase Shift gates act.
623 /// * `angle` - The phase shift angle in radians for all gates.
624 ///
625 /// # Returns
626 ///
627 /// * `Vec<Gate>` - A vector of Gate structs representing Phase Shift gates for each qubit index.
628 pub fn p_multi_gate(qubit_indices: Vec<usize>, angle: f64) -> Vec<Self> {
629 let op_template = PhaseShift::new(angle);
630 qubit_indices
631 .into_iter()
632 .map(|qubit_index| Gate::Operator(Box::new(op_template.clone()), vec![qubit_index], vec![]))
633 .collect()
634 }
635
636 /// Creates new controlled Phase Shift (P) gates for the specified qubit indices and angle.
637 ///
638 /// # Arguments
639 ///
640 /// * `target_indices` - The indices of the target qubits.
641 /// * `control_indices` - The indices of the control qubits.
642 /// * `angle` - The phase shift angle in radians for all gates.
643 ///
644 /// # Returns
645 ///
646 /// * `Gates` - A vector of Gate structs representing controlled Phase Shift gates for each target qubit index.
647 pub fn p_controlled_gates(
648 target_indices: Vec<usize>,
649 control_indices: Vec<usize>,
650 angle: f64,
651 ) -> Vec<Self> {
652 let op_template = PhaseShift::new(angle);
653 target_indices
654 .into_iter()
655 .map(|target_index| Gate::Operator(
656 Box::new(op_template.clone()),
657 vec![target_index],
658 control_indices.clone(),
659 ))
660 .collect()
661 }
662
663 /// Creates a new RotateX (RX) gate for the specified qubit index and angle.
664 ///
665 /// # Arguments
666 ///
667 /// * `qubit_index` - The index of the qubit on which the RotateX gate acts.
668 /// * `angle` - The rotation angle in radians.
669 ///
670 /// # Returns
671 ///
672 /// * `Gate` - A new instance of the Gate struct representing a RotateX gate.
673 pub fn rx_gate(qubit_index: usize, angle: f64) -> Self {
674 Gate::Operator(Box::new(RotateX::new(angle)), vec![qubit_index], vec![])
675 }
676
677 /// Creates new RotateX (RX) gates for the specified qubit indices and angle.
678 ///
679 /// # Arguments
680 ///
681 /// * `qubit_indices` - The indices of the qubits on which the RotateX gates act.
682 /// * `angle` - The rotation angle in radians for all gates.
683 ///
684 /// # Returns
685 ///
686 /// * `Vec<Gate>` - A vector of Gate structs representing RotateX gates for each qubit index.
687 pub fn rx_multi_gate(qubit_indices: Vec<usize>, angle: f64) -> Vec<Self> {
688 let op_template = RotateX::new(angle);
689 qubit_indices
690 .into_iter()
691 .map(|qubit_index| Gate::Operator(Box::new(op_template.clone()), vec![qubit_index], vec![]))
692 .collect()
693 }
694
695 /// Creates new controlled RotateX (RX) gates for the specified qubit indices and angle.
696 ///
697 /// # Arguments
698 ///
699 /// * `target_indices` - The indices of the target qubits.
700 /// * `control_indices` - The indices of the control qubits.
701 /// * `angle` - The rotation angle in radians for all gates.
702 ///
703 /// # Returns
704 ///
705 /// * `Gates` - A vector of Gate structs representing controlled RotateX gates for each target qubit index.
706 pub fn rx_controlled_gates(
707 target_indices: Vec<usize>,
708 control_indices: Vec<usize>,
709 angle: f64,
710 ) -> Vec<Self> {
711 let op_template = RotateX::new(angle);
712 target_indices
713 .into_iter()
714 .map(|target_index| Gate::Operator(
715 Box::new(op_template.clone()),
716 vec![target_index],
717 control_indices.clone(),
718 ))
719 .collect()
720 }
721
722 /// Creates a new RotateY (RY) gate for the specified qubit index and angle.
723 ///
724 /// # Arguments
725 ///
726 /// * `qubit_index` - The index of the qubit on which the RotateY gate acts.
727 /// * `angle` - The rotation angle in radians.
728 ///
729 /// # Returns
730 ///
731 /// * `Gate` - A new instance of the Gate struct representing a RotateY gate.
732 pub fn ry_gate(qubit_index: usize, angle: f64) -> Self {
733 Gate::Operator(Box::new(RotateY::new(angle)), vec![qubit_index], vec![])
734 }
735
736 /// Creates new RotateY (RY) gates for the specified qubit indices and angle.
737 ///
738 /// # Arguments
739 ///
740 /// * `qubit_indices` - The indices of the qubits on which the RotateY gates act.
741 /// * `angle` - The rotation angle in radians for all gates.
742 ///
743 /// # Returns
744 ///
745 /// * `Vec<Gate>` - A vector of Gate structs representing RotateY gates for each qubit index.
746 pub fn ry_multi_gate(qubit_indices: Vec<usize>, angle: f64) -> Vec<Self> {
747 let op_template = RotateY::new(angle);
748 qubit_indices
749 .into_iter()
750 .map(|qubit_index| Gate::Operator(Box::new(op_template.clone()), vec![qubit_index], vec![]))
751 .collect()
752 }
753
754 /// Creates new controlled RotateY (RY) gates for the specified qubit indices and angle.
755 ///
756 /// # Arguments
757 ///
758 /// * `target_indices` - The indices of the target qubits.
759 /// * `control_indices` - The indices of the control qubits.
760 /// * `angle` - The rotation angle in radians for all gates.
761 ///
762 /// # Returns
763 ///
764 /// * `Gates` - A vector of Gate structs representing controlled RotateY gates for each target qubit index.
765 pub fn ry_controlled_gates(
766 target_indices: Vec<usize>,
767 control_indices: Vec<usize>,
768 angle: f64,
769 ) -> Vec<Self> {
770 let op_template = RotateY::new(angle);
771 target_indices
772 .into_iter()
773 .map(|target_index| Gate::Operator(
774 Box::new(op_template.clone()),
775 vec![target_index],
776 control_indices.clone(),
777 ))
778 .collect()
779 }
780
781 /// Creates a new RotateZ (RZ) gate for the specified qubit index and angle.
782 ///
783 /// # Arguments
784 ///
785 /// * `qubit_index` - The index of the qubit on which the RotateZ gate acts.
786 /// * `angle` - The rotation angle in radians.
787 ///
788 /// # Returns
789 ///
790 /// * `Gate` - A new instance of the Gate struct representing a RotateZ gate.
791 pub fn rz_gate(qubit_index: usize, angle: f64) -> Self {
792 Gate::Operator(Box::new(RotateZ::new(angle)), vec![qubit_index], vec![])
793 }
794
795 /// Creates new RotateZ (RZ) gates for the specified qubit indices and angle.
796 ///
797 /// # Arguments
798 ///
799 /// * `qubit_indices` - The indices of the qubits on which the RotateZ gates act.
800 /// * `angle` - The rotation angle in radians for all gates.
801 ///
802 /// # Returns
803 ///
804 /// * `Vec<Gate>` - A vector of Gate structs representing RotateZ gates for each qubit index.
805 pub fn rz_multi_gate(qubit_indices: Vec<usize>, angle: f64) -> Vec<Self> {
806 let op_template = RotateZ::new(angle);
807 qubit_indices
808 .into_iter()
809 .map(|qubit_index| Gate::Operator(Box::new(op_template.clone()), vec![qubit_index], vec![]))
810 .collect()
811 }
812
813 /// Creates new controlled RotateZ (RZ) gates for the specified qubit indices and angle.
814 ///
815 /// # Arguments
816 ///
817 /// * `target_indices` - The indices of the target qubits.
818 /// * `control_indices` - The indices of the control qubits.
819 /// * `angle` - The rotation angle in radians for all gates.
820 ///
821 /// # Returns
822 ///
823 /// * `Gates` - A vector of Gate structs representing controlled RotateZ gates for each target qubit index.
824 pub fn rz_controlled_gates(
825 target_indices: Vec<usize>,
826 control_indices: Vec<usize>,
827 angle: f64,
828 ) -> Vec<Self> {
829 let op_template = RotateZ::new(angle);
830 target_indices
831 .into_iter()
832 .map(|target_index| Gate::Operator(
833 Box::new(op_template.clone()),
834 vec![target_index],
835 control_indices.clone(),
836 ))
837 .collect()
838 }
839
840 /// Creates a new Unitary2 gate for the specified qubit index and unitary matrix.
841 ///
842 /// # Arguments
843 ///
844 /// * `qubit_index` - The index of the qubit on which the Unitary2 gate acts.
845 /// * `unitary` - The unitary matrix to be applied.
846 ///
847 /// # Returns
848 ///
849 /// * `Gate` - A new instance of the Gate struct representing a Unitary2 gate.
850 pub fn unitary2_gate(qubit_index: usize, unitary: [[Complex<f64>; 2]; 2]) -> Self {
851 Gate::Operator(
852 Box::new(Unitary2::new(unitary).unwrap()),
853 vec![qubit_index],
854 vec![],
855 )
856 }
857
858 /// Creates new Unitary2 gates for the specified qubit indices and unitary matrix.
859 ///
860 /// # Arguments
861 ///
862 /// * `qubit_indices` - The indices of the qubits on which the Unitary2 gates act.
863 ///
864 /// * `unitary` - The unitary matrix to be applied.
865 ///
866 /// # Returns
867 ///
868 /// * `Vec<Gate>` - A vector of Gate structs representing Unitary2 gates for each qubit index.
869 pub fn unitary2_multi_gate(
870 qubit_indices: Vec<usize>,
871 unitary: [[Complex<f64>; 2]; 2],
872 ) -> Vec<Self> {
873 let op_template = Unitary2::new(unitary).unwrap();
874 qubit_indices
875 .into_iter()
876 .map(|qubit_index| Gate::Operator(Box::new(op_template.clone()), vec![qubit_index], vec![]))
877 .collect()
878 }
879
880 /// Creates new controlled Unitary2 gates for the specified qubit indices and unitary matrix.
881 ///
882 /// # Arguments
883 ///
884 /// * `target_indices` - The indices of the target qubits.
885 ///
886 /// * `control_indices` - The indices of the control qubits.
887 ///
888 /// * `unitary` - The unitary matrix to be applied.
889 ///
890 /// # Returns
891 ///
892 /// * `Gates` - A vector of Gate structs representing controlled Unitary2 gates for each target qubit index.
893 pub fn unitary2_controlled_gates(
894 target_indices: Vec<usize>,
895 control_indices: Vec<usize>,
896 unitary: [[Complex<f64>; 2]; 2],
897 ) -> Vec<Self> {
898 let op_template = Unitary2::new(unitary).unwrap();
899 target_indices
900 .into_iter()
901 .map(|target_index| Gate::Operator(
902 Box::new(op_template.clone()),
903 vec![target_index],
904 control_indices.clone(),
905 ))
906 .collect()
907 }
908
909 // -- MULTI-QUBIT GATES --
910
911 /// Creates a CNOT gate for the specified target and control qubit indices.
912 ///
913 /// # Arguments
914 ///
915 /// * `target_index` - The index of the target qubit.
916 ///
917 /// * `control_index` - The index of the control qubit.
918 ///
919 /// # Returns
920 ///
921 /// * `Gate` - A new instance of the Gate struct representing a CNOT gate.
922 pub fn cnot_gate(target_index: usize, control_index: usize) -> Self {
923 Gate::Operator(
924 Box::new(CNOT),
925 vec![target_index],
926 vec![control_index],
927 )
928 }
929
930 /// Creates a new SWAP gate for the specified qubit index.
931 ///
932 /// # Arguments
933 ///
934 /// * `qubit1` - The index of the first qubit.
935 /// * `qubit2` - The index of the second qubit.
936 ///
937 /// # Returns
938 ///
939 /// * `Gate` - A new instance of the Gate struct representing a SWAP gate.
940 pub fn swap_gate(qubit1_index: usize, qubit2_index: usize) -> Self {
941 Gate::Operator(Box::new(SWAP), vec![qubit1_index, qubit2_index], vec![])
942 }
943
944 /// Creates a new controlled SWAP gate for the specified target and control qubit indices.
945 ///
946 /// # Arguments
947 ///
948 /// * `target_indices` - The indices of the target qubits.
949 /// * `control_indices` - The indices of the control qubits.
950 ///
951 /// # Returns
952 ///
953 /// * `Gate` - A new instance of the Gate struct representing a controlled SWAP gate.
954 pub fn swap_controlled_gate(
955 target_indices: Vec<usize>,
956 control_indices: Vec<usize>,
957 ) -> Self {
958 Gate::Operator(Box::new(SWAP), target_indices, control_indices)
959 }
960
961 /// Creates a new Toffoli gate for the specified target and control qubit indices.
962 ///
963 /// # Arguments
964 ///
965 /// * `target_index` - The index of the target qubit.
966 ///
967 /// * `control_indices` - The indices of the control qubits.
968 ///
969 /// # Returns
970 ///
971 /// * `Gate` - A new instance of the Gate struct representing a Toffoli gate.
972 pub fn toffoli_gate(target_index: usize, control_indices: Vec<usize>) -> Self {
973 Gate::Operator(Box::new(Toffoli), vec![target_index], control_indices)
974 }
975}