quant_iron/components/
gate.rs

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