-
Notifications
You must be signed in to change notification settings - Fork 1
Implement pyqrack interpreter methods for squin dialect #207
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
Conversation
☂️ Python Coverage
Overall Coverage
New Files
Modified Files
|
Codecov ReportAttention: Patch coverage is
📢 Thoughts on this report? Let us know! |
9d2b332
to
19c95dc
Compare
So, the implementation here is somewhat complete. However, I'm still struggling with the wire dialect. @weinbe58 @johnzl-777 how do you even create a @squin.wired
def main():
q = squin.qubit.new(1)
w = squin.wire.unwrap(q[0])
x = squin.op.x()
squin.wire.apply(x, w)
return w But, of course, |
e6d79f4
to
0cf3d39
Compare
@david-pl I can handle the measurement stuff later on thanks you! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have some suggestions mostly for the runtime.
src/bloqade/pyqrack/squin/runtime.py
Outdated
def broadcast_apply(self, qubits: ilist.IList[PyQrackQubit, Any], **kwargs) -> None: | ||
for qbit in qubits: | ||
if not qbit.is_active(): | ||
continue | ||
|
||
self.apply(qbit, **kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the operator accepts two qubits? you should batch the qubits based on the operator size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean something like broadcast(CX, ...)
? How would the wrapper for this look, i.e. what's the second argument to broadcast(CX, ...)
? Not sure about the syntax here.
src/bloqade/pyqrack/squin/runtime.py
Outdated
def apply(self, *qubits: PyQrackQubit, adjoint: bool = False) -> None: | ||
self.op.apply(*qubits, adjoint=adjoint) | ||
|
||
target = qubits[-1] | ||
|
||
# NOTE: just factor * eye(2) | ||
m = self.mat(adjoint) | ||
|
||
# TODO: output seems to always be normalized -- no-op? | ||
target.sim_reg.mtrx(m, target.addr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if this is true we might want to error instead of allowing things to run. If we want to do something like rot(scale * op)
we can rewrite this to a standard rotation statement.
cc: @Roger-luo
src/bloqade/squin/op/__init__.py
Outdated
@_wraps(stmts.Mult) | ||
def mult(lhs: types.Op, rhs: types.Op) -> types.Op: ... | ||
|
||
|
||
@_wraps(stmts.Scale) | ||
def scale(op: types.Op, factor: complex) -> types.Op: ... | ||
|
||
|
||
@_wraps(stmts.Adjoint) | ||
def adjoint(op: types.Op, *, is_unitary: bool = False) -> types.Op: ... | ||
def adjoint(op: types.Op) -> types.Op: ... | ||
|
||
|
||
@_wraps(stmts.Control) | ||
def control(op: types.Op, *, n_controls: int, is_unitary: bool = False) -> types.Op: ... | ||
def control(op: types.Op, *, n_controls: int) -> types.Op: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove wrappers later when syntax sugar is implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just out of curiosity: why? What's the hurt in keeping the wrapper?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what syntax sugar are we proposing here for control?
w: PyQrackWire = frame.get(stmt.wire) | ||
qbit = w.qubit | ||
res: int = qbit.sim_reg.m(qbit.addr) | ||
qbit.sim_reg.force_m(qbit.addr, False) | ||
new_w = PyQrackWire(qbit) | ||
return (new_w, res) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to make sure this will work in general. I know using force_m
can create some issues. Lets leave it for now but I will revisit how to properly reset a qubit with pyqrack.
Co-authored-by: Phillip Weinberg <[email protected]>
Co-authored-by: Phillip Weinberg <[email protected]>
Since this PR is getting kind of long, I'm gonna summarize some of the discussions again here. For the most part, I think there was a bit of confusion as I originally only considered a single target for controlled gates and broadcast (which was wrong). That has been fixed. Here's an overview of the semantics we discussed in some comments and how I chose to implement them for now:
Pinging @cduck , @Roger-luo and @weinbe58 here. Do you all agree with this? Also, ready for another round of review from my side! |
Yes, I agree, I think these are good summarize of the semantics, worth putting them in the docstring of the wrappers later. just to be pedantic here
we should call it |
src/bloqade/pyqrack/squin/qubit.py
Outdated
@interp.impl(qubit.MeasureAny) | ||
def measure_any( | ||
self, interp: PyQrackInterpreter, frame: interp.Frame, stmt: qubit.MeasureAny | ||
): | ||
input = frame.get(stmt.input) | ||
|
||
if isinstance(input, PyQrackQubit) and input.is_active(): | ||
result = self._measure_qubit | ||
elif isinstance(input, ilist.IList): | ||
result = [] | ||
for qbit in input: | ||
if not isinstance(qbit, PyQrackQubit): | ||
raise InterpreterError(f"Cannot measure {type(qbit).__name__}") | ||
|
||
result.append(self._measure_qubit(qbit)) | ||
else: | ||
raise InterpreterError(f"Cannot measure {type(input).__name__}") | ||
|
||
return (result,) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This statement is only for syntax sugar not for runtime. can you remove this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, if we run into any issues we can polish them later.
Seemed sufficiently different from #207, so I created a new branch for it. @Roger-luo two things: * I'm not sure whether this should be a `Fixpoint`. * Should this also be part of the `wire` kernel? --------- Co-authored-by: Phillip Weinberg <[email protected]>
Closes #185