bloqade-circuit 0.7.8__py3-none-any.whl → 0.7.9__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/pyqrack/reg.py CHANGED
@@ -2,8 +2,8 @@ import enum
2
2
  from typing import TYPE_CHECKING
3
3
  from dataclasses import dataclass
4
4
 
5
- from bloqade.types import MeasurementResult
6
5
  from bloqade.qasm2.types import Qubit
6
+ from bloqade.squin.types import MeasurementResult
7
7
 
8
8
  if TYPE_CHECKING:
9
9
  from pyqrack import QrackSimulator
@@ -1,27 +1,12 @@
1
1
  from dataclasses import field, dataclass
2
2
 
3
3
  from kirin import ir
4
- from kirin.passes import Pass, TypeInfer
5
- from kirin.rewrite import (
6
- Walk,
7
- Chain,
8
- Inline,
9
- Fixpoint,
10
- WrapConst,
11
- Call2Invoke,
12
- ConstantFold,
13
- CFGCompactify,
14
- InlineGetItem,
15
- InlineGetField,
16
- DeadCodeElimination,
17
- CommonSubexpressionElimination,
18
- )
19
- from kirin.analysis import const
20
- from kirin.dialects import scf, ilist
4
+ from kirin.passes import Pass
21
5
  from kirin.ir.method import Method
22
6
  from kirin.rewrite.abc import RewriteResult
23
7
 
24
8
  from bloqade.qasm2.dialects import expr
9
+ from bloqade.rewrite.passes import AggressiveUnroll
25
10
 
26
11
  from .unroll_if import UnrollIfs
27
12
 
@@ -30,71 +15,27 @@ from .unroll_if import UnrollIfs
30
15
  class QASM2Fold(Pass):
31
16
  """Fold pass for qasm2.extended"""
32
17
 
33
- constprop: const.Propagate = field(init=False)
34
18
  inline_gate_subroutine: bool = True
35
19
  unroll_ifs: bool = True
20
+ aggressive_unroll: AggressiveUnroll = field(init=False)
36
21
 
37
22
  def __post_init__(self):
38
- self.constprop = const.Propagate(self.dialects)
39
- self.typeinfer = TypeInfer(self.dialects)
23
+ def inline_simple(node: ir.Statement):
24
+ if isinstance(node, expr.GateFunction):
25
+ return self.inline_gate_subroutine
40
26
 
41
- def unsafe_run(self, mt: Method) -> RewriteResult:
42
- result = RewriteResult()
43
- frame, _ = self.constprop.run_analysis(mt)
44
- result = Walk(WrapConst(frame)).rewrite(mt.code).join(result)
45
- rule = Chain(
46
- ConstantFold(),
47
- Call2Invoke(),
48
- InlineGetField(),
49
- InlineGetItem(),
50
- DeadCodeElimination(),
51
- CommonSubexpressionElimination(),
52
- )
53
- result = Fixpoint(Walk(rule)).rewrite(mt.code).join(result)
27
+ return True
54
28
 
