1use crate::{
2 circuit::Circuit,
3 compiler::ir::InstructionIR,
4 components::gate::Gate,
5 components::{
6 measurement::MeasurementOperation,
7 operator::{
8 CNOT, Hadamard, Identity, Pauli, PhaseS, PhaseSdag, PhaseShift, PhaseT, PhaseTdag,
9 RotateX, RotateY, RotateZ, SWAP, Toffoli, Unitary2,
10 },
11 },
12 errors::CompilerError,
13};
14use dyn_clone::DynClone;
15use rayon::prelude::*;
16use std::convert::TryFrom;
17
18pub trait Compilable: DynClone + Send + Sync + 'static {
25 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR>;
30}
31
32dyn_clone::clone_trait_object!(Compilable);
33
34pub(crate) struct CompilableCircuit {
38 pub num_qubits: usize,
40
41 pub gates: Vec<CompilableGate>,
45}
46
47impl CompilableCircuit {
48 pub(crate) fn to_ir(&self) -> Vec<InstructionIR> {
53 self.gates
54 .par_iter()
55 .flat_map(|gate| {
56 gate.operator
57 .to_ir(gate.targets.clone(), gate.controls.clone())
58 })
59 .collect()
60 }
61}
62
63pub(crate) struct CompilableGate {
67 pub operator: Box<dyn Compilable>,
69 pub targets: Vec<usize>,
71 pub controls: Vec<usize>,
73}
74
75impl TryFrom<&Circuit> for CompilableCircuit {
76 type Error = CompilerError;
77
78 fn try_from(circuit: &Circuit) -> Result<Self, CompilerError> {
86 let num_qubits: usize = circuit.get_num_qubits();
87 let mut compilable_gates: Vec<CompilableGate> = Vec::with_capacity(circuit.gates.len() * 2); for gate in &circuit.gates {
90 match gate {
91 Gate::Operator(op, _targets, _controls) => {
92 if let Some(compilable_op) = op.to_compilable() {
93 let targets = _targets.clone();
95 let controls = _controls.clone();
96 let operator = dyn_clone::clone_box(compilable_op);
97
98 let gate: CompilableGate = CompilableGate {
100 operator,
101 targets,
102 controls,
103 };
104 compilable_gates.push(gate);
105 } else {
106 return Err(CompilerError::UnsupportedOperator(
107 "Operator does not implement Compilable trait".to_string(),
108 ));
109 }
110 }
111 Gate::Measurement(measurement_basis, targets) => {
112 let measurement_op = MeasurementOperation {
114 basis: *measurement_basis,
115 };
116
117 let gate = CompilableGate {
119 operator: Box::new(measurement_op),
120 targets: targets.clone(),
121 controls: vec![],
122 };
123
124 compilable_gates.push(gate);
125 }
126 }
127 }
128 Ok(CompilableCircuit {
129 num_qubits,
130 gates: compilable_gates,
131 })
132 }
133}
134
135impl Compilable for Hadamard {
136 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
137 targets
138 .par_iter()
139 .map(|&target| InstructionIR::Hadamard(target, controls.clone()))
140 .collect()
141 }
142}
143
144impl Compilable for Pauli {
145 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
146 targets
147 .par_iter()
148 .map(|&target| match self {
149 Pauli::X => InstructionIR::PauliX(target, controls.clone()),
150 Pauli::Y => InstructionIR::PauliY(target, controls.clone()),
151 Pauli::Z => InstructionIR::PauliZ(target, controls.clone()),
152 })
153 .collect()
154 }
155}
156
157impl Compilable for CNOT {
158 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
159 targets
160 .par_iter()
161 .map(|&target| {
162 if controls.is_empty() {
163 InstructionIR::PauliX(target, vec![])
165 } else {
166 InstructionIR::PauliX(target, vec![controls[0]])
168 }
169 })
170 .collect()
171 }
172}
173
174impl Compilable for SWAP {
175 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
176 if targets.len() >= 2 {
178 targets
180 .par_chunks(2)
181 .filter_map(|chunk| {
182 if chunk.len() == 2 {
183 Some(InstructionIR::Swap(chunk[0], chunk[1], controls.clone()))
184 } else {
185 None
186 }
187 })
188 .collect()
189 } else {
190 vec![]
191 }
192 }
193}
194
195impl Compilable for Toffoli {
196 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
197 targets
198 .par_iter()
199 .map(|&target| {
200 InstructionIR::PauliX(target, controls.clone())
202 })
203 .collect()
204 }
205}
206
207impl Compilable for Identity {
208 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
209 targets
210 .par_iter()
211 .map(|&target| InstructionIR::Id(target, controls.clone()))
212 .collect()
213 }
214}
215
216impl Compilable for PhaseS {
217 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
218 targets
219 .par_iter()
220 .map(|&target| InstructionIR::S(target, controls.clone()))
221 .collect()
222 }
223}
224
225impl Compilable for PhaseT {
226 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
227 targets
228 .par_iter()
229 .map(|&target| InstructionIR::T(target, controls.clone()))
230 .collect()
231 }
232}
233
234impl Compilable for PhaseSdag {
235 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
236 targets
237 .par_iter()
238 .map(|&target| InstructionIR::Sdg(target, controls.clone()))
239 .collect()
240 }
241}
242
243impl Compilable for PhaseTdag {
244 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
245 targets
246 .par_iter()
247 .map(|&target| InstructionIR::Tdg(target, controls.clone()))
248 .collect()
249 }
250}
251
252impl Compilable for PhaseShift {
253 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
254 targets
255 .par_iter()
256 .map(|&target| InstructionIR::Phase(self.angle, target, controls.clone()))
257 .collect()
258 }
259}
260
261impl Compilable for RotateX {
262 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
263 targets
264 .par_iter()
265 .map(|&target| InstructionIR::Rx(self.angle, target, controls.clone()))
266 .collect()
267 }
268}
269
270impl Compilable for RotateY {
271 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
272 targets
273 .par_iter()
274 .map(|&target| InstructionIR::Ry(self.angle, target, controls.clone()))
275 .collect()
276 }
277}
278
279impl Compilable for RotateZ {
280 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
281 targets
282 .par_iter()
283 .map(|&target| InstructionIR::Rz(self.angle, target, controls.clone()))
284 .collect()
285 }
286}
287
288impl Compilable for Unitary2 {
289 fn to_ir(&self, targets: Vec<usize>, controls: Vec<usize>) -> Vec<InstructionIR> {
290 targets
291 .par_iter()
292 .map(|&target| InstructionIR::Unitary(self.matrix, target, controls.clone()))
293 .collect()
294 }
295}