-
Notifications
You must be signed in to change notification settings - Fork 1
QASM2 to squin #644
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
base: main
Are you sure you want to change the base?
QASM2 to squin #644
Changes from 1 commit
2f6e8a1
90d8578
509b9cc
006be62
1fa9865
6552782
d4f46bb
6b9e52f
cd53e5d
59dfcb0
99e66af
045fa00
5137de0
6390a23
0645d11
df35694
3468702
5f137de
aea7567
8e6e7e8
5ddc01d
b2cc014
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,9 @@ | ||
| from .uop_to_squin import QASM2UOPToSquin as QASM2UOPToSquin | ||
| from .id_to_squin import QASM2IdToSquin as QASM2IdToSquin | ||
| from .core_to_squin import QASM2CoreToSquin as QASM2CoreToSquin | ||
| from .noise_to_squin import QASM2NoiseToSquin as QASM2NoiseToSquin | ||
| from .uop_1q_to_squin import QASM2UOp1QToSquin as QASM2UOp1QToSquin | ||
| from .uop_2q_to_squin import QASM2UOp2QToSquin as QASM2UOp2QToSquin | ||
| from .glob_parallel_to_squin import QASM2GlobParallelToSquin as QASM2GlobParallelToSquin | ||
| from .parametrized_uop_1q_to_squin import ( | ||
| QASM2ParametrizedUOp1QToSquin as QASM2ParametrizedUOp1QToSquin, | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,47 +5,30 @@ | |
| from bloqade import squin | ||
| from bloqade.qasm2.dialects import glob, parallel | ||
|
|
||
| GLOBAL_PARALLEL_TO_SQUIN_MAP = { | ||
| glob.UGate: squin.broadcast.u3, | ||
| parallel.UGate: squin.broadcast.u3, | ||
| parallel.RZ: squin.broadcast.rz, | ||
| } | ||
|
|
||
|
|
||
| class QASM2GlobParallelToSquin(RewriteRule): | ||
|
|
||
| def rewrite_Statement(self, node: ir.Statement) -> RewriteResult: | ||
|
|
||
| match node: | ||
| case glob.UGate() | parallel.UGate() | parallel.RZ(): | ||
| return self.rewrite_1q_gates(node) | ||
| case _: | ||
| return RewriteResult() | ||
|
|
||
| return RewriteResult(has_done_something=True) | ||
|
|
||
| def rewrite_1q_gates( | ||
| self, stmt: glob.UGate | parallel.UGate | parallel.RZ | ||
| ) -> RewriteResult: | ||
|
|
||
| match stmt: | ||
| case glob.UGate(theta=theta, phi=phi, lam=lam) | parallel.UGate( | ||
| theta=theta, phi=phi, lam=lam | ||
| ): | ||
| # ever so slight naming difference, | ||
| # exists because intended semantics are different | ||
| match stmt: | ||
| case glob.UGate(): | ||
| qargs = stmt.registers | ||
| case parallel.UGate(): | ||
| qargs = stmt.qargs | ||
|
|
||
| invoke_u_broadcast_stmt = func.Invoke( | ||
| callee=squin.broadcast.u3, | ||
| inputs=(theta, phi, lam, qargs), | ||
| ) | ||
| stmt.replace_by(invoke_u_broadcast_stmt) | ||
| case parallel.RZ(theta=theta, qargs=qargs): | ||
| invoke_rz_broadcast_stmt = func.Invoke( | ||
| callee=squin.broadcast.rz, | ||
| inputs=(theta, qargs), | ||
| ) | ||
| stmt.replace_by(invoke_rz_broadcast_stmt) | ||
| case _: | ||
| return RewriteResult() | ||
|
|
||
| if isinstance(node, glob.UGate): | ||
|
||
| args = (node.theta, node.phi, node.lam, node.registers) | ||
| elif isinstance(node, parallel.UGate): | ||
| args = (node.theta, node.phi, node.lam, node.qargs) | ||
| elif isinstance(node, parallel.RZ): | ||
| args = (node.theta, node.qargs) | ||
| else: | ||
| return RewriteResult() | ||
|
|
||
| squin_equivalent_stmt = GLOBAL_PARALLEL_TO_SQUIN_MAP[type(node)] | ||
| invoke_stmt = func.Invoke( | ||
| callee=squin_equivalent_stmt, | ||
| inputs=args, | ||
| ) | ||
| node.replace_by(invoke_stmt) | ||
| return RewriteResult(has_done_something=True) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| from kirin import ir | ||
| from kirin.rewrite.abc import RewriteRule, RewriteResult | ||
|
|
||
| import bloqade.qasm2.dialects.uop.stmts as uop_stmts | ||
|
|
||
|
|
||
| class QASM2IdToSquin(RewriteRule): | ||
|
|
||
| def rewrite_Statement(self, node: ir.Statement) -> RewriteResult: | ||
|
|
||
| if not isinstance(node, uop_stmts.Id): | ||
| return RewriteResult() | ||
|
|
||
| node.delete() | ||
| return RewriteResult(has_done_something=True) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,67 +1,43 @@ | ||
| from kirin import ir | ||
| from kirin.dialects import py, func | ||
| from kirin.dialects import func | ||
| from kirin.rewrite.abc import RewriteRule, RewriteResult | ||
|
|
||
| from bloqade import squin | ||
| from bloqade.qasm2.dialects.noise import stmts as noise_stmts | ||
|
|
||
| from .util import num_to_py_constant | ||
johnzl-777 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| class QASM2NoiseToSquin(RewriteRule): | ||
|
|
||
| def rewrite_Statement(self, node: ir.Statement) -> RewriteResult: | ||
|
|
||
| match node: | ||
| case noise_stmts.AtomLossChannel(): | ||
| return self.rewrite_AtomLossChannel(node) | ||
| case noise_stmts.PauliChannel(): | ||
| return self.rewrite_PauliChannel(node) | ||
| case noise_stmts.CZPauliChannel(): | ||
| return self.rewrite_CZPauliChannel(node) | ||
| case _: | ||
| return RewriteResult() | ||
|
|
||
| return RewriteResult() | ||
| NOISE_TO_SQUIN_MAP = { | ||
| noise_stmts.AtomLossChannel: squin.broadcast.qubit_loss, | ||
| noise_stmts.PauliChannel: squin.broadcast.single_qubit_pauli_channel, | ||
| } | ||
|
|
||
| def rewrite_AtomLossChannel( | ||
| self, stmt: noise_stmts.AtomLossChannel | ||
| ) -> RewriteResult: | ||
|
|
||
| qargs = stmt.qargs | ||
| # this is a raw float, not in SSA form yet! | ||
| prob = stmt.prob | ||
| prob_stmt = py.Constant(value=prob) | ||
| prob_stmt.insert_before(stmt) | ||
|
|
||
| invoke_loss_stmt = func.Invoke( | ||
| callee=squin.broadcast.qubit_loss, | ||
| inputs=(prob_stmt.result, qargs), | ||
| ) | ||
|
|
||
| stmt.replace_by(invoke_loss_stmt) | ||
|
|
||
| return RewriteResult(has_done_something=True) | ||
|
|
||
| def rewrite_PauliChannel(self, stmt: noise_stmts.PauliChannel) -> RewriteResult: | ||
|
|
||
| qargs = stmt.qargs | ||
| p_x = stmt.px | ||
| p_y = stmt.py | ||
| p_z = stmt.pz | ||
|
|
||
| probs = [p_x, p_y, p_z] | ||
| probs_ssas = [] | ||
| class QASM2NoiseToSquin(RewriteRule): | ||
|
|
||
| for prob in probs: | ||
| prob_stmt = py.Constant(value=prob) | ||
| prob_stmt.insert_before(stmt) | ||
| probs_ssas.append(prob_stmt.result) | ||
| def rewrite_Statement(self, node: ir.Statement) -> RewriteResult: | ||
|
|
||
| invoke_pauli_channel_stmt = func.Invoke( | ||
| callee=squin.broadcast.single_qubit_pauli_channel, | ||
| inputs=(*probs_ssas, qargs), | ||
| if isinstance(node, noise_stmts.AtomLossChannel): | ||
| qargs = node.qargs | ||
| prob = node.prob | ||
| prob_ssas = num_to_py_constant([prob], stmt_to_insert_before=node) | ||
| elif isinstance(node, noise_stmts.PauliChannel): | ||
| qargs = node.qargs | ||
| p_x = node.px | ||
| p_y = node.py | ||
| p_z = node.pz | ||
| prob_ssas = num_to_py_constant([p_x, p_y, p_z], stmt_to_insert_before=node) | ||
| elif isinstance(node, noise_stmts.CZPauliChannel): | ||
| return self.rewrite_CZPauliChannel(node) | ||
| else: | ||
| return RewriteResult() | ||
|
|
||
| squin_noise_stmt = NOISE_TO_SQUIN_MAP[type(node)] | ||
| invoke_stmt = func.Invoke( | ||
|
Collaborator
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. If you know that you are going for the broadcast version, why not just rewrite to the statement directly instead of adding an invoke to the stdlib?
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. see the comment above |
||
| callee=squin_noise_stmt, | ||
| inputs=(*prob_ssas, qargs), | ||
| ) | ||
|
|
||
| stmt.replace_by(invoke_pauli_channel_stmt) | ||
| node.replace_by(invoke_stmt) | ||
| return RewriteResult(has_done_something=True) | ||
|
|
||
| def rewrite_CZPauliChannel(self, stmt: noise_stmts.CZPauliChannel) -> RewriteResult: | ||
|
|
@@ -78,11 +54,8 @@ def rewrite_CZPauliChannel(self, stmt: noise_stmts.CZPauliChannel) -> RewriteRes | |
|
|
||
| error_probs = [px_ctrl, py_ctrl, pz_ctrl, px_qarg, py_qarg, pz_qarg] | ||
| # first half of entries for control qubits, other half for targets | ||
| error_prob_ssas = [] | ||
| for error_prob in error_probs: | ||
| error_prob_stmt = py.Constant(value=error_prob) | ||
| error_prob_stmt.insert_before(stmt) | ||
| error_prob_ssas.append(error_prob_stmt.result) | ||
|
|
||
| error_prob_ssas = num_to_py_constant(error_probs, stmt_to_insert_before=stmt) | ||
|
|
||
| ctrl_pauli_channel_invoke = func.Invoke( | ||
| callee=squin.broadcast.single_qubit_pauli_channel, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| from math import pi | ||
|
|
||
| from kirin import ir | ||
| from kirin.dialects import py, func | ||
| from kirin.rewrite.abc import RewriteRule, RewriteResult | ||
|
|
||
| from bloqade import squin | ||
| from bloqade.qasm2.dialects.uop import stmts as uop_stmts | ||
|
|
||
| PARAMETRIZED_1Q_GATES_TO_SQUIN_MAP = { | ||
| uop_stmts.UGate: squin.u3, | ||
| uop_stmts.U1: squin.u3, | ||
| uop_stmts.U2: squin.u3, | ||
| uop_stmts.RZ: squin.rz, | ||
| uop_stmts.RX: squin.rx, | ||
| uop_stmts.RY: squin.ry, | ||
| } | ||
|
|
||
|
|
||
| class QASM2ParametrizedUOp1QToSquin(RewriteRule): | ||
|
|
||
| def rewrite_Statement(self, node: ir.Statement) -> RewriteResult: | ||
|
|
||
| if isinstance(node, (uop_stmts.RX, uop_stmts.RY, uop_stmts.RZ)): | ||
| args = (node.theta, node.qarg) | ||
| elif isinstance(node, (uop_stmts.UGate)): | ||
| args = (node.theta, node.phi, node.lam, node.qarg) | ||
| elif isinstance(node, (uop_stmts.U1)): | ||
| zero_stmt = py.Constant(value=0.0) | ||
| zero_stmt.insert_before(node) | ||
| args = (zero_stmt.result, zero_stmt.result, node.lam, node.qarg) | ||
| elif isinstance(node, (uop_stmts.U2)): | ||
| half_pi_stmt = py.Constant(value=pi / 2) | ||
| half_pi_stmt.insert_before(node) | ||
| args = (half_pi_stmt.result, node.phi, node.lam, node.qarg) | ||
| else: | ||
| return RewriteResult() | ||
johnzl-777 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| squin_equivalent_stmt = PARAMETRIZED_1Q_GATES_TO_SQUIN_MAP[type(node)] | ||
| invoke_stmt = func.Invoke( | ||
| callee=squin_equivalent_stmt, | ||
| inputs=args, | ||
| ) | ||
| node.replace_by(invoke_stmt) | ||
|
|
||
| return RewriteResult(has_done_something=True) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| from kirin import ir | ||
| from kirin.dialects import func | ||
| from kirin.rewrite.abc import RewriteRule, RewriteResult | ||
|
|
||
| from bloqade import squin | ||
| from bloqade.qasm2.dialects.uop import stmts as uop_stmts | ||
|
|
||
| ONE_Q_GATES_TO_SQUIN_MAP = { | ||
| uop_stmts.X: squin.x, | ||
| uop_stmts.Y: squin.y, | ||
| uop_stmts.Z: squin.z, | ||
| uop_stmts.H: squin.h, | ||
| uop_stmts.S: squin.s, | ||
| uop_stmts.T: squin.t, | ||
| uop_stmts.SX: squin.sqrt_x, | ||
| } | ||
|
|
||
|
|
||
| class QASM2UOp1QToSquin(RewriteRule): | ||
|
|
||
| def rewrite_Statement(self, node: ir.Statement) -> RewriteResult: | ||
|
|
||
| squin_1q_gate = ONE_Q_GATES_TO_SQUIN_MAP.get(type(node)) | ||
| if squin_1q_gate is None: | ||
| return RewriteResult() | ||
|
|
||
| invoke_stmt = func.Invoke( | ||
| callee=squin_1q_gate, | ||
| inputs=(node.qarg,), | ||
| ) | ||
| node.replace_by(invoke_stmt) | ||
|
|
||
| return RewriteResult(has_done_something=True) |
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 feel like you could just do this within the
ifabove, since theargshave to match the node type anyway.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.
something like