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