From 38ce5b73bda6d97acb33a163fa5c653e48ec8317 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas Date: Thu, 12 Dec 2024 15:37:09 +0100 Subject: [PATCH 01/22] Restore SGMQ notation for barrier links. Add tests for barrier links. --- CHANGELOG.md | 10 ++++ .../passes/exporter/cqasmv1_exporter.py | 35 +++++++----- test/exporter/test_cqasmv1_exporter.py | 54 +++++++++++++++++++ 3 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..c3d91f19 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +# Change Log + +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](http://semver.org/). + + +## [ 0.2.0 ] - [ xxxx-yy-zz ] + +### Added +- Restoring SGMQ notation for barrier links in cQASMv1 Exporter (with tests). diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index 8b8472fb..e698059e 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -1,9 +1,10 @@ from __future__ import annotations +from itertools import groupby from typing import TYPE_CHECKING, SupportsFloat, SupportsInt from opensquirrel.exceptions import UnsupportedGateError -from opensquirrel.ir import Barrier, Float, Gate, Init, Int, IRVisitor, Measure, Qubit, Reset, Wait +from opensquirrel.ir import Barrier, Float, Gate, Init, Int, IRVisitor, Measure, Qubit, Reset, Statement, Wait if TYPE_CHECKING: from opensquirrel.circuit import Circuit @@ -14,12 +15,13 @@ class _CQASMv1Creator(IRVisitor): # Precision used when writing out a float number FLOAT_PRECISION = 8 - def __init__(self, register_manager: RegisterManager) -> None: + def __init__(self, register_manager: RegisterManager, barrier_links: list[list[Statement]]) -> None: self.register_manager = register_manager qubit_register_size = self.register_manager.get_qubit_register_size() - self.cqasmv1_string = "version 1.0\n\n{}\n\n".format( + self.cqasm_v1_string = "version 1.0\n\n{}\n\n".format( f"qubits {qubit_register_size}" if qubit_register_size > 0 else "" ) + self.barrier_links = barrier_links def visit_qubit(self, qubit: Qubit) -> str: qubit_register_name = self.register_manager.get_qubit_register_name() @@ -35,24 +37,27 @@ def visit_float(self, f: SupportsFloat) -> str: def visit_measure(self, measure: Measure) -> None: qubit_argument = measure.arguments[0].accept(self) # type: ignore[index] - self.cqasmv1_string += f"{measure.name}_z {qubit_argument}\n" + self.cqasm_v1_string += f"{measure.name}_z {qubit_argument}\n" def visit_init(self, init: Init) -> None: qubit_argument = init.arguments[0].accept(self) # type: ignore[index] - self.cqasmv1_string += f"prep_z {qubit_argument}\n" + self.cqasm_v1_string += f"prep_z {qubit_argument}\n" def visit_reset(self, reset: Reset) -> None: qubit_argument = reset.arguments[0].accept(self) # type: ignore[index] - self.cqasmv1_string += f"prep_z {qubit_argument}\n" + self.cqasm_v1_string += f"prep_z {qubit_argument}\n" def visit_barrier(self, barrier: Barrier) -> None: - qubit_argument = barrier.arguments[0].accept(self) # type: ignore[index] - self.cqasmv1_string += f"barrier {qubit_argument}\n" + if self.barrier_links and barrier == self.barrier_links[0][-1]: + qubit_register_name = self.register_manager.get_qubit_register_name() + qubit_indices = [str(barrier.arguments[0].index) for barrier in self.barrier_links[0]] # type: ignore + self.cqasm_v1_string += f"barrier {qubit_register_name}[{', '.join(qubit_indices)}]\n" + del self.barrier_links[0] def visit_wait(self, wait: Wait) -> None: qubit_argument = wait.arguments[0].accept(self) # type: ignore[index] parameter = wait.arguments[1].accept(self) # type: ignore[index] - self.cqasmv1_string += f"wait {qubit_argument}, {parameter}\n" + self.cqasm_v1_string += f"wait {qubit_argument}, {parameter}\n" def visit_gate(self, gate: Gate) -> None: gate_name = gate.name.lower() @@ -62,15 +67,19 @@ def visit_gate(self, gate: Gate) -> None: if any(not isinstance(arg, Qubit) for arg in gate.arguments): # type: ignore[union-attr] params = [arg.accept(self) for arg in gate.arguments if not isinstance(arg, Qubit)] # type: ignore[union-attr] qubit_args = (arg.accept(self) for arg in gate.arguments if isinstance(arg, Qubit)) # type: ignore[union-attr] - self.cqasmv1_string += "{} {}{}\n".format( + self.cqasm_v1_string += "{} {}{}\n".format( gate_name, ", ".join(qubit_args), ", " + ", ".join(params) if params else "" ) def export(circuit: Circuit) -> str: - cqasmv1_creator = _CQASMv1Creator(circuit.register_manager) - + barrier_links = [ + list(barrier_link) + for barrier, barrier_link in groupby(circuit.ir.statements, lambda stmt: isinstance(stmt, Barrier)) + if barrier + ] + cqasmv1_creator = _CQASMv1Creator(circuit.register_manager, barrier_links) circuit.ir.accept(cqasmv1_creator) # Remove all trailing lines and leave only one - return cqasmv1_creator.cqasmv1_string.rstrip() + "\n" + return cqasmv1_creator.cqasm_v1_string.rstrip() + "\n" diff --git a/test/exporter/test_cqasmv1_exporter.py b/test/exporter/test_cqasmv1_exporter.py index 3010c3c3..ea21dc02 100644 --- a/test/exporter/test_cqasmv1_exporter.py +++ b/test/exporter/test_cqasmv1_exporter.py @@ -236,3 +236,57 @@ def test_anonymous_gates(gate: Gate) -> None: with pytest.raises(UnsupportedGateError, match="not supported"): # noqa: PT012 qc = builder.to_circuit() qc.export(fmt=ExportFormat.CQASM_V1) + + +@pytest.mark.parametrize( + ("v3_input", "v3_output", "v1_output"), + [ + ( + """version 3.0; qubit[1] q; barrier q[0]; """, + """version 3.0\n\nqubit[1] q\n\nbarrier q[0]\n""", + """version 1.0\n\nqubits 1\n\nbarrier q[0]\n""", + ), + ( + """version 3.0; qubit[3] q; barrier q[0:2]; """, + """version 3.0\n\nqubit[3] q\n\nbarrier q[0]\nbarrier q[1]\nbarrier q[2]\n""", + """version 1.0\n\nqubits 3\n\nbarrier q[0, 1, 2]\n""", + ), + ( + """version 3.0; qubit[1] q; barrier q[0, 0];""", + """version 3.0\n\nqubit[1] q\n\nbarrier q[0]\nbarrier q[0]\n""", + """version 1.0\n\nqubits 1\n\nbarrier q[0, 0]\n""", + ), + ( + """version 3.0; qubit[6] q; barrier q[0:2, 5, 3, 4, 1]; """, + """version 3.0\n\nqubit[6] q\n\nbarrier q[0]\nbarrier q[1]\nbarrier q[2]\nbarrier q[5]\nbarrier q[3] +barrier q[4]\nbarrier q[1]\n""", + """version 1.0\n\nqubits 6\n\nbarrier q[0, 1, 2, 5, 3, 4, 1]\n""", + ), + ( + """version 3.0; qubit[5] q; barrier q[0]; H q[1]; barrier q[1:2]; X q[2]; barrier q[3:4, 1]; Y q[3]; + barrier q[0];""", + """version 3.0\n\nqubit[5] q\n\nbarrier q[0]\nH q[1]\nbarrier q[1]\nbarrier q[2]\nX q[2] +barrier q[3]\nbarrier q[4]\nbarrier q[1]\nY q[3]\nbarrier q[0]\n""", + """version 1.0\n\nqubits 5\n\nbarrier q[0]\nh q[1]\nbarrier q[1, 2]\nx q[2]\nbarrier q[3, 4, 1]\ny q[3] +barrier q[0]\n""", + ), + ( + """version 3.0; qubit[3] q; barrier q[0]; barrier q[1]; X q[2]; barrier q[1]""", + """version 3.0\n\nqubit[3] q\n\nbarrier q[0]\nbarrier q[1]\nX q[2]\nbarrier q[1]\n""", + """version 1.0\n\nqubits 3\n\nbarrier q[0, 1]\nx q[2]\nbarrier q[1]\n""", + ), + ], + ids=[ + "no_link", + "single_link", + "repeated_index", + "preserve_order", + "with_instructions", + "link_consecutive_barriers", + ], +) +def test_barrier_links(v3_input: str, v3_output: str, v1_output: str) -> None: + qc = Circuit.from_string(v3_input) + assert str(qc) == v3_output + cqasm_v1_string = qc.export(fmt=ExportFormat.CQASM_V1) + assert cqasm_v1_string == v1_output From f4cbfde76fc21495d327687e92b9fd119d71190e Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Fri, 13 Dec 2024 14:20:02 +0100 Subject: [PATCH 02/22] Update CHANGELOG.md Co-authored-by: Roberto Turrado Camblor --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3d91f19..53d0eefa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,4 +7,4 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [ 0.2.0 ] - [ xxxx-yy-zz ] ### Added -- Restoring SGMQ notation for barrier links in cQASMv1 Exporter (with tests). +- Restore SGMQ notation for barrier links in cQASMv1 Exporter (with tests). From 2f6fb2a310414a06625a813ac7c8b77e3493f4c6 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Fri, 13 Dec 2024 14:21:31 +0100 Subject: [PATCH 03/22] Update opensquirrel/passes/exporter/cqasmv1_exporter.py Co-authored-by: Roberto Turrado Camblor --- opensquirrel/passes/exporter/cqasmv1_exporter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index e698059e..bd86bba5 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -18,7 +18,7 @@ class _CQASMv1Creator(IRVisitor): def __init__(self, register_manager: RegisterManager, barrier_links: list[list[Statement]]) -> None: self.register_manager = register_manager qubit_register_size = self.register_manager.get_qubit_register_size() - self.cqasm_v1_string = "version 1.0\n\n{}\n\n".format( + self.output = "version 1.0\n\n{}\n\n".format( f"qubits {qubit_register_size}" if qubit_register_size > 0 else "" ) self.barrier_links = barrier_links From 4cc918bb75b4cd40dfbfc3db3a2eb6f51d342db1 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Fri, 13 Dec 2024 14:25:22 +0100 Subject: [PATCH 04/22] Update test/exporter/test_cqasmv1_exporter.py Co-authored-by: Roberto Turrado Camblor --- test/exporter/test_cqasmv1_exporter.py | 44 +++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/test/exporter/test_cqasmv1_exporter.py b/test/exporter/test_cqasmv1_exporter.py index ea21dc02..a5e6abe8 100644 --- a/test/exporter/test_cqasmv1_exporter.py +++ b/test/exporter/test_cqasmv1_exporter.py @@ -242,38 +242,38 @@ def test_anonymous_gates(gate: Gate) -> None: ("v3_input", "v3_output", "v1_output"), [ ( - """version 3.0; qubit[1] q; barrier q[0]; """, - """version 3.0\n\nqubit[1] q\n\nbarrier q[0]\n""", - """version 1.0\n\nqubits 1\n\nbarrier q[0]\n""", + """version 3.0; qubit[1] q; barrier q[0]", + """version 3.0\n\nqubit[1] q\n\nbarrier q[0]\n", + """version 1.0\n\nqubits 1\n\nbarrier q[0]\n", ), ( - """version 3.0; qubit[3] q; barrier q[0:2]; """, - """version 3.0\n\nqubit[3] q\n\nbarrier q[0]\nbarrier q[1]\nbarrier q[2]\n""", - """version 1.0\n\nqubits 3\n\nbarrier q[0, 1, 2]\n""", + "version 3.0; qubit[3] q; barrier q[0:2]", + "version 3.0\n\nqubit[3] q\n\nbarrier q[0]\nbarrier q[1]\nbarrier q[2]\n", + "version 1.0\n\nqubits 3\n\nbarrier q[0, 1, 2]\n", ), ( - """version 3.0; qubit[1] q; barrier q[0, 0];""", - """version 3.0\n\nqubit[1] q\n\nbarrier q[0]\nbarrier q[0]\n""", - """version 1.0\n\nqubits 1\n\nbarrier q[0, 0]\n""", + "version 3.0; qubit[1] q; barrier q[0, 0]", + "version 3.0\n\nqubit[1] q\n\nbarrier q[0]\nbarrier q[0]\n", + "version 1.0\n\nqubits 1\n\nbarrier q[0, 0]\n", ), ( - """version 3.0; qubit[6] q; barrier q[0:2, 5, 3, 4, 1]; """, - """version 3.0\n\nqubit[6] q\n\nbarrier q[0]\nbarrier q[1]\nbarrier q[2]\nbarrier q[5]\nbarrier q[3] -barrier q[4]\nbarrier q[1]\n""", - """version 1.0\n\nqubits 6\n\nbarrier q[0, 1, 2, 5, 3, 4, 1]\n""", + "version 3.0; qubit[6] q; barrier q[0:2, 5, 3, 4, 1]", + "version 3.0\n\nqubit[6] q\n\nbarrier q[0]\nbarrier q[1]\nbarrier q[2]\nbarrier q[5]\nbarrier q[3] +barrier q[4]\nbarrier q[1]\n", + "version 1.0\n\nqubits 6\n\nbarrier q[0, 1, 2, 5, 3, 4, 1]\n", ), ( - """version 3.0; qubit[5] q; barrier q[0]; H q[1]; barrier q[1:2]; X q[2]; barrier q[3:4, 1]; Y q[3]; - barrier q[0];""", - """version 3.0\n\nqubit[5] q\n\nbarrier q[0]\nH q[1]\nbarrier q[1]\nbarrier q[2]\nX q[2] -barrier q[3]\nbarrier q[4]\nbarrier q[1]\nY q[3]\nbarrier q[0]\n""", - """version 1.0\n\nqubits 5\n\nbarrier q[0]\nh q[1]\nbarrier q[1, 2]\nx q[2]\nbarrier q[3, 4, 1]\ny q[3] -barrier q[0]\n""", + "version 3.0; qubit[5] q; barrier q[0]; H q[1]; barrier q[1:2]; X q[2]; barrier q[3:4, 1]; Y q[3]; + barrier q[0]", + "version 3.0\n\nqubit[5] q\n\nbarrier q[0]\nH q[1]\nbarrier q[1]\nbarrier q[2]\nX q[2] +barrier q[3]\nbarrier q[4]\nbarrier q[1]\nY q[3]\nbarrier q[0]\n", + "version 1.0\n\nqubits 5\n\nbarrier q[0]\nh q[1]\nbarrier q[1, 2]\nx q[2]\nbarrier q[3, 4, 1]\ny q[3] +barrier q[0]\n", ), ( - """version 3.0; qubit[3] q; barrier q[0]; barrier q[1]; X q[2]; barrier q[1]""", - """version 3.0\n\nqubit[3] q\n\nbarrier q[0]\nbarrier q[1]\nX q[2]\nbarrier q[1]\n""", - """version 1.0\n\nqubits 3\n\nbarrier q[0, 1]\nx q[2]\nbarrier q[1]\n""", + "version 3.0; qubit[3] q; barrier q[0]; barrier q[1]; X q[2]; barrier q[1]", + "version 3.0\n\nqubit[3] q\n\nbarrier q[0]\nbarrier q[1]\nX q[2]\nbarrier q[1]\n", + "version 1.0\n\nqubits 3\n\nbarrier q[0, 1]\nx q[2]\nbarrier q[1]\n", ), ], ids=[ From 30ff3b19634886835ea2e30f637948bdb244510a Mon Sep 17 00:00:00 2001 From: Chris Elenbaas Date: Fri, 13 Dec 2024 14:32:17 +0100 Subject: [PATCH 05/22] Resolve review comments. --- .../passes/exporter/cqasmv1_exporter.py | 20 +++++++---------- test/exporter/test_cqasmv1_exporter.py | 22 +++++++++---------- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index bd86bba5..cc55aa50 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -18,9 +18,7 @@ class _CQASMv1Creator(IRVisitor): def __init__(self, register_manager: RegisterManager, barrier_links: list[list[Statement]]) -> None: self.register_manager = register_manager qubit_register_size = self.register_manager.get_qubit_register_size() - self.output = "version 1.0\n\n{}\n\n".format( - f"qubits {qubit_register_size}" if qubit_register_size > 0 else "" - ) + self.output = "version 1.0\n\n{}\n\n".format(f"qubits {qubit_register_size}" if qubit_register_size > 0 else "") self.barrier_links = barrier_links def visit_qubit(self, qubit: Qubit) -> str: @@ -37,27 +35,27 @@ def visit_float(self, f: SupportsFloat) -> str: def visit_measure(self, measure: Measure) -> None: qubit_argument = measure.arguments[0].accept(self) # type: ignore[index] - self.cqasm_v1_string += f"{measure.name}_z {qubit_argument}\n" + self.output += f"{measure.name}_z {qubit_argument}\n" def visit_init(self, init: Init) -> None: qubit_argument = init.arguments[0].accept(self) # type: ignore[index] - self.cqasm_v1_string += f"prep_z {qubit_argument}\n" + self.output += f"prep_z {qubit_argument}\n" def visit_reset(self, reset: Reset) -> None: qubit_argument = reset.arguments[0].accept(self) # type: ignore[index] - self.cqasm_v1_string += f"prep_z {qubit_argument}\n" + self.output += f"prep_z {qubit_argument}\n" def visit_barrier(self, barrier: Barrier) -> None: if self.barrier_links and barrier == self.barrier_links[0][-1]: qubit_register_name = self.register_manager.get_qubit_register_name() qubit_indices = [str(barrier.arguments[0].index) for barrier in self.barrier_links[0]] # type: ignore - self.cqasm_v1_string += f"barrier {qubit_register_name}[{', '.join(qubit_indices)}]\n" + self.output += f"barrier {qubit_register_name}[{', '.join(qubit_indices)}]\n" del self.barrier_links[0] def visit_wait(self, wait: Wait) -> None: qubit_argument = wait.arguments[0].accept(self) # type: ignore[index] parameter = wait.arguments[1].accept(self) # type: ignore[index] - self.cqasm_v1_string += f"wait {qubit_argument}, {parameter}\n" + self.output += f"wait {qubit_argument}, {parameter}\n" def visit_gate(self, gate: Gate) -> None: gate_name = gate.name.lower() @@ -67,9 +65,7 @@ def visit_gate(self, gate: Gate) -> None: if any(not isinstance(arg, Qubit) for arg in gate.arguments): # type: ignore[union-attr] params = [arg.accept(self) for arg in gate.arguments if not isinstance(arg, Qubit)] # type: ignore[union-attr] qubit_args = (arg.accept(self) for arg in gate.arguments if isinstance(arg, Qubit)) # type: ignore[union-attr] - self.cqasm_v1_string += "{} {}{}\n".format( - gate_name, ", ".join(qubit_args), ", " + ", ".join(params) if params else "" - ) + self.output += "{} {}{}\n".format(gate_name, ", ".join(qubit_args), ", " + ", ".join(params) if params else "") def export(circuit: Circuit) -> str: @@ -82,4 +78,4 @@ def export(circuit: Circuit) -> str: circuit.ir.accept(cqasmv1_creator) # Remove all trailing lines and leave only one - return cqasmv1_creator.cqasm_v1_string.rstrip() + "\n" + return cqasmv1_creator.output.rstrip() + "\n" diff --git a/test/exporter/test_cqasmv1_exporter.py b/test/exporter/test_cqasmv1_exporter.py index a5e6abe8..72234d13 100644 --- a/test/exporter/test_cqasmv1_exporter.py +++ b/test/exporter/test_cqasmv1_exporter.py @@ -242,9 +242,9 @@ def test_anonymous_gates(gate: Gate) -> None: ("v3_input", "v3_output", "v1_output"), [ ( - """version 3.0; qubit[1] q; barrier q[0]", - """version 3.0\n\nqubit[1] q\n\nbarrier q[0]\n", - """version 1.0\n\nqubits 1\n\nbarrier q[0]\n", + "version 3.0; qubit[1] q; barrier q[0]", + "version 3.0\n\nqubit[1] q\n\nbarrier q[0]\n", + "version 1.0\n\nqubits 1\n\nbarrier q[0]\n", ), ( "version 3.0; qubit[3] q; barrier q[0:2]", @@ -258,17 +258,17 @@ def test_anonymous_gates(gate: Gate) -> None: ), ( "version 3.0; qubit[6] q; barrier q[0:2, 5, 3, 4, 1]", - "version 3.0\n\nqubit[6] q\n\nbarrier q[0]\nbarrier q[1]\nbarrier q[2]\nbarrier q[5]\nbarrier q[3] -barrier q[4]\nbarrier q[1]\n", + "version 3.0\n\nqubit[6] q\n\nbarrier q[0]\nbarrier q[1]\nbarrier q[2]\nbarrier q[5]\nbarrier q[3]\n" + "barrier q[4]\nbarrier q[1]\n", "version 1.0\n\nqubits 6\n\nbarrier q[0, 1, 2, 5, 3, 4, 1]\n", ), ( - "version 3.0; qubit[5] q; barrier q[0]; H q[1]; barrier q[1:2]; X q[2]; barrier q[3:4, 1]; Y q[3]; - barrier q[0]", - "version 3.0\n\nqubit[5] q\n\nbarrier q[0]\nH q[1]\nbarrier q[1]\nbarrier q[2]\nX q[2] -barrier q[3]\nbarrier q[4]\nbarrier q[1]\nY q[3]\nbarrier q[0]\n", - "version 1.0\n\nqubits 5\n\nbarrier q[0]\nh q[1]\nbarrier q[1, 2]\nx q[2]\nbarrier q[3, 4, 1]\ny q[3] -barrier q[0]\n", + "version 3.0; qubit[5] q; barrier q[0]; H q[1]; barrier q[1:2]; X q[2]; barrier q[3:4, 1]; Y q[3];" + "barrier q[0]", + "version 3.0\n\nqubit[5] q\n\nbarrier q[0]\nH q[1]\nbarrier q[1]\nbarrier q[2]\nX q[2]\n" + "barrier q[3]\nbarrier q[4]\nbarrier q[1]\nY q[3]\nbarrier q[0]\n", + "version 1.0\n\nqubits 5\n\nbarrier q[0]\nh q[1]\nbarrier q[1, 2]\nx q[2]\nbarrier q[3, 4, 1]\ny q[3]\n" + "barrier q[0]\n", ), ( "version 3.0; qubit[3] q; barrier q[0]; barrier q[1]; X q[2]; barrier q[1]", From 70f8ab9353c511c2a68a93ede39a86955a3e4107 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:53:59 +0100 Subject: [PATCH 06/22] Update opensquirrel/passes/exporter/cqasmv1_exporter.py Co-authored-by: Roberto Turrado Camblor --- opensquirrel/passes/exporter/cqasmv1_exporter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index cc55aa50..0eaf0098 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -18,7 +18,7 @@ class _CQASMv1Creator(IRVisitor): def __init__(self, register_manager: RegisterManager, barrier_links: list[list[Statement]]) -> None: self.register_manager = register_manager qubit_register_size = self.register_manager.get_qubit_register_size() - self.output = "version 1.0\n\n{}\n\n".format(f"qubits {qubit_register_size}" if qubit_register_size > 0 else "") + self.output = "version 1.0\n\n{}".format(f"qubits {qubit_register_size}\n\n" if qubit_register_size > 0 else "") self.barrier_links = barrier_links def visit_qubit(self, qubit: Qubit) -> str: From 7d95bad4afa203aba3b1c4bf024d8e8c077da278 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:54:45 +0100 Subject: [PATCH 07/22] Update test/exporter/test_cqasmv1_exporter.py Co-authored-by: Roberto Turrado Camblor --- test/exporter/test_cqasmv1_exporter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/exporter/test_cqasmv1_exporter.py b/test/exporter/test_cqasmv1_exporter.py index 72234d13..26d81145 100644 --- a/test/exporter/test_cqasmv1_exporter.py +++ b/test/exporter/test_cqasmv1_exporter.py @@ -239,7 +239,7 @@ def test_anonymous_gates(gate: Gate) -> None: @pytest.mark.parametrize( - ("v3_input", "v3_output", "v1_output"), + ("program", "expected_output"), [ ( "version 3.0; qubit[1] q; barrier q[0]", From d864fccce76a75671bd9e68931e20cb945a90c30 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:55:02 +0100 Subject: [PATCH 08/22] Update test/exporter/test_cqasmv1_exporter.py Co-authored-by: Roberto Turrado Camblor --- test/exporter/test_cqasmv1_exporter.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/exporter/test_cqasmv1_exporter.py b/test/exporter/test_cqasmv1_exporter.py index 26d81145..7b116d02 100644 --- a/test/exporter/test_cqasmv1_exporter.py +++ b/test/exporter/test_cqasmv1_exporter.py @@ -243,36 +243,28 @@ def test_anonymous_gates(gate: Gate) -> None: [ ( "version 3.0; qubit[1] q; barrier q[0]", - "version 3.0\n\nqubit[1] q\n\nbarrier q[0]\n", "version 1.0\n\nqubits 1\n\nbarrier q[0]\n", ), ( "version 3.0; qubit[3] q; barrier q[0:2]", - "version 3.0\n\nqubit[3] q\n\nbarrier q[0]\nbarrier q[1]\nbarrier q[2]\n", "version 1.0\n\nqubits 3\n\nbarrier q[0, 1, 2]\n", ), ( "version 3.0; qubit[1] q; barrier q[0, 0]", - "version 3.0\n\nqubit[1] q\n\nbarrier q[0]\nbarrier q[0]\n", "version 1.0\n\nqubits 1\n\nbarrier q[0, 0]\n", ), ( "version 3.0; qubit[6] q; barrier q[0:2, 5, 3, 4, 1]", - "version 3.0\n\nqubit[6] q\n\nbarrier q[0]\nbarrier q[1]\nbarrier q[2]\nbarrier q[5]\nbarrier q[3]\n" - "barrier q[4]\nbarrier q[1]\n", "version 1.0\n\nqubits 6\n\nbarrier q[0, 1, 2, 5, 3, 4, 1]\n", ), ( "version 3.0; qubit[5] q; barrier q[0]; H q[1]; barrier q[1:2]; X q[2]; barrier q[3:4, 1]; Y q[3];" "barrier q[0]", - "version 3.0\n\nqubit[5] q\n\nbarrier q[0]\nH q[1]\nbarrier q[1]\nbarrier q[2]\nX q[2]\n" - "barrier q[3]\nbarrier q[4]\nbarrier q[1]\nY q[3]\nbarrier q[0]\n", "version 1.0\n\nqubits 5\n\nbarrier q[0]\nh q[1]\nbarrier q[1, 2]\nx q[2]\nbarrier q[3, 4, 1]\ny q[3]\n" "barrier q[0]\n", ), ( "version 3.0; qubit[3] q; barrier q[0]; barrier q[1]; X q[2]; barrier q[1]", - "version 3.0\n\nqubit[3] q\n\nbarrier q[0]\nbarrier q[1]\nX q[2]\nbarrier q[1]\n", "version 1.0\n\nqubits 3\n\nbarrier q[0, 1]\nx q[2]\nbarrier q[1]\n", ), ], From 43f356043ef11a74df97a4d4da94c0a5803076ef Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Mon, 16 Dec 2024 11:03:10 +0100 Subject: [PATCH 09/22] Update test/exporter/test_cqasmv1_exporter.py Co-authored-by: Roberto Turrado Camblor --- test/exporter/test_cqasmv1_exporter.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/exporter/test_cqasmv1_exporter.py b/test/exporter/test_cqasmv1_exporter.py index 7b116d02..daeb29f4 100644 --- a/test/exporter/test_cqasmv1_exporter.py +++ b/test/exporter/test_cqasmv1_exporter.py @@ -277,8 +277,7 @@ def test_anonymous_gates(gate: Gate) -> None: "link_consecutive_barriers", ], ) -def test_barrier_links(v3_input: str, v3_output: str, v1_output: str) -> None: - qc = Circuit.from_string(v3_input) - assert str(qc) == v3_output - cqasm_v1_string = qc.export(fmt=ExportFormat.CQASM_V1) - assert cqasm_v1_string == v1_output +def test_barrier_links(program: str, expected_output: str) -> None: + qc = Circuit.from_string(program) + output = qc.export(fmt=ExportFormat.CQASM_V1) + assert output == expected_output From 3e3c55965e6307455f800466a49a313d57379e96 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas Date: Wed, 8 Jan 2025 14:14:40 +0100 Subject: [PATCH 10/22] Revert changes to cQASMv1 exporter and comment barrier tests. --- .../passes/exporter/cqasmv1_exporter.py | 23 ++--- test/exporter/test_cqasmv1_exporter.py | 86 +++++++++---------- 2 files changed, 50 insertions(+), 59 deletions(-) diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index 0eaf0098..efed929c 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -1,10 +1,9 @@ from __future__ import annotations -from itertools import groupby from typing import TYPE_CHECKING, SupportsFloat, SupportsInt from opensquirrel.exceptions import UnsupportedGateError -from opensquirrel.ir import Barrier, Float, Gate, Init, Int, IRVisitor, Measure, Qubit, Reset, Statement, Wait +from opensquirrel.ir import Barrier, Float, Gate, Init, Int, IRVisitor, Measure, Qubit, Reset, Wait if TYPE_CHECKING: from opensquirrel.circuit import Circuit @@ -15,11 +14,10 @@ class _CQASMv1Creator(IRVisitor): # Precision used when writing out a float number FLOAT_PRECISION = 8 - def __init__(self, register_manager: RegisterManager, barrier_links: list[list[Statement]]) -> None: + def __init__(self, register_manager: RegisterManager) -> None: self.register_manager = register_manager qubit_register_size = self.register_manager.get_qubit_register_size() - self.output = "version 1.0\n\n{}".format(f"qubits {qubit_register_size}\n\n" if qubit_register_size > 0 else "") - self.barrier_links = barrier_links + self.output = "version 1.0\n\n{}\n\n".format(f"qubits {qubit_register_size}" if qubit_register_size > 0 else "") def visit_qubit(self, qubit: Qubit) -> str: qubit_register_name = self.register_manager.get_qubit_register_name() @@ -46,11 +44,8 @@ def visit_reset(self, reset: Reset) -> None: self.output += f"prep_z {qubit_argument}\n" def visit_barrier(self, barrier: Barrier) -> None: - if self.barrier_links and barrier == self.barrier_links[0][-1]: - qubit_register_name = self.register_manager.get_qubit_register_name() - qubit_indices = [str(barrier.arguments[0].index) for barrier in self.barrier_links[0]] # type: ignore - self.output += f"barrier {qubit_register_name}[{', '.join(qubit_indices)}]\n" - del self.barrier_links[0] + qubit_argument = barrier.arguments[0].accept(self) # type: ignore[index] + self.output += f"barrier {qubit_argument}\n" def visit_wait(self, wait: Wait) -> None: qubit_argument = wait.arguments[0].accept(self) # type: ignore[index] @@ -69,12 +64,8 @@ def visit_gate(self, gate: Gate) -> None: def export(circuit: Circuit) -> str: - barrier_links = [ - list(barrier_link) - for barrier, barrier_link in groupby(circuit.ir.statements, lambda stmt: isinstance(stmt, Barrier)) - if barrier - ] - cqasmv1_creator = _CQASMv1Creator(circuit.register_manager, barrier_links) + cqasmv1_creator = _CQASMv1Creator(circuit.register_manager) + circuit.ir.accept(cqasmv1_creator) # Remove all trailing lines and leave only one diff --git a/test/exporter/test_cqasmv1_exporter.py b/test/exporter/test_cqasmv1_exporter.py index daeb29f4..9c57ce56 100644 --- a/test/exporter/test_cqasmv1_exporter.py +++ b/test/exporter/test_cqasmv1_exporter.py @@ -238,46 +238,46 @@ def test_anonymous_gates(gate: Gate) -> None: qc.export(fmt=ExportFormat.CQASM_V1) -@pytest.mark.parametrize( - ("program", "expected_output"), - [ - ( - "version 3.0; qubit[1] q; barrier q[0]", - "version 1.0\n\nqubits 1\n\nbarrier q[0]\n", - ), - ( - "version 3.0; qubit[3] q; barrier q[0:2]", - "version 1.0\n\nqubits 3\n\nbarrier q[0, 1, 2]\n", - ), - ( - "version 3.0; qubit[1] q; barrier q[0, 0]", - "version 1.0\n\nqubits 1\n\nbarrier q[0, 0]\n", - ), - ( - "version 3.0; qubit[6] q; barrier q[0:2, 5, 3, 4, 1]", - "version 1.0\n\nqubits 6\n\nbarrier q[0, 1, 2, 5, 3, 4, 1]\n", - ), - ( - "version 3.0; qubit[5] q; barrier q[0]; H q[1]; barrier q[1:2]; X q[2]; barrier q[3:4, 1]; Y q[3];" - "barrier q[0]", - "version 1.0\n\nqubits 5\n\nbarrier q[0]\nh q[1]\nbarrier q[1, 2]\nx q[2]\nbarrier q[3, 4, 1]\ny q[3]\n" - "barrier q[0]\n", - ), - ( - "version 3.0; qubit[3] q; barrier q[0]; barrier q[1]; X q[2]; barrier q[1]", - "version 1.0\n\nqubits 3\n\nbarrier q[0, 1]\nx q[2]\nbarrier q[1]\n", - ), - ], - ids=[ - "no_link", - "single_link", - "repeated_index", - "preserve_order", - "with_instructions", - "link_consecutive_barriers", - ], -) -def test_barrier_links(program: str, expected_output: str) -> None: - qc = Circuit.from_string(program) - output = qc.export(fmt=ExportFormat.CQASM_V1) - assert output == expected_output +# @pytest.mark.parametrize( +# ("program", "expected_output"), +# [ +# ( +# "version 3.0; qubit[1] q; barrier q[0]", +# "version 1.0\n\nqubits 1\n\nbarrier q[0]\n", +# ), +# ( +# "version 3.0; qubit[3] q; barrier q[0:2]", +# "version 1.0\n\nqubits 3\n\nbarrier q[0, 1, 2]\n", +# ), +# ( +# "version 3.0; qubit[1] q; barrier q[0, 0]", +# "version 1.0\n\nqubits 1\n\nbarrier q[0, 0]\n", +# ), +# ( +# "version 3.0; qubit[6] q; barrier q[0:2, 5, 3, 4, 1]", +# "version 1.0\n\nqubits 6\n\nbarrier q[0, 1, 2, 5, 3, 4, 1]\n", +# ), +# ( +# "version 3.0; qubit[5] q; barrier q[0]; H q[1]; barrier q[1:2]; X q[2]; barrier q[3:4, 1]; Y q[3];" +# "barrier q[0]", +# "version 1.0\n\nqubits 5\n\nbarrier q[0]\nh q[1]\nbarrier q[1, 2]\nx q[2]\nbarrier q[3, 4, 1]\ny q[3]\n" +# "barrier q[0]\n", +# ), +# ( +# "version 3.0; qubit[3] q; barrier q[0]; barrier q[1]; X q[2]; barrier q[1]", +# "version 1.0\n\nqubits 3\n\nbarrier q[0, 1]\nx q[2]\nbarrier q[1]\n", +# ), +# ], +# ids=[ +# "no_link", +# "single_link", +# "repeated_index", +# "preserve_order", +# "with_instructions", +# "link_consecutive_barriers", +# ], +# ) +# def test_barrier_links(program: str, expected_output: str) -> None: +# qc = Circuit.from_string(program) +# output = qc.export(fmt=ExportFormat.CQASM_V1) +# assert output == expected_output From c226368fcd842150b2dfcce0fe3dd9480cd124f9 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas Date: Wed, 8 Jan 2025 15:43:50 +0100 Subject: [PATCH 11/22] Implement barrier grouping as post-processing step --- .../passes/exporter/cqasmv1_exporter.py | 30 ++++++- test/exporter/test_cqasmv1_exporter.py | 86 +++++++++---------- 2 files changed, 72 insertions(+), 44 deletions(-) diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index efed929c..07162e1a 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -63,10 +63,38 @@ def visit_gate(self, gate: Gate) -> None: self.output += "{} {}{}\n".format(gate_name, ", ".join(qubit_args), ", " + ", ".join(params) if params else "") +def post_process(output: str) -> str: + post_output = _merge_barrier_groups(output) + return post_output.rstrip() + "\n" + + +def _merge_barrier_groups(output: str) -> str: + post_output: str = "" + barrier_group_indices: list[int] = [] + for line in output.split("\n"): + if not line.startswith("barrier"): + if barrier_group_indices: + post_output += _dump_barrier_group(barrier_group_indices) + barrier_group_indices = [] + post_output += f"{line}\n" + else: + barrier_group_indices.append(_get_barrier_index(line)) + return post_output + + +def _dump_barrier_group(indices: list[int]) -> str: + return "barrier q[{}]\n".format(", ".join(map(str, indices)) if len(indices) != 0 else "") + + +def _get_barrier_index(line: str) -> int: + return int("".join(s for s in line if s.isdigit())) + + def export(circuit: Circuit) -> str: cqasmv1_creator = _CQASMv1Creator(circuit.register_manager) circuit.ir.accept(cqasmv1_creator) # Remove all trailing lines and leave only one - return cqasmv1_creator.output.rstrip() + "\n" + output = cqasmv1_creator.output.rstrip() + "\n" + return post_process(output) diff --git a/test/exporter/test_cqasmv1_exporter.py b/test/exporter/test_cqasmv1_exporter.py index 9c57ce56..5c2dae68 100644 --- a/test/exporter/test_cqasmv1_exporter.py +++ b/test/exporter/test_cqasmv1_exporter.py @@ -238,46 +238,46 @@ def test_anonymous_gates(gate: Gate) -> None: qc.export(fmt=ExportFormat.CQASM_V1) -# @pytest.mark.parametrize( -# ("program", "expected_output"), -# [ -# ( -# "version 3.0; qubit[1] q; barrier q[0]", -# "version 1.0\n\nqubits 1\n\nbarrier q[0]\n", -# ), -# ( -# "version 3.0; qubit[3] q; barrier q[0:2]", -# "version 1.0\n\nqubits 3\n\nbarrier q[0, 1, 2]\n", -# ), -# ( -# "version 3.0; qubit[1] q; barrier q[0, 0]", -# "version 1.0\n\nqubits 1\n\nbarrier q[0, 0]\n", -# ), -# ( -# "version 3.0; qubit[6] q; barrier q[0:2, 5, 3, 4, 1]", -# "version 1.0\n\nqubits 6\n\nbarrier q[0, 1, 2, 5, 3, 4, 1]\n", -# ), -# ( -# "version 3.0; qubit[5] q; barrier q[0]; H q[1]; barrier q[1:2]; X q[2]; barrier q[3:4, 1]; Y q[3];" -# "barrier q[0]", -# "version 1.0\n\nqubits 5\n\nbarrier q[0]\nh q[1]\nbarrier q[1, 2]\nx q[2]\nbarrier q[3, 4, 1]\ny q[3]\n" -# "barrier q[0]\n", -# ), -# ( -# "version 3.0; qubit[3] q; barrier q[0]; barrier q[1]; X q[2]; barrier q[1]", -# "version 1.0\n\nqubits 3\n\nbarrier q[0, 1]\nx q[2]\nbarrier q[1]\n", -# ), -# ], -# ids=[ -# "no_link", -# "single_link", -# "repeated_index", -# "preserve_order", -# "with_instructions", -# "link_consecutive_barriers", -# ], -# ) -# def test_barrier_links(program: str, expected_output: str) -> None: -# qc = Circuit.from_string(program) -# output = qc.export(fmt=ExportFormat.CQASM_V1) -# assert output == expected_output +@pytest.mark.parametrize( + ("program", "expected_output"), + [ + ( + "version 3.0; qubit[1] q; barrier q[0];", + "version 1.0\n\nqubits 1\n\nbarrier q[0]\n", + ), + ( + "version 3.0; qubit[3] q; barrier q[0:2]", + "version 1.0\n\nqubits 3\n\nbarrier q[0, 1, 2]\n", + ), + ( + "version 3.0; qubit[1] q; barrier q[0, 0]", + "version 1.0\n\nqubits 1\n\nbarrier q[0, 0]\n", + ), + ( + "version 3.0; qubit[6] q; barrier q[0:2, 5, 3, 4, 1]", + "version 1.0\n\nqubits 6\n\nbarrier q[0, 1, 2, 5, 3, 4, 1]\n", + ), + ( + "version 3.0; qubit[5] q; barrier q[0]; H q[1]; barrier q[1:2]; X q[2]; barrier q[3:4, 1]; Y q[3];" + "barrier q[0]; barrier q[2]", + "version 1.0\n\nqubits 5\n\nbarrier q[0]\nh q[1]\nbarrier q[1, 2]\nx q[2]\nbarrier q[3, 4, 1]\ny q[3]\n" + "barrier q[0, 2]\n", + ), + ( + "version 3.0; qubit[3] q; barrier q[0]; barrier q[1]; X q[2]; barrier q[1]; X q[2]", + "version 1.0\n\nqubits 3\n\nbarrier q[0, 1]\nx q[2]\nbarrier q[1]\nx q[2]\n", + ), + ], + ids=[ + "no_group", + "single_group", + "repeated_index", + "preserve_order", + "with_instructions", + "group_consecutive_barriers", + ], +) +def test_barrier_groups(program: str, expected_output: str) -> None: + qc = Circuit.from_string(program) + output = qc.export(fmt=ExportFormat.CQASM_V1) + assert output == expected_output From 56827a9c0cef31e066b4f1d582af6e56b44e1e67 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Fri, 10 Jan 2025 09:52:33 +0100 Subject: [PATCH 12/22] Update opensquirrel/passes/exporter/cqasmv1_exporter.py Co-authored-by: Roberto Turrado Camblor --- opensquirrel/passes/exporter/cqasmv1_exporter.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index 07162e1a..b29b56e8 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -64,8 +64,7 @@ def visit_gate(self, gate: Gate) -> None: def post_process(output: str) -> str: - post_output = _merge_barrier_groups(output) - return post_output.rstrip() + "\n" + return _merge_barrier_groups(output) def _merge_barrier_groups(output: str) -> str: From d4b7b2820ab28cdf640ab08400f8f77f3336f3c2 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Fri, 10 Jan 2025 09:52:40 +0100 Subject: [PATCH 13/22] Update opensquirrel/passes/exporter/cqasmv1_exporter.py Co-authored-by: Roberto Turrado Camblor --- opensquirrel/passes/exporter/cqasmv1_exporter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index b29b56e8..f731a255 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -85,8 +85,10 @@ def _dump_barrier_group(indices: list[int]) -> str: return "barrier q[{}]\n".format(", ".join(map(str, indices)) if len(indices) != 0 else "") +import re + def _get_barrier_index(line: str) -> int: - return int("".join(s for s in line if s.isdigit())) + return int(re.find('\d+', line)) def export(circuit: Circuit) -> str: From 0c70f25e83cfad1e1b9ba68ee5c27f59a58f757a Mon Sep 17 00:00:00 2001 From: Chris Elenbaas Date: Fri, 10 Jan 2025 11:34:29 +0100 Subject: [PATCH 14/22] Fix regex module. Add test to check for double digit registers. Reinstate removing trailing lines and leaving one as the final step. --- opensquirrel/passes/exporter/cqasmv1_exporter.py | 8 +++----- test/exporter/test_cqasmv1_exporter.py | 5 +++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index f731a255..0e4a4640 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -1,5 +1,6 @@ from __future__ import annotations +import re from typing import TYPE_CHECKING, SupportsFloat, SupportsInt from opensquirrel.exceptions import UnsupportedGateError @@ -85,10 +86,8 @@ def _dump_barrier_group(indices: list[int]) -> str: return "barrier q[{}]\n".format(", ".join(map(str, indices)) if len(indices) != 0 else "") -import re - def _get_barrier_index(line: str) -> int: - return int(re.find('\d+', line)) + return int(re.findall("\d+", line)[0]) def export(circuit: Circuit) -> str: @@ -97,5 +96,4 @@ def export(circuit: Circuit) -> str: circuit.ir.accept(cqasmv1_creator) # Remove all trailing lines and leave only one - output = cqasmv1_creator.output.rstrip() + "\n" - return post_process(output) + return post_process(cqasmv1_creator.output).rstrip() + "\n" diff --git a/test/exporter/test_cqasmv1_exporter.py b/test/exporter/test_cqasmv1_exporter.py index 5c2dae68..a1fca593 100644 --- a/test/exporter/test_cqasmv1_exporter.py +++ b/test/exporter/test_cqasmv1_exporter.py @@ -267,6 +267,10 @@ def test_anonymous_gates(gate: Gate) -> None: "version 3.0; qubit[3] q; barrier q[0]; barrier q[1]; X q[2]; barrier q[1]; X q[2]", "version 1.0\n\nqubits 3\n\nbarrier q[0, 1]\nx q[2]\nbarrier q[1]\nx q[2]\n", ), + ( + "version 3.0; qubit[20] q; barrier q[14]; barrier q[9:12]; X q[2]; barrier q[19]", + "version 1.0\n\nqubits 20\n\nbarrier q[14, 9, 10, 11, 12]\nx q[2]\nbarrier q[19]\n", + ), ], ids=[ "no_group", @@ -275,6 +279,7 @@ def test_anonymous_gates(gate: Gate) -> None: "preserve_order", "with_instructions", "group_consecutive_barriers", + "double_digit_register_size", ], ) def test_barrier_groups(program: str, expected_output: str) -> None: From 7976aab832d1271a381b41d5e7721633fa7f194c Mon Sep 17 00:00:00 2001 From: Chris Elenbaas Date: Fri, 10 Jan 2025 11:36:16 +0100 Subject: [PATCH 15/22] Revert actions-poetry from v4 to v3 so the pipeline can run. --- .github/workflows/release.yaml | 2 +- .github/workflows/tests.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 48c1fde6..62ffdefa 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -22,7 +22,7 @@ jobs: with: python-version: "3.11" - name: Install poetry - uses: abatilo/actions-poetry@v4 + uses: abatilo/actions-poetry@v3 with: poetry-version: "1.8.3" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index ec54ca23..81f159b8 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -17,7 +17,7 @@ jobs: with: python-version: "3.11" - name: Install poetry - uses: abatilo/actions-poetry@v4 + uses: abatilo/actions-poetry@v3 with: poetry-version: "1.3.2" - name: Install tox @@ -47,7 +47,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Install poetry - uses: abatilo/actions-poetry@v4 + uses: abatilo/actions-poetry@v3 with: poetry-version: "1.3.2" - name: Install tox From d0f8361e7c1c829ffe89e92416fb4d2b0e4453d8 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas Date: Fri, 10 Jan 2025 11:40:52 +0100 Subject: [PATCH 16/22] Update changelog to use the right wording. --- CHANGELOG.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53d0eefa..c3ac8424 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,18 @@ -# Change Log +# Changelog All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +### Types of changes: +* **Added** for new features. +* **Changed** for changes in existing functionality. +* **Deprecated** for soon-to-be removed features. +* **Removed** for now removed features. +* **Fixed** for any bug fixes. +* **Security** in case of vulnerabilities. + ## [ 0.2.0 ] - [ xxxx-yy-zz ] ### Added -- Restore SGMQ notation for barrier links in cQASMv1 Exporter (with tests). +- Restore SGMQ notation for barrier groups in cQASMv1 Exporter. From 9e9bec7ccebc475720e7cfe468bb7bef1fe80174 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:06:06 +0100 Subject: [PATCH 17/22] Update CHANGELOG.md Co-authored-by: Roberto Turrado Camblor --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3ac8424..224fe8a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Types of changes: * **Added** for new features. * **Changed** for changes in existing functionality. -* **Deprecated** for soon-to-be removed features. * **Removed** for now removed features. * **Fixed** for any bug fixes. -* **Security** in case of vulnerabilities. ## [ 0.2.0 ] - [ xxxx-yy-zz ] From 4989b3effe3e79bb6eb845ff58ffe646d707d04f Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:27:30 +0100 Subject: [PATCH 18/22] Update CHANGELOG.md Co-authored-by: Roberto Turrado Camblor --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 224fe8a9..ffdfdcd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Types of changes: * **Added** for new features. * **Changed** for changes in existing functionality. -* **Removed** for now removed features. * **Fixed** for any bug fixes. +* **Removed** for now removed features. ## [ 0.2.0 ] - [ xxxx-yy-zz ] From d9577fbb625de549f88d891be75ca3af0adf1d83 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Tue, 14 Jan 2025 10:13:15 +0100 Subject: [PATCH 19/22] Update opensquirrel/passes/exporter/cqasmv1_exporter.py Co-authored-by: Roberto Turrado Camblor --- opensquirrel/passes/exporter/cqasmv1_exporter.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index 0e4a4640..58c48a46 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -69,17 +69,17 @@ def post_process(output: str) -> str: def _merge_barrier_groups(output: str) -> str: - post_output: str = "" + ret: str = "" barrier_group_indices: list[int] = [] for line in output.split("\n"): if not line.startswith("barrier"): if barrier_group_indices: - post_output += _dump_barrier_group(barrier_group_indices) + ret += _dump_barrier_group(barrier_group_indices) barrier_group_indices = [] - post_output += f"{line}\n" + ret += f"{line}\n" else: barrier_group_indices.append(_get_barrier_index(line)) - return post_output + return ret def _dump_barrier_group(indices: list[int]) -> str: From 580604b9f371a4681ddfbd138f85b0ec145b2b50 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas <67630508+elenbaasc@users.noreply.github.com> Date: Tue, 14 Jan 2025 10:14:09 +0100 Subject: [PATCH 20/22] Update opensquirrel/passes/exporter/cqasmv1_exporter.py Co-authored-by: Roberto Turrado Camblor --- opensquirrel/passes/exporter/cqasmv1_exporter.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index 58c48a46..23726c56 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -87,7 +87,10 @@ def _dump_barrier_group(indices: list[int]) -> str: def _get_barrier_index(line: str) -> int: - return int(re.findall("\d+", line)[0]) + barrier_index_match = re.search("\d+", line) + if not barrier_index_match: + raise CqasmV1ExporterParseError("expecting a barrier index but found none") + return int(barrier_index_match.group(0)) def export(circuit: Circuit) -> str: From 704d0047a0f62be521308bd41edd3a1fdabaa8a4 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas Date: Tue, 14 Jan 2025 10:32:41 +0100 Subject: [PATCH 21/22] Fix formatting error. --- opensquirrel/passes/exporter/cqasmv1_exporter.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index 23726c56..85b44433 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -86,10 +86,15 @@ def _dump_barrier_group(indices: list[int]) -> str: return "barrier q[{}]\n".format(", ".join(map(str, indices)) if len(indices) != 0 else "") +class CqasmV1ExporterParseError(Exception): + pass + + def _get_barrier_index(line: str) -> int: barrier_index_match = re.search("\d+", line) if not barrier_index_match: - raise CqasmV1ExporterParseError("expecting a barrier index but found none") + msg = "expecting a barrier index but found none" + raise CqasmV1ExporterParseError(msg) return int(barrier_index_match.group(0)) From 043053a842b93a42e5f87416f5dbdad7aefef103 Mon Sep 17 00:00:00 2001 From: Chris Elenbaas Date: Wed, 15 Jan 2025 09:39:32 +0100 Subject: [PATCH 22/22] Moved expection class to top of file. --- opensquirrel/passes/exporter/cqasmv1_exporter.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opensquirrel/passes/exporter/cqasmv1_exporter.py b/opensquirrel/passes/exporter/cqasmv1_exporter.py index 85b44433..bb25d7c8 100644 --- a/opensquirrel/passes/exporter/cqasmv1_exporter.py +++ b/opensquirrel/passes/exporter/cqasmv1_exporter.py @@ -11,6 +11,10 @@ from opensquirrel.register_manager import RegisterManager +class CqasmV1ExporterParseError(Exception): + pass + + class _CQASMv1Creator(IRVisitor): # Precision used when writing out a float number FLOAT_PRECISION = 8 @@ -86,10 +90,6 @@ def _dump_barrier_group(indices: list[int]) -> str: return "barrier q[{}]\n".format(", ".join(map(str, indices)) if len(indices) != 0 else "") -class CqasmV1ExporterParseError(Exception): - pass - - def _get_barrier_index(line: str) -> int: barrier_index_match = re.search("\d+", line) if not barrier_index_match: