Skip to content

Commit 40aa413

Browse files
committed
Implement methods for qubit statements
1 parent 1590ba2 commit 40aa413

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

src/bloqade/pyqrack/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@
1414
# NOTE: The following import is for registering the method tables
1515
from .noise import native as native
1616
from .qasm2 import uop as uop, core as core, glob as glob, parallel as parallel
17+
from .squin import qubit as qubit
1718
from .target import PyQrack as PyQrack

src/bloqade/pyqrack/squin/qubit.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from typing import Any
2+
3+
from kirin import interp
4+
from kirin.dialects import ilist
5+
6+
from bloqade.squin import qubit
7+
from bloqade.pyqrack.reg import QubitState, PyQrackQubit
8+
from bloqade.pyqrack.base import PyQrackInterpreter
9+
10+
11+
@qubit.dialect.register(key="pyqrack")
12+
class PyQrackMethods(interp.MethodTable):
13+
@interp.impl(qubit.New)
14+
def new(self, interp: PyQrackInterpreter, frame: interp.Frame, stmt: qubit.New):
15+
n_qubits: int = frame.get(stmt.n_qubits)
16+
qreg = ilist.IList(
17+
[
18+
PyQrackQubit(i, interp.memory.sim_reg, QubitState.Active)
19+
for i in interp.memory.allocate(n_qubits=n_qubits)
20+
]
21+
)
22+
return (qreg,)
23+
24+
@interp.impl(qubit.Apply)
25+
def apply(self, interp: PyQrackInterpreter, frame: interp.Frame, stmt: qubit.Apply):
26+
# TODO
27+
# operator: ir.SSAValue = info.argument(OpType)
28+
# qubits: ir.SSAValue = info.argument(ilist.IListType[QubitType])
29+
pass
30+
31+
@interp.impl(qubit.Measure)
32+
def measure(
33+
self, interp: PyQrackInterpreter, frame: interp.Frame, stmt: qubit.Measure
34+
):
35+
qubits: ilist.IList[PyQrackQubit, Any] = frame.get(stmt.qubits)
36+
result = [qbit.sim_reg.m(qbit.addr) for qbit in qubits]
37+
return (result,)
38+
39+
@interp.impl(qubit.MeasureAndReset)
40+
def measure_and_reset(
41+
self,
42+
interp: PyQrackInterpreter,
43+
frame: interp.Frame,
44+
stmt: qubit.MeasureAndReset,
45+
):
46+
qubits: ilist.IList[PyQrackQubit, Any] = frame.get(stmt.qubits)
47+
result = [qbit.sim_reg.m(qbit.addr) for qbit in qubits]
48+
for qbit in qubits:
49+
qbit.sim_reg.force_m(qbit.addr, 0)
50+
51+
return (result,)
52+
53+
@interp.impl(qubit.Reset)
54+
def reset(self, interp: PyQrackInterpreter, frame: interp.Frame, stmt: qubit.Reset):
55+
qubits: ilist.IList[PyQrackQubit, Any] = frame.get(stmt.qubits)
56+
for qbit in qubits:
57+
qbit.sim_reg.force_m(qbit.addr, 0)
58+
59+
# @interp.impl(glob.UGate)
60+
# def ugate(self, interp: PyQrackInterpreter, frame: interp.Frame, stmt: glob.UGate):
61+
# registers: ilist.IList[ilist.IList[PyQrackQubit, Any], Any] = frame.get(
62+
# stmt.registers
63+
# )
64+
# theta, phi, lam = (
65+
# frame.get(stmt.theta),
66+
# frame.get(stmt.phi),
67+
# frame.get(stmt.lam),
68+
# )
69+
70+
# for qreg in registers:
71+
# for qarg in qreg:
72+
# if qarg.is_active():
73+
# interp.memory.sim_reg.u(qarg.addr, theta, phi, lam)
74+
# return ()

test/pyqrack/test_squin.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
from kirin.dialects import ilist
2+
3+
from bloqade import squin
4+
from bloqade.pyqrack import PyQrack, PyQrackQubit
5+
6+
7+
def test_qubit():
8+
@squin.kernel
9+
def new():
10+
return squin.qubit.new(3)
11+
12+
new.print()
13+
14+
target = PyQrack(3)
15+
result = target.run(new)
16+
assert isinstance(result, ilist.IList)
17+
assert isinstance(qubit := result[0], PyQrackQubit)
18+
19+
out = qubit.sim_reg.out_ket()
20+
assert out == [1.0] + [0.0] * (2**3 - 1)
21+
22+
@squin.kernel
23+
def measure():
24+
q = squin.qubit.new(3)
25+
m = squin.qubit.measure(q)
26+
squin.qubit.reset(q)
27+
return m
28+
29+
target = PyQrack(3)
30+
result = target.run(measure)
31+
assert isinstance(result, list)
32+
assert result == [0, 0, 0]
33+
34+
@squin.kernel
35+
def measure_and_reset():
36+
q = squin.qubit.new(3)
37+
m = squin.qubit.measure_and_reset(q)
38+
return m
39+
40+
target = PyQrack(3)
41+
result = target.run(measure_and_reset)
42+
assert isinstance(result, list)
43+
assert result == [0, 0, 0]
44+
45+
46+
# @squin.kernel
47+
# def main():
48+
# q = squin.qubit.new(3)
49+
# x = squin.op.x()
50+
# id = squin.op.identity(sites=2)
51+
52+
# # FIXME? Should we have a method apply(x, q, idx)?
53+
# squin.qubit.apply(squin.op.kron(x, id), q)
54+
55+
# return squin.qubit.measure(q)
56+
57+
58+
# main.print()
59+
60+
# target = PyQrack(2)
61+
# result = target.run(main)
62+
63+
64+
if __name__ == "main":
65+
test_qubit()

0 commit comments

Comments
 (0)