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.

Files changed (153) hide show
  1. bloqade/analysis/__init__.py +0 -0
  2. bloqade/analysis/address/__init__.py +11 -0
  3. bloqade/analysis/address/analysis.py +60 -0
  4. bloqade/analysis/address/impls.py +228 -0
  5. bloqade/analysis/address/lattice.py +85 -0
  6. bloqade/noise/__init__.py +1 -0
  7. bloqade/noise/native/__init__.py +20 -0
  8. bloqade/noise/native/_dialect.py +3 -0
  9. bloqade/noise/native/_wrappers.py +34 -0
  10. bloqade/noise/native/model.py +347 -0
  11. bloqade/noise/native/rewrite.py +35 -0
  12. bloqade/noise/native/stmts.py +46 -0
  13. bloqade/pyqrack/__init__.py +18 -0
  14. bloqade/pyqrack/base.py +131 -0
  15. bloqade/pyqrack/noise/__init__.py +0 -0
  16. bloqade/pyqrack/noise/native.py +100 -0
  17. bloqade/pyqrack/qasm2/__init__.py +0 -0
  18. bloqade/pyqrack/qasm2/core.py +79 -0
  19. bloqade/pyqrack/qasm2/parallel.py +46 -0
  20. bloqade/pyqrack/qasm2/uop.py +247 -0
  21. bloqade/pyqrack/reg.py +109 -0
  22. bloqade/pyqrack/target.py +112 -0
  23. bloqade/qasm2/__init__.py +19 -0
  24. bloqade/qasm2/_wrappers.py +674 -0
  25. bloqade/qasm2/dialects/__init__.py +10 -0
  26. bloqade/qasm2/dialects/core/__init__.py +3 -0
  27. bloqade/qasm2/dialects/core/_dialect.py +3 -0
  28. bloqade/qasm2/dialects/core/_emit.py +68 -0
  29. bloqade/qasm2/dialects/core/_typeinfer.py +23 -0
  30. bloqade/qasm2/dialects/core/address.py +38 -0
  31. bloqade/qasm2/dialects/core/stmts.py +94 -0
  32. bloqade/qasm2/dialects/expr/__init__.py +3 -0
  33. bloqade/qasm2/dialects/expr/_dialect.py +3 -0
  34. bloqade/qasm2/dialects/expr/_emit.py +103 -0
  35. bloqade/qasm2/dialects/expr/_from_python.py +86 -0
  36. bloqade/qasm2/dialects/expr/_interp.py +75 -0
  37. bloqade/qasm2/dialects/expr/stmts.py +262 -0
  38. bloqade/qasm2/dialects/glob.py +45 -0
  39. bloqade/qasm2/dialects/indexing.py +64 -0
  40. bloqade/qasm2/dialects/inline.py +76 -0
  41. bloqade/qasm2/dialects/noise.py +16 -0
  42. bloqade/qasm2/dialects/parallel.py +110 -0
  43. bloqade/qasm2/dialects/uop/__init__.py +4 -0
  44. bloqade/qasm2/dialects/uop/_dialect.py +3 -0
  45. bloqade/qasm2/dialects/uop/_emit.py +211 -0
  46. bloqade/qasm2/dialects/uop/schedule.py +89 -0
  47. bloqade/qasm2/dialects/uop/stmts.py +325 -0
  48. bloqade/qasm2/emit/__init__.py +1 -0
  49. bloqade/qasm2/emit/base.py +72 -0
  50. bloqade/qasm2/emit/gate.py +102 -0
  51. bloqade/qasm2/emit/main.py +106 -0
  52. bloqade/qasm2/emit/target.py +165 -0
  53. bloqade/qasm2/glob.py +24 -0
  54. bloqade/qasm2/groups.py +120 -0
  55. bloqade/qasm2/parallel.py +48 -0
  56. bloqade/qasm2/parse/__init__.py +37 -0
  57. bloqade/qasm2/parse/ast.py +235 -0
  58. bloqade/qasm2/parse/build.py +289 -0
  59. bloqade/qasm2/parse/lowering.py +553 -0
  60. bloqade/qasm2/parse/parser.py +5 -0
  61. bloqade/qasm2/parse/print.py +293 -0
  62. bloqade/qasm2/parse/qasm2.lark +75 -0
  63. bloqade/qasm2/parse/visitor.py +16 -0
  64. bloqade/qasm2/parse/visitor.pyi +39 -0
  65. bloqade/qasm2/passes/__init__.py +5 -0
  66. bloqade/qasm2/passes/fold.py +94 -0
  67. bloqade/qasm2/passes/glob.py +119 -0
  68. bloqade/qasm2/passes/noise.py +61 -0
  69. bloqade/qasm2/passes/parallel.py +176 -0
  70. bloqade/qasm2/passes/py2qasm.py +63 -0
  71. bloqade/qasm2/passes/qasm2py.py +61 -0
  72. bloqade/qasm2/rewrite/__init__.py +12 -0
  73. bloqade/qasm2/rewrite/desugar.py +28 -0
  74. bloqade/qasm2/rewrite/glob.py +103 -0
  75. bloqade/qasm2/rewrite/heuristic_noise.py +247 -0
  76. bloqade/qasm2/rewrite/native_gates.py +447 -0
  77. bloqade/qasm2/rewrite/parallel_to_uop.py +83 -0
  78. bloqade/qasm2/rewrite/register.py +45 -0
  79. bloqade/qasm2/rewrite/uop_to_parallel.py +395 -0
  80. bloqade/qasm2/types.py +39 -0
  81. bloqade/qbraid/__init__.py +2 -0
  82. bloqade/qbraid/lowering.py +324 -0
  83. bloqade/qbraid/schema.py +252 -0
  84. bloqade/qbraid/simulation_result.py +99 -0
  85. bloqade/qbraid/target.py +86 -0
  86. bloqade/squin/__init__.py +2 -0
  87. bloqade/squin/analysis/__init__.py +0 -0
  88. bloqade/squin/analysis/nsites/__init__.py +8 -0
  89. bloqade/squin/analysis/nsites/analysis.py +52 -0
  90. bloqade/squin/analysis/nsites/impls.py +69 -0
  91. bloqade/squin/analysis/nsites/lattice.py +49 -0
  92. bloqade/squin/analysis/schedule.py +244 -0
  93. bloqade/squin/groups.py +38 -0
  94. bloqade/squin/op/__init__.py +132 -0
  95. bloqade/squin/op/_dialect.py +3 -0
  96. bloqade/squin/op/complex.py +6 -0
  97. bloqade/squin/op/stmts.py +220 -0
  98. bloqade/squin/op/traits.py +43 -0
  99. bloqade/squin/op/types.py +10 -0
  100. bloqade/squin/qubit.py +118 -0
  101. bloqade/squin/wire.py +103 -0
  102. bloqade/stim/__init__.py +6 -0
  103. bloqade/stim/_wrappers.py +186 -0
  104. bloqade/stim/dialects/__init__.py +5 -0
  105. bloqade/stim/dialects/aux/__init__.py +11 -0
  106. bloqade/stim/dialects/aux/_dialect.py +3 -0
  107. bloqade/stim/dialects/aux/emit.py +102 -0
  108. bloqade/stim/dialects/aux/interp.py +39 -0
  109. bloqade/stim/dialects/aux/lowering.py +40 -0
  110. bloqade/stim/dialects/aux/stmts/__init__.py +14 -0
  111. bloqade/stim/dialects/aux/stmts/annotate.py +47 -0
  112. bloqade/stim/dialects/aux/stmts/const.py +95 -0
  113. bloqade/stim/dialects/aux/types.py +19 -0
  114. bloqade/stim/dialects/collapse/__init__.py +3 -0
  115. bloqade/stim/dialects/collapse/_dialect.py +3 -0
  116. bloqade/stim/dialects/collapse/emit.py +68 -0
  117. bloqade/stim/dialects/collapse/stmts/__init__.py +3 -0
  118. bloqade/stim/dialects/collapse/stmts/measure.py +45 -0
  119. bloqade/stim/dialects/collapse/stmts/pp_measure.py +14 -0
  120. bloqade/stim/dialects/collapse/stmts/reset.py +26 -0
  121. bloqade/stim/dialects/gate/__init__.py +3 -0
  122. bloqade/stim/dialects/gate/_dialect.py +3 -0
  123. bloqade/stim/dialects/gate/emit.py +87 -0
  124. bloqade/stim/dialects/gate/stmts/__init__.py +14 -0
  125. bloqade/stim/dialects/gate/stmts/base.py +31 -0
  126. bloqade/stim/dialects/gate/stmts/clifford_1q.py +53 -0
  127. bloqade/stim/dialects/gate/stmts/clifford_2q.py +11 -0
  128. bloqade/stim/dialects/gate/stmts/control_2q.py +21 -0
  129. bloqade/stim/dialects/gate/stmts/pp.py +15 -0
  130. bloqade/stim/dialects/noise/__init__.py +3 -0
  131. bloqade/stim/dialects/noise/_dialect.py +3 -0
  132. bloqade/stim/dialects/noise/emit.py +66 -0
  133. bloqade/stim/dialects/noise/stmts.py +77 -0
  134. bloqade/stim/emit/__init__.py +1 -0
  135. bloqade/stim/emit/stim.py +54 -0
  136. bloqade/stim/groups.py +26 -0
  137. bloqade/test_utils.py +35 -0
  138. bloqade/types.py +24 -0
  139. bloqade/visual/__init__.py +1 -0
  140. bloqade/visual/animation/__init__.py +0 -0
  141. bloqade/visual/animation/animate.py +267 -0
  142. bloqade/visual/animation/base.py +346 -0
  143. bloqade/visual/animation/gate_event.py +24 -0
  144. bloqade/visual/animation/runtime/__init__.py +0 -0
  145. bloqade/visual/animation/runtime/aod.py +36 -0
  146. bloqade/visual/animation/runtime/atoms.py +55 -0
  147. bloqade/visual/animation/runtime/ppoly.py +50 -0
  148. bloqade/visual/animation/runtime/qpustate.py +119 -0
  149. bloqade/visual/animation/runtime/utils.py +43 -0
  150. bloqade_circuit-0.1.0.dist-info/METADATA +70 -0
  151. bloqade_circuit-0.1.0.dist-info/RECORD +153 -0
  152. bloqade_circuit-0.1.0.dist-info/WHEEL +4 -0
  153. bloqade_circuit-0.1.0.dist-info/licenses/LICENSE +234 -0
