-
Notifications
You must be signed in to change notification settings - Fork 23
Fix barrier unrolling to preserve multi-qubit barrier statements #295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5ec3144
66764e3
dcd3ce8
b11a92e
65c00b4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -761,6 +761,42 @@ def _visit_reset(self, statement: qasm3_ast.QuantumReset) -> list[qasm3_ast.Quan | |
|
|
||
| return unrolled_resets | ||
|
|
||
| def _expand_barrier_ranges( | ||
| self, | ||
| barrier: qasm3_ast.QuantumBarrier, | ||
| barrier_qubits: list[qasm3_ast.IndexedIdentifier | qasm3_ast.Identifier], | ||
| ) -> list: | ||
| """Replace RangeDefinition-containing qubits in a barrier with their | ||
| expanded IndexedIdentifier equivalents so that consolidate_qubit_registers | ||
| only sees IntegerLiteral indices.""" | ||
| consolidated_qubits: list = [] | ||
| expanded_idx = 0 | ||
| for op_qubit in barrier.qubits: | ||
| # Expand this single operand to find how many bits it produces. | ||
| temp_barrier = qasm3_ast.QuantumBarrier(qubits=[op_qubit]) | ||
| temp_barrier.span = barrier.span | ||
| op_expanded = self._get_op_bits(temp_barrier, qubits=True) | ||
| num_bits = len(op_expanded) | ||
|
|
||
| if isinstance(op_qubit, qasm3_ast.IndexedIdentifier): | ||
| has_range = any( | ||
| isinstance(ind, qasm3_ast.RangeDefinition) | ||
| for dim in op_qubit.indices | ||
| for ind in dim # type: ignore[union-attr] | ||
| ) | ||
| if has_range: | ||
| consolidated_qubits.extend( | ||
| barrier_qubits[expanded_idx : expanded_idx + num_bits] | ||
| ) | ||
| else: | ||
| consolidated_qubits.append(op_qubit) | ||
| else: | ||
| # Bare Identifier — keep as-is for compact slice notation | ||
| consolidated_qubits.append(op_qubit) | ||
|
|
||
| expanded_idx += num_bits | ||
| return consolidated_qubits | ||
|
|
||
| def _visit_barrier( # pylint: disable=too-many-locals, too-many-branches | ||
| self, barrier: qasm3_ast.QuantumBarrier | ||
| ) -> list[qasm3_ast.QuantumBarrier]: | ||
|
|
@@ -834,29 +870,38 @@ def _visit_barrier( # pylint: disable=too-many-locals, too-many-branches | |
|
|
||
| if not self._unroll_barriers: | ||
| if self._consolidate_qubits: | ||
| consolidated_qubits = self._expand_barrier_ranges(barrier, barrier_qubits) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There seems to be an edge case here - from pyqasm import loads
qasm3_string = """OPENQASM 3.0;
include "stdgates.inc";
qubit[2] q;
qreg q2[3];
barrier q2;
barrier q, q2;
"""
mod = loads(qasm3_string)
mod.unroll(unroll_barriers = False, consolidate_qubits = True)
mod.unroll(unroll_barriers = True, consolidate_qubits = True)raises - ERROR:pyqasm: Error at line 5, column 4 in QASM file
>>>>>> barrier __PYQASM_QUBITS__[2:];
...
File ~/Desktop/qBraid/repos/pyqasm/src/pyqasm/visitor.py:849, in QasmVisitor._visit_barrier(self, barrier)
839 for transform_map, size_map in zip(
840 reversed(self._function_qreg_transform_map), reversed(self._function_qreg_size_map)
841 ):
842 barrier.qubits = (
843 Qasm3Transformer.transform_function_qubits( # type: ignore [assignment]
844 barrier,
(...) 847 )
848 )
--> 849 barrier_qubits = self._get_op_bits(barrier, qubits=True)
850 unrolled_barriers = []
851 max_involved_depth = 0
File ~/Desktop/qBraid/repos/pyqasm/src/pyqasm/visitor.py:340, in QasmVisitor._get_op_bits(self, operation, qubits, function_qubit_sizes)
335 if function_qubit_sizes is None:
336 err_msg = (
337 f"Missing {'qubit' if qubits else 'clbit'} register declaration "
338 f"for '{reg_name}' in {type(operation).__name__}"
339 )
--> 340 raise_qasm3_error(
341 err_msg,
342 error_node=operation,
343 span=operation.span,
344 )
345 # we are trying to replace the qubits inside a nested function
346 assert function_qubit_sizes is not None
File ~/Desktop/qBraid/repos/pyqasm/src/pyqasm/exceptions.py:137, in raise_qasm3_error(message, err_type, error_node, span, raised_from)
135 if raised_from:
136 raise err_type(message) from raised_from
--> 137 raise err_type(message)
ValidationError: Missing qubit register declaration for '__PYQASM_QUBITS__[2:]' in QuantumBarrierSome weird behaviour where the commands work individually , and with switched order - # works individually and in this order
mod.unroll(unroll_barriers = True, consolidate_qubits = True)
mod.unroll(unroll_barriers = False, consolidate_qubits = True)but fail with - # fails
mod.unroll(unroll_barriers = False, consolidate_qubits = True)
mod.unroll(unroll_barriers = True, consolidate_qubits = True)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Edit : seems like this is a |
||
| expanded = qasm3_ast.QuantumBarrier( | ||
| qubits=consolidated_qubits # type: ignore[arg-type] | ||
| ) | ||
| barrier = cast( | ||
| qasm3_ast.QuantumBarrier, | ||
| Qasm3Transformer.consolidate_qubit_registers( | ||
| barrier, | ||
| expanded, | ||
| self._qubit_register_offsets, | ||
| self._global_qreg_size_map, | ||
| self._module._device_qubits, | ||
| ), | ||
| ) | ||
| return [barrier] | ||
|
|
||
| # Keep barrier as a single multi-qubit statement with expanded qubit | ||
| # references (e.g. q -> q[0], q[1], q[2]) instead of splitting into | ||
| # individual per-qubit barriers. | ||
| expanded_barrier = qasm3_ast.QuantumBarrier(qubits=barrier_qubits) # type: ignore[arg-type] | ||
|
|
||
| if self._consolidate_qubits: | ||
| unrolled_barriers = cast( | ||
| list[qasm3_ast.QuantumBarrier], | ||
| expanded_barrier = cast( | ||
| qasm3_ast.QuantumBarrier, | ||
| Qasm3Transformer.consolidate_qubit_registers( | ||
| unrolled_barriers, | ||
| expanded_barrier, | ||
| self._qubit_register_offsets, | ||
| self._global_qreg_size_map, | ||
| self._module._device_qubits, | ||
| ), | ||
| ) | ||
|
|
||
| return unrolled_barriers | ||
| return [expanded_barrier] | ||
|
|
||
| def _get_op_parameters(self, operation: qasm3_ast.QuantumGate) -> list[float]: | ||
| """Get the parameters for the operation. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.