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}