Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/pyqasm/modules/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,23 @@ 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:
Expand Down
14 changes: 13 additions & 1 deletion src/pyqasm/visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand All @@ -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()}

Expand Down Expand Up @@ -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]:
Expand Down
30 changes: 30 additions & 0 deletions tests/qasm3/test_barrier.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = """
Expand Down