bloqade-circuit 0.7.7__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/cirq_utils/__init__.py +1 -1
- bloqade/cirq_utils/noise/model.py +4 -3
- bloqade/cirq_utils/parallelize.py +9 -6
- bloqade/pyqrack/base.py +6 -0
- bloqade/pyqrack/reg.py +6 -1
- bloqade/pyqrack/squin/noise/native.py +1 -1
- bloqade/pyqrack/squin/qubit.py +20 -3
- bloqade/qasm2/passes/fold.py +14 -73
- bloqade/rewrite/passes/__init__.py +1 -0
- bloqade/rewrite/passes/aggressive_unroll.py +93 -0
- bloqade/rewrite/passes/canonicalize_ilist.py +18 -14
- bloqade/squin/cirq/lowering.py +5 -0
- bloqade/squin/qubit.py +25 -2
- {bloqade_circuit-0.7.7.dist-info → bloqade_circuit-0.7.9.dist-info}/METADATA +4 -5
- {bloqade_circuit-0.7.7.dist-info → bloqade_circuit-0.7.9.dist-info}/RECORD +17 -18
- bloqade/rewrite/rules/flatten_ilist.py +0 -51
- bloqade/rewrite/rules/inline_getitem_ilist.py +0 -31
- {bloqade_circuit-0.7.7.dist-info → bloqade_circuit-0.7.9.dist-info}/WHEEL +0 -0
- {bloqade_circuit-0.7.7.dist-info → bloqade_circuit-0.7.9.dist-info}/licenses/LICENSE +0 -0
bloqade/cirq_utils/__init__.py
CHANGED
|
@@ -2,7 +2,7 @@ from . import noise as noise
|
|
|
2
2
|
from .parallelize import (
|
|
3
3
|
transpile as transpile,
|
|
4
4
|
parallelize as parallelize,
|
|
5
|
-
|
|
5
|
+
remove_tags as remove_tags,
|
|
6
6
|
auto_similarity as auto_similarity,
|
|
7
7
|
block_similarity as block_similarity,
|
|
8
8
|
moment_similarity as moment_similarity,
|
|
@@ -357,9 +357,10 @@ class GeminiOneZoneNoiseModelConflictGraphMoves(GeminiOneZoneNoiseModel):
|
|
|
357
357
|
def noisy_moment(self, moment, system_qubits):
|
|
358
358
|
# Moment with original ops
|
|
359
359
|
original_moment = moment
|
|
360
|
-
assert np.all(
|
|
361
|
-
|
|
362
|
-
|
|
360
|
+
assert np.all([isinstance(q, cirq.GridQubit) for q in system_qubits]), (
|
|
361
|
+
"Found a qubit that is not a GridQubit. In order for the conflict graph to know the qubit geometry, "
|
|
362
|
+
"all qubits in the circuit must be defined as cirq.GridQubit objects."
|
|
363
|
+
)
|
|
363
364
|
# Check if the moment is empty
|
|
364
365
|
if len(moment.operations) == 0:
|
|
365
366
|
move_moments = []
|
|
@@ -136,7 +136,7 @@ def auto_similarity(
|
|
|
136
136
|
return cirq.Circuit(flattened_circuit), weights
|
|
137
137
|
|
|
138
138
|
|
|
139
|
-
def
|
|
139
|
+
def remove_tags(circuit: cirq.Circuit) -> cirq.Circuit:
|
|
140
140
|
"""
|
|
141
141
|
Removes all tags from the circuit
|
|
142
142
|
|
|
@@ -146,10 +146,11 @@ def no_similarity(circuit: cirq.Circuit) -> cirq.Circuit:
|
|
|
146
146
|
Returns:
|
|
147
147
|
[0] - cirq.Circuit - the circuit with all tags removed.
|
|
148
148
|
"""
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
149
|
+
|
|
150
|
+
def remove_tag(op: cirq.Operation, _):
|
|
151
|
+
return op.untagged
|
|
152
|
+
|
|
153
|
+
return cirq.map_operations(circuit, remove_tag)
|
|
153
154
|
|
|
154
155
|
|
|
155
156
|
def to_dag_circuit(circuit: cirq.Circuit, can_reorder=None) -> nx.DiGraph:
|
|
@@ -399,4 +400,6 @@ def parallelize(
|
|
|
399
400
|
)
|
|
400
401
|
# Convert the epochs to a cirq circuit.
|
|
401
402
|
moments = map(cirq.Moment, epochs)
|
|
402
|
-
|
|
403
|
+
circuit = cirq.Circuit(moments)
|
|
404
|
+
|
|
405
|
+
return remove_tags(circuit)
|
bloqade/pyqrack/base.py
CHANGED
|
@@ -146,7 +146,13 @@ class PyQrackInterpreter(Interpreter, typing.Generic[MemoryType]):
|
|
|
146
146
|
loss_m_result: Measurement = field(default=Measurement.One, kw_only=True)
|
|
147
147
|
"""The value of a measurement result when a qubit is lost."""
|
|
148
148
|
|
|
149
|
+
global_measurement_id: int = field(init=False, default=0)
|
|
150
|
+
|
|
149
151
|
def initialize(self) -> Self:
|
|
150
152
|
super().initialize()
|
|
151
153
|
self.memory.reset() # reset allocated qubits
|
|
152
154
|
return self
|
|
155
|
+
|
|
156
|
+
def set_global_measurement_id(self, m: Measurement):
|
|
157
|
+
m.measurement_id = self.global_measurement_id
|
|
158
|
+
self.global_measurement_id += 1
|
bloqade/pyqrack/reg.py
CHANGED
|
@@ -3,14 +3,19 @@ from typing import TYPE_CHECKING
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
|
|
5
5
|
from bloqade.qasm2.types import Qubit
|
|
6
|
+
from bloqade.squin.types import MeasurementResult
|
|
6
7
|
|
|
7
8
|
if TYPE_CHECKING:
|
|
8
9
|
from pyqrack import QrackSimulator
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
class Measurement(enum.IntEnum):
|
|
12
|
+
class Measurement(MeasurementResult, enum.IntEnum):
|
|
12
13
|
"""Enumeration of measurement results."""
|
|
13
14
|
|
|
15
|
+
def __init__(self, measurement_id: int = 0) -> None:
|
|
16
|
+
super().__init__()
|
|
17
|
+
self.measurement_id = measurement_id
|
|
18
|
+
|
|
14
19
|
Zero = 0
|
|
15
20
|
One = 1
|
|
16
21
|
Lost = enum.auto()
|
bloqade/pyqrack/squin/qubit.py
CHANGED
|
@@ -4,7 +4,7 @@ from kirin import interp
|
|
|
4
4
|
from kirin.dialects import ilist
|
|
5
5
|
|
|
6
6
|
from bloqade.squin import qubit
|
|
7
|
-
from bloqade.pyqrack.reg import QubitState, PyQrackQubit
|
|
7
|
+
from bloqade.pyqrack.reg import QubitState, Measurement, PyQrackQubit
|
|
8
8
|
from bloqade.pyqrack.base import PyQrackInterpreter
|
|
9
9
|
|
|
10
10
|
from .runtime import OperatorRuntimeABC
|
|
@@ -41,9 +41,12 @@ class PyQrackMethods(interp.MethodTable):
|
|
|
41
41
|
|
|
42
42
|
def _measure_qubit(self, qbit: PyQrackQubit, interp: PyQrackInterpreter):
|
|
43
43
|
if qbit.is_active():
|
|
44
|
-
|
|
44
|
+
m = Measurement(bool(qbit.sim_reg.m(qbit.addr)))
|
|
45
45
|
else:
|
|
46
|
-
|
|
46
|
+
m = Measurement(interp.loss_m_result)
|
|
47
|
+
|
|
48
|
+
interp.set_global_measurement_id(m)
|
|
49
|
+
return m
|
|
47
50
|
|
|
48
51
|
@interp.impl(qubit.MeasureQubitList)
|
|
49
52
|
def measure_qubit_list(
|
|
@@ -63,3 +66,17 @@ class PyQrackMethods(interp.MethodTable):
|
|
|
63
66
|
qbit: PyQrackQubit = frame.get(stmt.qubit)
|
|
64
67
|
result = self._measure_qubit(qbit, interp)
|
|
65
68
|
return (result,)
|
|
69
|
+
|
|
70
|
+
@interp.impl(qubit.QubitId)
|
|
71
|
+
def qubit_id(
|
|
72
|
+
self, interp: PyQrackInterpreter, frame: interp.Frame, stmt: qubit.QubitId
|
|
73
|
+
):
|
|
74
|
+
qbit: PyQrackQubit = frame.get(stmt.qubit)
|
|
75
|
+
return (qbit.addr,)
|
|
76
|
+
|
|
77
|
+
@interp.impl(qubit.MeasurementId)
|
|
78
|
+
def measurement_id(
|
|
79
|
+
self, interp: PyQrackInterpreter, frame: interp.Frame, stmt: qubit.MeasurementId
|
|
80
|
+
):
|
|
81
|
+
measurement: Measurement = frame.get(stmt.measurement)
|
|
82
|
+
return (measurement.measurement_id,)
|
bloqade/qasm2/passes/fold.py
CHANGED
|
@@ -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
|
|
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
|
-
|
|
39
|
-
|
|
23
|
+
def inline_simple(node: ir.Statement):
|
|
24
|
+
if isinstance(node, expr.GateFunction):
|
|
25
|
+
return self.inline_gate_subroutine
|
|
40
26
|
|
|
41
|
-
|
|
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
|
-
|
|
56
|
-
|
|
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
|
-
|
|
68
|
-
|
|
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
|
-
|
|
84
|
-
|
|
36
|
+
if self.unroll_ifs:
|
|
37
|
+
result = UnrollIfs(mt.dialects).unsafe_run(mt).join(result)
|
|
85
38
|
|
|
86
|
-
|
|
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
|
|
@@ -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.
|
|
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
|
-
|
|
15
|
+
fold_pass: passes.Fold = field(init=False)
|
|
20
16
|
|
|
21
|
-
|
|
17
|
+
def __post_init__(self):
|
|
18
|
+
self.fold_pass = passes.Fold(self.dialects, no_raise=self.no_raise)
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
bloqade/squin/cirq/lowering.py
CHANGED
|
@@ -144,6 +144,11 @@ class Squin(lowering.LoweringABC[CirqNode]):
|
|
|
144
144
|
qbits = self.lower_qubit_getindices(state, node.qubits)
|
|
145
145
|
return state.current_frame.push(qubit.Apply(operator=op_, qubits=qbits))
|
|
146
146
|
|
|
147
|
+
def visit_TaggedOperation(
|
|
148
|
+
self, state: lowering.State[CirqNode], node: cirq.TaggedOperation
|
|
149
|
+
):
|
|
150
|
+
state.lower(node.untagged)
|
|
151
|
+
|
|
147
152
|
def lower_measurement(
|
|
148
153
|
self, state: lowering.State[CirqNode], node: cirq.GateOperation
|
|
149
154
|
):
|
bloqade/squin/qubit.py
CHANGED
|
@@ -79,6 +79,20 @@ class MeasureQubitList(ir.Statement):
|
|
|
79
79
|
result: ir.ResultValue = info.result(ilist.IListType[MeasurementResultType])
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
@statement(dialect=dialect)
|
|
83
|
+
class QubitId(ir.Statement):
|
|
84
|
+
traits = frozenset({lowering.FromPythonCall(), ir.Pure()})
|
|
85
|
+
qubit: ir.SSAValue = info.argument(QubitType)
|
|
86
|
+
result: ir.ResultValue = info.result(types.Int)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@statement(dialect=dialect)
|
|
90
|
+
class MeasurementId(ir.Statement):
|
|
91
|
+
traits = frozenset({lowering.FromPythonCall(), ir.Pure()})
|
|
92
|
+
measurement: ir.SSAValue = info.argument(MeasurementResultType)
|
|
93
|
+
result: ir.ResultValue = info.result(types.Int)
|
|
94
|
+
|
|
95
|
+
|
|
82
96
|
# NOTE: no dependent types in Python, so we have to mark it Any...
|
|
83
97
|
@wraps(New)
|
|
84
98
|
def new(n_qubits: int) -> ilist.IList[Qubit, Any]:
|
|
@@ -127,9 +141,10 @@ def measure(input: Any) -> Any:
|
|
|
127
141
|
input: A qubit or a list of qubits to measure.
|
|
128
142
|
|
|
129
143
|
Returns:
|
|
130
|
-
|
|
131
|
-
a single
|
|
144
|
+
MeasurementResult | list[MeasurementResult]: The result of the measurement. If a single qubit is measured,
|
|
145
|
+
a single result is returned. If a list of qubits is measured, a list of results
|
|
132
146
|
is returned.
|
|
147
|
+
A MeasurementResult can represent both 0 and 1, but also atoms that are lost.
|
|
133
148
|
"""
|
|
134
149
|
...
|
|
135
150
|
|
|
@@ -169,3 +184,11 @@ def broadcast(operator: Op, *qubits: ilist.IList[Qubit, OpSize] | list[Qubit]) -
|
|
|
169
184
|
None
|
|
170
185
|
"""
|
|
171
186
|
...
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
@wraps(QubitId)
|
|
190
|
+
def get_qubit_id(qubit: Qubit) -> int: ...
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
@wraps(MeasurementId)
|
|
194
|
+
def get_measurement_id(measurement: MeasurementResult) -> int: ...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bloqade-circuit
|
|
3
|
-
Version: 0.7.
|
|
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
|
|
@@ -9,8 +9,7 @@ Requires-Dist: kirin-toolchain~=0.17.23
|
|
|
9
9
|
Requires-Dist: numpy>=1.22.0
|
|
10
10
|
Requires-Dist: pandas>=2.2.3
|
|
11
11
|
Requires-Dist: pydantic<2.11.0,>=1.3.0
|
|
12
|
-
Requires-Dist: pyqrack-cpu>=1.69.
|
|
13
|
-
Requires-Dist: pyqrack>=1.69.0; sys_platform == 'darwin-arm64'
|
|
12
|
+
Requires-Dist: pyqrack-cpu>=1.69.1
|
|
14
13
|
Requires-Dist: rich>=13.9.4
|
|
15
14
|
Requires-Dist: scipy>=1.13.1
|
|
16
15
|
Provides-Extra: cirq
|
|
@@ -18,9 +17,9 @@ Requires-Dist: cirq-core>=1.4.1; extra == 'cirq'
|
|
|
18
17
|
Requires-Dist: cirq-core[contrib]>=1.4.1; extra == 'cirq'
|
|
19
18
|
Requires-Dist: qpsolvers[clarabel]>=4.7.0; extra == 'cirq'
|
|
20
19
|
Provides-Extra: pyqrack-cuda
|
|
21
|
-
Requires-Dist: pyqrack-cuda>=1.69.
|
|
20
|
+
Requires-Dist: pyqrack-cuda>=1.69.1; extra == 'pyqrack-cuda'
|
|
22
21
|
Provides-Extra: pyqrack-opencl
|
|
23
|
-
Requires-Dist: pyqrack>=1.69.
|
|
22
|
+
Requires-Dist: pyqrack>=1.69.1; extra == 'pyqrack-opencl'
|
|
24
23
|
Provides-Extra: qasm2
|
|
25
24
|
Requires-Dist: lark>=1.2.2; extra == 'qasm2'
|
|
26
25
|
Provides-Extra: qbraid
|
|
@@ -13,13 +13,13 @@ bloqade/analysis/measure_id/__init__.py,sha256=r_R_br1e3H7ZzwkeQw4TnDAP4M_bUaRlR
|
|
|
13
13
|
bloqade/analysis/measure_id/analysis.py,sha256=D8KcV8aL1yrqKhtqgaqMArX-PGXYcFXumEC5tx36plU,1974
|
|
14
14
|
bloqade/analysis/measure_id/impls.py,sha256=q_HKSxptGfOvvGrRcpl42UGoe7eRL2-5dIGiA0tDyrA,6866
|
|
15
15
|
bloqade/analysis/measure_id/lattice.py,sha256=WPrn0R79umCH909BFWsUJ64qx9n_3KYimIW5UaXNuGU,1891
|
|
16
|
-
bloqade/cirq_utils/__init__.py,sha256=
|
|
16
|
+
bloqade/cirq_utils/__init__.py,sha256=NOChrzb4vxb3xHKxM0gg7HdZ7R76X5yU8RJZ9hECXWs,276
|
|
17
17
|
bloqade/cirq_utils/lineprog.py,sha256=JosrhfeOHI9FycUT_sYFj8TBzLpo97TL8zK-Ap2U4eQ,11021
|
|
18
|
-
bloqade/cirq_utils/parallelize.py,sha256=
|
|
18
|
+
bloqade/cirq_utils/parallelize.py,sha256=u9AP6l7YwBatFfIvrcCjbcYMiavk7MU6HKSKPkqlxtY,13803
|
|
19
19
|
bloqade/cirq_utils/noise/__init__.py,sha256=hUBi53U0wE4u3AqGh5cNdgdCspt3O-Vw-SR68cfBZYc,421
|
|
20
20
|
bloqade/cirq_utils/noise/_two_zone_utils.py,sha256=iq4nwdJQITFlGB61wfrV7vyPA2194p-i_nv36powZ90,17883
|
|
21
21
|
bloqade/cirq_utils/noise/conflict_graph.py,sha256=ZUwPWTknrb6SgtZUVPeICn3YA-nUeWQJDuKKX5jL9tE,7179
|
|
22
|
-
bloqade/cirq_utils/noise/model.py,sha256=
|
|
22
|
+
bloqade/cirq_utils/noise/model.py,sha256=tKzK_d1u81miQu1LMeum7wKRXeuyP1M182SEJ8lNTbo,18605
|
|
23
23
|
bloqade/cirq_utils/noise/transform.py,sha256=pauFnOKbk2QjxeyXEV_x2zyRGypr5wiQ6ySirU7C2zg,2278
|
|
24
24
|
bloqade/native/__init__.py,sha256=MtQZmq7KqNGkjxsO_22DpY-13X23Ovw8JKs7lfuv55w,443
|
|
25
25
|
bloqade/native/_prelude.py,sha256=znle4mSTLZtRMCmmiZ-bCPfHqNdgVxsKuY64Fgj2kko,1258
|
|
@@ -32,10 +32,10 @@ bloqade/native/stdlib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
|
|
|
32
32
|
bloqade/native/stdlib/broadcast.py,sha256=0DEK6pRcz0IG5BZHt0sV1wZpDvlJgvw4-Qwd1xYLSYM,6141
|
|
33
33
|
bloqade/native/stdlib/simple.py,sha256=mK_p9x_TUr4g-q-Q4LfbVBtXxBS21XPh1meyCC4to_k,5416
|
|
34
34
|
bloqade/pyqrack/__init__.py,sha256=OV8-2fw44gP_JgY8mAUiwISO_qYxS-t0fKsbuUB-r9Y,861
|
|
35
|
-
bloqade/pyqrack/base.py,sha256=
|
|
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=
|
|
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
|
|
@@ -47,11 +47,11 @@ bloqade/pyqrack/qasm2/parallel.py,sha256=ITetuXOH2KUDpDOBuFnJoz2DhduvyBC72cOAOOi
|
|
|
47
47
|
bloqade/pyqrack/qasm2/uop.py,sha256=bLZONsEK15ymFGIQwy7muQv-TX0mvLrECuMp1Y3XTfA,8612
|
|
48
48
|
bloqade/pyqrack/squin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
49
|
bloqade/pyqrack/squin/op.py,sha256=m9QiQgQnKy1tYvrieU6MjXf_b9i2fovj4r2novcQwIc,5535
|
|
50
|
-
bloqade/pyqrack/squin/qubit.py,sha256=
|
|
50
|
+
bloqade/pyqrack/squin/qubit.py,sha256=M32AhO3HRc_-FrOj7h_1Arj6jr9WiaHoxc4aeU1KoIY,2859
|
|
51
51
|
bloqade/pyqrack/squin/runtime.py,sha256=3iVCN3XMUL8uk-bm0y4HSaVU7i5xZsNm5sY285rUKQE,15583
|
|
52
52
|
bloqade/pyqrack/squin/wire.py,sha256=rqlAeU-r_EHOwJMqHrEAxpZ_rKsvUpwGG7MP4BW75Nw,1658
|
|
53
53
|
bloqade/pyqrack/squin/noise/__init__.py,sha256=uXgRQPOrHNRp3k2ff2HD8mheUEaqxZPKEnwV-s4BiV4,31
|
|
54
|
-
bloqade/pyqrack/squin/noise/native.py,sha256=
|
|
54
|
+
bloqade/pyqrack/squin/noise/native.py,sha256=gs2At4fDKTN3LJl5DVZ-Z3Pn3YTSwZCQCAoPrMJxEcQ,2287
|
|
55
55
|
bloqade/qasm2/__init__.py,sha256=W9dR4Qnvigc7e7Ay7puSJHAIuiQk8vWqY-W64SMu5oU,515
|
|
56
56
|
bloqade/qasm2/_qasm_loading.py,sha256=dSfjlB6Bm1ednfxc9L42dEa48s5q4N5SGQ9Iw21sBZQ,4753
|
|
57
57
|
bloqade/qasm2/_wrappers.py,sha256=4x3fldC4sV2K_XZ0FPZOorQKAbs_7pualListXtak4A,11148
|
|
@@ -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=
|
|
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,18 +130,17 @@ 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
|
|
134
|
-
bloqade/rewrite/passes/
|
|
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
|
|
141
140
|
bloqade/squin/groups.py,sha256=RXGJnNZUSXF_f5ljjhZ9At8UhaijayoxFoWvxEsUOWc,1310
|
|
142
141
|
bloqade/squin/lowering.py,sha256=bfrPjx6t2mnd1qoBshF_RW-FXMWg3TOUA6XKUeONyig,2560
|
|
143
142
|
bloqade/squin/parallel.py,sha256=X6Ps9kQIgnFMlZO14y2ntdxvivqbIP28PAWF8KmxByM,5172
|
|
144
|
-
bloqade/squin/qubit.py,sha256=
|
|
143
|
+
bloqade/squin/qubit.py,sha256=eX24PLk0CILaooQZDD6gv5MwSAXSncazv86M-cyT3cc,5649
|
|
145
144
|
bloqade/squin/types.py,sha256=T3lkqid4HEWuAK_wRns_p-K5DbLDwlldoyZtVay7A3o,119
|
|
146
145
|
bloqade/squin/wire.py,sha256=GZhF0EHCu7OU70zTV_N83yann-eQnYG_lM2u0QYFoAs,6596
|
|
147
146
|
bloqade/squin/analysis/__init__.py,sha256=DvnFHmEqMxRG92jVT3ZWwAQDTb6DC4fZDTV8ZSLZgP0,43
|
|
@@ -152,7 +151,7 @@ bloqade/squin/analysis/nsites/analysis.py,sha256=rIe1RU1MZRItcE2aB8DYahLrv73HfD3
|
|
|
152
151
|
bloqade/squin/analysis/nsites/impls.py,sha256=wSNWjNmgwCP35FgmreyLKmRYedxlebWi7LhsEq9jPs4,3097
|
|
153
152
|
bloqade/squin/analysis/nsites/lattice.py,sha256=ruh0808SHtj3ecuT-C3AZTsLY2j3DRhtezGiTZvcuVs,942
|
|
154
153
|
bloqade/squin/cirq/__init__.py,sha256=7OYYboSl5lPwdWOKk4AJgm1s1lBX_WAstVqPfaynSv8,10156
|
|
155
|
-
bloqade/squin/cirq/lowering.py,sha256=
|
|
154
|
+
bloqade/squin/cirq/lowering.py,sha256=i5-IakuJGo3CYw7VNHqB0uM3AiFMw__a3oizKce3F7I,17937
|
|
156
155
|
bloqade/squin/cirq/emit/emit_circuit.py,sha256=JVFXiaSB7A9kamRwCjLqs03Sel4PVCBT-6kRNRWX-jo,4393
|
|
157
156
|
bloqade/squin/cirq/emit/noise.py,sha256=rESjGC_66s2Y4FwwYda4rY3mYHYjbqLlKE_vnqpZDYI,1534
|
|
158
157
|
bloqade/squin/cirq/emit/op.py,sha256=u1FoOlbz7NNXPlU-hMbnX_yRB5suKbsEm2jF3Ts4f68,5764
|
|
@@ -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.
|
|
247
|
-
bloqade_circuit-0.7.
|
|
248
|
-
bloqade_circuit-0.7.
|
|
249
|
-
bloqade_circuit-0.7.
|
|
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
|
-
)
|
|
File without changes
|
|
File without changes
|