quant_iron/components/parametric/
parametric_gate.rs

1use crate::components::gate::Gate;
2use crate::components::parametric::parameter::Parameter;
3use std::fmt::Debug;
4
5/// A trait for gates that can be parametrised.
6///
7/// The trait defines the `to_concrete_gate` method for creating a concrete gate from the parametrised gate.
8/// This is required for applying the parametrised gate in a circuit or compiling it into OpenQASM.
9pub trait ParametricGate: Debug + Send + Sync {
10    /// Creates a concrete `Gate` using the current parameter values.
11    ///
12    /// # Arguments
13    ///
14    /// * `target_indices` - The indices of the target qubits.
15    /// * `control_indices` - The indices of the control qubits.
16    ///
17    /// # Returns
18    ///
19    /// Concrete `Gate::Operator` variants of the parameterised gate instance.
20    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate>;
21
22    /// Clones the trait object.
23    /// This is required by the `Gate` trait.
24    fn box_clone(&self) -> Box<dyn ParametricGate>;
25}
26
27impl Clone for Box<dyn ParametricGate> {
28    fn clone(&self) -> Self {
29        self.box_clone()
30    }
31}
32
33/// A parametrised RY phase gate
34///
35/// This operator can be decomposed into a rotation around the Y axis followed by a phase shift.
36/// The enclosed unitary matrix is guaranteed to be unitary.
37///
38/// # Fields
39/// - `parameter`: A `Parameter<2>` instance that holds the rotation angle (theta) and phase shift (phi).
40#[derive(Debug, Clone)]
41pub struct ParametricRyPhase {
42    pub parameter: Parameter<2>, // theta, phi
43}
44
45impl ParametricGate for ParametricRyPhase {
46    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate> {
47        let params = self.parameter.get();
48        Gate::ry_phase_controlled_gates(
49            target_indices.to_vec(),
50            control_indices.to_vec(),
51            params[0],
52            params[1],
53        )
54    }
55
56    fn box_clone(&self) -> Box<dyn ParametricGate> {
57        Box::new(self.clone())
58    }
59}
60
61/// A parametrised matchgate
62///
63/// A two-qubit operator that applies a matchgate transformation to the adjacent target qubits.
64/// This gate can be decomposed into a two-qubit rotation and phase shifts.
65///
66/// # Fields
67/// - `parameter`: A `Parameter<3>` instance that holds the rotation angle (theta) and phase shifts (phi1, phi2).
68#[derive(Debug, Clone)]
69pub struct ParametricMatchgate {
70    pub parameter: Parameter<3>, // theta, phi1, phi2
71}
72
73impl ParametricGate for ParametricMatchgate {
74    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate> {
75        let params = self.parameter.get();
76        vec![Gate::controlled_matchgate(
77            target_indices[0],
78            control_indices.to_vec(),
79            params[0],
80            params[1],
81            params[2],
82        )]
83    }
84
85    fn box_clone(&self) -> Box<dyn ParametricGate> {
86        Box::new(self.clone())
87    }
88}
89
90/// A parametrised RX gate
91///
92/// # Fields
93/// - `parameter`: A `Parameter<1>` instance that holds the rotation angle (theta).
94#[derive(Debug, Clone)]
95pub struct ParametricRx {
96    pub parameter: Parameter<1>, // theta
97}
98
99impl ParametricGate for ParametricRx {
100    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate> {
101        let params = self.parameter.get();
102        Gate::rx_controlled_gates(
103            target_indices.to_vec(),
104            control_indices.to_vec(),
105            params[0],
106        )
107    }
108
109    fn box_clone(&self) -> Box<dyn ParametricGate> {
110        Box::new(self.clone())
111    }
112}
113
114/// A parametrised RY gate
115///
116/// # Fields
117/// - `parameter`: A `Parameter<1>` instance that holds the rotation angle (theta).
118#[derive(Debug, Clone)]
119pub struct ParametricRy {
120    pub parameter: Parameter<1>, // theta
121}
122
123impl ParametricGate for ParametricRy {
124    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate> {
125        let params = self.parameter.get();
126        Gate::ry_controlled_gates(
127            target_indices.to_vec(),
128            control_indices.to_vec(),
129            params[0],
130        )
131    }
132
133    fn box_clone(&self) -> Box<dyn ParametricGate> {
134        Box::new(self.clone())
135    }
136}
137
138/// A parametrised RZ gate
139///
140/// # Fields
141/// - `parameter`: A `Parameter<1>` instance that holds the rotation angle (theta).
142#[derive(Debug, Clone)]
143pub struct ParametricRz {
144    pub parameter: Parameter<1>, // theta
145}
146
147impl ParametricGate for ParametricRz {
148    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate> {
149        let params = self.parameter.get();
150        Gate::rz_controlled_gates(
151            target_indices.to_vec(),
152            control_indices.to_vec(),
153            params[0],
154        )
155    }
156
157    fn box_clone(&self) -> Box<dyn ParametricGate> {
158        Box::new(self.clone())
159    }
160}
161
162/// A parametrised Phase Shift gate
163///
164/// # Fields
165/// - `parameter`: A `Parameter<1>` instance that holds the phase shift (phi).
166#[derive(Debug, Clone)]
167pub struct ParametricP {
168    pub parameter: Parameter<1>, // phi
169}
170
171impl ParametricGate for ParametricP {
172    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate> {
173        let params = self.parameter.get();
174        Gate::p_controlled_gates(
175            target_indices.to_vec(),
176            control_indices.to_vec(),
177            params[0],
178        )
179    }
180
181    fn box_clone(&self) -> Box<dyn ParametricGate> {
182        Box::new(self.clone())
183    }
184}