File without changes
@@ -0,0 +1,11 @@
1
+ from . import impls as impls
2
+ from .lattice import (
3
+ Address as Address,
4
+ NotQubit as NotQubit,
5
+ AddressReg as AddressReg,
6
+ AnyAddress as AnyAddress,
7
+ AddressWire as AddressWire,
8
+ AddressQubit as AddressQubit,
9
+ AddressTuple as AddressTuple,
10
+ )
11
+ from .analysis import AddressAnalysis as AddressAnalysis
@@ -0,0 +1,60 @@
1
+ from typing import TypeVar
2
+ from dataclasses import field
3
+
4
+ from kirin import ir, interp
5
+ from kirin.analysis import Forward, const
6
+ from kirin.analysis.forward import ForwardFrame
7
+
8
+ from bloqade.types import QubitType
9
+
10
+ from .lattice import Address
11
+
12
+
13
+ class AddressAnalysis(Forward[Address]):
14
+ """
15
+ This analysis pass can be used to track the global addresses of qubits and wires.
16
+ """
17
+
18
+ keys = ["qubit.address"]
19
+ lattice = Address
20
+ next_address: int = field(init=False)
21
+
22
+ def initialize(self):
23
+ super().initialize()
24
+ self.next_address: int = 0
25
+ return self
26
+
27
+ @property
28
+ def qubit_count(self) -> int:
29
+ """Total number of qubits found by the analysis."""
30
+ return self.next_address
31
+
32
+ T = TypeVar("T")
33
+
34
+ def get_const_value(self, typ: type[T], value: ir.SSAValue) -> T:
35
+ if isinstance(hint := value.hints.get("const"), const.Value):
36
+ data = hint.data
37
+ if isinstance(data, typ):
38
+ return hint.data
39
+ raise interp.InterpreterError(
40
+ f"Expected constant value <type = {typ}>, got {data}"
41
+ )
42
+ raise interp.InterpreterError(
43
+ f"Expected constant value <type = {typ}>, got {value}"
44
+ )
45
+
46
+ def eval_stmt_fallback(
47
+ self, frame: ForwardFrame[Address], stmt: ir.Statement
48
+ ) -> tuple[Address, ...] | interp.SpecialValue[Address]:
49
+ return tuple(
50
+ (
51
+ self.lattice.top()
52
+ if result.type.is_subseteq(QubitType)
53
+ else self.lattice.bottom()
54
+ )
55
+ for result in stmt.results
56
+ )
57
+
58
+ def run_method(self, method: ir.Method, args: tuple[Address, ...]):
59
+ # NOTE: we do not support dynamic calls here, thus no need to propagate method object
60
+ return self.run_callable(method.code, (self.lattice.bottom(),) + args)
@@ -0,0 +1,228 @@
1
+ """
2
+ qubit.address method table for a few builtin dialects.
3
+ """
4
+
5
+ from kirin import interp
6
+ from kirin.analysis import ForwardFrame, const
7
+ from kirin.dialects import cf, py, scf, func, ilist
8
+
9
+ from bloqade import squin
10
+
11
+ from .lattice import (
12
+ Address,
13
+ NotQubit,
14
+ AddressReg,
15
+ AddressWire,
16
+ AddressQubit,
17
+ AddressTuple,
18
+ )
19
+ from .analysis import AddressAnalysis
20
+
21
+
22
+ @py.binop.dialect.register(key="qubit.address")
23
+ class PyBinOp(interp.MethodTable):
24
+
25
+ @interp.impl(py.Add)
26
+ def add(self, interp: AddressAnalysis, frame: interp.Frame, stmt: py.Add):
27
+ lhs = frame.get(stmt.lhs)
28
+ rhs = frame.get(stmt.rhs)
29
+
30
+ if isinstance(lhs, AddressTuple) and isinstance(rhs, AddressTuple):
31
+ return (AddressTuple(data=lhs.data + rhs.data),)
32
+ else:
33
+ return (NotQubit(),)
34
+
35
+
36
+ @py.tuple.dialect.register(key="qubit.address")
37
+ class PyTuple(interp.MethodTable):
38
+ @interp.impl(py.tuple.New)
39
+ def new_tuple(
40
+ self,
41
+ interp: AddressAnalysis,
42
+ frame: interp.Frame,
43
+ stmt: py.tuple.New,
44
+ ):
45
+ return (AddressTuple(frame.get_values(stmt.args)),)
46
+
47
+
48
+ @ilist.dialect.register(key="qubit.address")
49
+ class IList(interp.MethodTable):
50
+ @interp.impl(ilist.New)
51
+ def new_ilist(
52
+ self,
53
+ interp: AddressAnalysis,
54
+ frame: interp.Frame,
55
+ stmt: ilist.New,
56
+ ):
57
+ return (AddressTuple(frame.get_values(stmt.values)),)
58
+
59
+
60
+ @py.list.dialect.register(key="qubit.address")
61
+ class PyList(interp.MethodTable):
62
+ @interp.impl(py.list.New)
63
+ def new_ilist(
64
+ self,
65
+ interp: AddressAnalysis,
66
+ frame: interp.Frame,
67
+ stmt: py.list.New,
68
+ ):
69
+ return (AddressTuple(frame.get_values(stmt.args)),)
70
+
71
+
72
+ @py.indexing.dialect.register(key="qubit.address")
73
+ class PyIndexing(interp.MethodTable):
74
+ @interp.impl(py.GetItem)
75
+ def getitem(self, interp: AddressAnalysis, frame: interp.Frame, stmt: py.GetItem):
76
+ # Integer index into the thing being indexed
77
+ idx = interp.get_const_value(int, stmt.index)
78
+ # The object being indexed into
79
+ obj = frame.get(stmt.obj)
80
+ # The `data` attributes holds onto other Address types
81
+ # so we just extract that here
82
+ if isinstance(obj, AddressTuple):
83
+ return (obj.data[idx],)
84
+ # an AddressReg is guaranteed to just have some sequence
85
+ # of integers which is directly pluggable to AddressQubit
86
+ elif isinstance(obj, AddressReg):
87
+ return (AddressQubit(obj.data[idx]),)
88
+ else:
89
+ return (NotQubit(),)
90
+
91
+
92
+ @py.assign.dialect.register(key="qubit.address")
93
+ class PyAssign(interp.MethodTable):
94
+ @interp.impl(py.Alias)
95
+ def alias(self, interp: AddressAnalysis, frame: interp.Frame, stmt: py.Alias):
96
+ return (frame.get(stmt.value),)
97
+
98
+
99
+ @func.dialect.register(key="qubit.address")
100
+ class Func(interp.MethodTable):
101
+ @interp.impl(func.Return)
102
+ def return_(self, _: AddressAnalysis, frame: interp.Frame, stmt: func.Return):
103
+ return interp.ReturnValue(frame.get(stmt.value))
104
+
105
+ # TODO: replace with the generic implementation
106
+ @interp.impl(func.Invoke)
107
+ def invoke(self, interp_: AddressAnalysis, frame: interp.Frame, stmt: func.Invoke):
108
+ _, ret = interp_.run_method(
109
+ stmt.callee,
110
+ interp_.permute_values(
111
+ stmt.callee.arg_names, frame.get_values(stmt.inputs), stmt.kwargs
112
+ ),
113
+ )
114
+ return (ret,)
115
+
116
+ # TODO: support lambda?
117
+
118
+
119
+ @cf.dialect.register(key="qubit.address")
120
+ class Cf(cf.typeinfer.TypeInfer):
121
+ # NOTE: cf just re-use the type infer method table
122
+ # it's the same process as type infer.
123
+ pass
124
+
125
+
126
+ @scf.dialect.register(key="qubit.address")
127
+ class Scf(scf.absint.Methods):
128
+
129
+ @interp.impl(scf.For)
130
+ def for_loop(
131
+ self,
132
+ interp_: AddressAnalysis,
133
+ frame: ForwardFrame[Address],
134
+ stmt: scf.For,
135
+ ):
136
+ if not isinstance(hint := stmt.iterable.hints.get("const"), const.Value):
137
+ return interp_.eval_stmt_fallback(frame, stmt)
138
+
139
+ iterable = hint.data
140
+ loop_vars = frame.get_values(stmt.initializers)
141
+ body_block = stmt.body.blocks[0]
142
+ block_args = body_block.args
143
+
144
+ # NOTE: we need to actually run iteration in case there are
145
+ # new allocations/re-assign in the loop body.
146
+ for _ in iterable:
147
+ with interp_.state.new_frame(interp_.new_frame(stmt)) as body_frame:
148
+ body_frame.entries.update(frame.entries)
149
+ body_frame.set_values(
150
+ block_args,
151
+ (NotQubit(),) + loop_vars,
152
+ )
153
+ loop_vars = interp_.run_ssacfg_region(body_frame, stmt.body)
154
+
155
+ if loop_vars is None:
156
+ loop_vars = ()
157
+ elif isinstance(loop_vars, interp.ReturnValue):
158
+ return loop_vars
159
+
160
+ if isinstance(body_block.last_stmt, func.Return):
161
+ frame.worklist.append(interp.Successor(body_block, NotQubit(), *loop_vars))
162
+ return # if terminate is Return, there is no result
163
+
164
+ return loop_vars
165
+
166
+
167
+ # Address lattice elements we can work with:
168
+ ## NotQubit (bottom), AnyAddress (top)
169
+
170
+ ## AddressTuple -> data: tuple[Address, ...]
171
+ ### Recursive type, could contain itself or other variants
172
+ ### This pops up in cases where you can have an IList/Tuple
173
+ ### That contains elements that could be other Address types
174
+
175
+ ## AddressReg -> data: Sequence[int]
176
+ ### specific to creation of a register of qubits
177
+
178
+ ## AddressQubit -> data: int
179
+ ### Base qubit address type
180
+
181
+
182
+ @squin.wire.dialect.register(key="qubit.address")
183
+ class SquinWireMethodTable(interp.MethodTable):
184
+
185
+ @interp.impl(squin.wire.Unwrap)
186
+ def unwrap(
187
+ self,
188
+ interp_: AddressAnalysis,
189
+ frame: ForwardFrame[Address],
190
+ stmt: squin.wire.Unwrap,
191
+ ):
192
+
193
+ origin_qubit = frame.get(stmt.qubit)
194
+
195
+ return (AddressWire(origin_qubit=origin_qubit),)
196
+
197
+ @interp.impl(squin.wire.Apply)
198
+ def apply(
199
+ self,
200
+ interp_: AddressAnalysis,
201
+ frame: ForwardFrame[Address],
202
+ stmt: squin.wire.Apply,
203
+ ):
204
+
205
+ origin_qubits = tuple(
206
+ [frame.get(input_elem).origin_qubit for input_elem in stmt.inputs]
207
+ )
208
+ new_address_wires = tuple(
209
+ [AddressWire(origin_qubit=origin_qubit) for origin_qubit in origin_qubits]
210
+ )
211
+ return new_address_wires
212
+
213
+
214
+ @squin.qubit.dialect.register(key="qubit.address")
215
+ class SquinQubitMethodTable(interp.MethodTable):
216
+
217
+ # This can be treated like a QRegNew impl
218
+ @interp.impl(squin.qubit.New)
219
+ def new(
220
+ self,
221
+ interp_: AddressAnalysis,
222
+ frame: ForwardFrame[Address],
223
+ stmt: squin.qubit.New,
224
+ ):
225
+ n_qubits = interp_.get_const_value(int, stmt.n_qubits)
226
+ addr = AddressReg(range(interp_.next_address, interp_.next_address + n_qubits))
227
+ interp_.next_address += n_qubits
228
+ return (addr,)
@@ -0,0 +1,85 @@
1
+ from typing import Sequence, final
2
+ from dataclasses import dataclass
3
+
4
+ from kirin.lattice import (
5
+ SingletonMeta,
6
+ BoundedLattice,
7
+ SimpleJoinMixin,
8
+ SimpleMeetMixin,
9
+ )
10
+
11
+
12
+ @dataclass
13
+ class Address(
14
+ SimpleJoinMixin["Address"],
15
+ SimpleMeetMixin["Address"],
16
+ BoundedLattice["Address"],
17
+ ):
18
+
19
+ @classmethod
20
+ def bottom(cls) -> "Address":
21
+ return NotQubit()
22
+
23
+ @classmethod
24
+ def top(cls) -> "Address":
25
+ return AnyAddress()
26
+
27
+
28
+ @final
29
+ @dataclass
30
+ class NotQubit(Address, metaclass=SingletonMeta):
31
+
32
+ def is_subseteq(self, other: Address) -> bool:
33
+ return True
34
+
35
+
36
+ @final
37
+ @dataclass
38
+ class AnyAddress(Address, metaclass=SingletonMeta):
39
+
40
+ def is_subseteq(self, other: Address) -> bool:
41
+ return isinstance(other, AnyAddress)
42
+
43
+
44
+ @final
45
+ @dataclass
46
+ class AddressTuple(Address):
47
+ data: tuple[Address, ...]
48
+
49
+ def is_subseteq(self, other: Address) -> bool:
50
+ if isinstance(other, AddressTuple):
51
+ return all(a.is_subseteq(b) for a, b in zip(self.data, other.data))
52
+ return False
53
+
54
+
55
+ @final
56
+ @dataclass
57
+ class AddressReg(Address):
58
+ data: Sequence[int]
59
+
60
+ def is_subseteq(self, other: Address) -> bool:
61
+ if isinstance(other, AddressReg):
62
+ return self.data == other.data
63
+ return False
64
+
65
+
66
+ @final
67
+ @dataclass
68
+ class AddressQubit(Address):
69
+ data: int
70
+
71
+ def is_subseteq(self, other: Address) -> bool:
72
+ if isinstance(other, AddressQubit):
73
+ return self.data == other.data
74
+ return False
75
+
76
+
77
+ @final
78
+ @dataclass
79
+ class AddressWire(Address):
80
+ origin_qubit: AddressQubit
81
+
82
+ def is_subseteq(self, other: Address) -> bool:
83
+ if isinstance(other, AddressWire):
84
+ return self.origin_qubit == self.origin_qubit
85
+ return False
@@ -0,0 +1 @@
1
+ from . import native as native
@@ -0,0 +1,20 @@
1
+ """NOTE: This module is not guaranteed to be supported long-term in bloqade. We will be
2
+ moving towards a more general approach to noise modeling in the future."""
3
+
4
+ from .model import (
5
+ GateNoiseParams as GateNoiseParams,
6
+ TwoRowZoneModel as TwoRowZoneModel,
7
+ MoveNoiseModelABC as MoveNoiseModelABC,
8
+ )
9
+ from .stmts import (
10
+ PauliChannel as PauliChannel,
11
+ CZPauliChannel as CZPauliChannel,
12
+ AtomLossChannel as AtomLossChannel,
13
+ )
14
+ from .rewrite import RemoveNoisePass as RemoveNoisePass
15
+ from ._dialect import dialect as dialect
16
+ from ._wrappers import (
17
+ pauli_channel as pauli_channel,
18
+ cz_pauli_channel as cz_pauli_channel,
19
+ atom_loss_channel as atom_loss_channel,
20
+ )
@@ -0,0 +1,3 @@
1
+ from kirin import ir
2
+
3
+ dialect = ir.Dialect("native")
@@ -0,0 +1,34 @@
1
+ from typing import Any
2
+
3
+ from kirin.dialects import ilist
4
+ from kirin.lowering import wraps
5
+
6
+ from bloqade.noise import native
7
+ from bloqade.qasm2.types import Qubit
8
+
9
+
10
+ @wraps(native.AtomLossChannel)
11
+ def atom_loss_channel(
12
+ qargs: ilist.IList[Qubit, Any] | list, *, prob: float
13
+ ) -> None: ...
14
+
15
+
16
+ @wraps(native.PauliChannel)
17
+ def pauli_channel(
18
+ qargs: ilist.IList[Qubit, Any] | list, *, px: float, py: float, pz: float
19
+ ) -> None: ...
20
+
21
+
22
+ @wraps(native.CZPauliChannel)
23
+ def cz_pauli_channel(
24
+ ctrls: ilist.IList[Qubit, Any] | list,
25
+ qarg2: ilist.IList[Qubit, Any] | list,
26
+ *,
27
+ px_ctrl: float,
28
+ py_ctrl: float,
29
+ pz_ctrl: float,
30
+ px_qarg: float,
31
+ py_qarg: float,
32
+ pz_qarg: float,
33
+ paired: bool,
34
+ ) -> None: ...