55
- result = (
56
- Walk(
57
- Chain(
58
- scf.unroll.PickIfElse(),
59
- scf.unroll.ForLoop(),
60
- scf.trim.UnusedYield(),
61
- )
62
- )
63
- .rewrite(mt.code)
64
- .join(result)
29
+ self.aggressive_unroll = AggressiveUnroll(
30
+ self.dialects, inline_simple, no_raise=self.no_raise
65
31
  )
66
32
 
67
- if self.unroll_ifs:
68
- UnrollIfs(mt.dialects).unsafe_run(mt).join(result)
69
-
70
- # run typeinfer again after unroll etc. because we now insert
71
- # a lot of new nodes, which might have more precise types
72
- self.typeinfer.unsafe_run(mt)
73
- result = (
74
- Walk(Chain(ilist.rewrite.ConstList2IList(), ilist.rewrite.Unroll()))
75
- .rewrite(mt.code)
76
- .join(result)
77
- )
78
-
79
- def inline_simple(node: ir.Statement):
80
- if isinstance(node, expr.GateFunction):
81
- return self.inline_gate_subroutine
33
+ def unsafe_run(self, mt: Method) -> RewriteResult:
34
+ result = RewriteResult()
82
35
 
83
- if not isinstance(node.parent_stmt, (scf.For, scf.IfElse)):
84
- return True # always inline calls outside of loops and if-else
36
+ if self.unroll_ifs:
37
+ result = UnrollIfs(mt.dialects).unsafe_run(mt).join(result)
85
38
 
86
- # inside loops and if-else, only inline simple functions, i.e. functions with a single block
87
- if (trait := node.get_trait(ir.CallableStmtInterface)) is None:
88
- return False # not a callable, don't inline to be safe
89
- region = trait.get_callable_region(node)
90
- return len(region.blocks) == 1
39
+ result = self.aggressive_unroll.unsafe_run(mt).join(result)
91
40
 
92
- result = (
93
- Walk(
94
- Inline(inline_simple),
95
- )
96
- .rewrite(mt.code)
97
- .join(result)
98
- )
99
- result = Walk(Fixpoint(CFGCompactify())).rewrite(mt.code).join(result)
100
41
  return result
@@ -1 +1,2 @@
1
+ from .aggressive_unroll import AggressiveUnroll as AggressiveUnroll
1
2
  from .canonicalize_ilist import CanonicalizeIList as CanonicalizeIList
@@ -0,0 +1,93 @@
1
+ from typing import Callable
2
+ from dataclasses import field, dataclass
3
+
4
+ from kirin import ir
5
+ from kirin.passes import Pass, HintConst, TypeInfer
6
+ from kirin.rewrite import (
7
+ Walk,
8
+ Chain,
9
+ Inline,
10
+ Fixpoint,
11
+ Call2Invoke,
12
+ ConstantFold,
13
+ CFGCompactify,
14
+ InlineGetItem,
15
+ InlineGetField,
16
+ DeadCodeElimination,
17
+ )
18
+ from kirin.dialects import scf, ilist
19
+ from kirin.ir.method import Method
20
+ from kirin.rewrite.abc import RewriteResult
21
+ from kirin.rewrite.cse import CommonSubexpressionElimination
22
+ from kirin.passes.aggressive import UnrollScf
23
+
24
+
25
+ @dataclass
26
+ class Fold(Pass):
27
+ hint_const: HintConst = field(init=False)
28
+
29
+ def __post_init__(self):
30
+ self.hint_const = HintConst(self.dialects, no_raise=self.no_raise)
31
+
32
+ def unsafe_run(self, mt: Method) -> RewriteResult:
33
+ result = RewriteResult()
34
+ result = self.hint_const.unsafe_run(mt).join(result)
35
+ rule = Chain(
36
+ ConstantFold(),
37
+ Call2Invoke(),
38
+ InlineGetField(),
39
+ InlineGetItem(),
40
+ ilist.rewrite.InlineGetItem(),
41
+ ilist.rewrite.HintLen(),
42
+ )
43
+ result = Fixpoint(Walk(rule)).rewrite(mt.code).join(result)
44
+
45
+ return result
46
+
47
+
48
+ @dataclass
49
+ class AggressiveUnroll(Pass):
50
+ """A pass to unroll structured control flow"""
51
+
52
+ additional_inline_heuristic: Callable[[ir.Statement], bool] = lambda node: True
53
+
54
+ fold: Fold = field(init=False)
55
+ typeinfer: TypeInfer = field(init=False)
56
+ scf_unroll: UnrollScf = field(init=False)
57
+
58
+ def __post_init__(self):
59
+ self.fold = Fold(self.dialects, no_raise=self.no_raise)
60
+ self.typeinfer = TypeInfer(self.dialects, no_raise=self.no_raise)
61
+ self.scf_unroll = UnrollScf(self.dialects, no_raise=self.no_raise)
62
+
63
+ def unsafe_run(self, mt: Method) -> RewriteResult:
64
+ result = RewriteResult()
65
+ result = self.scf_unroll.unsafe_run(mt).join(result)
66
+ result = (
67
+ Walk(Chain(ilist.rewrite.ConstList2IList(), ilist.rewrite.Unroll()))
68
+ .rewrite(mt.code)
69
+ .join(result)
70
+ )
71
+ result = self.typeinfer.unsafe_run(mt).join(result)
72
+ result = self.fold.unsafe_run(mt).join(result)
73
+ result = Walk(Inline(self.inline_heuristic)).rewrite(mt.code).join(result)
74
+ result = Walk(Fixpoint(CFGCompactify())).rewrite(mt.code).join(result)
75
+
76
+ rule = Chain(
77
+ CommonSubexpressionElimination(),
78
+ DeadCodeElimination(),
79
+ )
80
+ result = Fixpoint(Walk(rule)).rewrite(mt.code).join(result)
81
+
82
+ return result
83
+
84
+ def inline_heuristic(self, node: ir.Statement) -> bool:
85
+ """The heuristic to decide whether to inline a function call or not.
86
+ inside loops and if-else, only inline simple functions, i.e.
87
+ functions with a single block
88
+ """
89
+ return not isinstance(
90
+ node.parent_stmt, (scf.For, scf.IfElse)
91
+ ) and self.additional_inline_heuristic(
92
+ node
93
+ ) # always inline calls outside of loops and if-else
@@ -1,28 +1,32 @@
1
- from dataclasses import dataclass
1
+ from dataclasses import field, dataclass
2
2
 
3
- from kirin import ir
4
- from kirin.passes import Pass
3
+ from kirin import ir, passes
5
4
  from kirin.rewrite import (
6
5
  Walk,
7
6
  Chain,
8
7
  Fixpoint,
9
8
  )
10
- from kirin.analysis import const
11
-
12
- from ..rules.flatten_ilist import FlattenAddOpIList
13
- from ..rules.inline_getitem_ilist import InlineGetItemFromIList
9
+ from kirin.dialects.ilist import rewrite
14
10
 
15
11
 
16
12
  @dataclass
17
- class CanonicalizeIList(Pass):
13
+ class CanonicalizeIList(passes.Pass):
18
14
 
19
- def unsafe_run(self, mt: ir.Method):
15
+ fold_pass: passes.Fold = field(init=False)
20
16
 
21
- cp_result_frame, _ = const.Propagate(dialects=mt.dialects).run_analysis(mt)
17
+ def __post_init__(self):
18
+ self.fold_pass = passes.Fold(self.dialects, no_raise=self.no_raise)
22
19
 
23
- return Fixpoint(
24
- Chain(
25
- Walk(InlineGetItemFromIList(constprop_result=cp_result_frame.entries)),
26
- Walk(FlattenAddOpIList()),
20
+ def unsafe_run(self, mt: ir.Method):
21
+ result = Fixpoint(
22
+ Walk(
23
+ Chain(
24
+ rewrite.InlineGetItem(),
25
+ rewrite.FlattenAdd(),
26
+ rewrite.HintLen(),
27
+ )
27
28
  )
28
29
  ).rewrite(mt.code)
30
+
31
+ result = self.fold_pass(mt).join(result)
32
+ return result
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bloqade-circuit
3
- Version: 0.7.8
3
+ Version: 0.7.9
4
4
  Summary: The software development toolkit for neutral atom arrays.
5
5
  Author-email: Roger-luo <rluo@quera.com>, kaihsin <khwu@quera.com>, weinbe58 <pweinberg@quera.com>, johnzl-777 <jlong@quera.com>
6
6
  License-File: LICENSE
@@ -35,7 +35,7 @@ bloqade/pyqrack/__init__.py,sha256=OV8-2fw44gP_JgY8mAUiwISO_qYxS-t0fKsbuUB-r9Y,8
35
35
  bloqade/pyqrack/base.py,sha256=Q2GjAcqEZBo-Lhe2jpXuNCB0xXVIdwtdy6cUmDM_OZI,4623
36
36
  bloqade/pyqrack/device.py,sha256=ruseNWt3scvjw0KyHZjwnM6Z6lFjROgmW3Zdi1lucgQ,15195
37
37
  bloqade/pyqrack/native.py,sha256=ErbVQCatn_JT3Ej-iQzMMfb_q50JF_K1Iv1vRYvu5VA,1857
38
- bloqade/pyqrack/reg.py,sha256=75XW6qJLYOJp9BtpyYMUFmpqFfGrCydNLS40bKcghGM,1853
38
+ bloqade/pyqrack/reg.py,sha256=2GK7QW1dhCfqDHtwzYK-C37fNtnbGK8DhdhMrMidP_w,1859
39
39
  bloqade/pyqrack/target.py,sha256=c78VtLWAiDNp_0sXwvVzhaEoeFsr1fUVsupxWuo6p3s,3661
40
40
  bloqade/pyqrack/task.py,sha256=nRmI3tM_y4134_Uld-D9xwNXG9ie-OHNAqwRT5Ss-Y0,5266
41
41
  bloqade/pyqrack/noise/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -104,7 +104,7 @@ bloqade/qasm2/parse/qasm2.lark,sha256=IYrBydUoVLn1VCNDPP5uNN5BHDET3fQ2yG11cOy900
104
104
  bloqade/qasm2/parse/visitor.py,sha256=W4NUkBw97e3Z4Y1ek6jVNn-5lLVd3A5HXxc-FYTGYbY,427
105
105
  bloqade/qasm2/parse/visitor.pyi,sha256=JafCo1QztL6fvmWtJXu4dlqwbTJ6iLVrSa8L-Zd72t4,1851
106
106
  bloqade/qasm2/passes/__init__.py,sha256=9vz9F9Mgb5OFgnPWqw8pOJ-7r-tShoa7XevJ41ZmPXM,262
107
- bloqade/qasm2/passes/fold.py,sha256=NMT9MVpc7eWtqmdCztcztrfVewk5SCz5OTDMjSNPGaE,3046
107
+ bloqade/qasm2/passes/fold.py,sha256=OA4mVarUYRAfZSODOA9wgoW7HNNmpQWfPG5qGVEbA6I,1117
108
108
  bloqade/qasm2/passes/glob.py,sha256=qGmUTJSvDPf6qatapg4U69bTRKOAwZEHcFdts3mRxjI,3563
109
109
  bloqade/qasm2/passes/lift_qubits.py,sha256=VgIuqaZecozA3cwGAq8Nzqdv8IqQlzyQv2XlaqY4H4g,759
110
110
  bloqade/qasm2/passes/noise.py,sha256=w7U91jOAabcCZZXm8uPxojsVRtcIkxtpZS2hwEDsDN0,2709
@@ -130,11 +130,10 @@ bloqade/qbraid/schema.py,sha256=dTPexUFOiBNBnFv0GEbGh6jpIbMIFHk4hFXmXbeihxA,7854
130
130
  bloqade/qbraid/simulation_result.py,sha256=zdCJcAdbQkEDzFFuC2q3gqOFTOLAXHk4wh8RRDB6cgc,3956
131
131
  bloqade/qbraid/target.py,sha256=LcFHHyLe74yBmrHI9251xHgLN_nUz35lN8RPNwrT6mI,3149
132
132
  bloqade/rewrite/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
133
- bloqade/rewrite/passes/__init__.py,sha256=Qfe1PDADGySGuqNn5UuXiH48P70EykEMDaEKkd80ikk,71
134
- bloqade/rewrite/passes/canonicalize_ilist.py,sha256=LmX09aPjagT6NzU-M87V8kZaCGkYR_qvmtRNCRuVK1U,689
133
+ bloqade/rewrite/passes/__init__.py,sha256=-J8Ng97AlSCy6hJGmQORbVPjSCWhXdyU4EJx6XHnqXE,139
134
+ bloqade/rewrite/passes/aggressive_unroll.py,sha256=bXXOjooo_qJVIejniSfPMxa9ySrTaK3C57PgkpYa1dw,3025
135
+ bloqade/rewrite/passes/canonicalize_ilist.py,sha256=Y7twcmmtEEnXb4ulKhLi7JFBicCMxaP76_KiQMkOq7w,749
135
136
  bloqade/rewrite/rules/__init__.py,sha256=3e1Z5T3INqNtP6OU0Vivu_SdMOR_2KDixeA0Yjoddgg,82
136
- bloqade/rewrite/rules/flatten_ilist.py,sha256=QoIxMaBXSlatpWzi5s_MAPnV3bV3GeoWc31RBw0WQ3s,1465
137
- bloqade/rewrite/rules/inline_getitem_ilist.py,sha256=uIXQRCsr3_GPMciDT4ghI-ezhQmkDcGcC6pguABPUVw,875
138
137
  bloqade/rewrite/rules/split_ifs.py,sha256=KhwvUx-oBrBO2F1j-J5kwNbdnrnEZcZtJflzyQm-UOI,2613
139
138
  bloqade/squin/__init__.py,sha256=j9jgH39eQHedbVR9poKx2YHxOihclAI0GpIA05NejHM,675
140
139
  bloqade/squin/_typeinfer.py,sha256=bilWfC6whTMwewFCqDgB6vDHZsgXPr3azNOYqqnvtB4,780
@@ -243,7 +242,7 @@ bloqade/visual/animation/runtime/atoms.py,sha256=EmjxhujLiHHPS_HtH_B-7TiqeHgvW5u
243
242
  bloqade/visual/animation/runtime/ppoly.py,sha256=JB9IP53N1w6adBJEue6J5Nmj818Id9JvrlgrmiQTU1I,1385
244
243
  bloqade/visual/animation/runtime/qpustate.py,sha256=rlmxQeJSvaohXrTpXQL5y-NJcpvfW33xPaYM1slv7cc,4270
245
244
  bloqade/visual/animation/runtime/utils.py,sha256=ju9IzOWX-vKwfpqUjlUKu3Ssr_UFPFFq-tzH_Nqyo_c,1212
246
- bloqade_circuit-0.7.8.dist-info/METADATA,sha256=svrqjS1xWz1xDQDyERLzAfIUnKfY-9uVedF-S_aGS3U,3724
247
- bloqade_circuit-0.7.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
248
- bloqade_circuit-0.7.8.dist-info/licenses/LICENSE,sha256=S5GIJwR6QCixPA9wryYb44ZEek0Nz4rt_zLUqP05UbU,13160
249
- bloqade_circuit-0.7.8.dist-info/RECORD,,
245
+ bloqade_circuit-0.7.9.dist-info/METADATA,sha256=VhYLXjeRULFvq59sRDSx_0bLWHDbVbK1sF4CTNTmSOY,3724
246
+ bloqade_circuit-0.7.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
247
+ bloqade_circuit-0.7.9.dist-info/licenses/LICENSE,sha256=S5GIJwR6QCixPA9wryYb44ZEek0Nz4rt_zLUqP05UbU,13160
248
+ bloqade_circuit-0.7.9.dist-info/RECORD,,
@@ -1,51 +0,0 @@
1
- from dataclasses import dataclass
2
-
3
- from kirin import ir
4
- from kirin.dialects import py, ilist
5
- from kirin.rewrite.abc import RewriteRule, RewriteResult
6
-
7
-
8
- @dataclass
9
- class FlattenAddOpIList(RewriteRule):
10
-
11
- def rewrite_Statement(self, node: ir.Statement) -> RewriteResult:
12
- if not isinstance(node, py.binop.Add):
13
- return RewriteResult()
14
-
15
- # check if we are adding two ilist.New objects
16
- new_data = ()
17
-
18
- # lhs:
19
- if not isinstance(node.lhs.owner, ilist.New):
20
- if not (
21
- isinstance(node.lhs.owner, py.Constant)
22
- and isinstance(
23
- const_ilist := node.lhs.owner.value.unwrap(), ilist.IList
24
- )
25
- and len(const_ilist.data) == 0
26
- ):
27
- return RewriteResult()
28
-
29
- else:
30
- new_data += node.lhs.owner.values
31
-
32
- # rhs:
33
- if not isinstance(node.rhs.owner, ilist.New):
34
- if not (
35
- isinstance(node.rhs.owner, py.Constant)
36
- and isinstance(
37
- const_ilist := node.rhs.owner.value.unwrap(), ilist.IList
38
- )
39
- and len(const_ilist.data) == 0
40
- ):
41
- return RewriteResult()
42
-
43
- else:
44
- new_data += node.rhs.owner.values
45
-
46
- new_stmt = ilist.New(values=new_data)
47
- node.replace_by(new_stmt)
48
-
49
- return RewriteResult(
50
- has_done_something=True,
51
- )
@@ -1,31 +0,0 @@
1
- from dataclasses import dataclass
2
-
3
- from kirin import ir
4
- from kirin.analysis import const
5
- from kirin.dialects import py, ilist
6
- from kirin.rewrite.abc import RewriteRule, RewriteResult
7
-
8
-
9
- @dataclass
10
- class InlineGetItemFromIList(RewriteRule):
11
- constprop_result: dict[ir.SSAValue, const.Result]
12
-
13
- def rewrite_Statement(self, node: ir.Statement) -> RewriteResult:
14
- if not isinstance(node, py.indexing.GetItem):
15
- return RewriteResult()
16
-
17
- if not isinstance(node.obj.owner, ilist.New):
18
- return RewriteResult()
19
-
20
- if not isinstance(
21
- index_value := self.constprop_result.get(node.index), const.Value
22
- ):
23
- return RewriteResult()
24
-
25
- elem_ssa = node.obj.owner.values[index_value.data]
26
-
27
- node.result.replace_by(elem_ssa)
28
-
29
- return RewriteResult(
30
- has_done_something=True,
31
- )