bloqade-circuit 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bloqade-circuit might be problematic. Click here for more details.
- bloqade/analysis/__init__.py +0 -0
- bloqade/analysis/address/__init__.py +11 -0
- bloqade/analysis/address/analysis.py +60 -0
- bloqade/analysis/address/impls.py +228 -0
- bloqade/analysis/address/lattice.py +85 -0
- bloqade/noise/__init__.py +1 -0
- bloqade/noise/native/__init__.py +20 -0
- bloqade/noise/native/_dialect.py +3 -0
- bloqade/noise/native/_wrappers.py +34 -0
- bloqade/noise/native/model.py +347 -0
- bloqade/noise/native/rewrite.py +35 -0
- bloqade/noise/native/stmts.py +46 -0
- bloqade/pyqrack/__init__.py +18 -0
- bloqade/pyqrack/base.py +131 -0
- bloqade/pyqrack/noise/__init__.py +0 -0
- bloqade/pyqrack/noise/native.py +100 -0
- bloqade/pyqrack/qasm2/__init__.py +0 -0
- bloqade/pyqrack/qasm2/core.py +79 -0
- bloqade/pyqrack/qasm2/parallel.py +46 -0
- bloqade/pyqrack/qasm2/uop.py +247 -0
- bloqade/pyqrack/reg.py +109 -0
- bloqade/pyqrack/target.py +112 -0
- bloqade/qasm2/__init__.py +19 -0
- bloqade/qasm2/_wrappers.py +674 -0
- bloqade/qasm2/dialects/__init__.py +10 -0
- bloqade/qasm2/dialects/core/__init__.py +3 -0
- bloqade/qasm2/dialects/core/_dialect.py +3 -0
- bloqade/qasm2/dialects/core/_emit.py +68 -0
- bloqade/qasm2/dialects/core/_typeinfer.py +23 -0
- bloqade/qasm2/dialects/core/address.py +38 -0
- bloqade/qasm2/dialects/core/stmts.py +94 -0
- bloqade/qasm2/dialects/expr/__init__.py +3 -0
- bloqade/qasm2/dialects/expr/_dialect.py +3 -0
- bloqade/qasm2/dialects/expr/_emit.py +103 -0
- bloqade/qasm2/dialects/expr/_from_python.py +86 -0
- bloqade/qasm2/dialects/expr/_interp.py +75 -0
- bloqade/qasm2/dialects/expr/stmts.py +262 -0
- bloqade/qasm2/dialects/glob.py +45 -0
- bloqade/qasm2/dialects/indexing.py +64 -0
- bloqade/qasm2/dialects/inline.py +76 -0
- bloqade/qasm2/dialects/noise.py +16 -0
- bloqade/qasm2/dialects/parallel.py +110 -0
- bloqade/qasm2/dialects/uop/__init__.py +4 -0
- bloqade/qasm2/dialects/uop/_dialect.py +3 -0
- bloqade/qasm2/dialects/uop/_emit.py +211 -0
- bloqade/qasm2/dialects/uop/schedule.py +89 -0
- bloqade/qasm2/dialects/uop/stmts.py +325 -0
- bloqade/qasm2/emit/__init__.py +1 -0
- bloqade/qasm2/emit/base.py +72 -0
- bloqade/qasm2/emit/gate.py +102 -0
- bloqade/qasm2/emit/main.py +106 -0
- bloqade/qasm2/emit/target.py +165 -0
- bloqade/qasm2/glob.py +24 -0
- bloqade/qasm2/groups.py +120 -0
- bloqade/qasm2/parallel.py +48 -0
- bloqade/qasm2/parse/__init__.py +37 -0
- bloqade/qasm2/parse/ast.py +235 -0
- bloqade/qasm2/parse/build.py +289 -0
- bloqade/qasm2/parse/lowering.py +553 -0
- bloqade/qasm2/parse/parser.py +5 -0
- bloqade/qasm2/parse/print.py +293 -0
- bloqade/qasm2/parse/qasm2.lark +75 -0
- bloqade/qasm2/parse/visitor.py +16 -0
- bloqade/qasm2/parse/visitor.pyi +39 -0
- bloqade/qasm2/passes/__init__.py +5 -0
- bloqade/qasm2/passes/fold.py +94 -0
- bloqade/qasm2/passes/glob.py +119 -0
- bloqade/qasm2/passes/noise.py +61 -0
- bloqade/qasm2/passes/parallel.py +176 -0
- bloqade/qasm2/passes/py2qasm.py +63 -0
- bloqade/qasm2/passes/qasm2py.py +61 -0
- bloqade/qasm2/rewrite/__init__.py +12 -0
- bloqade/qasm2/rewrite/desugar.py +28 -0
- bloqade/qasm2/rewrite/glob.py +103 -0
- bloqade/qasm2/rewrite/heuristic_noise.py +247 -0
- bloqade/qasm2/rewrite/native_gates.py +447 -0
- bloqade/qasm2/rewrite/parallel_to_uop.py +83 -0
- bloqade/qasm2/rewrite/register.py +45 -0
- bloqade/qasm2/rewrite/uop_to_parallel.py +395 -0
- bloqade/qasm2/types.py +39 -0
- bloqade/qbraid/__init__.py +2 -0
- bloqade/qbraid/lowering.py +324 -0
- bloqade/qbraid/schema.py +252 -0
- bloqade/qbraid/simulation_result.py +99 -0
- bloqade/qbraid/target.py +86 -0
- bloqade/squin/__init__.py +2 -0
- bloqade/squin/analysis/__init__.py +0 -0
- bloqade/squin/analysis/nsites/__init__.py +8 -0
- bloqade/squin/analysis/nsites/analysis.py +52 -0
- bloqade/squin/analysis/nsites/impls.py +69 -0
- bloqade/squin/analysis/nsites/lattice.py +49 -0
- bloqade/squin/analysis/schedule.py +244 -0
- bloqade/squin/groups.py +38 -0
- bloqade/squin/op/__init__.py +132 -0
- bloqade/squin/op/_dialect.py +3 -0
- bloqade/squin/op/complex.py +6 -0
- bloqade/squin/op/stmts.py +220 -0
- bloqade/squin/op/traits.py +43 -0
- bloqade/squin/op/types.py +10 -0
- bloqade/squin/qubit.py +118 -0
- bloqade/squin/wire.py +103 -0
- bloqade/stim/__init__.py +6 -0
- bloqade/stim/_wrappers.py +186 -0
- bloqade/stim/dialects/__init__.py +5 -0
- bloqade/stim/dialects/aux/__init__.py +11 -0
- bloqade/stim/dialects/aux/_dialect.py +3 -0
- bloqade/stim/dialects/aux/emit.py +102 -0
- bloqade/stim/dialects/aux/interp.py +39 -0
- bloqade/stim/dialects/aux/lowering.py +40 -0
- bloqade/stim/dialects/aux/stmts/__init__.py +14 -0
- bloqade/stim/dialects/aux/stmts/annotate.py +47 -0
- bloqade/stim/dialects/aux/stmts/const.py +95 -0
- bloqade/stim/dialects/aux/types.py +19 -0
- bloqade/stim/dialects/collapse/__init__.py +3 -0
- bloqade/stim/dialects/collapse/_dialect.py +3 -0
- bloqade/stim/dialects/collapse/emit.py +68 -0
- bloqade/stim/dialects/collapse/stmts/__init__.py +3 -0
- bloqade/stim/dialects/collapse/stmts/measure.py +45 -0
- bloqade/stim/dialects/collapse/stmts/pp_measure.py +14 -0
- bloqade/stim/dialects/collapse/stmts/reset.py +26 -0
- bloqade/stim/dialects/gate/__init__.py +3 -0
- bloqade/stim/dialects/gate/_dialect.py +3 -0
- bloqade/stim/dialects/gate/emit.py +87 -0
- bloqade/stim/dialects/gate/stmts/__init__.py +14 -0
- bloqade/stim/dialects/gate/stmts/base.py +31 -0
- bloqade/stim/dialects/gate/stmts/clifford_1q.py +53 -0
- bloqade/stim/dialects/gate/stmts/clifford_2q.py +11 -0
- bloqade/stim/dialects/gate/stmts/control_2q.py +21 -0
- bloqade/stim/dialects/gate/stmts/pp.py +15 -0
- bloqade/stim/dialects/noise/__init__.py +3 -0
- bloqade/stim/dialects/noise/_dialect.py +3 -0
- bloqade/stim/dialects/noise/emit.py +66 -0
- bloqade/stim/dialects/noise/stmts.py +77 -0
- bloqade/stim/emit/__init__.py +1 -0
- bloqade/stim/emit/stim.py +54 -0
- bloqade/stim/groups.py +26 -0
- bloqade/test_utils.py +35 -0
- bloqade/types.py +24 -0
- bloqade/visual/__init__.py +1 -0
- bloqade/visual/animation/__init__.py +0 -0
- bloqade/visual/animation/animate.py +267 -0
- bloqade/visual/animation/base.py +346 -0
- bloqade/visual/animation/gate_event.py +24 -0
- bloqade/visual/animation/runtime/__init__.py +0 -0
- bloqade/visual/animation/runtime/aod.py +36 -0
- bloqade/visual/animation/runtime/atoms.py +55 -0
- bloqade/visual/animation/runtime/ppoly.py +50 -0
- bloqade/visual/animation/runtime/qpustate.py +119 -0
- bloqade/visual/animation/runtime/utils.py +43 -0
- bloqade_circuit-0.1.0.dist-info/METADATA +70 -0
- bloqade_circuit-0.1.0.dist-info/RECORD +153 -0
- bloqade_circuit-0.1.0.dist-info/WHEEL +4 -0
- bloqade_circuit-0.1.0.dist-info/licenses/LICENSE +234 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
from kirin import interp
|
|
2
|
+
|
|
3
|
+
from bloqade.qasm2.parse import ast
|
|
4
|
+
from bloqade.qasm2.emit.gate import EmitQASM2Gate, EmitQASM2Frame
|
|
5
|
+
|
|
6
|
+
from . import stmts
|
|
7
|
+
from ._dialect import dialect
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dialect.register(key="emit.qasm2.gate")
|
|
11
|
+
class UOp(interp.MethodTable):
|
|
12
|
+
|
|
13
|
+
@interp.impl(stmts.CX)
|
|
14
|
+
def emit_cx(
|
|
15
|
+
self,
|
|
16
|
+
emit: EmitQASM2Gate,
|
|
17
|
+
frame: EmitQASM2Frame,
|
|
18
|
+
stmt: stmts.CX,
|
|
19
|
+
):
|
|
20
|
+
ctrl = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.ctrl))
|
|
21
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
22
|
+
frame.body.append(ast.CXGate(ctrl=ctrl, qarg=qarg))
|
|
23
|
+
return ()
|
|
24
|
+
|
|
25
|
+
@interp.impl(stmts.UGate)
|
|
26
|
+
def emit_ugate(
|
|
27
|
+
self,
|
|
28
|
+
emit: EmitQASM2Gate,
|
|
29
|
+
frame: EmitQASM2Frame,
|
|
30
|
+
stmt: stmts.UGate,
|
|
31
|
+
):
|
|
32
|
+
theta = emit.assert_node(ast.Expr, frame.get(stmt.theta))
|
|
33
|
+
phi = emit.assert_node(ast.Expr, frame.get(stmt.phi))
|
|
34
|
+
lam = emit.assert_node(ast.Expr, frame.get(stmt.lam))
|
|
35
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
36
|
+
frame.body.append(ast.UGate(theta=theta, phi=phi, lam=lam, qarg=qarg))
|
|
37
|
+
return ()
|
|
38
|
+
|
|
39
|
+
@interp.impl(stmts.Barrier)
|
|
40
|
+
def emit_barrier(
|
|
41
|
+
self,
|
|
42
|
+
emit: EmitQASM2Gate,
|
|
43
|
+
frame: EmitQASM2Frame,
|
|
44
|
+
stmt: stmts.Barrier,
|
|
45
|
+
):
|
|
46
|
+
qargs = [
|
|
47
|
+
emit.assert_node((ast.Bit, ast.Name), frame.get(qarg))
|
|
48
|
+
for qarg in stmt.qargs
|
|
49
|
+
]
|
|
50
|
+
frame.body.append(ast.Barrier(qargs=qargs))
|
|
51
|
+
return ()
|
|
52
|
+
|
|
53
|
+
@interp.impl(stmts.SX)
|
|
54
|
+
@interp.impl(stmts.SXdag)
|
|
55
|
+
@interp.impl(stmts.Id)
|
|
56
|
+
@interp.impl(stmts.H)
|
|
57
|
+
@interp.impl(stmts.X)
|
|
58
|
+
@interp.impl(stmts.Y)
|
|
59
|
+
@interp.impl(stmts.Z)
|
|
60
|
+
@interp.impl(stmts.S)
|
|
61
|
+
@interp.impl(stmts.Sdag)
|
|
62
|
+
@interp.impl(stmts.T)
|
|
63
|
+
@interp.impl(stmts.Tdag)
|
|
64
|
+
def emit_single_qubit_gate(
|
|
65
|
+
self, emit: EmitQASM2Gate, frame: EmitQASM2Frame, stmt: stmts.SingleQubitGate
|
|
66
|
+
):
|
|
67
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
68
|
+
frame.body.append(
|
|
69
|
+
ast.Instruction(name=ast.Name(stmt.name), params=[], qargs=[qarg])
|
|
70
|
+
)
|
|
71
|
+
return ()
|
|
72
|
+
|
|
73
|
+
@interp.impl(stmts.RX)
|
|
74
|
+
@interp.impl(stmts.RY)
|
|
75
|
+
@interp.impl(stmts.RZ)
|
|
76
|
+
def emit_rotation(
|
|
77
|
+
self,
|
|
78
|
+
emit: EmitQASM2Gate,
|
|
79
|
+
frame: EmitQASM2Frame,
|
|
80
|
+
stmt: stmts.RX | stmts.RY | stmts.RZ,
|
|
81
|
+
):
|
|
82
|
+
theta = emit.assert_node(ast.Expr, frame.get(stmt.theta))
|
|
83
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
84
|
+
frame.body.append(
|
|
85
|
+
ast.Instruction(name=ast.Name(stmt.name), params=[theta], qargs=[qarg])
|
|
86
|
+
)
|
|
87
|
+
return ()
|
|
88
|
+
|
|
89
|
+
@interp.impl(stmts.U1)
|
|
90
|
+
def emit_u1(self, emit: EmitQASM2Gate, frame: EmitQASM2Frame, stmt: stmts.U1):
|
|
91
|
+
lam = emit.assert_node(ast.Expr, frame.get(stmt.lam))
|
|
92
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
93
|
+
frame.body.append(
|
|
94
|
+
ast.Instruction(name=ast.Name(stmt.name), params=[lam], qargs=[qarg])
|
|
95
|
+
)
|
|
96
|
+
return ()
|
|
97
|
+
|
|
98
|
+
@interp.impl(stmts.U2)
|
|
99
|
+
def emit_u2(self, emit: EmitQASM2Gate, frame: EmitQASM2Frame, stmt: stmts.U2):
|
|
100
|
+
phi = emit.assert_node(ast.Expr, frame.get(stmt.phi))
|
|
101
|
+
lam = emit.assert_node(ast.Expr, frame.get(stmt.lam))
|
|
102
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
103
|
+
frame.body.append(
|
|
104
|
+
ast.Instruction(name=ast.Name(stmt.name), params=[phi, lam], qargs=[qarg])
|
|
105
|
+
)
|
|
106
|
+
return ()
|
|
107
|
+
|
|
108
|
+
@interp.impl(stmts.Swap)
|
|
109
|
+
@interp.impl(stmts.CSX)
|
|
110
|
+
@interp.impl(stmts.CZ)
|
|
111
|
+
@interp.impl(stmts.CY)
|
|
112
|
+
@interp.impl(stmts.CH)
|
|
113
|
+
def emit_two_qubit_gate(
|
|
114
|
+
self, emit: EmitQASM2Gate, frame: EmitQASM2Frame, stmt: stmts.CZ
|
|
115
|
+
):
|
|
116
|
+
ctrl = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.ctrl))
|
|
117
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
118
|
+
frame.body.append(
|
|
119
|
+
ast.Instruction(name=ast.Name(stmt.name), params=[], qargs=[ctrl, qarg])
|
|
120
|
+
)
|
|
121
|
+
return ()
|
|
122
|
+
|
|
123
|
+
@interp.impl(stmts.CCX)
|
|
124
|
+
def emit_ccx(self, emit: EmitQASM2Gate, frame: EmitQASM2Frame, stmt: stmts.CCX):
|
|
125
|
+
ctrl1 = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.ctrl1))
|
|
126
|
+
ctrl2 = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.ctrl2))
|
|
127
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
128
|
+
frame.body.append(
|
|
129
|
+
ast.Instruction(
|
|
130
|
+
name=ast.Name(stmt.name), params=[], qargs=[ctrl1, ctrl2, qarg]
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
return ()
|
|
134
|
+
|
|
135
|
+
@interp.impl(stmts.CSwap)
|
|
136
|
+
def emit_cswap(self, emit: EmitQASM2Gate, frame: EmitQASM2Frame, stmt: stmts.CSwap):
|
|
137
|
+
ctrl = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.ctrl))
|
|
138
|
+
qarg1 = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg1))
|
|
139
|
+
qarg2 = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg2))
|
|
140
|
+
frame.body.append(
|
|
141
|
+
ast.Instruction(
|
|
142
|
+
name=ast.Name(stmt.name), params=[], qargs=[ctrl, qarg1, qarg2]
|
|
143
|
+
)
|
|
144
|
+
)
|
|
145
|
+
return ()
|
|
146
|
+
|
|
147
|
+
@interp.impl(stmts.CRZ)
|
|
148
|
+
@interp.impl(stmts.CRY)
|
|
149
|
+
@interp.impl(stmts.CRX)
|
|
150
|
+
def emit_cr(self, emit: EmitQASM2Gate, frame: EmitQASM2Frame, stmt: stmts.CRX):
|
|
151
|
+
lam = emit.assert_node(ast.Expr, frame.get(stmt.lam))
|
|
152
|
+
ctrl = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.ctrl))
|
|
153
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
154
|
+
frame.body.append(
|
|
155
|
+
ast.Instruction(name=ast.Name(stmt.name), params=[lam], qargs=[ctrl, qarg])
|
|
156
|
+
)
|
|
157
|
+
return ()
|
|
158
|
+
|
|
159
|
+
@interp.impl(stmts.CU1)
|
|
160
|
+
def emit_cu1(self, emit: EmitQASM2Gate, frame: EmitQASM2Frame, stmt: stmts.CU1):
|
|
161
|
+
lam = emit.assert_node(ast.Expr, frame.get(stmt.lam))
|
|
162
|
+
ctrl = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.ctrl))
|
|
163
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
164
|
+
frame.body.append(
|
|
165
|
+
ast.Instruction(name=ast.Name(stmt.name), params=[lam], qargs=[ctrl, qarg])
|
|
166
|
+
)
|
|
167
|
+
return ()
|
|
168
|
+
|
|
169
|
+
@interp.impl(stmts.CU3)
|
|
170
|
+
def emit_cu3(self, emit: EmitQASM2Gate, frame: EmitQASM2Frame, stmt: stmts.CU3):
|
|
171
|
+
theta = emit.assert_node(ast.Expr, frame.get(stmt.theta))
|
|
172
|
+
phi = emit.assert_node(ast.Expr, frame.get(stmt.phi))
|
|
173
|
+
lam = emit.assert_node(ast.Expr, frame.get(stmt.lam))
|
|
174
|
+
ctrl = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.ctrl))
|
|
175
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
176
|
+
frame.body.append(
|
|
177
|
+
ast.Instruction(
|
|
178
|
+
name=ast.Name(stmt.name), params=[theta, phi, lam], qargs=[ctrl, qarg]
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
return ()
|
|
182
|
+
|
|
183
|
+
@interp.impl(stmts.CU)
|
|
184
|
+
def emit_cu(self, emit: EmitQASM2Gate, frame: EmitQASM2Frame, stmt: stmts.CU):
|
|
185
|
+
theta = emit.assert_node(ast.Expr, frame.get(stmt.theta))
|
|
186
|
+
phi = emit.assert_node(ast.Expr, frame.get(stmt.phi))
|
|
187
|
+
lam = emit.assert_node(ast.Expr, frame.get(stmt.lam))
|
|
188
|
+
gamma = emit.assert_node(ast.Expr, frame.get(stmt.gamma))
|
|
189
|
+
ctrl = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.ctrl))
|
|
190
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
191
|
+
frame.body.append(
|
|
192
|
+
ast.Instruction(
|
|
193
|
+
name=ast.Name(stmt.name),
|
|
194
|
+
params=[theta, phi, lam, gamma],
|
|
195
|
+
qargs=[ctrl, qarg],
|
|
196
|
+
)
|
|
197
|
+
)
|
|
198
|
+
return ()
|
|
199
|
+
|
|
200
|
+
@interp.impl(stmts.RZZ)
|
|
201
|
+
@interp.impl(stmts.RXX)
|
|
202
|
+
def emit_r2q(self, emit: EmitQASM2Gate, frame: EmitQASM2Frame, stmt: stmts.RZZ):
|
|
203
|
+
theta = emit.assert_node(ast.Expr, frame.get(stmt.theta))
|
|
204
|
+
ctrl = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.ctrl))
|
|
205
|
+
qarg = emit.assert_node((ast.Bit, ast.Name), frame.get(stmt.qarg))
|
|
206
|
+
frame.body.append(
|
|
207
|
+
ast.Instruction(
|
|
208
|
+
name=ast.Name(stmt.name), params=[theta], qargs=[ctrl, qarg]
|
|
209
|
+
)
|
|
210
|
+
)
|
|
211
|
+
return ()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
from kirin import interp
|
|
2
|
+
from kirin.analysis import ForwardFrame
|
|
3
|
+
|
|
4
|
+
from bloqade.squin.analysis.schedule import DagScheduleAnalysis
|
|
5
|
+
|
|
6
|
+
from . import stmts
|
|
7
|
+
from ._dialect import dialect
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dialect.register(key="qasm2.schedule.dag")
|
|
11
|
+
class UOp(interp.MethodTable):
|
|
12
|
+
|
|
13
|
+
@interp.impl(stmts.Id)
|
|
14
|
+
@interp.impl(stmts.SXdag)
|
|
15
|
+
@interp.impl(stmts.SX)
|
|
16
|
+
@interp.impl(stmts.X)
|
|
17
|
+
@interp.impl(stmts.Y)
|
|
18
|
+
@interp.impl(stmts.Z)
|
|
19
|
+
@interp.impl(stmts.H)
|
|
20
|
+
@interp.impl(stmts.S)
|
|
21
|
+
@interp.impl(stmts.Sdag)
|
|
22
|
+
@interp.impl(stmts.T)
|
|
23
|
+
@interp.impl(stmts.Tdag)
|
|
24
|
+
@interp.impl(stmts.RX)
|
|
25
|
+
@interp.impl(stmts.RY)
|
|
26
|
+
@interp.impl(stmts.RZ)
|
|
27
|
+
@interp.impl(stmts.U1)
|
|
28
|
+
@interp.impl(stmts.U2)
|
|
29
|
+
@interp.impl(stmts.UGate)
|
|
30
|
+
def single_qubit_gate(
|
|
31
|
+
self,
|
|
32
|
+
interp: DagScheduleAnalysis,
|
|
33
|
+
frame: ForwardFrame,
|
|
34
|
+
stmt: stmts.SingleQubitGate,
|
|
35
|
+
):
|
|
36
|
+
interp.update_dag(stmt, [stmt.qarg])
|
|
37
|
+
return ()
|
|
38
|
+
|
|
39
|
+
@interp.impl(stmts.RXX)
|
|
40
|
+
@interp.impl(stmts.RZZ)
|
|
41
|
+
@interp.impl(stmts.CX)
|
|
42
|
+
@interp.impl(stmts.CY)
|
|
43
|
+
@interp.impl(stmts.CZ)
|
|
44
|
+
@interp.impl(stmts.CH)
|
|
45
|
+
@interp.impl(stmts.CRZ)
|
|
46
|
+
@interp.impl(stmts.CRY)
|
|
47
|
+
@interp.impl(stmts.CRX)
|
|
48
|
+
@interp.impl(stmts.CU1)
|
|
49
|
+
@interp.impl(stmts.CU3)
|
|
50
|
+
@interp.impl(stmts.CU)
|
|
51
|
+
@interp.impl(stmts.CSX)
|
|
52
|
+
def two_qubit_ctrl_gate(
|
|
53
|
+
self,
|
|
54
|
+
interp: DagScheduleAnalysis,
|
|
55
|
+
frame: ForwardFrame,
|
|
56
|
+
stmt: stmts.TwoQubitCtrlGate,
|
|
57
|
+
):
|
|
58
|
+
interp.update_dag(stmt, [stmt.ctrl, stmt.qarg])
|
|
59
|
+
return ()
|
|
60
|
+
|
|
61
|
+
@interp.impl(stmts.CCX)
|
|
62
|
+
def ccx_gate(
|
|
63
|
+
self,
|
|
64
|
+
interp: DagScheduleAnalysis,
|
|
65
|
+
frame: ForwardFrame,
|
|
66
|
+
stmt: stmts.CCX,
|
|
67
|
+
):
|
|
68
|
+
interp.update_dag(stmt, [stmt.ctrl1, stmt.ctrl2, stmt.qarg])
|
|
69
|
+
return ()
|
|
70
|
+
|
|
71
|
+
@interp.impl(stmts.CSwap)
|
|
72
|
+
def cswap_gate(
|
|
73
|
+
self,
|
|
74
|
+
interp: DagScheduleAnalysis,
|
|
75
|
+
frame: ForwardFrame,
|
|
76
|
+
stmt: stmts.CSwap,
|
|
77
|
+
):
|
|
78
|
+
interp.update_dag(stmt, [stmt.ctrl, stmt.qarg1, stmt.qarg2])
|
|
79
|
+
return ()
|
|
80
|
+
|
|
81
|
+
@interp.impl(stmts.Barrier)
|
|
82
|
+
def barrier(
|
|
83
|
+
self,
|
|
84
|
+
interp: DagScheduleAnalysis,
|
|
85
|
+
frame: ForwardFrame,
|
|
86
|
+
stmt: stmts.Barrier,
|
|
87
|
+
):
|
|
88
|
+
interp.update_dag(stmt, stmt.qargs)
|
|
89
|
+
return ()
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
from kirin import ir, lowering
|
|
2
|
+
from kirin.decl import info, statement
|
|
3
|
+
|
|
4
|
+
from bloqade.qasm2.types import QubitType
|
|
5
|
+
from bloqade.qasm2.dialects.expr.stmts import PyNum
|
|
6
|
+
|
|
7
|
+
from ._dialect import dialect
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# trait
|
|
11
|
+
@statement
|
|
12
|
+
class SingleQubitGate(ir.Statement):
|
|
13
|
+
"""Base class for single qubit gates."""
|
|
14
|
+
|
|
15
|
+
traits = frozenset({lowering.FromPythonCall()})
|
|
16
|
+
qarg: ir.SSAValue = info.argument(QubitType)
|
|
17
|
+
"""qarg (Qubit): The qubit argument."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@statement
|
|
21
|
+
class TwoQubitCtrlGate(ir.Statement):
|
|
22
|
+
traits = frozenset({lowering.FromPythonCall()})
|
|
23
|
+
ctrl: ir.SSAValue = info.argument(QubitType)
|
|
24
|
+
"""ctrl (Qubit): The control qubit."""
|
|
25
|
+
qarg: ir.SSAValue = info.argument(QubitType)
|
|
26
|
+
"""qarg (Qubit): The target qubit."""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@statement(dialect=dialect)
|
|
30
|
+
class CX(TwoQubitCtrlGate):
|
|
31
|
+
"""Alias for the CNOT or CH gate operations."""
|
|
32
|
+
|
|
33
|
+
name = "CX" # Note this is capitalized
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@statement(dialect=dialect)
|
|
37
|
+
class UGate(SingleQubitGate):
|
|
38
|
+
"""Apply A general single qubit unitary gate."""
|
|
39
|
+
|
|
40
|
+
name = "U"
|
|
41
|
+
theta: ir.SSAValue = info.argument(PyNum)
|
|
42
|
+
"""theta (float): The theta parameter."""
|
|
43
|
+
phi: ir.SSAValue = info.argument(PyNum)
|
|
44
|
+
"""phi (float): The phi parameter."""
|
|
45
|
+
lam: ir.SSAValue = info.argument(PyNum)
|
|
46
|
+
"""lam (float): The lambda parameter."""
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@statement(dialect=dialect)
|
|
50
|
+
class Barrier(ir.Statement):
|
|
51
|
+
"""Apply the Barrier statement."""
|
|
52
|
+
|
|
53
|
+
name = "barrier"
|
|
54
|
+
traits = frozenset({lowering.FromPythonCall()})
|
|
55
|
+
qargs: tuple[ir.SSAValue, ...] = info.argument(QubitType)
|
|
56
|
+
"""qargs: tuple of qubits to apply the barrier to."""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
# qelib1.inc as statements
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@statement(dialect=dialect)
|
|
63
|
+
class Id(SingleQubitGate):
|
|
64
|
+
"""Apply the Identity gate."""
|
|
65
|
+
|
|
66
|
+
name = "id"
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@statement(dialect=dialect)
|
|
70
|
+
class H(SingleQubitGate):
|
|
71
|
+
"""Apply the Hadamard gate."""
|
|
72
|
+
|
|
73
|
+
name = "h"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@statement(dialect=dialect)
|
|
77
|
+
class X(SingleQubitGate):
|
|
78
|
+
"""Apply the X gate."""
|
|
79
|
+
|
|
80
|
+
name = "x"
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@statement(dialect=dialect)
|
|
84
|
+
class Y(SingleQubitGate):
|
|
85
|
+
"""Apply the Y gate."""
|
|
86
|
+
|
|
87
|
+
name = "y"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@statement(dialect=dialect)
|
|
91
|
+
class Z(SingleQubitGate):
|
|
92
|
+
"""Apply the Z gate."""
|
|
93
|
+
|
|
94
|
+
name = "z"
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@statement(dialect=dialect)
|
|
98
|
+
class S(SingleQubitGate):
|
|
99
|
+
"""Apply the S gate."""
|
|
100
|
+
|
|
101
|
+
name = "s"
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@statement(dialect=dialect)
|
|
105
|
+
class Sdag(SingleQubitGate):
|
|
106
|
+
"""Apply the hermitian conj of S gate."""
|
|
107
|
+
|
|
108
|
+
name = "sdg"
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@statement(dialect=dialect)
|
|
112
|
+
class SX(SingleQubitGate):
|
|
113
|
+
"""Apply the quantum Sqrt(X) gate."""
|
|
114
|
+
|
|
115
|
+
name = "sx"
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@statement(dialect=dialect)
|
|
119
|
+
class SXdag(SingleQubitGate):
|
|
120
|
+
"""Apply the dagger of quantum Sqrt(X) gate."""
|
|
121
|
+
|
|
122
|
+
name = "sxdg"
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@statement(dialect=dialect)
|
|
126
|
+
class T(SingleQubitGate):
|
|
127
|
+
"""Apply the T gate."""
|
|
128
|
+
|
|
129
|
+
name = "t"
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@statement(dialect=dialect)
|
|
133
|
+
class Tdag(SingleQubitGate):
|
|
134
|
+
"""Apply the hermitian conj of T gate."""
|
|
135
|
+
|
|
136
|
+
name = "tdg"
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@statement(dialect=dialect)
|
|
140
|
+
class RX(SingleQubitGate):
|
|
141
|
+
"""Apply the RX gate."""
|
|
142
|
+
|
|
143
|
+
name = "rx"
|
|
144
|
+
theta: ir.SSAValue = info.argument(PyNum)
|
|
145
|
+
"""theta (float): The angle of rotation around x axis."""
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@statement(dialect=dialect)
|
|
149
|
+
class RY(SingleQubitGate):
|
|
150
|
+
"""Apply the RY gate."""
|
|
151
|
+
|
|
152
|
+
name = "ry"
|
|
153
|
+
theta: ir.SSAValue = info.argument(PyNum)
|
|
154
|
+
"""theta (float): The angle of rotation around y axis."""
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@statement(dialect=dialect)
|
|
158
|
+
class RZ(SingleQubitGate):
|
|
159
|
+
"""Apply the RZ gate."""
|
|
160
|
+
|
|
161
|
+
name = "rz"
|
|
162
|
+
theta: ir.SSAValue = info.argument(PyNum)
|
|
163
|
+
"""theta (float): the angle of rotation around Z axis."""
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@statement(dialect=dialect)
|
|
167
|
+
class U1(SingleQubitGate):
|
|
168
|
+
"""Apply the U1 gate."""
|
|
169
|
+
|
|
170
|
+
name = "u1"
|
|
171
|
+
lam: ir.SSAValue = info.argument(PyNum)
|
|
172
|
+
"""lam (float): The lambda parameter."""
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
@statement(dialect=dialect)
|
|
176
|
+
class U2(SingleQubitGate):
|
|
177
|
+
"""Apply the U2 gate."""
|
|
178
|
+
|
|
179
|
+
name = "u2"
|
|
180
|
+
phi: ir.SSAValue = info.argument(PyNum)
|
|
181
|
+
"""phi (float): The phi parameter."""
|
|
182
|
+
lam: ir.SSAValue = info.argument(PyNum)
|
|
183
|
+
"""lam (float): The lambda parameter."""
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@statement(dialect=dialect)
|
|
187
|
+
class CZ(TwoQubitCtrlGate):
|
|
188
|
+
"""Apply the Controlled-Z gate."""
|
|
189
|
+
|
|
190
|
+
name = "cz"
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@statement(dialect=dialect)
|
|
194
|
+
class CY(TwoQubitCtrlGate):
|
|
195
|
+
"""Apply the Controlled-Y gate."""
|
|
196
|
+
|
|
197
|
+
name = "cy"
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@statement(dialect=dialect)
|
|
201
|
+
class CSX(TwoQubitCtrlGate):
|
|
202
|
+
"""Apply the Controlled-Sqrt(X) gate."""
|
|
203
|
+
|
|
204
|
+
name = "csx"
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
@statement(dialect=dialect)
|
|
208
|
+
class Swap(TwoQubitCtrlGate):
|
|
209
|
+
"""Apply the Swap gate."""
|
|
210
|
+
|
|
211
|
+
name = "swap"
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
@statement(dialect=dialect)
|
|
215
|
+
class CH(TwoQubitCtrlGate):
|
|
216
|
+
"""Apply the Controlled-H gate."""
|
|
217
|
+
|
|
218
|
+
name = "ch"
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
@statement(dialect=dialect)
|
|
222
|
+
class CCX(ir.Statement):
|
|
223
|
+
"""Apply the doubly controlled X gate."""
|
|
224
|
+
|
|
225
|
+
name = "ccx"
|
|
226
|
+
traits = frozenset({lowering.FromPythonCall()})
|
|
227
|
+
ctrl1: ir.SSAValue = info.argument(QubitType)
|
|
228
|
+
"""ctrl1 (Qubit): The first control qubit."""
|
|
229
|
+
ctrl2: ir.SSAValue = info.argument(QubitType)
|
|
230
|
+
"""ctrl2 (Qubit): The second control qubit."""
|
|
231
|
+
qarg: ir.SSAValue = info.argument(QubitType)
|
|
232
|
+
"""qarg (Qubit): The target qubit."""
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
@statement(dialect=dialect)
|
|
236
|
+
class CSwap(ir.Statement):
|
|
237
|
+
"""Apply the controlled swap gate."""
|
|
238
|
+
|
|
239
|
+
name = "ccx"
|
|
240
|
+
traits = frozenset({lowering.FromPythonCall()})
|
|
241
|
+
ctrl: ir.SSAValue = info.argument(QubitType)
|
|
242
|
+
"""ctrl (Qubit): The control qubit."""
|
|
243
|
+
qarg1: ir.SSAValue = info.argument(QubitType)
|
|
244
|
+
"""qarg1 (Qubit): The first target qubit."""
|
|
245
|
+
qarg2: ir.SSAValue = info.argument(QubitType)
|
|
246
|
+
"""qarg2 (Qubit): The second target qubit."""
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
@statement(dialect=dialect)
|
|
250
|
+
class CRX(TwoQubitCtrlGate):
|
|
251
|
+
"""Apply the Controlled-RX gate."""
|
|
252
|
+
|
|
253
|
+
name = "crx"
|
|
254
|
+
lam: ir.SSAValue = info.argument(PyNum)
|
|
255
|
+
"""lam (float): The angle to rotate around the X axis."""
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
@statement(dialect=dialect)
|
|
259
|
+
class CRY(TwoQubitCtrlGate):
|
|
260
|
+
"""Apply the Controlled-RY gate."""
|
|
261
|
+
|
|
262
|
+
name = "cry"
|
|
263
|
+
lam: ir.SSAValue = info.argument(PyNum)
|
|
264
|
+
"""lam (float): The angle to rotate around the Y axis."""
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
@statement(dialect=dialect)
|
|
268
|
+
class CRZ(TwoQubitCtrlGate):
|
|
269
|
+
"""Apply the Controlled-RZ gate."""
|
|
270
|
+
|
|
271
|
+
name = "crz"
|
|
272
|
+
lam: ir.SSAValue = info.argument(PyNum)
|
|
273
|
+
"""lam (float): The angle to rotate around the Z axis."""
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
@statement(dialect=dialect)
|
|
277
|
+
class CU1(TwoQubitCtrlGate):
|
|
278
|
+
"""Apply the Controlled-U1 gate."""
|
|
279
|
+
|
|
280
|
+
name = "cu1"
|
|
281
|
+
lam: ir.SSAValue = info.argument(PyNum)
|
|
282
|
+
"""lam (float): The lambda parameter."""
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
@statement(dialect=dialect)
|
|
286
|
+
class CU3(TwoQubitCtrlGate):
|
|
287
|
+
"""Apply the Controlled-U3 gate."""
|
|
288
|
+
|
|
289
|
+
name = "cu3"
|
|
290
|
+
theta: ir.SSAValue = info.argument(PyNum)
|
|
291
|
+
phi: ir.SSAValue = info.argument(PyNum)
|
|
292
|
+
"""phi (float): The phi parameter."""
|
|
293
|
+
lam: ir.SSAValue = info.argument(PyNum)
|
|
294
|
+
"""lam (float): The lambda parameter."""
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
@statement(dialect=dialect)
|
|
298
|
+
class CU(TwoQubitCtrlGate):
|
|
299
|
+
"""Apply the Controlled-U gate."""
|
|
300
|
+
|
|
301
|
+
name = "cu"
|
|
302
|
+
theta: ir.SSAValue = info.argument(PyNum)
|
|
303
|
+
phi: ir.SSAValue = info.argument(PyNum)
|
|
304
|
+
"""phi (float): The phi parameter."""
|
|
305
|
+
lam: ir.SSAValue = info.argument(PyNum)
|
|
306
|
+
"""lam (float): The lambda parameter."""
|
|
307
|
+
gamma: ir.SSAValue = info.argument(PyNum)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
@statement(dialect=dialect)
|
|
311
|
+
class RXX(TwoQubitCtrlGate):
|
|
312
|
+
"""Apply the XX rotation gate."""
|
|
313
|
+
|
|
314
|
+
name = "rxx"
|
|
315
|
+
theta: ir.SSAValue = info.argument(PyNum)
|
|
316
|
+
"""theta (float): The angle of rotation around the X axis."""
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
@statement(dialect=dialect)
|
|
320
|
+
class RZZ(TwoQubitCtrlGate):
|
|
321
|
+
"""Apply the ZZ rotation gate."""
|
|
322
|
+
|
|
323
|
+
name = "rzz"
|
|
324
|
+
theta: ir.SSAValue = info.argument(PyNum)
|
|
325
|
+
"""theta (float): The angle of rotation around the Z axis."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .target import QASM2 as QASM2
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from abc import ABC
|
|
2
|
+
from typing import Generic, TypeVar, overload
|
|
3
|
+
from dataclasses import field, dataclass
|
|
4
|
+
|
|
5
|
+
from kirin import ir, idtable
|
|
6
|
+
from kirin.emit import EmitABC, EmitError, EmitFrame
|
|
7
|
+
from typing_extensions import Self
|
|
8
|
+
|
|
9
|
+
from bloqade.qasm2.parse import ast
|
|
10
|
+
|
|
11
|
+
StmtType = TypeVar("StmtType", bound=ast.Node)
|
|
12
|
+
EmitNode = TypeVar("EmitNode", bound=ast.Node)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class EmitQASM2Frame(EmitFrame[ast.Node | None], Generic[StmtType]):
|
|
17
|
+
body: list[StmtType] = field(default_factory=list)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class EmitQASM2Base(
|
|
22
|
+
EmitABC[EmitQASM2Frame[StmtType], ast.Node | None], ABC, Generic[StmtType, EmitNode]
|
|
23
|
+
):
|
|
24
|
+
void = None
|
|
25
|
+
prefix: str = field(default="", kw_only=True)
|
|
26
|
+
prefix_if_none: str = field(default="var_", kw_only=True)
|
|
27
|
+
|
|
28
|
+
output: EmitNode | None = field(init=False)
|
|
29
|
+
ssa_id: idtable.IdTable[ir.SSAValue] = field(init=False)
|
|
30
|
+
|
|
31
|
+
def initialize(self) -> Self:
|
|
32
|
+
super().initialize()
|
|
33
|
+
self.output: EmitNode | None = None
|
|
34
|
+
self.ssa_id = idtable.IdTable[ir.SSAValue](
|
|
35
|
+
prefix=self.prefix, prefix_if_none=self.prefix_if_none
|
|
36
|
+
)
|
|
37
|
+
return self
|
|
38
|
+
|
|
39
|
+
def new_frame(self, code: ir.Statement) -> EmitQASM2Frame:
|
|
40
|
+
return EmitQASM2Frame.from_func_like(code)
|
|
41
|
+
|
|
42
|
+
def run_method(
|
|
43
|
+
self, method: ir.Method, args: tuple[ast.Node | None, ...]
|
|
44
|
+
) -> tuple[EmitQASM2Frame[StmtType], ast.Node | None]:
|
|
45
|
+
return self.run_callable(method.code, (ast.Name(method.sym_name),) + args)
|
|
46
|
+
|
|
47
|
+
def emit_block(self, frame: EmitQASM2Frame, block: ir.Block) -> ast.Node | None:
|
|
48
|
+
for stmt in block.stmts:
|
|
49
|
+
result = self.eval_stmt(frame, stmt)
|
|
50
|
+
if isinstance(result, tuple):
|
|
51
|
+
frame.set_values(stmt.results, result)
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
A = TypeVar("A")
|
|
55
|
+
B = TypeVar("B")
|
|
56
|
+
|
|
57
|
+
@overload
|
|
58
|
+
def assert_node(self, typ: type[A], node: ast.Node | None) -> A: ...
|
|
59
|
+
|
|
60
|
+
@overload
|
|
61
|
+
def assert_node(
|
|
62
|
+
self, typ: tuple[type[A], type[B]], node: ast.Node | None
|
|
63
|
+
) -> A | B: ...
|
|
64
|
+
|
|
65
|
+
def assert_node(
|
|
66
|
+
self,
|
|
67
|
+
typ: type[A] | tuple[type[A], type[B]],
|
|
68
|
+
node: ast.Node | None,
|
|
69
|
+
) -> A | B:
|
|
70
|
+
if not isinstance(node, typ):
|
|
71
|
+
raise EmitError(f"expected {typ}, got {type(node)}")
|
|
72
|
+
return node
|