quant_iron/components/
gate.rs

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