Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
28 changes: 23 additions & 5 deletions src/bloqade/pyqrack/qasm2/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,30 @@
def measure(
self, interp: PyQrackInterpreter, frame: interp.Frame, stmt: core.Measure
):
qarg: PyQrackQubit = frame.get(stmt.qarg)
carg: CBitRef = frame.get(stmt.carg)
if qarg.is_active():
carg.set_value(Measurement(qarg.sim_reg.m(qarg.addr)))
qarg: PyQrackQubit | PyQrackReg = frame.get(stmt.qarg)
carg: CBitRef | CRegister = frame.get(stmt.carg)

if isinstance(qarg, PyQrackQubit) and isinstance(carg, CBitRef):
if qarg.is_active():
carg.set_value(Measurement(qarg.sim_reg.m(qarg.addr)))
else:
carg.set_value(interp.loss_m_result)
elif isinstance(qarg, PyQrackReg) and isinstance(carg, CRegister):
# TODO: clean up iteration after PyQrackReg is refactored
for i in range(qarg.size):
qubit = qarg[i]

# TODO: make this consistent with PyQrackReg __getitem__ ?
cbit = CBitRef(carg, i)

if qubit.is_active():
cbit.set_value(Measurement(qarg.sim_reg.m(qubit.addr)))
else:
cbit.set_value(interp.loss_m_result)

Check warning on line 73 in src/bloqade/pyqrack/qasm2/core.py

View check run for this annotation

Codecov / codecov/patch

src/bloqade/pyqrack/qasm2/core.py#L73

Added line #L73 was not covered by tests
else:
carg.set_value(interp.loss_m_result)
raise RuntimeError(

Check warning on line 75 in src/bloqade/pyqrack/qasm2/core.py

View check run for this annotation

Codecov / codecov/patch

src/bloqade/pyqrack/qasm2/core.py#L75

Added line #L75 was not covered by tests
f"Expected measure call on either a single qubit and classical bit, or two registers, but got the types {type(qarg)} and {type(carg)}"
)

return ()

Expand Down
2 changes: 1 addition & 1 deletion src/bloqade/qasm2/_wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def reset(qarg: Qubit) -> None:


@wraps(core.Measure)
def measure(qarg: Qubit, cbit: Bit) -> None:
def measure(qarg: Qubit | QReg, cbit: Bit | CReg) -> None:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so you can fix the type hinting by adding the following separately

from typing import overload

@overload
def measure(qarg: Qubit, cbit: Bit) -> None: ...

@overload
def measure(qarg: QReg, cbit: CReg) -> None: ...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is what it looks like in IDE

image

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Roger-luo I had already done that following your message on slack. I just forgot to push the commit yesterday 😅

"""
Measure the qubit `qarg` and store the result in the classical bit `cbit`.

Expand Down
4 changes: 2 additions & 2 deletions src/bloqade/qasm2/dialects/core/stmts.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ class Measure(ir.Statement):

name = "measure"
traits = frozenset({lowering.FromPythonCall()})
qarg: ir.SSAValue = info.argument(QubitType)
qarg: ir.SSAValue = info.argument(QubitType | QRegType)
"""qarg (Qubit): The qubit to measure."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget an out the doc strings!

carg: ir.SSAValue = info.argument(BitType)
carg: ir.SSAValue = info.argument(BitType | CRegType)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to add a def check_type(self) method to validate the type here because here your definition allows QubitType appear with CRegType.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the type check test. FWIW, mixing the types would have already triggered a RuntimeError in the impl.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to have the error at compile time compared to run time since in some cases you might not run the function with the simulator for awhile if at all.

"""carg (Bit): The bit to store the result in."""


Expand Down
27 changes: 26 additions & 1 deletion test/pyqrack/test_target.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,29 @@ def multiple_registers():
assert True


test_target_glob()
def test_measurement():

@qasm2.main
def measure_register():
q = qasm2.qreg(2)
c = qasm2.creg(2)
qasm2.x(q[0])
qasm2.cx(q[0], q[1])
qasm2.measure(q, c)
return c

@qasm2.main
def measure_single_qubits():
q = qasm2.qreg(2)
c = qasm2.creg(2)
qasm2.x(q[0])
qasm2.cx(q[0], q[1])
qasm2.measure(q[0], c[0])
qasm2.measure(q[1], c[1])
return c

target = PyQrack(2)
result_single = target.run(measure_single_qubits)
result_reg = target.run(measure_register)

assert result_single == result_reg == [reg.Measurement.One, reg.Measurement.One]