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 RY phase dagger gate
62///
63/// This operator is the dagger of the RY phase gate.
64///
65/// # Fields
66/// - `parameter`: A `Parameter<2>` instance that holds the rotation angle (theta) and phase shift (phi).
67#[derive(Debug, Clone)]
68pub struct ParametricRyPhaseDag {
69    pub parameter: Parameter<2>, // theta, phi
70}
71
72impl ParametricGate for ParametricRyPhaseDag {
73    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate> {
74        let params = self.parameter.get();
75        Gate::ry_phase_dag_controlled_gates(
76            target_indices.to_vec(),
77            control_indices.to_vec(),
78            params[0],
79            params[1],
80        )
81    }
82
83    fn box_clone(&self) -> Box<dyn ParametricGate> {
84        Box::new(self.clone())
85    }
86}
87
88/// A parametrised matchgate
89///
90/// A two-qubit operator that applies a matchgate transformation to the adjacent target qubits.
91/// This gate can be decomposed into a two-qubit rotation and phase shifts.
92///
93/// # Fields
94/// - `parameter`: A `Parameter<3>` instance that holds the rotation angle (theta) and phase shifts (phi1, phi2).
95#[derive(Debug, Clone)]
96pub struct ParametricMatchgate {
97    pub parameter: Parameter<3>, // theta, phi1, phi2
98}
99
100impl ParametricGate for ParametricMatchgate {
101    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate> {
102        let params = self.parameter.get();
103        vec![Gate::controlled_matchgate(
104            target_indices[0],
105            control_indices.to_vec(),
106            params[0],
107            params[1],
108            params[2],
109        )]
110    }
111
112    fn box_clone(&self) -> Box<dyn ParametricGate> {
113        Box::new(self.clone())
114    }
115}
116
117/// A parametrised RX gate
118///
119/// # Fields
120/// - `parameter`: A `Parameter<1>` instance that holds the rotation angle (theta).
121#[derive(Debug, Clone)]
122pub struct ParametricRx {
123    pub parameter: Parameter<1>, // theta
124}
125
126impl ParametricGate for ParametricRx {
127    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate> {
128        let params = self.parameter.get();
129        Gate::rx_controlled_gates(
130            target_indices.to_vec(),
131            control_indices.to_vec(),
132            params[0],
133        )
134    }
135
136    fn box_clone(&self) -> Box<dyn ParametricGate> {
137        Box::new(self.clone())
138    }
139}
140
141/// A parametrised RY gate
142///
143/// # Fields
144/// - `parameter`: A `Parameter<1>` instance that holds the rotation angle (theta).
145#[derive(Debug, Clone)]
146pub struct ParametricRy {
147    pub parameter: Parameter<1>, // theta
148}
149
150impl ParametricGate for ParametricRy {
151    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate> {
152        let params = self.parameter.get();
153        Gate::ry_controlled_gates(
154            target_indices.to_vec(),
155            control_indices.to_vec(),
156            params[0],
157        )
158    }
159
160    fn box_clone(&self) -> Box<dyn ParametricGate> {
161        Box::new(self.clone())
162    }
163}
164
165/// A parametrised RZ gate
166///
167/// # Fields
168/// - `parameter`: A `Parameter<1>` instance that holds the rotation angle (theta).
169#[derive(Debug, Clone)]
170pub struct ParametricRz {
171    pub parameter: Parameter<1>, // theta
172}
173
174impl ParametricGate for ParametricRz {
175    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate> {
176        let params = self.parameter.get();
177        Gate::rz_controlled_gates(
178            target_indices.to_vec(),
179            control_indices.to_vec(),
180            params[0],
181        )
182    }
183
184    fn box_clone(&self) -> Box<dyn ParametricGate> {
185        Box::new(self.clone())
186    }
187}
188
189/// A parametrised Phase Shift gate
190///
191/// # Fields
192/// - `parameter`: A `Parameter<1>` instance that holds the phase shift (phi).
193#[derive(Debug, Clone)]
194pub struct ParametricP {
195    pub parameter: Parameter<1>, // phi
196}
197
198impl ParametricGate for ParametricP {
199    fn to_concrete_gates(&self, target_indices: &[usize], control_indices: &[usize]) -> Vec<Gate> {
200        let params = self.parameter.get();
201        Gate::p_controlled_gates(
202            target_indices.to_vec(),
203            control_indices.to_vec(),
204            params[0],
205        )
206    }
207
208    fn box_clone(&self) -> Box<dyn ParametricGate> {
209        Box::new(self.clone())
210    }
211}