Skip to main content

lift_export/
qasm_export.rs

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        // Count qubits needed
30        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        // Estimate unique qubits from block args
38        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        // Export gate operations
59        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                    // 1-qubit standard
74                    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                    // 1-qubit parametric
102                    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                    // 1-qubit fixed-angle
124                    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                    // 1-qubit special
131                    QuantumGate::VirtualRZ => {
132                        let _ = writeln!(output, "rz({}) q[{}]; // virtual", angle, q0);
133                    }
134                    QuantumGate::GlobalPhase => {
135                        let _ = writeln!(output, "gphase({});", angle);
136                    }
137                    // 2-qubit standard
138                    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                    // 2-qubit parametric
160                    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                    // 3-qubit
182                    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                    // Multi-controlled
189                    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                    // Measurement and control
196                    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                    // IonQ native
217                    QuantumGate::GPI => {
218                        let _ = writeln!(output, "gpi({}) q[{}];", angle, q0);
219                    }
220                    QuantumGate::GPI2 => {
221                        let _ = writeln!(output, "gpi2({}) q[{}];", angle, q0);
222                    }
223                    // Control flow and generic
224                    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}