quant_iron/components/
gate.rs

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