1use crate::{
26 error::{QuantRS2Error, QuantRS2Result},
27 gate::GateOp,
28 qubit::QubitId,
29};
30use std::collections::HashMap;
31use std::fmt::Write as FmtWrite;
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
39pub enum QuantumLanguage {
40 OpenQASM2,
42 OpenQASM3,
44 Quil,
46 QSharp,
48 Cirq,
50 Qiskit,
52 PyQuil,
54 ProjectQ,
56 BraketIR,
58 Silq,
60 Pennylane,
62}
63
64impl QuantumLanguage {
65 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 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 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#[derive(Debug, Clone)]
177pub struct CompilableCircuit {
178 pub num_qubits: usize,
180 pub num_cbits: usize,
182 pub gates: Vec<GateInstruction>,
184 pub measurements: Vec<(usize, usize)>, }
187
188#[derive(Debug, Clone)]
190pub struct GateInstruction {
191 pub name: String,
193 pub params: Vec<f64>,
195 pub qubits: Vec<usize>,
197 pub controls: Vec<usize>,
199}
200
201impl CompilableCircuit {
202 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 pub fn add_gate(&mut self, instruction: GateInstruction) {
214 self.gates.push(instruction);
215 }
216
217 pub fn add_measurement(&mut self, qubit: usize, cbit: usize) {
219 self.measurements.push((qubit, cbit));
220 }
221
222 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
230pub struct QuantumLanguageCompiler {
236 target_language: QuantumLanguage,
237 optimize: bool,
238 include_comments: bool,
239}
240
241impl QuantumLanguageCompiler {
242 pub fn new(target_language: QuantumLanguage) -> Self {
244 Self {
245 target_language,
246 optimize: true,
247 include_comments: true,
248 }
249 }
250
251 pub fn with_optimization(mut self, optimize: bool) -> Self {
253 self.optimize = optimize;
254 self
255 }
256
257 pub fn with_comments(mut self, include_comments: bool) -> Self {
259 self.include_comments = include_comments;
260 self
261 }
262
263 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 fn compile_to_openqasm2(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
282 let mut output = String::new();
283
284 writeln!(output, "OPENQASM 2.0;").unwrap();
286 writeln!(output, "include \"qelib1.inc\";").unwrap();
287 writeln!(output).unwrap();
288
289 writeln!(output, "qreg q[{}];", circuit.num_qubits).unwrap();
291
292 if circuit.num_cbits > 0 {
294 writeln!(output, "creg c[{}];", circuit.num_cbits).unwrap();
295 }
296 writeln!(output).unwrap();
297
298 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 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 fn compile_to_openqasm3(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
359 let mut output = String::new();
360
361 writeln!(output, "OPENQASM 3.0;").unwrap();
363 writeln!(output, "include \"stdgates.inc\";").unwrap();
364 writeln!(output).unwrap();
365
366 writeln!(output, "qubit[{}] q;", circuit.num_qubits).unwrap();
368
369 if circuit.num_cbits > 0 {
371 writeln!(output, "bit[{}] c;", circuit.num_cbits).unwrap();
372 }
373 writeln!(output).unwrap();
374
375 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 for (qubit, cbit) in &circuit.measurements {
389 writeln!(output, "c[{}] = measure q[{}];", cbit, qubit).unwrap();
390 }
391
392 Ok(output)
393 }
394
395 fn compile_to_quil(&self, circuit: &CompilableCircuit) -> QuantRS2Result<String> {
397 let mut output = String::new();
398
399 if circuit.num_cbits > 0 {
401 writeln!(output, "DECLARE ro BIT[{}]", circuit.num_cbits).unwrap();
402 writeln!(output).unwrap();
403 }
404
405 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 for (qubit, cbit) in &circuit.measurements {
433 writeln!(output, "MEASURE {} ro[{}]", qubit, cbit).unwrap();
434 }
435
436 Ok(output)
437 }
438
439 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}