Skip to content

Commit

Permalink
add check for qubits (#134)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheGupta2012 authored Aug 9, 2024
1 parent e6c5997 commit 06b0934
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 9 deletions.
40 changes: 31 additions & 9 deletions qbraid_qir/qasm3/visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,16 +390,35 @@ def visit_register(self, register: Union[QubitDeclaration, ClassicalDeclaration]
else:
register_size = 1 if register.type.size is None else register.type.size.value
register_name = register.qubit.name if is_qubit else register.identifier.name
self._label_scope_level[self._curr_scope].add(register_name)

size_map = self._qreg_size_map if is_qubit else self._creg_size_map
label_map = self._qubit_labels if is_qubit else self._clbit_labels

if self._check_in_scope(register_name):
self._print_err_location(register.span)
raise Qasm3ConversionError(
f"Invalid declaration of register with name '{register_name}'"
)

if is_qubit: # as bit type vars are added in classical decl handler
self._add_var_in_scope(
Variable(
register_name,
QubitDeclaration,
register_size,
None,
None,
False,
)
)

for i in range(register_size):
# required if indices are not used while applying a gate or measurement
if is_qubit:
self._qreg_size_map[f"{register_name}"] = register_size
self._qubit_labels[f"{register_name}_{i}"] = current_size + i
else:
self._creg_size_map[f"{register_name}"] = register_size
self._clbit_labels[f"{register_name}_{i}"] = current_size + i
size_map[f"{register_name}"] = register_size
label_map[f"{register_name}_{i}"] = current_size + i

self._label_scope_level[self._curr_scope].add(register_name)

_log.debug("Added labels for register '%s'", str(register))

def _print_err_location(self, element: Span) -> str:
Expand Down Expand Up @@ -1916,15 +1935,18 @@ def _process_quantum_arg(formal_arg, actual_arg, formal_reg_name, actual_arg_nam
formal_qubit_size = 1
formal_qreg_size_map[formal_reg_name] = formal_qubit_size

self._label_scope_level[self._curr_scope].add(formal_reg_name)

# we expect that actual arg is qubit type only
if actual_arg_name not in self._qreg_size_map:
self._print_err_location(statement.span)
raise Qasm3ConversionError(
f"Expecting qubit argument for '{formal_reg_name}'."
f" Qubit register '{actual_arg_name}' not found for function '{fn_name}'"
)
self._label_scope_level[self._curr_scope].add(formal_reg_name)

self._add_var_in_scope(
Variable(formal_reg_name, QubitDeclaration, formal_qubit_size, None, None, False)
)

actual_qids, actual_qubits_size = self._get_target_qubits(
actual_arg, self._qreg_size_map, actual_arg_name
Expand Down
30 changes: 30 additions & 0 deletions tests/qasm3_qir/converter/declarations/test_quantum.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
Module containing unit tests for QASM3 to QIR conversion functions.
"""
import pytest

from qbraid_qir.qasm3.convert import qasm3_to_qir
from qbraid_qir.qasm3.exceptions import Qasm3ConversionError
from tests.qir_utils import check_attributes


Expand Down Expand Up @@ -74,3 +76,31 @@ def test_qubit_clbit_declarations():
result = qasm3_to_qir(qasm3_string)
generated_qir = str(result).splitlines()
check_attributes(generated_qir, 7, 7)


def test_qubit_redeclaration_error():
"""Test redeclaration of qubit"""
with pytest.raises(
Qasm3ConversionError, match="Invalid declaration of register with name 'q1'"
):
qasm3_string = """
OPENQASM 3;
include "stdgates.inc";
qubit q1;
qubit q1;
"""
qasm3_to_qir(qasm3_string)


def test_clbit_redeclaration_error():
"""Test redeclaration of clbit"""
with pytest.raises(
Qasm3ConversionError, match="Invalid declaration of register with name 'c1'"
):
qasm3_string = """
OPENQASM 3;
include "stdgates.inc";
bit c1;
bit[4] c1;
"""
qasm3_to_qir(qasm3_string)
13 changes: 13 additions & 0 deletions tests/qasm3_qir/fixtures/subroutines.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ def my_function(qubit q) -> float[32] {
""",
"Redefinition of subroutine 'my_function'",
),
"redefinition_raises_error_2": (
"""
OPENQASM 3;
include "stdgates.inc";
def my_function(qubit q) {
int[32] q = 1;
return;
}
qubit q;
my_function(q);
""",
"Re-declaration of variable q",
),
"incorrect_param_count_1": (
"""
OPENQASM 3;
Expand Down
18 changes: 18 additions & 0 deletions tests/qasm3_qir/fixtures/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,24 @@
""",
"Re-declaration of variable x",
),
"variable_redeclaration_with_qubits_1": (
"""
OPENQASM 3.0;
include "stdgates.inc";
int x;
qubit x;
""",
"Invalid declaration of register with name 'x'",
),
"variable_redeclaration_with_qubits_2": (
"""
OPENQASM 3.0;
include "stdgates.inc";
qubit x;
int x;
""",
"Re-declaration of variable x",
),
"const_variable_redeclaration": (
"""
OPENQASM 3.0;
Expand Down

0 comments on commit 06b0934

Please sign in to comment.