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 parametric::parametric_gate::ParametricGate,
10 },
11 errors::Error,
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 /// Represents a parametric gate.
38 Parametric(Box<dyn ParametricGate>, Vec<usize>, Vec<usize>),
39}
40
41impl Gate {
42 /// Creates a new measurement gate for the specified qubit indices.
43 ///
44 /// # Arguments
45 ///
46 /// * `qubit_indices` - The indices of the qubits to be measured.
47 /// * `basis` - The basis of measurement (e.g., computational basis).
48 ///
49 /// # Returns
50 ///
51 /// * `Gate` - A new instance of the Gate struct representing a measurement gate.
52 pub fn new_measurement(qubit_indices: Vec<usize>, basis: MeasurementBasis) -> Self {
53 Gate::Measurement(basis, qubit_indices)
54 }
55
56 /// Creates a new operator gate for the specified qubit indices.
57 ///
58 /// # Arguments
59 ///
60 /// * `operator` - A boxed dynamic operator trait object.
61 ///
62 /// * `target_indices` - The indices of the qubits on which the operator acts.
63 ///
64 /// * `control_indices` - Optional control qubit indices for controlled gates.
65 ///
66 /// # Returns
67 ///
68 /// * `Gate` - A new instance of the Gate struct representing an operator gate.
69 pub fn new_operator(
70 operator: Box<dyn Operator>,
71 target_indices: Vec<usize>,
72 control_indices: Vec<usize>,
73 ) -> Self {
74 Gate::Operator(operator, target_indices, control_indices)
75 }
76
77 /// Applies the gate to the given state and returns the new state.
78 ///
79 /// # Arguments
80 ///
81 /// * `state` - The quantum state to which the gate will be applied.
82 ///
83 /// # Returns
84 ///
85 /// * `State` - The new quantum state after applying the gate.
86 pub fn apply(&self, state: &State) -> Result<State, Error> {
87 match self {
88 Gate::Operator(operator, target_indices, control_indices) => {
89 operator.apply(state, target_indices, control_indices.as_slice())
90 }
91 Gate::Measurement(basis, indices) => state
92 .measure(*basis, indices.as_slice())
93 .map(|measurementresult| measurementresult.get_new_state().clone()),
94 Gate::Parametric(p_gate, target_indices, control_indices) => {
95 let concrete_gates = p_gate.to_concrete_gates(target_indices, control_indices);
96 concrete_gates
97 .into_iter()
98 .try_fold(state.clone(), |current_state, gate| {
99 gate.apply(¤t_state)
100 })
101 }
102 }
103 }
104
105 /// Returns the indices of the qubits on which the gate acts.
106 ///
107 /// # Returns
108 ///
109 /// * `&Vec<usize>` - A vector of indices of the qubits on which the gate acts.
110 pub fn get_target_qubits(&self) -> &Vec<usize> {
111 match self {
112 Gate::Operator(_, target_indices, _) => target_indices,
113 Gate::Measurement(_, indices) => indices,
114 Gate::Parametric(_, target_indices, _) => target_indices,
115 }
116 }
117
118 /// Returns the control indices of the gate if it has any.
119 ///
120 /// # Returns
121 ///
122 /// * `Option<&Vec<usize>>` - An optional vector of control indices.
123 pub fn get_control_qubits(&self) -> Option<&Vec<usize>> {
124 match self {
125 Gate::Operator(_, _, control_indices) => Some(control_indices),
126 Gate::Measurement(_, _) => None,
127 Gate::Parametric(_, _, control_indices) => Some(control_indices),
128 }
129 }
130
131 // -- SINGLE-QUBIT GATES --
132
133 /// Creates a new Hadamard gate for the specified qubit index.
134 ///
135 /// # Arguments
136 ///
137 /// * `qubit_index` - The index of the qubit on which the Hadamard gate acts.
138 ///
139 /// # Returns
140 ///
141 /// * `Gate` - A new instance of the Gate struct representing a Hadamard gate.
142 pub fn h_gate(qubit_index: usize) -> Self {
143 Gate::Operator(Box::new(Hadamard), vec![qubit_index], vec![])
144 }
145
146 /// Creates new Hadamard gates for the specified qubit indices.
147 ///
148 /// # Arguments
149 ///
150 /// * `qubit_indices` - The indices of the qubits on which the Hadamard gate acts.
151 ///
152 /// # Returns
153 ///
154 /// * `Gates` - A vector of Gate structs representing Hadamard gates for each qubit index.
155 pub fn h_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
156 qubit_indices
157 .into_iter()
158 .map(Gate::h_gate)
159 .collect()
160 }
161
162 /// Creates new controlled Hadamard gates for the specified qubit indices.
163 ///
164 /// # Arguments
165 ///
166 /// * `target_indices` - The indices of the target qubits.
167 /// * `control_indices` - The indices of the control qubits.
168 ///
169 /// # Returns
170 ///
171 /// * `Gates` - A vector of Gate structs representing controlled Hadamard gates for each target qubit index.
172 pub fn h_controlled_gates(
173 target_indices: Vec<usize>,
174 control_indices: Vec<usize>,
175 ) -> Vec<Self> {
176 target_indices
177 .into_iter()
178 .map(|target_index| Gate::Operator(
179 Box::new(Hadamard),
180 vec![target_index],
181 control_indices.clone(),
182 ))
183 .collect()
184 }
185
186 /// Creates a new Pauli-X gate for the specified qubit index.
187 ///
188 /// # Arguments
189 ///
190 /// * `qubit_index` - The index of the qubit on which the Pauli-X gate acts.
191 ///
192 /// # Returns
193 ///
194 /// * `Gate` - A new instance of the Gate struct representing a Pauli-X gate.
195 pub fn x_gate(qubit_index: usize) -> Self {
196 Gate::Operator(Box::new(Pauli::X), vec![qubit_index], vec![])
197 }
198
199 /// Creates new controlled Pauli-X gates for the specified qubit indices.
200 ///
201 /// # Arguments
202 ///
203 /// * `qubit_indices` - The indices of the qubits on which the Pauli-X gates act.
204 ///
205 /// # Returns
206 ///
207 /// * `Vec<Gate>` - A vector of Gate structs representing Pauli-X gates for each qubit index.
208 pub fn x_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
209 qubit_indices
210 .into_iter()
211 .map(Gate::x_gate)
212 .collect()
213 }
214
215 /// Creates new Pauli-X gates for the specified qubit indices with control qubits.
216 ///
217 /// # Arguments
218 ///
219 /// * `target_indices` - The indices of the target qubits.
220 ///
221 /// * `control_indices` - The indices of the control qubits.
222 ///
223 /// # Returns
224 ///
225 /// * `Gates` - A vector of Gate structs representing controlled Pauli-X gates for each target qubit index.
226 pub fn x_controlled_gates(
227 target_indices: Vec<usize>,
228 control_indices: Vec<usize>,
229 ) -> Vec<Self> {
230 target_indices
231 .into_iter()
232 .map(|target_index| Gate::Operator(
233 Box::new(Pauli::X),
234 vec![target_index],
235 control_indices.clone(),
236 ))
237 .collect()
238 }
239
240 /// Creates a new Pauli-Y gate for the specified qubit index.
241 ///
242 /// # Arguments
243 ///
244 /// * `qubit_index` - The index of the qubit on which the Pauli-Y gate acts.
245 ///
246 /// # Returns
247 ///
248 /// * `Gate` - A new instance of the Gate struct representing a Pauli-Y gate.
249 pub fn y_gate(qubit_index: usize) -> Self {
250 Gate::Operator(Box::new(Pauli::Y), vec![qubit_index], vec![])
251 }
252
253 /// Creates new Pauli-Y gates for the specified qubit indices.
254 ///
255 /// # Arguments
256 ///
257 /// * `qubit_indices` - The indices of the qubits on which the Pauli-Y gates act.
258 ///
259 /// # Returns
260 ///
261 /// * `Vec<Gate>` - A vector of Gate structs representing Pauli-Y gates for each qubit index.
262 pub fn y_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
263 qubit_indices
264 .into_iter()
265 .map(Gate::y_gate)
266 .collect()
267 }
268
269 /// Creates new controlled Pauli-Y gates for the specified qubit indices.
270 ///
271 /// # Arguments
272 ///
273 /// * `target_indices` - The indices of the target qubits.
274 ///
275 /// * `control_indices` - The indices of the control qubits.
276 ///
277 /// # Returns
278 ///
279 /// * `Gates` - A vector of Gate structs representing controlled Pauli-Y gates for each target qubit index.
280 pub fn y_controlled_gates(
281 target_indices: Vec<usize>,
282 control_indices: Vec<usize>,
283 ) -> Vec<Self> {
284 target_indices
285 .into_iter()
286 .map(|target_index| Gate::Operator(
287 Box::new(Pauli::Y),
288 vec![target_index],
289 control_indices.clone(),
290 ))
291 .collect()
292 }
293
294 /// Creates a new Pauli-Z gate for the specified qubit index.
295 ///
296 /// # Arguments
297 ///
298 /// * `qubit_index` - The index of the qubit on which the Pauli-Z gate acts.
299 ///
300 /// # Returns
301 ///
302 /// * `Gate` - A new instance of the Gate struct representing a Pauli-Z gate.
303 pub fn z_gate(qubit_index: usize) -> Self {
304 Gate::Operator(Box::new(Pauli::Z), vec![qubit_index], vec![])
305 }
306
307 /// Creates new Pauli-Z gates for the specified qubit indices.
308 ///
309 /// # Arguments
310 ///
311 /// * `qubit_indices` - The indices of the qubits on which the Pauli-Z gates act.
312 ///
313 /// # Returns
314 ///
315 /// * `Vec<Gate>` - A vector of Gate structs representing Pauli-Z gates for each qubit index.
316 pub fn z_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
317 qubit_indices
318 .into_iter()
319 .map(Gate::z_gate)
320 .collect()
321 }
322
323 /// Creates new controlled Pauli-Z gates for the specified qubit indices.
324 ///
325 /// # Arguments
326 ///
327 /// * `target_indices` - The indices of the target qubits.
328 ///
329 /// * `control_indices` - The indices of the control qubits.
330 ///
331 /// # Returns
332 ///
333 /// * `Gates` - A vector of Gate structs representing controlled Pauli-Z gates for each target qubit index.
334 pub fn z_controlled_gates(
335 target_indices: Vec<usize>,
336 control_indices: Vec<usize>,
337 ) -> Vec<Self> {
338 target_indices
339 .into_iter()
340 .map(|target_index| Gate::Operator(
341 Box::new(Pauli::Z),
342 vec![target_index],
343 control_indices.clone(),
344 ))
345 .collect()
346 }
347
348 /// Creates a new Identity gate for the specified qubit index.
349 ///
350 /// # Arguments
351 ///
352 /// * `qubit_index` - The index of the qubit on which the Identity gate acts.
353 ///
354 /// # Returns
355 ///
356 /// * `Gate` - A new instance of the Gate struct representing an Identity gate.
357 pub fn i_gate(qubit_index: usize) -> Self {
358 Gate::Operator(Box::new(Identity), vec![qubit_index], vec![])
359 }
360
361 /// Creates new Identity gates for the specified qubit indices.
362 ///
363 /// # Arguments
364 ///
365 /// * `qubit_indices` - The indices of the qubits on which the Identity gates act.
366 ///
367 /// # Returns
368 ///
369 /// * `Vec<Gate>` - A vector of Gate structs representing Identity gates for each qubit index.
370 pub fn i_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
371 qubit_indices
372 .into_iter()
373 .map(Gate::i_gate)
374 .collect()
375 }
376
377 /// Creates new controlled Identity gates for the specified qubit indices.
378 ///
379 /// # Arguments
380 ///
381 /// * `target_indices` - The indices of the target qubits.
382 ///
383 /// * `control_indices` - The indices of the control qubits.
384 ///
385 /// # Returns
386 ///
387 /// * `Gates` - A vector of Gate structs representing controlled Identity gates for each target qubit index.
388 pub fn i_controlled_gates(
389 target_indices: Vec<usize>,
390 control_indices: Vec<usize>,
391 ) -> Vec<Self> {
392 target_indices
393 .into_iter()
394 .map(|target_index| Gate::Operator(
395 Box::new(Identity),
396 vec![target_index],
397 control_indices.clone(),
398 ))
399 .collect()
400 }
401
402 /// Creates a new Phase-S gate for the specified qubit index.
403 ///
404 /// # Arguments
405 ///
406 /// * `qubit_index` - The index of the qubit on which the Phase-S gate acts.
407 ///
408 /// # Returns
409 ///
410 /// * `Gate` - A new instance of the Gate struct representing a Phase-S gate.
411 pub fn s_gate(qubit_index: usize) -> Self {
412 Gate::Operator(Box::new(PhaseS), vec![qubit_index], vec![])
413 }
414
415 /// Creates new Phase-S gates for the specified qubit indices.
416 ///
417 /// # Arguments
418 ///
419 /// * `qubit_indices` - The indices of the qubits on which the Phase-S gates act.
420 ///
421 /// # Returns
422 ///
423 /// * `Vec<Gate>` - A vector of Gate structs representing Phase-S gates for each qubit index.
424 pub fn s_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
425 qubit_indices
426 .into_iter()
427 .map(Gate::s_gate)
428 .collect()
429 }
430
431 /// Creates new controlled Phase-S gates for the specified qubit indices.
432 ///
433 /// # Arguments
434 ///
435 /// * `target_indices` - The indices of the target qubits.
436 ///
437 /// * `control_indices` - The indices of the control qubits.
438 ///
439 /// # Returns
440 ///
441 /// * `Gates` - A vector of Gate structs representing controlled Phase-S gates for each target qubit index.
442 pub fn s_controlled_gates(
443 target_indices: Vec<usize>,
444 control_indices: Vec<usize>,
445 ) -> Vec<Self> {
446 target_indices
447 .into_iter()
448 .map(|target_index| Gate::Operator(
449 Box::new(PhaseS),
450 vec![target_index],
451 control_indices.clone(),
452 ))
453 .collect()
454 }
455
456 /// Creates a new Phase-S dagger gate for the specified qubit index.
457 ///
458 /// # Arguments
459 ///
460 /// * `qubit_index` - The index of the qubit on which the Phase-S dagger gate acts.
461 ///
462 /// # Returns
463 ///
464 /// * `Gate` - A new instance of the Gate struct representing a Phase-S dagger gate.
465 pub fn s_dag_gate(qubit_index: usize) -> Self {
466 Gate::Operator(Box::new(PhaseSdag), vec![qubit_index], vec![])
467 }
468
469 /// Creates new Phase-S dagger gates for the specified qubit indices.
470 ///
471 /// # Arguments
472 ///
473 /// * `qubit_indices` - The indices of the qubits on which the Phase-S dagger gates act.
474 ///
475 /// # Returns
476 ///
477 /// * `Vec<Gate>` - A vector of Gate structs representing Phase-S dagger gates for each qubit index.
478 pub fn s_dag_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
479 qubit_indices
480 .into_iter()
481 .map(Gate::s_dag_gate)
482 .collect()
483 }
484
485 /// Creates new controlled Phase-S dagger gates for the specified qubit indices.
486 ///
487 /// # Arguments
488 ///
489 /// * `target_indices` - The indices of the target qubits.
490 ///
491 /// * `control_indices` - The indices of the control qubits.
492 ///
493 /// # Returns
494 ///
495 /// * `Gates` - A vector of Gate structs representing controlled Phase-S dagger gates for each target qubit index.
496 pub fn s_dag_controlled_gates(
497 target_indices: Vec<usize>,
498 control_indices: Vec<usize>,
499 ) -> Vec<Self> {
500 target_indices
501 .into_iter()
502 .map(|target_index| Gate::Operator(
503 Box::new(PhaseSdag),
504 vec![target_index],
505 control_indices.clone(),
506 ))
507 .collect()
508 }
509
510 /// Creates a new Phase-T gate for the specified qubit index.
511 ///
512 /// # Arguments
513 ///
514 /// * `qubit_index` - The index of the qubit on which the Phase-T gate acts.
515 ///
516 /// # Returns
517 ///
518 /// * `Gate` - A new instance of the Gate struct representing a Phase-T gate.
519 pub fn t_gate(qubit_index: usize) -> Self {
520 Gate::Operator(Box::new(PhaseT), vec![qubit_index], vec![])
521 }
522
523 /// Creates new Phase-T gates for the specified qubit indices.
524 ///
525 /// # Arguments
526 ///
527 /// * `qubit_indices` - The indices of the qubits on which the Phase-T gates act.
528 ///
529 /// # Returns
530 ///
531 /// * `Vec<Gate>` - A vector of Gate structs representing Phase-T gates for each qubit index.
532 pub fn t_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
533 qubit_indices
534 .into_iter()
535 .map(Gate::t_gate)
536 .collect()
537 }
538
539 /// Creates new controlled Phase-T gates for the specified qubit indices.
540 ///
541 /// # Arguments
542 ///
543 /// * `target_indices` - The indices of the target qubits.
544 ///
545 /// * `control_indices` - The indices of the control qubits.
546 ///
547 /// # Returns
548 ///
549 /// * `Gates` - A vector of Gate structs representing controlled Phase-T gates for each target qubit index.
550 pub fn t_controlled_gates(
551 target_indices: Vec<usize>,
552 control_indices: Vec<usize>,
553 ) -> Vec<Self> {
554 target_indices
555 .into_iter()
556 .map(|target_index| Gate::Operator(
557 Box::new(PhaseT),
558 vec![target_index],
559 control_indices.clone(),
560 ))
561 .collect()
562 }
563
564 /// Creates a new Phase-T dagger gate for the specified qubit index.
565 ///
566 /// # Arguments
567 ///
568 /// * `qubit_index` - The index of the qubit on which the Phase-T dagger gate acts.
569 ///
570 /// # Returns
571 ///
572 /// * `Gate` - A new instance of the Gate struct representing a Phase-T dagger gate.
573 pub fn t_dag_gate(qubit_index: usize) -> Self {
574 Gate::Operator(Box::new(PhaseTdag), vec![qubit_index], vec![])
575 }
576
577 /// Creates new Phase-T dagger gates for the specified qubit indices.
578 ///
579 /// # Arguments
580 ///
581 /// * `qubit_indices` - The indices of the qubits on which the Phase-T dagger gates act.
582 ///
583 /// # Returns
584 ///
585 /// * `Vec<Gate>` - A vector of Gate structs representing Phase-T dagger gates for each qubit index.
586 pub fn t_dag_multi_gate(qubit_indices: Vec<usize>) -> Vec<Self> {
587 qubit_indices
588 .into_iter()
589 .map(Gate::t_dag_gate)
590 .collect()
591 }
592
593 /// Creates new controlled Phase-T dagger gates for the specified qubit indices.
594 ///
595 /// # Arguments
596 ///
597 /// * `target_indices` - The indices of the target qubits.
598 ///
599 /// * `control_indices` - The indices of the control qubits.
600 ///
601 /// # Returns
602 ///
603 /// * `Gates` - A vector of Gate structs representing controlled Phase-T dagger gates for each target qubit index.
604 pub fn t_dag_controlled_gates(
605 target_indices: Vec<usize>,
606 control_indices: Vec<usize>,
607 ) -> Vec<Self> {
608 target_indices
609 .into_iter()
610 .map(|target_index| Gate::Operator(
611 Box::new(PhaseTdag),
612 vec![target_index],
613 control_indices.clone(),
614 ))
615 .collect()
616 }
617
618 /// Creates a new Phase Shift (P) gate for the specified qubit index and angle.
619 ///
620 /// # Arguments
621 ///
622 /// * `qubit_index` - The index of the qubit on which the Phase Shift gate acts.
623 /// * `angle` - The phase shift angle in radians.
624 ///
625 /// # Returns
626 ///
627 /// * `Gate` - A new instance of the Gate struct representing a Phase Shift gate.
628 pub fn p_gate(qubit_index: usize, angle: f64) -> Self {
629 Gate::Operator(Box::new(PhaseShift::new(angle)), vec![qubit_index], vec![])
630 }
631
632 /// Creates new Phase Shift (P) gates for the specified qubit indices and angle.
633 ///
634 /// # Arguments
635 ///
636 /// * `qubit_indices` - The indices of the qubits on which the Phase Shift gates act.
637 /// * `angle` - The phase shift angle in radians for all gates.
638 ///
639 /// # Returns
640 ///
641 /// * `Vec<Gate>` - A vector of Gate structs representing Phase Shift gates for each qubit index.
642 pub fn p_multi_gate(qubit_indices: Vec<usize>, angle: f64) -> Vec<Self> {
643 let op_template = PhaseShift::new(angle);
644 qubit_indices
645 .into_iter()
646 .map(|qubit_index| Gate::Operator(Box::new(op_template), vec![qubit_index], vec![]))
647 .collect()
648 }
649
650 /// Creates new controlled Phase Shift (P) gates for the specified qubit indices and angle.
651 ///
652 /// # Arguments
653 ///
654 /// * `target_indices` - The indices of the target qubits.
655 /// * `control_indices` - The indices of the control qubits.
656 /// * `angle` - The phase shift angle in radians for all gates.
657 ///
658 /// # Returns
659 ///
660 /// * `Gates` - A vector of Gate structs representing controlled Phase Shift gates for each target qubit index.
661 pub fn p_controlled_gates(
662 target_indices: Vec<usize>,
663 control_indices: Vec<usize>,
664 angle: f64,
665 ) -> Vec<Self> {
666 let op_template = PhaseShift::new(angle);
667 target_indices
668 .into_iter()
669 .map(|target_index| Gate::Operator(
670 Box::new(op_template),
671 vec![target_index],
672 control_indices.clone(),
673 ))
674 .collect()
675 }
676
677 /// Creates a new RotateX (RX) gate for the specified qubit index and angle.
678 ///
679 /// # Arguments
680 ///
681 /// * `qubit_index` - The index of the qubit on which the RotateX gate acts.
682 /// * `angle` - The rotation angle in radians.
683 ///
684 /// # Returns
685 ///
686 /// * `Gate` - A new instance of the Gate struct representing a RotateX gate.
687 pub fn rx_gate(qubit_index: usize, angle: f64) -> Self {
688 Gate::Operator(Box::new(RotateX::new(angle)), vec![qubit_index], vec![])
689 }
690
691 /// Creates new RotateX (RX) gates for the specified qubit indices and angle.
692 ///
693 /// # Arguments
694 ///
695 /// * `qubit_indices` - The indices of the qubits on which the RotateX gates act.
696 /// * `angle` - The rotation angle in radians for all gates.
697 ///
698 /// # Returns
699 ///
700 /// * `Vec<Gate>` - A vector of Gate structs representing RotateX gates for each qubit index.
701 pub fn rx_multi_gate(qubit_indices: Vec<usize>, angle: f64) -> Vec<Self> {
702 let op_template = RotateX::new(angle);
703 qubit_indices
704 .into_iter()
705 .map(|qubit_index| Gate::Operator(Box::new(op_template), vec![qubit_index], vec![]))
706 .collect()
707 }
708
709 /// Creates new controlled RotateX (RX) gates for the specified qubit indices and angle.
710 ///
711 /// # Arguments
712 ///
713 /// * `target_indices` - The indices of the target qubits.
714 /// * `control_indices` - The indices of the control qubits.
715 /// * `angle` - The rotation angle in radians for all gates.
716 ///
717 /// # Returns
718 ///
719 /// * `Gates` - A vector of Gate structs representing controlled RotateX gates for each target qubit index.
720 pub fn rx_controlled_gates(
721 target_indices: Vec<usize>,
722 control_indices: Vec<usize>,
723 angle: f64,
724 ) -> Vec<Self> {
725 let op_template = RotateX::new(angle);
726 target_indices
727 .into_iter()
728 .map(|target_index| Gate::Operator(
729 Box::new(op_template),
730 vec![target_index],
731 control_indices.clone(),
732 ))
733 .collect()
734 }
735
736 /// Creates a new RotateY (RY) gate for the specified qubit index and angle.
737 ///
738 /// # Arguments
739 ///
740 /// * `qubit_index` - The index of the qubit on which the RotateY gate acts.
741 /// * `angle` - The rotation angle in radians.
742 ///
743 /// # Returns
744 ///
745 /// * `Gate` - A new instance of the Gate struct representing a RotateY gate.
746 pub fn ry_gate(qubit_index: usize, angle: f64) -> Self {
747 Gate::Operator(Box::new(RotateY::new(angle)), vec![qubit_index], vec![])
748 }
749
750 /// Creates new RotateY (RY) gates for the specified qubit indices and angle.
751 ///
752 /// # Arguments
753 ///
754 /// * `qubit_indices` - The indices of the qubits on which the RotateY gates act.
755 /// * `angle` - The rotation angle in radians for all gates.
756 ///
757 /// # Returns
758 ///
759 /// * `Vec<Gate>` - A vector of Gate structs representing RotateY gates for each qubit index.
760 pub fn ry_multi_gate(qubit_indices: Vec<usize>, angle: f64) -> Vec<Self> {
761 let op_template = RotateY::new(angle);
762 qubit_indices
763 .into_iter()
764 .map(|qubit_index| Gate::Operator(Box::new(op_template), vec![qubit_index], vec![]))
765 .collect()
766 }
767
768 /// Creates new controlled RotateY (RY) gates for the specified qubit indices and angle.
769 ///
770 /// # Arguments
771 ///
772 /// * `target_indices` - The indices of the target qubits.
773 /// * `control_indices` - The indices of the control qubits.
774 /// * `angle` - The rotation angle in radians for all gates.
775 ///
776 /// # Returns
777 ///
778 /// * `Gates` - A vector of Gate structs representing controlled RotateY gates for each target qubit index.
779 pub fn ry_controlled_gates(
780 target_indices: Vec<usize>,
781 control_indices: Vec<usize>,
782 angle: f64,
783 ) -> Vec<Self> {
784 let op_template = RotateY::new(angle);
785 target_indices
786 .into_iter()
787 .map(|target_index| Gate::Operator(
788 Box::new(op_template),
789 vec![target_index],
790 control_indices.clone(),
791 ))
792 .collect()
793 }
794
795 /// Creates a new RotateZ (RZ) gate for the specified qubit index and angle.
796 ///
797 /// # Arguments
798 ///
799 /// * `qubit_index` - The index of the qubit on which the RotateZ gate acts.
800 /// * `angle` - The rotation angle in radians.
801 ///
802 /// # Returns
803 ///
804 /// * `Gate` - A new instance of the Gate struct representing a RotateZ gate.
805 pub fn rz_gate(qubit_index: usize, angle: f64) -> Self {
806 Gate::Operator(Box::new(RotateZ::new(angle)), vec![qubit_index], vec![])
807 }
808
809 /// Creates new RotateZ (RZ) gates for the specified qubit indices and angle.
810 ///
811 /// # Arguments
812 ///
813 /// * `qubit_indices` - The indices of the qubits on which the RotateZ gates act.
814 /// * `angle` - The rotation angle in radians for all gates.
815 ///
816 /// # Returns
817 ///
818 /// * `Vec<Gate>` - A vector of Gate structs representing RotateZ gates for each qubit index.
819 pub fn rz_multi_gate(qubit_indices: Vec<usize>, angle: f64) -> Vec<Self> {
820 let op_template = RotateZ::new(angle);
821 qubit_indices
822 .into_iter()
823 .map(|qubit_index| Gate::Operator(Box::new(op_template), vec![qubit_index], vec![]))
824 .collect()
825 }
826
827 /// Creates new controlled RotateZ (RZ) gates for the specified qubit indices and angle.
828 ///
829 /// # Arguments
830 ///
831 /// * `target_indices` - The indices of the target qubits.
832 /// * `control_indices` - The indices of the control qubits.
833 /// * `angle` - The rotation angle in radians for all gates.
834 ///
835 /// # Returns
836 ///
837 /// * `Gates` - A vector of Gate structs representing controlled RotateZ gates for each target qubit index.
838 pub fn rz_controlled_gates(
839 target_indices: Vec<usize>,
840 control_indices: Vec<usize>,
841 angle: f64,
842 ) -> Vec<Self> {
843 let op_template = RotateZ::new(angle);
844 target_indices
845 .into_iter()
846 .map(|target_index| Gate::Operator(
847 Box::new(op_template),
848 vec![target_index],
849 control_indices.clone(),
850 ))
851 .collect()
852 }
853
854 /// Creates a new Unitary2 gate for the specified qubit index and unitary matrix.
855 ///
856 /// # Arguments
857 ///
858 /// * `qubit_index` - The index of the qubit on which the Unitary2 gate acts.
859 /// * `unitary` - The unitary matrix to be applied.
860 ///
861 /// # Returns
862 ///
863 /// * `Result<Gate, Error>` - A Gate struct representing a Unitary2 gate if the unitary is valid, else an error.
864 pub fn unitary2_gate(qubit_index: usize, unitary: [[Complex<f64>; 2]; 2]) -> Result<Self, Error> {
865 Ok(Gate::Operator(
866 Box::new(Unitary2::new(unitary)?),
867 vec![qubit_index],
868 vec![],
869 ))
870 }
871
872 /// Creates new Unitary2 gates for the specified qubit indices and unitary matrix.
873 ///
874 /// # Arguments
875 ///
876 /// * `qubit_indices` - The indices of the qubits on which the Unitary2 gates act.
877 ///
878 /// * `unitary` - The unitary matrix to be applied.
879 ///
880 /// # Returns
881 ///
882 /// * `Result<Vec<Gate>, Error>` - A vector of Gate structs representing Unitary2 gates for each qubit index if the unitary is valid,, else an error.
883 pub fn unitary2_multi_gate(
884 qubit_indices: Vec<usize>,
885 unitary: [[Complex<f64>; 2]; 2],
886 ) -> Result<Vec<Self>, Error> {
887 let op_template = Unitary2::new(unitary)?;
888 let gates = qubit_indices
889 .into_iter()
890 .map(|qubit_index| Gate::Operator(Box::new(op_template), vec![qubit_index], vec![]))
891 .collect();
892 Ok(gates)
893 }
894
895 /// Creates new controlled Unitary2 gates for the specified qubit indices and unitary matrix.
896 ///
897 /// # Arguments
898 ///
899 /// * `target_indices` - The indices of the target qubits.
900 ///
901 /// * `control_indices` - The indices of the control qubits.
902 ///
903 /// * `unitary` - The unitary matrix to be applied.
904 ///
905 /// # Returns
906 ///
907 /// * `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.
908 pub fn unitary2_controlled_gates(
909 target_indices: Vec<usize>,
910 control_indices: Vec<usize>,
911 unitary: [[Complex<f64>; 2]; 2],
912 ) -> Result<Vec<Self>, Error> {
913 let op_template = Unitary2::new(unitary)?;
914 let gates = target_indices
915 .into_iter()
916 .map(|target_index| Gate::Operator(
917 Box::new(op_template),
918 vec![target_index],
919 control_indices.clone(),
920 ))
921 .collect();
922 Ok(gates)
923 }
924
925 /// Creates a new Unitary2 gate for the specified qubit index and unitary matrix using a rotation angle and phase shift.
926 /// Unlike custom Unitary2 gates, the generated unitary matrix is guaranteed to be valid.
927 /// Therefore, this method does not return an error.
928 ///
929 /// # Arguments
930 ///
931 /// * qubit_index - The index of the qubit on which the Unitary2 gate acts.
932 ///
933 /// * theta - The rotation angle in radians.
934 ///
935 /// * phi - The phase shift in radians.
936 ///
937 /// # Returns
938 ///
939 /// * Gate - A new instance of the Gate struct representing a Unitary2 gate.
940 pub fn ry_phase_gate(
941 qubit_index: usize,
942 theta: f64,
943 phi: f64,
944 ) -> Self {
945 Gate::Operator(
946 Box::new(Unitary2::from_ry_phase(theta, phi)),
947 vec![qubit_index],
948 vec![],
949 )
950 }
951
952 /// Creates new Unitary2 gates for the specified qubit indices and unitary matrix using a rotation angle and phase shift.
953 /// Unlike custom Unitary2 gates, the generated unitary matrix is guaranteed to be valid.
954 /// Therefore, this method does not return an error.
955 ///
956 /// # Arguments
957 ///
958 /// * qubit_indices - The indices of the qubits on which the Unitary2 gates act.
959 ///
960 /// * theta - The rotation angle in radians for all gates.
961 ///
962 /// * phi - The phase shift in radians for all gates.
963 ///
964 /// # Returns
965 ///
966 /// * `Vec<Gate>` - A vector of Gate structs representing Unitary2 gates for each qubit index.
967 pub fn ry_phase_multi_gate(
968 qubit_indices: Vec<usize>,
969 theta: f64,
970 phi: f64,
971 ) -> Vec<Self> {
972 let op_template = Unitary2::from_ry_phase(theta, phi);
973 qubit_indices
974 .into_iter()
975 .map(|qubit_index| Gate::Operator(Box::new(op_template), vec![qubit_index], vec![]))
976 .collect()
977 }
978
979 /// Creates new controlled Unitary2 gates for the specified qubit indices and unitary matrix using a rotation angle and phase shift.
980 ///
981 /// # Arguments
982 ///
983 /// * target_indices - The indices of the target qubits.
984 ///
985 /// * control_indices - The indices of the control qubits.
986 ///
987 /// * theta - The rotation angle in radians for all gates.
988 ///
989 /// * phi - The phase shift in radians for all gates.
990 ///
991 /// # Returns
992 ///
993 /// * `Vec<Gate>` - A vector of Gate structs representing controlled Unitary2 gates for each target qubit index.
994 pub fn ry_phase_controlled_gates(
995 target_indices: Vec<usize>,
996 control_indices: Vec<usize>,
997 theta: f64,
998 phi: f64,
999 ) -> Vec<Self> {
1000 let op_template = Unitary2::from_ry_phase(theta, phi);
1001 target_indices
1002 .into_iter()
1003 .map(|target_index| {
1004 Gate::Operator(
1005 Box::new(op_template.clone()),
1006 vec![target_index],
1007 control_indices.clone(),
1008 )
1009 })
1010 .collect()
1011 }
1012
1013 /// Creates a new Unitary2 gate from a rotation angle theta and phase shift angle phi.
1014 ///
1015 /// # Arguments
1016 ///
1017 /// * `qubit_index` - The index of the qubit on which the Unitary2 gate acts.
1018 /// * `theta` - The rotation angle in radians.
1019 /// * `phi` - The phase shift angle in radians.
1020 ///
1021 /// # Returns
1022 ///
1023 /// * Gate - A new instance of the Gate struct representing a Unitary2 gate.
1024 pub fn ry_phase_dag_gate(
1025 qubit_index: usize,
1026 theta: f64,
1027 phi: f64,
1028 ) -> Self {
1029 Gate::Operator(
1030 Box::new(Unitary2::from_ry_phase_dagger(theta, phi)),
1031 vec![qubit_index],
1032 vec![],
1033 )
1034 }
1035
1036 /// Creates new Unitary2 gates from a rotation angle theta and phase shift angle phi.
1037 ///
1038 /// # Arguments
1039 ///
1040 /// * `qubit_indices` - The indices of the qubits on which the Unitary2 gates act.
1041 /// * `theta` - The rotation angle in radians.
1042 /// * `phi` - The phase shift angle in radians.
1043 ///
1044 // # Returns
1045 ///
1046 /// * `Vec<Gate>` - A vector of Gate structs representing Unitary2 gates for each qubit index.
1047 pub fn ry_phase_dag_multi_gate(
1048 qubit_indices: Vec<usize>,
1049 theta: f64,
1050 phi: f64,
1051 ) -> Vec<Self> {
1052 let op_template = Unitary2::from_ry_phase_dagger(theta, phi);
1053 qubit_indices
1054 .into_iter()
1055 .map(|qubit_index| {
1056 Gate::Operator(Box::new(op_template.clone()), vec![qubit_index], vec![])
1057 })
1058 .collect()
1059 }
1060
1061 /// Creates new controlled Unitary2 gates from a rotation angle theta and phase shift angle phi.
1062 ///
1063 /// # Arguments
1064 ///
1065 /// * `target_indices` - The indices of the target qubits.
1066 /// * `control_indices` - The indices of the control qubits.
1067 /// * `theta` - The rotation angle in radians.
1068 /// * `phi` - The phase shift angle in radians.
1069 ///
1070 /// # Returns
1071 ///
1072 /// * `Vec<Gate>` - A vector of Gate structs representing controlled Unitary2 gates for each target qubit index.
1073 pub fn ry_phase_dag_controlled_gates(
1074 target_indices: Vec<usize>,
1075 control_indices: Vec<usize>,
1076 theta: f64,
1077 phi: f64,
1078 ) -> Vec<Self> {
1079 let op_template = Unitary2::from_ry_phase_dagger(theta, phi);
1080 target_indices
1081 .into_iter()
1082 .map(|target_index| {
1083 Gate::Operator(
1084 Box::new(op_template.clone()),
1085 vec![target_index],
1086 control_indices.clone(),
1087 )
1088 })
1089 .collect()
1090 }
1091
1092 // -- MULTI-QUBIT GATES --
1093
1094 /// Creates a CNOT gate for the specified target and control qubit indices.
1095 ///
1096 /// # Arguments
1097 ///
1098 /// * `target_index` - The index of the target qubit.
1099 ///
1100 /// * `control_index` - The index of the control qubit.
1101 ///
1102 /// # Returns
1103 ///
1104 /// * `Gate` - A new instance of the Gate struct representing a CNOT gate.
1105 pub fn cnot_gate(target_index: usize, control_index: usize) -> Self {
1106 Gate::Operator(
1107 Box::new(CNOT),
1108 vec![target_index],
1109 vec![control_index],
1110 )
1111 }
1112
1113 /// Creates a new SWAP gate for the specified qubit index.
1114 ///
1115 /// # Arguments
1116 ///
1117 /// * `qubit1` - The index of the first qubit.
1118 /// * `qubit2` - The index of the second qubit.
1119 ///
1120 /// # Returns
1121 ///
1122 /// * `Gate` - A new instance of the Gate struct representing a SWAP gate.
1123 pub fn swap_gate(qubit1_index: usize, qubit2_index: usize) -> Self {
1124 Gate::Operator(Box::new(SWAP), vec![qubit1_index, qubit2_index], vec![])
1125 }
1126
1127 /// Creates a new controlled SWAP gate for the specified target and control qubit indices.
1128 ///
1129 /// # Arguments
1130 ///
1131 /// * `target_indices` - The indices of the target qubits.
1132 /// * `control_indices` - The indices of the control qubits.
1133 ///
1134 /// # Returns
1135 ///
1136 /// * `Gate` - A new instance of the Gate struct representing a controlled SWAP gate.
1137 pub fn swap_controlled_gate(
1138 target_indices: Vec<usize>,
1139 control_indices: Vec<usize>,
1140 ) -> Self {
1141 Gate::Operator(Box::new(SWAP), target_indices, control_indices)
1142 }
1143
1144 /// Creates a new Toffoli gate for the specified target and control qubit indices.
1145 ///
1146 /// # Arguments
1147 ///
1148 /// * `target_index` - The index of the target qubit.
1149 ///
1150 /// * `control_indices` - The indices of the control qubits.
1151 ///
1152 /// # Returns
1153 ///
1154 /// * `Gate` - A new instance of the Gate struct representing a Toffoli gate.
1155 pub fn toffoli_gate(target_index: usize, control_indices: Vec<usize>) -> Self {
1156 Gate::Operator(Box::new(Toffoli), vec![target_index], control_indices)
1157 }
1158
1159 /// Creates a new Matchgate with the specified qubit index and its adjacent as targets.
1160 ///
1161 /// # Arguments
1162 ///
1163 /// * `target_index` - The index of the first target qubit. The second target qubit is assumed to be the next qubit.
1164 /// * `theta` - The angle of rotation in radians.
1165 /// * `phi1` - The first phase shift in radians.
1166 /// * `phi2` - The second phase shift in radians.
1167 ///
1168 /// # Returns
1169 ///
1170 /// * `Gate` - A new instance of the Gate struct representing a Matchgate.
1171 ///
1172 /// # Warning
1173 ///
1174 /// This gate is not yet compilable to OpenQASM, since it requires advanced decomposition techniques.
1175 pub fn matchgate(
1176 target_index: usize,
1177 theta: f64,
1178 phi1: f64,
1179 phi2: f64,
1180 ) -> Self {
1181 Gate::Operator(
1182 Box::new(Matchgate::new(theta, phi1, phi2)),
1183 vec![target_index],
1184 vec![],
1185 )
1186 }
1187
1188 /// Creates a new controlled Matchgate with the specified qubit index and its adjacent as target qubits.
1189 ///
1190 /// # Arguments
1191 ///
1192 /// * `target_index` - The index of the first target qubit. The second target qubit is assumed to be the next qubit.
1193 /// * `control_indices` - The indices of the control qubits.
1194 /// * `theta` - The angle of rotation in radians.
1195 /// * `phi1` - The first phase shift in radians.
1196 /// * `phi2` - The second phase shift in radians.
1197 ///
1198 /// # Returns
1199 ///
1200 /// * `Gate` - A new instance of the Gate struct representing a controlled Matchgate.
1201 ///
1202 /// # Warning
1203 ///
1204 /// This gate is not yet compilable to OpenQASM, since it requires advanced decomposition techniques.
1205 pub fn controlled_matchgate(
1206 target_index: usize,
1207 control_indices: Vec<usize>,
1208 theta: f64,
1209 phi1: f64,
1210 phi2: f64,
1211 ) -> Self {
1212 Gate::Operator(
1213 Box::new(Matchgate::new(theta, phi1, phi2)),
1214 vec![target_index],
1215 control_indices,
1216 )
1217 }
1218}