quantrs2_core/
quantum_language_compiler.rs

1//! Quantum Programming Language Compilation Targets
2//!
3//! This module provides compilation from QuantRS2's internal circuit representation
4//! to various quantum programming languages and frameworks.
5//!
6//! ## Supported Target Languages
7//!
8//! - **OpenQASM 2.0/3.0**: IBM's open quantum assembly language
9//! - **Quil**: Rigetti's quantum instruction language
10//! - **Q#**: Microsoft's quantum programming language
11//! - **Cirq**: Google's quantum programming framework (Python)
12//! - **Qiskit**: IBM's quantum development kit (Python)
13//! - **PyQuil**: Rigetti's quantum programming library (Python)
14//! - **ProjectQ**: ETH Zurich's quantum programming framework
15//! - **Braket IR**: AWS Braket's intermediate representation
16//! - **Silq**: ETH Zurich's high-level quantum language
17//!
18//! ## Features
19//!
20//! - Automatic gate decomposition to target gate sets
21//! - Optimization for target platform
22//! - Preserves circuit structure and comments
23//! - Handles classical registers and measurements
24
25use crate::{
26    error::{QuantRS2Error, QuantRS2Result},
27    gate::GateOp,
28    qubit::QubitId,
29};
30use std::collections::HashMap;
31use std::fmt::Write as FmtWrite;
32
33// ================================================================================================
34// Target Language Types
35// ================================================================================================
36
37/// Supported quantum programming languages
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
39pub enum QuantumLanguage {
40    /// OpenQASM 2.0
41    OpenQASM2,
42    /// OpenQASM 3.0
43    OpenQASM3,
44    /// Rigetti Quil
45    Quil,
46    /// Microsoft Q#
47    QSharp,
48    /// Google Cirq (Python)
49    Cirq,
50    /// IBM Qiskit (Python)
51    Qiskit,
52    /// Rigetti PyQuil (Python)
53    PyQuil,
54    /// ProjectQ (Python)
55    ProjectQ,
56    /// AWS Braket IR (JSON)
57    BraketIR,
58    /// Silq high-level language
59    Silq,
60    /// Pennylane (Python)
61    Pennylane,
62}
63
64impl QuantumLanguage {
65    /// Get language name
66    pub fn name(&self) -> &'static str {
67        match self {
68            QuantumLanguage::OpenQASM2 => "OpenQASM 2.0",
69            QuantumLanguage::OpenQASM3 => "OpenQASM 3.0",
70            QuantumLanguage::Quil => "Quil",
71            QuantumLanguage::QSharp => "Q#",
72            QuantumLanguage::Cirq => "Cirq",
73            QuantumLanguage::Qiskit => "Qiskit",
74            QuantumLanguage::PyQuil => "PyQuil",
75            QuantumLanguage::ProjectQ => "ProjectQ",
76            QuantumLanguage::BraketIR => "Braket IR",
77            QuantumLanguage::Silq => "Silq",
78            QuantumLanguage::Pennylane => "Pennylane",
79        }
80    }
81
82    /// Get file extension
83    pub fn extension(&self) -> &'static str {
84        match self {
85            QuantumLanguage::OpenQASM2 | QuantumLanguage::OpenQASM3 => "qasm",
86            QuantumLanguage::Quil => "quil",
87            QuantumLanguage::QSharp => "qs",
88            QuantumLanguage::Cirq
89            | QuantumLanguage::Qiskit
90            | QuantumLanguage::PyQuil
91            | QuantumLanguage::ProjectQ
92            | QuantumLanguage::Pennylane => "py",
93            QuantumLanguage::BraketIR => "json",
94            QuantumLanguage::Silq => "slq",
95        }
96    }
97
98    /// Get supported gate set
99    pub fn supported_gates(&self) -> Vec<&'static str> {
100        match self {
101            QuantumLanguage::OpenQASM2 | QuantumLanguage::OpenQASM3 => {
102                vec![
103                    "x", "y", "z", "h", "s", "sdg", "t", "tdg", "rx", "ry", "rz", "cx", "cy", "cz",
104                    "ch", "swap", "ccx", "cswap",
105                ]
106            }
107            QuantumLanguage::Quil => {
108                vec![
109                    "X", "Y", "Z", "H", "S", "T", "RX", "RY", "RZ", "CNOT", "CZ", "SWAP", "CCNOT",
110                    "CSWAP", "PHASE",
111                ]
112            }
113            QuantumLanguage::QSharp => {
114                vec![
115                    "X", "Y", "Z", "H", "S", "T", "CNOT", "CCNOT", "SWAP", "Rx", "Ry", "Rz", "R1",
116                ]
117            }
118            QuantumLanguage::Cirq => {
119                vec![
120                    "X",
121                    "Y",
122                    "Z",
123                    "H",
124                    "S",
125                    "T",
126                    "CNOT",
127                    "CZ",
128                    "SWAP",
129                    "Rx",
130                    "Ry",
131                    "Rz",
132                    "ISWAP",
133                    "SQRT_ISWAP",
134                ]
135            }
136            QuantumLanguage::Qiskit => {
137                vec![
138                    "x", "y", "z", "h", "s", "sdg", "t", "tdg", "rx", "ry", "rz", "cx", "cy", "cz",
139                    "ch", "swap", "ccx",
140                ]
141            }
142            QuantumLanguage::PyQuil => {
143                vec![
144                    "X", "Y", "Z", "H", "S", "T", "RX", "RY", "RZ", "CNOT", "CZ", "SWAP", "PHASE",
145                ]
146            }
147            QuantumLanguage::ProjectQ => {
148                vec![
149                    "X", "Y", "Z", "H", "S", "T", "Rx", "Ry", "Rz", "CNOT", "Swap",
150                ]
151            }
152            QuantumLanguage::BraketIR => {
153                vec![
154                    "x", "y", "z", "h", "s", "si", "t", "ti", "rx", "ry", "rz", "cnot", "cy", "cz",
155                    "swap", "iswap",
156                ]
157            }
158            QuantumLanguage::Silq => {
159                vec!["X", "Y", "Z", "H", "S", "T", "CNOT", "phase"]
160            }
161            QuantumLanguage::Pennylane => {
162                vec![
163                    "PauliX", "PauliY", "PauliZ", "Hadamard", "S", "T", "RX", "RY", "RZ", "CNOT",
164                    "CZ", "SWAP",
165                ]
166            }
167        }
168    }
169}
170
171// ================================================================================================
172// Circuit Representation
173// ================================================================================================
174
175/// Quantum circuit for compilation
176#[derive(Debug, Clone)]
177pub struct CompilableCircuit {
178    /// Number of qubits
179    pub num_qubits: usize,
180    /// Number of classical bits
181    pub num_cbits: usize,
182    /// Circuit gates
183    pub gates: Vec<GateInstruction>,
184    /// Measurements
185    pub measurements: Vec<(usize, usize)>, // (qubit, cbit)
186}
187
188/// Gate instruction in the circuit
189#[derive(Debug, Clone)]
190pub struct GateInstruction {
191    /// Gate name
192    pub name: String,
193    /// Parameters (angles, etc.)
194    pub params: Vec<f64>,
195    /// Target qubits
196    pub qubits: Vec<usize>,
197    /// Control qubits (if controlled gate)
198    pub controls: Vec<usize>,
199}
200
201impl CompilableCircuit {
202    /// Create a new compilable circuit
203    pub fn new(num_qubits: usize, num_cbits: usize) -> Self {
204        Self {
205            num_qubits,
206            num_cbits,
207            gates: Vec::new(),
208            measurements: Vec::new(),
209        }
210    }
211
212    /// Add a gate instruction
213    pub fn add_gate(&mut self, instruction: GateInstruction) {
214        self.gates.push(instruction);
215    }
216
217    /// Add measurement
218    pub fn add_measurement(&mut self, qubit: usize, cbit: usize) {
219        self.measurements.push((qubit, cbit));
220    }
221
222    /// Measure all qubits
223    pub fn measure_all(&mut self) {
224        for i in 0..self.num_qubits.min(self.num_cbits) {
225            self.measurements.push((i, i));
226        }
227    }
228}
229
230// ================================================================================================
231// Language Compiler
232// ================================================================================================
233
234/// Compiler for quantum programming languages
235pub struct QuantumLanguageCompiler {
236    target_language: QuantumLanguage,
237    optimize: bool,
238    include_comments: bool,
239}
240
241impl QuantumLanguageCompiler {
242    /// Create a new compiler
243    pub fn new(target_language: QuantumLanguage) -> Self {
244        Self {
245            target_language,
246            optimize: true,
247            include_comments: true,
248        }
249    }
250
251    /// Enable/disable optimization
252    pub fn with_optimization(mut self, optimize: bool) -> Self {
253        self.optimize = optimize;
254        self
255    }
256
257    /// Enable/disable comments
258    pub fn with_comments(mut self, include_comments: bool) -> Self {
259        self.include_comments = include_comments;
260        self
261    }
262
263    /// Compile circuit to target language
264    pub fn compile(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
265        match self.target_language {
266            QuantumLanguage::OpenQASM2 => self.compile_to_openqasm2(circuit),
267            QuantumLanguage::OpenQASM3 => self.compile_to_openqasm3(circuit),
268            QuantumLanguage::Quil => self.compile_to_quil(circuit),
269            QuantumLanguage::QSharp => self.compile_to_qsharp(circuit),
270            QuantumLanguage::Cirq => self.compile_to_cirq(circuit),
271            QuantumLanguage::Qiskit => self.compile_to_qiskit(circuit),
272            QuantumLanguage::PyQuil => self.compile_to_pyquil(circuit),
273            QuantumLanguage::ProjectQ => self.compile_to_projectq(circuit),
274            QuantumLanguage::BraketIR => self.compile_to_braket_ir(circuit),
275            QuantumLanguage::Silq => self.compile_to_silq(circuit),
276            QuantumLanguage::Pennylane => self.compile_to_pennylane(circuit),
277        }
278    }
279
280    /// Compile to OpenQASM 2.0
281    fn compile_to_openqasm2(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
282        let mut output = String::new();
283
284        // Header
285        writeln!(output, "OPENQASM 2.0;").unwrap();
286        writeln!(output, "include \"qelib1.inc\";").unwrap();
287        writeln!(output).unwrap();
288
289        // Quantum register
290        writeln!(output, "qreg q[{}];", circuit.num_qubits).unwrap();
291
292        // Classical register
293        if circuit.num_cbits > 0 {
294            writeln!(output, "creg c[{}];", circuit.num_cbits).unwrap();
295        }
296        writeln!(output).unwrap();
297
298        // Gates
299        for gate in &circuit.gates {
300            match gate.name.as_str() {
301                "H" | "h" => {
302                    writeln!(output, "h q[{}];", gate.qubits[0]).unwrap();
303                }
304                "X" | "x" => {
305                    writeln!(output, "x q[{}];", gate.qubits[0]).unwrap();
306                }
307                "Y" | "y" => {
308                    writeln!(output, "y q[{}];", gate.qubits[0]).unwrap();
309                }
310                "Z" | "z" => {
311                    writeln!(output, "z q[{}];", gate.qubits[0]).unwrap();
312                }
313                "S" | "s" => {
314                    writeln!(output, "s q[{}];", gate.qubits[0]).unwrap();
315                }
316                "T" | "t" => {
317                    writeln!(output, "t q[{}];", gate.qubits[0]).unwrap();
318                }
319                "RX" | "rx" => {
320                    writeln!(output, "rx({}) q[{}];", gate.params[0], gate.qubits[0]).unwrap();
321                }
322                "RY" | "ry" => {
323                    writeln!(output, "ry({}) q[{}];", gate.params[0], gate.qubits[0]).unwrap();
324                }
325                "RZ" | "rz" => {
326                    writeln!(output, "rz({}) q[{}];", gate.params[0], gate.qubits[0]).unwrap();
327                }
328                "CNOT" | "cx" => {
329                    writeln!(output, "cx q[{}], q[{}];", gate.qubits[0], gate.qubits[1]).unwrap();
330                }
331                "CZ" | "cz" => {
332                    writeln!(output, "cz q[{}], q[{}];", gate.qubits[0], gate.qubits[1]).unwrap();
333                }
334                "SWAP" | "swap" => {
335                    writeln!(output, "swap q[{}], q[{}];", gate.qubits[0], gate.qubits[1]).unwrap();
336                }
337                _ => {
338                    return Err(QuantRS2Error::UnsupportedOperation(format!(
339                        "Gate {} not supported in OpenQASM 2.0",
340                        gate.name
341                    )));
342                }
343            }
344        }
345
346        // Measurements
347        if !circuit.measurements.is_empty() {
348            writeln!(output).unwrap();
349            for (qubit, cbit) in &circuit.measurements {
350                writeln!(output, "measure q[{}] -> c[{}];", qubit, cbit).unwrap();
351            }
352        }
353
354        Ok(output)
355    }
356
357    /// Compile to OpenQASM 3.0
358    fn compile_to_openqasm3(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
359        let mut output = String::new();
360
361        // Header
362        writeln!(output, "OPENQASM 3.0;").unwrap();
363        writeln!(output, "include \"stdgates.inc\";").unwrap();
364        writeln!(output).unwrap();
365
366        // Quantum bits
367        writeln!(output, "qubit[{}] q;", circuit.num_qubits).unwrap();
368
369        // Classical bits
370        if circuit.num_cbits > 0 {
371            writeln!(output, "bit[{}] c;", circuit.num_cbits).unwrap();
372        }
373        writeln!(output).unwrap();
374
375        // Gates (similar to QASM 2.0)
376        for gate in &circuit.gates {
377            match gate.name.as_str() {
378                "H" | "h" => writeln!(output, "h q[{}];", gate.qubits[0]).unwrap(),
379                "X" | "x" => writeln!(output, "x q[{}];", gate.qubits[0]).unwrap(),
380                "CNOT" | "cx" => {
381                    writeln!(output, "cx q[{}], q[{}];", gate.qubits[0], gate.qubits[1]).unwrap()
382                }
383                _ => {}
384            }
385        }
386
387        // Measurements
388        for (qubit, cbit) in &circuit.measurements {
389            writeln!(output, "c[{}] = measure q[{}];", cbit, qubit).unwrap();
390        }
391
392        Ok(output)
393    }
394
395    /// Compile to Quil
396    fn compile_to_quil(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
397        let mut output = String::new();
398
399        // Declare memory
400        if circuit.num_cbits > 0 {
401            writeln!(output, "DECLARE ro BIT[{}]", circuit.num_cbits).unwrap();
402            writeln!(output).unwrap();
403        }
404
405        // Gates
406        for gate in &circuit.gates {
407            match gate.name.as_str() {
408                "H" | "h" => writeln!(output, "H {}", gate.qubits[0]).unwrap(),
409                "X" | "x" => writeln!(output, "X {}", gate.qubits[0]).unwrap(),
410                "Y" | "y" => writeln!(output, "Y {}", gate.qubits[0]).unwrap(),
411                "Z" | "z" => writeln!(output, "Z {}", gate.qubits[0]).unwrap(),
412                "RX" | "rx" => {
413                    writeln!(output, "RX({}) {}", gate.params[0], gate.qubits[0]).unwrap()
414                }
415                "RY" | "ry" => {
416                    writeln!(output, "RY({}) {}", gate.params[0], gate.qubits[0]).unwrap()
417                }
418                "RZ" | "rz" => {
419                    writeln!(output, "RZ({}) {}", gate.params[0], gate.qubits[0]).unwrap()
420                }
421                "CNOT" | "cx" => {
422                    writeln!(output, "CNOT {} {}", gate.qubits[0], gate.qubits[1]).unwrap()
423                }
424                "CZ" | "cz" => {
425                    writeln!(output, "CZ {} {}", gate.qubits[0], gate.qubits[1]).unwrap()
426                }
427                _ => {}
428            }
429        }
430
431        // Measurements
432        for (qubit, cbit) in &circuit.measurements {
433            writeln!(output, "MEASURE {} ro[{}]", qubit, cbit).unwrap();
434        }
435
436        Ok(output)
437    }
438
439    /// Compile to Q#
440    fn compile_to_qsharp(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
441        let mut output = String::new();
442
443        writeln!(output, "namespace QuantumCircuit {{").unwrap();
444        writeln!(output, "    open Microsoft.Quantum.Canon;").unwrap();
445        writeln!(output, "    open Microsoft.Quantum.Intrinsic;").unwrap();
446        writeln!(output).unwrap();
447        writeln!(output, "    operation RunCircuit() : Result[] {{").unwrap();
448        writeln!(
449            output,
450            "        use qubits = Qubit[{}];",
451            circuit.num_qubits
452        )
453        .unwrap();
454        writeln!(output).unwrap();
455
456        // Gates
457        for gate in &circuit.gates {
458            match gate.name.as_str() {
459                "H" | "h" => writeln!(output, "        H(qubits[{}]);", gate.qubits[0]).unwrap(),
460                "X" | "x" => writeln!(output, "        X(qubits[{}]);", gate.qubits[0]).unwrap(),
461                "Y" | "y" => writeln!(output, "        Y(qubits[{}]);", gate.qubits[0]).unwrap(),
462                "Z" | "z" => writeln!(output, "        Z(qubits[{}]);", gate.qubits[0]).unwrap(),
463                "CNOT" | "cx" => writeln!(
464                    output,
465                    "        CNOT(qubits[{}], qubits[{}]);",
466                    gate.qubits[0], gate.qubits[1]
467                )
468                .unwrap(),
469                _ => {}
470            }
471        }
472
473        writeln!(output).unwrap();
474        writeln!(output, "        let results = ForEach(M, qubits);").unwrap();
475        writeln!(output, "        ResetAll(qubits);").unwrap();
476        writeln!(output, "        return results;").unwrap();
477        writeln!(output, "    }}").unwrap();
478        writeln!(output, "}}").unwrap();
479
480        Ok(output)
481    }
482
483    /// Compile to Cirq (Python)
484    fn compile_to_cirq(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
485        let mut output = String::new();
486
487        writeln!(output, "import cirq").unwrap();
488        writeln!(output).unwrap();
489        writeln!(output, "# Create qubits").unwrap();
490        writeln!(
491            output,
492            "qubits = [cirq.LineQubit(i) for i in range({})]",
493            circuit.num_qubits
494        )
495        .unwrap();
496        writeln!(output).unwrap();
497        writeln!(output, "# Create circuit").unwrap();
498        writeln!(output, "circuit = cirq.Circuit()").unwrap();
499        writeln!(output).unwrap();
500
501        // Gates
502        for gate in &circuit.gates {
503            match gate.name.as_str() {
504                "H" | "h" => {
505                    writeln!(output, "circuit.append(cirq.H(qubits[{}]))", gate.qubits[0]).unwrap()
506                }
507                "X" | "x" => {
508                    writeln!(output, "circuit.append(cirq.X(qubits[{}]))", gate.qubits[0]).unwrap()
509                }
510                "Y" | "y" => {
511                    writeln!(output, "circuit.append(cirq.Y(qubits[{}]))", gate.qubits[0]).unwrap()
512                }
513                "Z" | "z" => {
514                    writeln!(output, "circuit.append(cirq.Z(qubits[{}]))", gate.qubits[0]).unwrap()
515                }
516                "CNOT" | "cx" => writeln!(
517                    output,
518                    "circuit.append(cirq.CNOT(qubits[{}], qubits[{}]))",
519                    gate.qubits[0], gate.qubits[1]
520                )
521                .unwrap(),
522                "RX" | "rx" => writeln!(
523                    output,
524                    "circuit.append(cirq.rx({}).on(qubits[{}]))",
525                    gate.params[0], gate.qubits[0]
526                )
527                .unwrap(),
528                "RY" | "ry" => writeln!(
529                    output,
530                    "circuit.append(cirq.ry({}).on(qubits[{}]))",
531                    gate.params[0], gate.qubits[0]
532                )
533                .unwrap(),
534                "RZ" | "rz" => writeln!(
535                    output,
536                    "circuit.append(cirq.rz({}).on(qubits[{}]))",
537                    gate.params[0], gate.qubits[0]
538                )
539                .unwrap(),
540                _ => {}
541            }
542        }
543
544        // Measurements
545        if !circuit.measurements.is_empty() {
546            writeln!(output).unwrap();
547            write!(output, "circuit.append(cirq.measure(").unwrap();
548            for (i, (qubit, _)) in circuit.measurements.iter().enumerate() {
549                if i > 0 {
550                    write!(output, ", ").unwrap();
551                }
552                write!(output, "qubits[{}]", qubit).unwrap();
553            }
554            writeln!(output, ", key='result'))").unwrap();
555        }
556
557        writeln!(output).unwrap();
558        writeln!(output, "print(circuit)").unwrap();
559
560        Ok(output)
561    }
562
563    /// Compile to Qiskit (Python)
564    fn compile_to_qiskit(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
565        let mut output = String::new();
566
567        writeln!(
568            output,
569            "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister"
570        )
571        .unwrap();
572        writeln!(output).unwrap();
573        writeln!(output, "# Create registers").unwrap();
574        writeln!(
575            output,
576            "qreg = QuantumRegister({}, 'q'))",
577            circuit.num_qubits
578        )
579        .unwrap();
580
581        if circuit.num_cbits > 0 {
582            writeln!(
583                output,
584                "creg = ClassicalRegister({}, 'c')",
585                circuit.num_cbits
586            )
587            .unwrap();
588            writeln!(output, "circuit = QuantumCircuit(qreg, creg)").unwrap();
589        } else {
590            writeln!(output, "circuit = QuantumCircuit(qreg)").unwrap();
591        }
592
593        writeln!(output).unwrap();
594
595        // Gates
596        for gate in &circuit.gates {
597            match gate.name.as_str() {
598                "H" | "h" => writeln!(output, "circuit.h({})", gate.qubits[0]).unwrap(),
599                "X" | "x" => writeln!(output, "circuit.x({})", gate.qubits[0]).unwrap(),
600                "CNOT" | "cx" => {
601                    writeln!(output, "circuit.cx({}, {})", gate.qubits[0], gate.qubits[1]).unwrap()
602                }
603                _ => {}
604            }
605        }
606
607        // Measurements
608        for (qubit, cbit) in &circuit.measurements {
609            writeln!(output, "circuit.measure({}, {})", qubit, cbit).unwrap();
610        }
611
612        writeln!(output).unwrap();
613        writeln!(output, "print(circuit)").unwrap();
614
615        Ok(output)
616    }
617
618    /// Compile to PyQuil
619    fn compile_to_pyquil(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
620        let mut output = String::new();
621
622        writeln!(output, "from pyquil import Program").unwrap();
623        writeln!(output, "from pyquil.gates import *").unwrap();
624        writeln!(output).unwrap();
625        writeln!(output, "program = Program()").unwrap();
626        writeln!(output).unwrap();
627
628        // Gates
629        for gate in &circuit.gates {
630            match gate.name.as_str() {
631                "H" | "h" => writeln!(output, "program += H({})", gate.qubits[0]).unwrap(),
632                "X" | "x" => writeln!(output, "program += X({})", gate.qubits[0]).unwrap(),
633                "CNOT" | "cx" => writeln!(
634                    output,
635                    "program += CNOT({}, {})",
636                    gate.qubits[0], gate.qubits[1]
637                )
638                .unwrap(),
639                _ => {}
640            }
641        }
642
643        Ok(output)
644    }
645
646    /// Compile to ProjectQ
647    fn compile_to_projectq(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
648        let mut output = String::new();
649
650        writeln!(output, "from projectq import MainEngine").unwrap();
651        writeln!(output, "from projectq.ops import *").unwrap();
652        writeln!(output).unwrap();
653        writeln!(output, "eng = MainEngine()").unwrap();
654        writeln!(
655            output,
656            "qubits = eng.allocate_qureg({}))",
657            circuit.num_qubits
658        )
659        .unwrap();
660        writeln!(output).unwrap();
661
662        // Gates
663        for gate in &circuit.gates {
664            match gate.name.as_str() {
665                "H" | "h" => writeln!(output, "H | qubits[{}]", gate.qubits[0]).unwrap(),
666                "X" | "x" => writeln!(output, "X | qubits[{}]", gate.qubits[0]).unwrap(),
667                "CNOT" | "cx" => writeln!(
668                    output,
669                    "CNOT | (qubits[{}], qubits[{}])",
670                    gate.qubits[0], gate.qubits[1]
671                )
672                .unwrap(),
673                _ => {}
674            }
675        }
676
677        Ok(output)
678    }
679
680    /// Compile to Braket IR (JSON)
681    fn compile_to_braket_ir(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
682        let mut output = String::new();
683
684        writeln!(output, "{{").unwrap();
685        writeln!(output, "  \"braketSchemaHeader\": {{").unwrap();
686        writeln!(output, "    \"name\": \"braket.ir.jaqcd.program\",").unwrap();
687        writeln!(output, "    \"version\": \"1\"").unwrap();
688        writeln!(output, "  }},").unwrap();
689        writeln!(output, "  \"instructions\": [").unwrap();
690
691        for (i, gate) in circuit.gates.iter().enumerate() {
692            if i > 0 {
693                writeln!(output, ",").unwrap();
694            }
695            write!(output, "    {{").unwrap();
696
697            match gate.name.as_str() {
698                "H" | "h" => {
699                    write!(output, "\"type\": \"h\", \"target\": {}", gate.qubits[0]).unwrap();
700                }
701                "X" | "x" => {
702                    write!(output, "\"type\": \"x\", \"target\": {}", gate.qubits[0]).unwrap();
703                }
704                "CNOT" | "cx" => {
705                    write!(
706                        output,
707                        "\"type\": \"cnot\", \"control\": {}, \"target\": {}",
708                        gate.qubits[0], gate.qubits[1]
709                    )
710                    .unwrap();
711                }
712                _ => {}
713            }
714
715            write!(output, "}}").unwrap();
716        }
717
718        writeln!(output, "").unwrap();
719        writeln!(output, "  ]").unwrap();
720        writeln!(output, "}}").unwrap();
721
722        Ok(output)
723    }
724
725    /// Compile to Silq
726    fn compile_to_silq(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
727        let mut output = String::new();
728
729        writeln!(output, "def circuit() {{").unwrap();
730        writeln!(output, "  // Allocate qubits").unwrap();
731        writeln!(output, "  q := 0:^{};", circuit.num_qubits).unwrap();
732        writeln!(output).unwrap();
733
734        for gate in &circuit.gates {
735            match gate.name.as_str() {
736                "H" | "h" => writeln!(
737                    output,
738                    "  q[{}] := H(q[{}]);",
739                    gate.qubits[0], gate.qubits[0]
740                )
741                .unwrap(),
742                "X" | "x" => writeln!(
743                    output,
744                    "  q[{}] := X(q[{}]);",
745                    gate.qubits[0], gate.qubits[0]
746                )
747                .unwrap(),
748                _ => {}
749            }
750        }
751
752        writeln!(output, "  return q;").unwrap();
753        writeln!(output, "}}").unwrap();
754
755        Ok(output)
756    }
757
758    /// Compile to Pennylane
759    fn compile_to_pennylane(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
760        let mut output = String::new();
761
762        writeln!(output, "import pennylane as qml").unwrap();
763        writeln!(output).unwrap();
764        writeln!(
765            output,
766            "dev = qml.device('default.qubit', wires={})",
767            circuit.num_qubits
768        )
769        .unwrap();
770        writeln!(output).unwrap();
771        writeln!(output, "@qml.qnode(dev)").unwrap();
772        writeln!(output, "def circuit():").unwrap();
773
774        for gate in &circuit.gates {
775            match gate.name.as_str() {
776                "H" | "h" => {
777                    writeln!(output, "    qml.Hadamard(wires={})", gate.qubits[0]).unwrap()
778                }
779                "X" | "x" => writeln!(output, "    qml.PauliX(wires={})", gate.qubits[0]).unwrap(),
780                "CNOT" | "cx" => writeln!(
781                    output,
782                    "    qml.CNOT(wires=[{}, {}])",
783                    gate.qubits[0], gate.qubits[1]
784                )
785                .unwrap(),
786                _ => {}
787            }
788        }
789
790        writeln!(
791            output,
792            "    return qml.probs(wires=range({}))",
793            circuit.num_qubits
794        )
795        .unwrap();
796
797        Ok(output)
798    }
799}
800
801#[cfg(test)]
802mod tests {
803    use super::*;
804
805    #[test]
806    fn test_openqasm2_compilation() {
807        let mut circuit = CompilableCircuit::new(2, 2);
808        circuit.add_gate(GateInstruction {
809            name: "H".to_string(),
810            params: vec![],
811            qubits: vec![0],
812            controls: vec![],
813        });
814        circuit.add_gate(GateInstruction {
815            name: "CNOT".to_string(),
816            params: vec![],
817            qubits: vec![0, 1],
818            controls: vec![],
819        });
820        circuit.add_measurement(0, 0);
821        circuit.add_measurement(1, 1);
822
823        let compiler = QuantumLanguageCompiler::new(QuantumLanguage::OpenQASM2);
824        let result = compiler.compile(&circuit).unwrap();
825
826        assert!(result.contains("OPENQASM 2.0"));
827        assert!(result.contains("h q[0]"));
828        assert!(result.contains("cx q[0], q[1]"));
829        assert!(result.contains("measure q[0] -> c[0]"));
830    }
831
832    #[test]
833    fn test_quil_compilation() {
834        let mut circuit = CompilableCircuit::new(1, 1);
835        circuit.add_gate(GateInstruction {
836            name: "H".to_string(),
837            params: vec![],
838            qubits: vec![0],
839            controls: vec![],
840        });
841
842        let compiler = QuantumLanguageCompiler::new(QuantumLanguage::Quil);
843        let result = compiler.compile(&circuit).unwrap();
844
845        assert!(result.contains("H 0"));
846    }
847}