1use lift_core::context::Context;
2use lift_quantum::gates::QuantumGate;
3use std::fmt::Write;
4use thiserror::Error;
5
6#[derive(Debug, Error)]
7pub enum QasmExportError {
8 #[error("Unsupported gate for QASM export: {0}")]
9 UnsupportedGate(String),
10 #[error("Export error: {0}")]
11 General(String),
12}
13
14#[derive(Debug)]
15pub struct QasmExporter;
16
17impl QasmExporter {
18 pub fn new() -> Self {
19 Self
20 }
21
22 pub fn export(&self, ctx: &Context) -> Result<String, QasmExportError> {
23 let mut output = String::new();
24
25 let _ = writeln!(output, "OPENQASM 3.0;");
26 let _ = writeln!(output, "// Generated by LIFT framework");
27 let _ = writeln!(output);
28
29 let mut max_qubits = 0usize;
31 for (_val_key, val) in &ctx.values {
32 if ctx.is_qubit_type(val.ty) {
33 max_qubits += 1;
34 }
35 }
36
37 let mut qubit_args = 0;
39 for (_block_key, block) in &ctx.blocks {
40 for &arg in &block.args {
41 if let Some(val) = ctx.get_value(arg) {
42 if ctx.is_qubit_type(val.ty) {
43 qubit_args += 1;
44 }
45 }
46 }
47 }
48 let num_qubits = if qubit_args > 0 {
49 qubit_args
50 } else {
51 max_qubits.max(1)
52 };
53
54 let _ = writeln!(output, "qubit[{}] q;", num_qubits);
55 let _ = writeln!(output, "bit[{}] c;", num_qubits);
56 let _ = writeln!(output);
57
58 let mut qubit_counter = 0usize;
60 for (_op_key, op) in &ctx.ops {
61 let op_name = ctx.strings.resolve(op.name).to_string();
62
63 if let Some(gate) = QuantumGate::from_name(&op_name) {
64 let q0 = qubit_counter % num_qubits;
65 let q1 = (qubit_counter + 1) % num_qubits;
66 let q2 = (qubit_counter + 2) % num_qubits;
67 let angle = op.attrs.get_float("angle").unwrap_or(0.0);
68 let theta = op.attrs.get_float("theta").unwrap_or(0.0);
69 let phi = op.attrs.get_float("phi").unwrap_or(0.0);
70 let lambda = op.attrs.get_float("lambda").unwrap_or(0.0);
71
72 match gate {
73 QuantumGate::H => {
75 let _ = writeln!(output, "h q[{}];", q0);
76 }
77 QuantumGate::X => {
78 let _ = writeln!(output, "x q[{}];", q0);
79 }
80 QuantumGate::Y => {
81 let _ = writeln!(output, "y q[{}];", q0);
82 }
83 QuantumGate::Z => {
84 let _ = writeln!(output, "z q[{}];", q0);
85 }
86 QuantumGate::S => {
87 let _ = writeln!(output, "s q[{}];", q0);
88 }
89 QuantumGate::Sdg => {
90 let _ = writeln!(output, "sdg q[{}];", q0);
91 }
92 QuantumGate::T => {
93 let _ = writeln!(output, "t q[{}];", q0);
94 }
95 QuantumGate::Tdg => {
96 let _ = writeln!(output, "tdg q[{}];", q0);
97 }
98 QuantumGate::SX => {
99 let _ = writeln!(output, "sx q[{}];", q0);
100 }
101 QuantumGate::RX => {
103 let _ = writeln!(output, "rx({}) q[{}];", angle, q0);
104 }
105 QuantumGate::RY => {
106 let _ = writeln!(output, "ry({}) q[{}];", angle, q0);
107 }
108 QuantumGate::RZ => {
109 let _ = writeln!(output, "rz({}) q[{}];", angle, q0);
110 }
111 QuantumGate::P => {
112 let _ = writeln!(output, "p({}) q[{}];", angle, q0);
113 }
114 QuantumGate::U1 => {
115 let _ = writeln!(output, "u1({}) q[{}];", lambda, q0);
116 }
117 QuantumGate::U2 => {
118 let _ = writeln!(output, "u2({}, {}) q[{}];", phi, lambda, q0);
119 }
120 QuantumGate::U3 => {
121 let _ = writeln!(output, "u3({}, {}, {}) q[{}];", theta, phi, lambda, q0);
122 }
123 QuantumGate::Rx90 => {
125 let _ = writeln!(output, "rx(pi/2) q[{}];", q0);
126 }
127 QuantumGate::Rx180 => {
128 let _ = writeln!(output, "rx(pi) q[{}];", q0);
129 }
130 QuantumGate::VirtualRZ => {
132 let _ = writeln!(output, "rz({}) q[{}]; // virtual", angle, q0);
133 }
134 QuantumGate::GlobalPhase => {
135 let _ = writeln!(output, "gphase({});", angle);
136 }
137 QuantumGate::CX => {
139 let _ = writeln!(output, "cx q[{}], q[{}];", q0, q1);
140 }
141 QuantumGate::CZ => {
142 let _ = writeln!(output, "cz q[{}], q[{}];", q0, q1);
143 }
144 QuantumGate::CY => {
145 let _ = writeln!(output, "cy q[{}], q[{}];", q0, q1);
146 }
147 QuantumGate::SWAP => {
148 let _ = writeln!(output, "swap q[{}], q[{}];", q0, q1);
149 }
150 QuantumGate::ISWAP => {
151 let _ = writeln!(output, "iswap q[{}], q[{}];", q0, q1);
152 }
153 QuantumGate::ECR => {
154 let _ = writeln!(output, "ecr q[{}], q[{}];", q0, q1);
155 }
156 QuantumGate::RZX => {
157 let _ = writeln!(output, "rzx({}) q[{}], q[{}];", angle, q0, q1);
158 }
159 QuantumGate::CP => {
161 let _ = writeln!(output, "cp({}) q[{}], q[{}];", angle, q0, q1);
162 }
163 QuantumGate::CPhase => {
164 let _ = writeln!(output, "cphase({}) q[{}], q[{}];", angle, q0, q1);
165 }
166 QuantumGate::XX => {
167 let _ = writeln!(output, "rxx({}) q[{}], q[{}];", angle, q0, q1);
168 }
169 QuantumGate::YY => {
170 let _ = writeln!(output, "ryy({}) q[{}], q[{}];", angle, q0, q1);
171 }
172 QuantumGate::ZZ => {
173 let _ = writeln!(output, "rzz({}) q[{}], q[{}];", angle, q0, q1);
174 }
175 QuantumGate::XY => {
176 let _ = writeln!(output, "xy({}) q[{}], q[{}];", angle, q0, q1);
177 }
178 QuantumGate::MS => {
179 let _ = writeln!(output, "ms q[{}], q[{}];", q0, q1);
180 }
181 QuantumGate::CCX => {
183 let _ = writeln!(output, "ccx q[{}], q[{}], q[{}];", q0, q1, q2);
184 }
185 QuantumGate::CSWAP => {
186 let _ = writeln!(output, "cswap q[{}], q[{}], q[{}];", q0, q1, q2);
187 }
188 QuantumGate::MCX => {
190 let _ = writeln!(output, "mcx q[{}], q[{}], q[{}];", q0, q1, q2);
191 }
192 QuantumGate::MCZ => {
193 let _ = writeln!(output, "mcz q[{}], q[{}], q[{}];", q0, q1, q2);
194 }
195 QuantumGate::Measure => {
197 let _ = writeln!(output, "c[{}] = measure q[{}];", q0, q0);
198 }
199 QuantumGate::MeasureAll => {
200 for i in 0..num_qubits {
201 let _ = writeln!(output, "c[{}] = measure q[{}];", i, i);
202 }
203 }
204 QuantumGate::Reset => {
205 let _ = writeln!(output, "reset q[{}];", q0);
206 }
207 QuantumGate::Barrier => {
208 let _ = writeln!(output, "barrier q;");
209 }
210 QuantumGate::Init => {
211 let _ = writeln!(output, "reset q[{}];", q0);
212 }
213 QuantumGate::Delay => {
214 let _ = writeln!(output, "delay[100ns] q[{}];", q0);
215 }
216 QuantumGate::GPI => {
218 let _ = writeln!(output, "gpi({}) q[{}];", angle, q0);
219 }
220 QuantumGate::GPI2 => {
221 let _ = writeln!(output, "gpi2({}) q[{}];", angle, q0);
222 }
223 QuantumGate::IfElse => {
225 let _ = writeln!(output, "// if-else control flow");
226 }
227 QuantumGate::ParamGate => {
228 let _ = writeln!(output, "// parameterised gate: {}", op_name);
229 }
230 }
231 qubit_counter += 1;
232 }
233 }
234
235 Ok(output)
236 }
237}
238
239impl Default for QasmExporter {
240 fn default() -> Self {
241 Self::new()
242 }
243}