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, Matchgate
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(Gate::h_gate)
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(Gate::x_gate)
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(Gate::y_gate)
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(Gate::z_gate)
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(Gate::i_gate)
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(Gate::s_gate)
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(Gate::s_dag_gate)
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(Gate::t_gate)
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(Gate::t_dag_gate)
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), 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),
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), 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),
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), 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),
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), 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),
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 /// * `Result<Gate, Error>` - A Gate struct representing a Unitary2 gate if the unitary is valid, else an error.
851 pub fn unitary2_gate(qubit_index: usize, unitary: [[Complex<f64>; 2]; 2]) -> Result<Self, Error> {
852 Ok(Gate::Operator(
853 Box::new(Unitary2::new(unitary)?),
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 /// * `Result<Vec<Gate>, Error>` - A vector of Gate structs representing Unitary2 gates for each qubit index if the unitary is valid,, else an error.
870 pub fn unitary2_multi_gate(
871 qubit_indices: Vec<usize>,
872 unitary: [[Complex<f64>; 2]; 2],
873 ) -> Result<Vec<Self>, Error> {
874 let op_template = Unitary2::new(unitary)?;
875 let gates = qubit_indices
876 .into_iter()
877 .map(|qubit_index| Gate::Operator(Box::new(op_template), vec![qubit_index], vec![]))
878 .collect();
879 Ok(gates)
880 }
881
882 /// Creates new controlled Unitary2 gates for the specified qubit indices and unitary matrix.
883 ///
884 /// # Arguments
885 ///
886 /// * `target_indices` - The indices of the target qubits.
887 ///
888 /// * `control_indices` - The indices of the control qubits.
889 ///
890 /// * `unitary` - The unitary matrix to be applied.
891 ///
892 /// # Returns
893 ///
894 /// * Result<Vec<Gate>, Error> - A vector of Gate structs representing controlled Unitary2 gates for each target qubit index if the unitary is valid, else an error.
895 pub fn unitary2_controlled_gates(
896 target_indices: Vec<usize>,
897 control_indices: Vec<usize>,
898 unitary: [[Complex<f64>; 2]; 2],
899 ) -> Result<Vec<Self>, Error> {
900 let op_template = Unitary2::new(unitary)?;
901 let gates = target_indices
902 .into_iter()
903 .map(|target_index| Gate::Operator(
904 Box::new(op_template),
905 vec![target_index],
906 control_indices.clone(),
907 ))
908 .collect();
909 Ok(gates)
910 }
911
912 /// Creates a new Unitary2 gate for the specified qubit index and unitary matrix using a rotation angle and phase shift.
913 /// Unlike custom Unitary2 gates, the generated unitary matrix is guaranteed to be valid.
914 /// Therefore, this method does not return an error.
915 ///
916 /// # Arguments
917 ///
918 /// * qubit_index - The index of the qubit on which the Unitary2 gate acts.
919 ///
920 /// * theta - The rotation angle in radians.
921 ///
922 /// * phi - The phase shift in radians.
923 ///
924 /// # Returns
925 ///
926 /// * Gate - A new instance of the Gate struct representing a Unitary2 gate.
927 pub fn ry_phase_gate(
928 qubit_index: usize,
929 theta: f64,
930 phi: f64,
931 ) -> Self {
932 Gate::Operator(
933 Box::new(Unitary2::from_ry_phase(theta, phi)),
934 vec![qubit_index],
935 vec![],
936 )
937 }
938
939 /// Creates new Unitary2 gates for the specified qubit indices and unitary matrix using a rotation angle and phase shift.
940 /// Unlike custom Unitary2 gates, the generated unitary matrix is guaranteed to be valid.
941 /// Therefore, this method does not return an error.
942 ///
943 /// # Arguments
944 ///
945 /// * qubit_indices - The indices of the qubits on which the Unitary2 gates act.
946 ///
947 /// * theta - The rotation angle in radians for all gates.
948 ///
949 /// * phi - The phase shift in radians for all gates.
950 ///
951 /// # Returns
952 ///
953 /// * Vec<Gate> - A vector of Gate structs representing Unitary2 gates for each qubit index.
954 pub fn ry_phase_multi_gate(
955 qubit_indices: Vec<usize>,
956 theta: f64,
957 phi: f64,
958 ) -> Vec<Self> {
959 let op_template = Unitary2::from_ry_phase(theta, phi);
960 qubit_indices
961 .into_iter()
962 .map(|qubit_index| Gate::Operator(Box::new(op_template), vec![qubit_index], vec![]))
963 .collect()
964 }
965
966 /// Creates new controlled Unitary2 gates for the specified qubit indices and unitary matrix using a rotation angle and phase shift.
967 ///
968 /// # Arguments
969 ///
970 /// * target_indices - The indices of the target qubits.
971 ///
972 /// * control_indices - The indices of the control qubits.
973 ///
974 /// * theta - The rotation angle in radians for all gates.
975 ///
976 /// * phi - The phase shift in radians for all gates.
977 ///
978 /// # Returns
979 ///
980 /// * Vec<Gate> - A vector of Gate structs representing controlled Unitary2 gates for each target qubit index.
981 pub fn ry_phase_controlled_gates(
982 target_indices: Vec<usize>,
983 control_indices: Vec<usize>,
984 theta: f64,
985 phi: f64,
986 ) -> Vec<Self> {
987 let op_template = Unitary2::from_ry_phase(theta, phi);
988 target_indices
989 .into_iter()
990 .map(|target_index| Gate::Operator(
991 Box::new(op_template),
992 vec![target_index],
993 control_indices.clone(),
994 ))
995 .collect()
996 }
997
998 // -- MULTI-QUBIT GATES --
999
1000 /// Creates a CNOT gate for the specified target and control qubit indices.
1001 ///
1002 /// # Arguments
1003 ///
1004 /// * `target_index` - The index of the target qubit.
1005 ///
1006 /// * `control_index` - The index of the control qubit.
1007 ///
1008 /// # Returns
1009 ///
1010 /// * `Gate` - A new instance of the Gate struct representing a CNOT gate.
1011 pub fn cnot_gate(target_index: usize, control_index: usize) -> Self {
1012 Gate::Operator(
1013 Box::new(CNOT),
1014 vec![target_index],
1015 vec![control_index],
1016 )
1017 }
1018
1019 /// Creates a new SWAP gate for the specified qubit index.
1020 ///
1021 /// # Arguments
1022 ///
1023 /// * `qubit1` - The index of the first qubit.
1024 /// * `qubit2` - The index of the second qubit.
1025 ///
1026 /// # Returns
1027 ///
1028 /// * `Gate` - A new instance of the Gate struct representing a SWAP gate.
1029 pub fn swap_gate(qubit1_index: usize, qubit2_index: usize) -> Self {
1030 Gate::Operator(Box::new(SWAP), vec![qubit1_index, qubit2_index], vec![])
1031 }
1032
1033 /// Creates a new controlled SWAP gate for the specified target and control qubit indices.
1034 ///
1035 /// # Arguments
1036 ///
1037 /// * `target_indices` - The indices of the target qubits.
1038 /// * `control_indices` - The indices of the control qubits.
1039 ///
1040 /// # Returns
1041 ///
1042 /// * `Gate` - A new instance of the Gate struct representing a controlled SWAP gate.
1043 pub fn swap_controlled_gate(
1044 target_indices: Vec<usize>,
1045 control_indices: Vec<usize>,
1046 ) -> Self {
1047 Gate::Operator(Box::new(SWAP), target_indices, control_indices)
1048 }
1049
1050 /// Creates a new Toffoli gate for the specified target and control qubit indices.
1051 ///
1052 /// # Arguments
1053 ///
1054 /// * `target_index` - The index of the target qubit.
1055 ///
1056 /// * `control_indices` - The indices of the control qubits.
1057 ///
1058 /// # Returns
1059 ///
1060 /// * `Gate` - A new instance of the Gate struct representing a Toffoli gate.
1061 pub fn toffoli_gate(target_index: usize, control_indices: Vec<usize>) -> Self {
1062 Gate::Operator(Box::new(Toffoli), vec![target_index], control_indices)
1063 }
1064
1065 /// Creates a new Matchgate with the specified qubit index and its adjacent as targets.
1066 ///
1067 /// # Arguments
1068 ///
1069 /// * `target_index` - The index of the first target qubit. The second target qubit is assumed to be the next qubit.
1070 /// * `theta` - The angle of rotation in radians.
1071 /// * `phi1` - The first phase shift in radians.
1072 /// * `phi2` - The second phase shift in radians.
1073 ///
1074 /// # Returns
1075 ///
1076 /// * `Gate` - A new instance of the Gate struct representing a Matchgate.
1077 ///
1078 /// # Warning
1079 ///
1080 /// This gate is not yet compilable to OpenQASM, since it requires advanced decomposition techniques.
1081 pub fn matchgate(
1082 target_index: usize,
1083 theta: f64,
1084 phi1: f64,
1085 phi2: f64,
1086 ) -> Self {
1087 Gate::Operator(
1088 Box::new(Matchgate::new(theta, phi1, phi2)),
1089 vec![target_index],
1090 vec![],
1091 )
1092 }
1093
1094 /// Creates a new controlled Matchgate with the specified qubit index and its adjacent as target qubits.
1095 ///
1096 /// # Arguments
1097 ///
1098 /// * `target_index` - The index of the first target qubit. The second target qubit is assumed to be the next qubit.
1099 /// * `control_indices` - The indices of the control qubits.
1100 /// * `theta` - The angle of rotation in radians.
1101 /// * `phi1` - The first phase shift in radians.
1102 /// * `phi2` - The second phase shift in radians.
1103 ///
1104 /// # Returns
1105 ///
1106 /// * `Gate` - A new instance of the Gate struct representing a controlled Matchgate.
1107 ///
1108 /// # Warning
1109 ///
1110 /// This gate is not yet compilable to OpenQASM, since it requires advanced decomposition techniques.
1111 pub fn controlled_matchgate(
1112 target_index: usize,
1113 control_indices: Vec<usize>,
1114 theta: f64,
1115 phi1: f64,
1116 phi2: f64,
1117 ) -> Self {
1118 Gate::Operator(
1119 Box::new(Matchgate::new(theta, phi1, phi2)),
1120 vec![target_index],
1121 control_indices,
1122 )
1123 }
1124}