From 30f878b25ec9e450a9320d56e13a14d870fca0d3 Mon Sep 17 00:00:00 2001 From: TheGupta2012 Date: Thu, 3 Apr 2025 12:14:39 +0530 Subject: [PATCH 1/2] add conditional barrier unrolling --- src/pyqasm/modules/base.py | 17 ++++++++++++++++- src/pyqasm/visitor.py | 14 +++++++++++++- tests/qasm3/test_barrier.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/pyqasm/modules/base.py b/src/pyqasm/modules/base.py index 07d77f64..427a1f2b 100644 --- a/src/pyqasm/modules/base.py +++ b/src/pyqasm/modules/base.py @@ -518,7 +518,22 @@ def validate(self): self._validated_program = True def unroll(self, **kwargs): - """Unroll the module into basic qasm operations""" + """Unroll the module into basic qasm operations. + + Args: + **kwargs: Additional arguments to pass to the QasmVisitor. + external_gates (list[str]): List of gates that should not be unrolled. + unroll_barriers (bool): If True, barriers will be unrolled. Defaults to True. + check_only (bool): If True, only check the program without executing it. Defaults to False. + + Raises: + ValidationError: If the module fails validation during unrolling. + UnrollError: If an error occurs during the unrolling process. + + Notes: + This method resets the module's qubit and classical bit counts before unrolling, + and sets them to -1 if an error occurs during unrolling. + """ if not kwargs: kwargs = {} try: diff --git a/src/pyqasm/visitor.py b/src/pyqasm/visitor.py index 6dce1837..4c9ec5c9 100644 --- a/src/pyqasm/visitor.py +++ b/src/pyqasm/visitor.py @@ -55,9 +55,17 @@ class QasmVisitor: initialize_runtime (bool): If True, quantum runtime will be initialized. Defaults to True. record_output (bool): If True, output of the circuit will be recorded. Defaults to True. external_gates (list[str]): List of gates that should not be unrolled. + unroll_barriers (bool): If True, barriers will be unrolled. Defaults to True. + check_only (bool): If True, only check the program without executing it. Defaults to False. """ - def __init__(self, module, check_only: bool = False, external_gates: list[str] | None = None): + def __init__( + self, + module, + check_only: bool = False, + external_gates: list[str] | None = None, + unroll_barriers: bool = True, + ): self._module = module self._scope: deque = deque([{}]) self._context: deque = deque([Context.GLOBAL]) @@ -74,6 +82,7 @@ def __init__(self, module, check_only: bool = False, external_gates: list[str] | self._external_gates: list[str] = [] if external_gates is None else external_gates self._subroutine_defns: dict[str, qasm3_ast.SubroutineDefinition] = {} self._check_only: bool = check_only + self._unroll_barriers: bool = unroll_barriers self._curr_scope: int = 0 self._label_scope_level: dict[int, set] = {self._curr_scope: set()} @@ -597,6 +606,9 @@ def _visit_barrier(self, barrier: qasm3_ast.QuantumBarrier) -> list[qasm3_ast.Qu if self._check_only: return [] + if not self._unroll_barriers: + return [barrier] + return unrolled_barriers def _get_op_parameters(self, operation: qasm3_ast.QuantumGate) -> list[float]: diff --git a/tests/qasm3/test_barrier.py b/tests/qasm3/test_barrier.py index 654d0ed8..7d122bd0 100644 --- a/tests/qasm3/test_barrier.py +++ b/tests/qasm3/test_barrier.py @@ -125,6 +125,36 @@ def test_remove_barriers(): check_unrolled_qasm(dumps(module), expected_qasm) +def test_unroll_barrier(): + qasm_str = """ + OPENQASM 3.0; + include "stdgates.inc"; + + qubit[2] q1; + qubit[3] q2; + qubit q3; + + // barriers + barrier q1, q2, q3; + barrier q2[:3]; + barrier q3[0]; + """ + expected_qasm = """OPENQASM 3.0; + include "stdgates.inc"; + qubit[2] q1; + qubit[3] q2; + qubit[1] q3; + barrier q1, q2, q3; + barrier q2[:3]; + barrier q3[0]; + """ + module = loads(qasm_str) + assert module.has_barriers() is True + module.unroll(unroll_barriers=False) + assert module.has_barriers() is True + check_unrolled_qasm(dumps(module), expected_qasm) + + def test_incorrect_barrier(): undeclared = """ From a978e5aec13ae16c29262d8d8b559c484c592921 Mon Sep 17 00:00:00 2001 From: TheGupta2012 Date: Thu, 3 Apr 2025 12:25:31 +0530 Subject: [PATCH 2/2] format --- src/pyqasm/modules/base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pyqasm/modules/base.py b/src/pyqasm/modules/base.py index 427a1f2b..5b6890cb 100644 --- a/src/pyqasm/modules/base.py +++ b/src/pyqasm/modules/base.py @@ -524,7 +524,8 @@ def unroll(self, **kwargs): **kwargs: Additional arguments to pass to the QasmVisitor. external_gates (list[str]): List of gates that should not be unrolled. unroll_barriers (bool): If True, barriers will be unrolled. Defaults to True. - check_only (bool): If True, only check the program without executing it. Defaults to False. + check_only (bool): If True, only check the program without executing it. + Defaults to False. Raises: ValidationError: If the module fails validation during unrolling.