bloqade-circuit 0.1.0__py3-none-any.whl → 0.2.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/address/impls.py +5 -9
- bloqade/analysis/address/lattice.py +1 -1
- bloqade/analysis/fidelity/__init__.py +1 -0
- bloqade/analysis/fidelity/analysis.py +69 -0
- bloqade/device.py +130 -0
- bloqade/noise/__init__.py +2 -1
- bloqade/noise/fidelity.py +51 -0
- bloqade/noise/native/model.py +1 -2
- bloqade/noise/native/rewrite.py +5 -5
- bloqade/noise/native/stmts.py +40 -11
- bloqade/pyqrack/__init__.py +8 -2
- bloqade/pyqrack/base.py +24 -3
- bloqade/pyqrack/device.py +166 -0
- bloqade/pyqrack/noise/native.py +1 -2
- bloqade/pyqrack/qasm2/core.py +31 -15
- bloqade/pyqrack/qasm2/glob.py +28 -0
- bloqade/pyqrack/qasm2/uop.py +9 -1
- bloqade/pyqrack/reg.py +17 -49
- bloqade/pyqrack/squin/__init__.py +0 -0
- bloqade/pyqrack/squin/op.py +154 -0
- bloqade/pyqrack/squin/qubit.py +85 -0
- bloqade/pyqrack/squin/runtime.py +515 -0
- bloqade/pyqrack/squin/wire.py +69 -0
- bloqade/pyqrack/target.py +9 -2
- bloqade/pyqrack/task.py +30 -0
- bloqade/qasm2/_wrappers.py +11 -1
- bloqade/qasm2/dialects/core/stmts.py +15 -4
- bloqade/qasm2/dialects/expr/_emit.py +9 -8
- bloqade/qasm2/emit/base.py +4 -2
- bloqade/qasm2/emit/gate.py +0 -14
- bloqade/qasm2/emit/main.py +19 -15
- bloqade/qasm2/emit/target.py +2 -6
- bloqade/qasm2/glob.py +1 -1
- bloqade/qasm2/parse/lowering.py +124 -1
- bloqade/qasm2/passes/glob.py +3 -3
- bloqade/qasm2/passes/lift_qubits.py +26 -0
- bloqade/qasm2/passes/noise.py +6 -14
- bloqade/qasm2/passes/parallel.py +3 -3
- bloqade/qasm2/passes/py2qasm.py +1 -2
- bloqade/qasm2/passes/qasm2py.py +1 -2
- bloqade/qasm2/rewrite/desugar.py +6 -6
- bloqade/qasm2/rewrite/glob.py +9 -9
- bloqade/qasm2/rewrite/heuristic_noise.py +30 -38
- bloqade/qasm2/rewrite/insert_qubits.py +34 -0
- bloqade/qasm2/rewrite/native_gates.py +54 -55
- bloqade/qasm2/rewrite/parallel_to_uop.py +9 -9
- bloqade/qasm2/rewrite/uop_to_parallel.py +20 -22
- bloqade/qasm2/types.py +3 -6
- bloqade/qbraid/schema.py +10 -12
- bloqade/squin/__init__.py +1 -1
- bloqade/squin/analysis/nsites/analysis.py +4 -6
- bloqade/squin/analysis/nsites/impls.py +2 -6
- bloqade/squin/analysis/schedule.py +1 -1
- bloqade/squin/groups.py +15 -7
- bloqade/squin/noise/__init__.py +27 -0
- bloqade/squin/noise/_dialect.py +3 -0
- bloqade/squin/noise/stmts.py +59 -0
- bloqade/squin/op/__init__.py +35 -5
- bloqade/squin/op/number.py +5 -0
- bloqade/squin/op/rewrite.py +46 -0
- bloqade/squin/op/stmts.py +23 -2
- bloqade/squin/op/types.py +14 -0
- bloqade/squin/qubit.py +79 -11
- bloqade/squin/rewrite/__init__.py +0 -0
- bloqade/squin/rewrite/measure_desugar.py +33 -0
- bloqade/squin/wire.py +31 -2
- bloqade/stim/emit/stim.py +1 -1
- bloqade/task.py +94 -0
- bloqade/visual/animation/base.py +25 -15
- {bloqade_circuit-0.1.0.dist-info → bloqade_circuit-0.2.0.dist-info}/METADATA +8 -2
- {bloqade_circuit-0.1.0.dist-info → bloqade_circuit-0.2.0.dist-info}/RECORD +73 -52
- bloqade/squin/op/complex.py +0 -6
- {bloqade_circuit-0.1.0.dist-info → bloqade_circuit-0.2.0.dist-info}/WHEEL +0 -0
- {bloqade_circuit-0.1.0.dist-info → bloqade_circuit-0.2.0.dist-info}/licenses/LICENSE +0 -0
bloqade/squin/qubit.py
CHANGED
|
@@ -7,7 +7,7 @@ Depends on:
|
|
|
7
7
|
- `kirin.dialects.ilist`: provides the `ilist.IListType` type for lists of qubits.
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
from typing import Any
|
|
10
|
+
from typing import Any, overload
|
|
11
11
|
|
|
12
12
|
from kirin import ir, types, lowering
|
|
13
13
|
from kirin.decl import info, statement
|
|
@@ -35,21 +35,49 @@ class Apply(ir.Statement):
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
@statement(dialect=dialect)
|
|
38
|
-
class
|
|
38
|
+
class Broadcast(ir.Statement):
|
|
39
|
+
traits = frozenset({lowering.FromPythonCall()})
|
|
40
|
+
operator: ir.SSAValue = info.argument(OpType)
|
|
41
|
+
qubits: ir.SSAValue = info.argument(ilist.IListType[QubitType])
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@statement(dialect=dialect)
|
|
45
|
+
class MeasureAny(ir.Statement):
|
|
46
|
+
name = "measure"
|
|
47
|
+
|
|
48
|
+
traits = frozenset({lowering.FromPythonCall()})
|
|
49
|
+
input: ir.SSAValue = info.argument(types.Any)
|
|
50
|
+
result: ir.ResultValue = info.result(types.Any)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@statement(dialect=dialect)
|
|
54
|
+
class MeasureQubit(ir.Statement):
|
|
55
|
+
name = "measure.qubit"
|
|
56
|
+
|
|
57
|
+
traits = frozenset({lowering.FromPythonCall()})
|
|
58
|
+
qubit: ir.SSAValue = info.argument(ilist.IListType[QubitType])
|
|
59
|
+
result: ir.ResultValue = info.result(ilist.IListType[types.Bool])
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@statement(dialect=dialect)
|
|
63
|
+
class MeasureQubitList(ir.Statement):
|
|
64
|
+
name = "measure.qubit.list"
|
|
65
|
+
|
|
39
66
|
traits = frozenset({lowering.FromPythonCall()})
|
|
40
67
|
qubits: ir.SSAValue = info.argument(ilist.IListType[QubitType])
|
|
41
|
-
result: ir.ResultValue = info.result(types.
|
|
68
|
+
result: ir.ResultValue = info.result(ilist.IListType[types.Bool])
|
|
42
69
|
|
|
43
70
|
|
|
44
71
|
@statement(dialect=dialect)
|
|
45
72
|
class MeasureAndReset(ir.Statement):
|
|
46
73
|
traits = frozenset({lowering.FromPythonCall()})
|
|
47
74
|
qubits: ir.SSAValue = info.argument(ilist.IListType[QubitType])
|
|
48
|
-
result: ir.ResultValue = info.result(types.
|
|
75
|
+
result: ir.ResultValue = info.result(ilist.IListType[types.Bool])
|
|
49
76
|
|
|
50
77
|
|
|
51
78
|
@statement(dialect=dialect)
|
|
52
79
|
class Reset(ir.Statement):
|
|
80
|
+
traits = frozenset({lowering.FromPythonCall()})
|
|
53
81
|
qubits: ir.SSAValue = info.argument(ilist.IListType[QubitType])
|
|
54
82
|
|
|
55
83
|
|
|
@@ -71,6 +99,8 @@ def new(n_qubits: int) -> ilist.IList[Qubit, Any]:
|
|
|
71
99
|
def apply(operator: Op, qubits: ilist.IList[Qubit, Any] | list[Qubit]) -> None:
|
|
72
100
|
"""Apply an operator to a list of qubits.
|
|
73
101
|
|
|
102
|
+
Note, that when considering atom loss, lost qubits will be skipped.
|
|
103
|
+
|
|
74
104
|
Args:
|
|
75
105
|
operator: The operator to apply.
|
|
76
106
|
qubits: The list of qubits to apply the operator to. The size of the list
|
|
@@ -82,28 +112,66 @@ def apply(operator: Op, qubits: ilist.IList[Qubit, Any] | list[Qubit]) -> None:
|
|
|
82
112
|
...
|
|
83
113
|
|
|
84
114
|
|
|
85
|
-
@
|
|
86
|
-
def measure(
|
|
87
|
-
|
|
115
|
+
@overload
|
|
116
|
+
def measure(input: Qubit) -> bool: ...
|
|
117
|
+
@overload
|
|
118
|
+
def measure(input: ilist.IList[Qubit, Any] | list[Qubit]) -> ilist.IList[bool, Any]: ...
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@wraps(MeasureAny)
|
|
122
|
+
def measure(input: Any) -> Any:
|
|
123
|
+
"""Measure a qubit or qubits in the list.
|
|
88
124
|
|
|
89
125
|
Args:
|
|
90
|
-
|
|
126
|
+
input: A qubit or a list of qubits to measure.
|
|
91
127
|
|
|
92
128
|
Returns:
|
|
93
|
-
|
|
129
|
+
bool | list[bool]: The result of the measurement. If a single qubit is measured,
|
|
130
|
+
a single boolean is returned. If a list of qubits is measured, a list of booleans
|
|
131
|
+
is returned.
|
|
132
|
+
"""
|
|
133
|
+
...
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@wraps(Broadcast)
|
|
137
|
+
def broadcast(operator: Op, qubits: ilist.IList[Qubit, Any] | list[Qubit]) -> None:
|
|
138
|
+
"""Broadcast and apply an operator to a list of qubits. For example, an operator
|
|
139
|
+
that expects 2 qubits can be applied to a list of 2n qubits, where n is an integer > 0.
|
|
140
|
+
|
|
141
|
+
For controlled operators, the list of qubits is interpreted as sets of (controls, targets).
|
|
142
|
+
For example
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
apply(CX, [q0, q1, q2, q3])
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
is equivalent to
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
apply(CX, [q0, q1])
|
|
152
|
+
apply(CX, [q2, q3])
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
operator: The operator to broadcast and apply.
|
|
157
|
+
qubits: The list of qubits to broadcast and apply the operator to. The size of the list
|
|
158
|
+
must be inferable and match the number of qubits expected by the operator.
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
None
|
|
94
162
|
"""
|
|
95
163
|
...
|
|
96
164
|
|
|
97
165
|
|
|
98
166
|
@wraps(MeasureAndReset)
|
|
99
|
-
def measure_and_reset(qubits: ilist.IList[Qubit, Any]) ->
|
|
167
|
+
def measure_and_reset(qubits: ilist.IList[Qubit, Any]) -> ilist.IList[bool, Any]:
|
|
100
168
|
"""Measure the qubits in the list and reset them."
|
|
101
169
|
|
|
102
170
|
Args:
|
|
103
171
|
qubits: The list of qubits to measure and reset.
|
|
104
172
|
|
|
105
173
|
Returns:
|
|
106
|
-
|
|
174
|
+
list[bool]: The result of the measurement.
|
|
107
175
|
"""
|
|
108
176
|
...
|
|
109
177
|
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from kirin import ir, types
|
|
2
|
+
from kirin.dialects import ilist
|
|
3
|
+
from kirin.rewrite.abc import RewriteRule, RewriteResult
|
|
4
|
+
|
|
5
|
+
from bloqade.squin.qubit import QubitType, MeasureAny, MeasureQubit, MeasureQubitList
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class MeasureDesugarRule(RewriteRule):
|
|
9
|
+
"""
|
|
10
|
+
Desugar measure operations in the circuit.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
def rewrite_Statement(self, node: ir.Statement) -> RewriteResult:
|
|
14
|
+
|
|
15
|
+
if not isinstance(node, MeasureAny):
|
|
16
|
+
return RewriteResult()
|
|
17
|
+
|
|
18
|
+
if node.input.type.is_subseteq(QubitType):
|
|
19
|
+
node.replace_by(
|
|
20
|
+
MeasureQubit(
|
|
21
|
+
qubit=node.input,
|
|
22
|
+
)
|
|
23
|
+
)
|
|
24
|
+
return RewriteResult(has_done_something=True)
|
|
25
|
+
elif node.input.type.is_subseteq(ilist.IListType[QubitType, types.Any]):
|
|
26
|
+
node.replace_by(
|
|
27
|
+
MeasureQubitList(
|
|
28
|
+
qubits=node.input,
|
|
29
|
+
)
|
|
30
|
+
)
|
|
31
|
+
return RewriteResult(has_done_something=True)
|
|
32
|
+
|
|
33
|
+
return RewriteResult()
|
bloqade/squin/wire.py
CHANGED
|
@@ -8,10 +8,11 @@ dialect.
|
|
|
8
8
|
|
|
9
9
|
from kirin import ir, types, interp, lowering
|
|
10
10
|
from kirin.decl import info, statement
|
|
11
|
+
from kirin.lowering import wraps
|
|
11
12
|
|
|
12
|
-
from bloqade.types import QubitType
|
|
13
|
+
from bloqade.types import Qubit, QubitType
|
|
13
14
|
|
|
14
|
-
from .op.types import OpType
|
|
15
|
+
from .op.types import Op, OpType
|
|
15
16
|
|
|
16
17
|
# from kirin.lowering import wraps
|
|
17
18
|
|
|
@@ -68,6 +69,25 @@ class Apply(ir.Statement): # apply(op, w1, w2, ...)
|
|
|
68
69
|
) # custom lowering required for wrapper to work here
|
|
69
70
|
|
|
70
71
|
|
|
72
|
+
# Carry over from Qubit dialect
|
|
73
|
+
@statement(dialect=dialect)
|
|
74
|
+
class Broadcast(ir.Statement):
|
|
75
|
+
traits = frozenset({lowering.FromPythonCall(), ir.Pure()})
|
|
76
|
+
operator: ir.SSAValue = info.argument(OpType)
|
|
77
|
+
inputs: tuple[ir.SSAValue, ...] = info.argument(WireType)
|
|
78
|
+
|
|
79
|
+
def __init__(self, operator: ir.SSAValue, *args: ir.SSAValue):
|
|
80
|
+
result_types = tuple(WireType for _ in args)
|
|
81
|
+
super().__init__(
|
|
82
|
+
args=(operator,) + args,
|
|
83
|
+
result_types=result_types,
|
|
84
|
+
args_slice={
|
|
85
|
+
"operator": 0,
|
|
86
|
+
"inputs": slice(1, None),
|
|
87
|
+
}, # pretty printing + syntax sugar
|
|
88
|
+
) # custom lowering required for wrapper to work here
|
|
89
|
+
|
|
90
|
+
|
|
71
91
|
# NOTE: measurement cannot be pure because they will collapse the state
|
|
72
92
|
# of the qubit. The state is a hidden state that is not visible to
|
|
73
93
|
# the user in the wire dialect.
|
|
@@ -98,6 +118,15 @@ class Reset(ir.Statement):
|
|
|
98
118
|
class ConstPropWire(interp.MethodTable):
|
|
99
119
|
|
|
100
120
|
@interp.impl(Apply)
|
|
121
|
+
@interp.impl(Broadcast)
|
|
101
122
|
def apply(self, interp, frame, stmt: Apply):
|
|
102
123
|
|
|
103
124
|
return frame.get_values(stmt.inputs)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@wraps(Unwrap)
|
|
128
|
+
def unwrap(qubit: Qubit) -> Wire: ...
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@wraps(Apply)
|
|
132
|
+
def apply(op: Op, w: Wire) -> Wire: ...
|
bloqade/stim/emit/stim.py
CHANGED
|
@@ -49,6 +49,6 @@ class FuncEmit(interp.MethodTable):
|
|
|
49
49
|
|
|
50
50
|
@interp.impl(func.Function)
|
|
51
51
|
def emit_func(self, emit: EmitStimMain, frame: EmitStrFrame, stmt: func.Function):
|
|
52
|
-
_ = emit.run_ssacfg_region(frame, stmt.body)
|
|
52
|
+
_ = emit.run_ssacfg_region(frame, stmt.body, ())
|
|
53
53
|
# emit.output = "\n".join(frame.body)
|
|
54
54
|
return ()
|
bloqade/task.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from typing import Any, Generic, Literal, TypeVar, ParamSpec
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from kirin import ir
|
|
6
|
+
|
|
7
|
+
Params = ParamSpec("Params")
|
|
8
|
+
RetType = TypeVar("RetType")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BatchFuture(abc.ABC, Generic[RetType]):
|
|
12
|
+
"""Protocol for future objects that can be awaited."""
|
|
13
|
+
|
|
14
|
+
MISSING_RESULT = Literal[None]
|
|
15
|
+
|
|
16
|
+
@abc.abstractmethod
|
|
17
|
+
def result(self, timeout: float | None) -> list[RetType]:
|
|
18
|
+
"""Returns the result of the future, blocking until it is available or the timeout expires."""
|
|
19
|
+
|
|
20
|
+
@abc.abstractmethod
|
|
21
|
+
def partial_result(self) -> list[RetType | MISSING_RESULT]:
|
|
22
|
+
"""Return all results that are available so far, or MISSING_RESULT for those that are not yet available."""
|
|
23
|
+
|
|
24
|
+
@abc.abstractmethod
|
|
25
|
+
def fetch(self) -> None:
|
|
26
|
+
"""Fetches the result of the future that are currently available."""
|
|
27
|
+
|
|
28
|
+
def cancel(self):
|
|
29
|
+
"""Attempts to cancel the execution of the future."""
|
|
30
|
+
raise NotImplementedError(
|
|
31
|
+
f"cancel method not implemented for {self.__class__.__name__}"
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def cancelled(self) -> bool:
|
|
35
|
+
"""Returns True if the future was cancelled, False otherwise."""
|
|
36
|
+
raise NotImplementedError(
|
|
37
|
+
f"cancelled method not implemented for {self.__class__.__name__}"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def done(self) -> bool:
|
|
41
|
+
self.fetch()
|
|
42
|
+
return not any(
|
|
43
|
+
result is self.MISSING_RESULT for result in self.partial_result()
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
ClassRetType = TypeVar("ClassRetType")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass
|
|
51
|
+
class AbstractTask(abc.ABC, Generic[Params, RetType]):
|
|
52
|
+
kernel: ir.Method[Params, RetType]
|
|
53
|
+
args: tuple[Any, ...]
|
|
54
|
+
kwargs: dict[str, Any]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class DeviceTaskExpectMixin(AbstractTask):
|
|
58
|
+
|
|
59
|
+
ObsType = TypeVar("ObsType")
|
|
60
|
+
|
|
61
|
+
@abc.abstractmethod
|
|
62
|
+
def expect(self, observable: ir.Method[[RetType], ObsType], shots: int) -> ObsType:
|
|
63
|
+
"""Returns the expectation value of the given observable after running the task."""
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass
|
|
67
|
+
class AbstractRemoteTask(AbstractTask[Params, RetType]):
|
|
68
|
+
"""Base class for tasks generated by the devices."""
|
|
69
|
+
|
|
70
|
+
def run(self, *, shots: int = 1, timeout: float | None = None) -> list[RetType]:
|
|
71
|
+
return self.run_async(shots=shots).result(timeout=timeout)
|
|
72
|
+
|
|
73
|
+
@abc.abstractmethod
|
|
74
|
+
def run_async(self, *, shots: int = 1) -> BatchFuture[RetType]:
|
|
75
|
+
"""Executes the kernel asynchronously and returns a Future object."""
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
StateType = TypeVar("StateType")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@dataclass
|
|
82
|
+
class AbstractSimulatorTask(
|
|
83
|
+
AbstractTask[Params, RetType], Generic[Params, RetType, StateType]
|
|
84
|
+
):
|
|
85
|
+
"""Base class for tasks generated by local simulators."""
|
|
86
|
+
|
|
87
|
+
@abc.abstractmethod
|
|
88
|
+
def run(self) -> RetType:
|
|
89
|
+
"""Executes the kernel and returns the result."""
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
@abc.abstractmethod
|
|
93
|
+
def state(self) -> StateType:
|
|
94
|
+
"""Returns the state of the simulator after running the task."""
|
bloqade/visual/animation/base.py
CHANGED
|
@@ -45,10 +45,12 @@ class GateArtist:
|
|
|
45
45
|
class GlobalGateArtist(GateArtist):
|
|
46
46
|
mpl_obj: mpatches.Rectangle
|
|
47
47
|
|
|
48
|
-
def __init__(
|
|
48
|
+
def __init__(
|
|
49
|
+
self, mpl_ax: Any, xmin: float, ymin: float, width: float, height: float, color
|
|
50
|
+
):
|
|
49
51
|
super().__init__(mpl_ax)
|
|
50
52
|
rc = mpatches.Rectangle(
|
|
51
|
-
|
|
53
|
+
(xmin, ymin), width, height, color=color, alpha=0.6, visible=False
|
|
52
54
|
)
|
|
53
55
|
mpl_ax.add_patch(rc)
|
|
54
56
|
self.mpl_obj = rc
|
|
@@ -56,7 +58,7 @@ class GlobalGateArtist(GateArtist):
|
|
|
56
58
|
def clear_data(self) -> None:
|
|
57
59
|
self.mpl_obj.set_width(0)
|
|
58
60
|
self.mpl_obj.set_height(0)
|
|
59
|
-
self.mpl_obj.set_xy(
|
|
61
|
+
self.mpl_obj.set_xy((0, 0))
|
|
60
62
|
|
|
61
63
|
def get_artists(self) -> Tuple[Any]:
|
|
62
64
|
return (self.mpl_obj,)
|
|
@@ -86,7 +88,7 @@ class RowRegionGateArtist(GateArtist):
|
|
|
86
88
|
self.width = width
|
|
87
89
|
self.xmin = xmin
|
|
88
90
|
rc_btm = mpatches.Rectangle(
|
|
89
|
-
|
|
91
|
+
(xmin, ymin_keepout),
|
|
90
92
|
width,
|
|
91
93
|
ymin - ymin_keepout,
|
|
92
94
|
color=color,
|
|
@@ -97,13 +99,13 @@ class RowRegionGateArtist(GateArtist):
|
|
|
97
99
|
self.mpl_obj_keepout_btm = rc_btm
|
|
98
100
|
|
|
99
101
|
rc = mpatches.Rectangle(
|
|
100
|
-
|
|
102
|
+
(xmin, ymin), width, ymax - ymin, color=color, alpha=0.6, visible=False
|
|
101
103
|
)
|
|
102
104
|
mpl_ax.add_patch(rc)
|
|
103
105
|
self.mpl_obj = rc
|
|
104
106
|
|
|
105
107
|
rc_top = mpatches.Rectangle(
|
|
106
|
-
|
|
108
|
+
(xmin, ymax),
|
|
107
109
|
width,
|
|
108
110
|
ymax_keepout - ymax,
|
|
109
111
|
color=color,
|
|
@@ -116,31 +118,31 @@ class RowRegionGateArtist(GateArtist):
|
|
|
116
118
|
def clear_data(self) -> None:
|
|
117
119
|
self.mpl_obj.set_width(0)
|
|
118
120
|
self.mpl_obj.set_height(0)
|
|
119
|
-
self.mpl_obj.set_xy(
|
|
121
|
+
self.mpl_obj.set_xy((0, 0))
|
|
120
122
|
|
|
121
123
|
self.mpl_obj_keepout_top.set_width(0)
|
|
122
124
|
self.mpl_obj_keepout_top.set_height(0)
|
|
123
|
-
self.mpl_obj_keepout_top.set_xy(
|
|
125
|
+
self.mpl_obj_keepout_top.set_xy((0, 0))
|
|
124
126
|
|
|
125
127
|
self.mpl_obj_keepout_btm.set_width(0)
|
|
126
128
|
self.mpl_obj_keepout_btm.set_height(0)
|
|
127
|
-
self.mpl_obj_keepout_btm.set_xy(
|
|
129
|
+
self.mpl_obj_keepout_btm.set_xy((0, 0))
|
|
128
130
|
|
|
129
|
-
def get_artists(self) -> Tuple[Any]:
|
|
131
|
+
def get_artists(self) -> Tuple[Any, ...]:
|
|
130
132
|
return (self.mpl_obj, self.mpl_obj_keepout_top, self.mpl_obj_keepout_btm)
|
|
131
133
|
|
|
132
134
|
def update_data(self, ymin, ymax, ymin_keepout, ymax_keepout):
|
|
133
135
|
self.mpl_obj.set_height(ymax - ymin)
|
|
134
136
|
self.mpl_obj.set_width(self.width)
|
|
135
|
-
self.mpl_obj.set_xy(
|
|
137
|
+
self.mpl_obj.set_xy((self.xmin, ymin))
|
|
136
138
|
|
|
137
139
|
self.mpl_obj_keepout_top.set_height(ymax_keepout - ymax)
|
|
138
140
|
self.mpl_obj_keepout_top.set_width(self.width)
|
|
139
|
-
self.mpl_obj_keepout_top.set_xy(
|
|
141
|
+
self.mpl_obj_keepout_top.set_xy((self.xmin, ymax))
|
|
140
142
|
|
|
141
143
|
self.mpl_obj_keepout_btm.set_height(ymin - ymin_keepout)
|
|
142
144
|
self.mpl_obj_keepout_btm.set_width(self.width)
|
|
143
|
-
self.mpl_obj_keepout_btm.set_xy(
|
|
145
|
+
self.mpl_obj_keepout_btm.set_xy((self.xmin, ymin_keepout))
|
|
144
146
|
|
|
145
147
|
def set_visible(self, visible: bool):
|
|
146
148
|
self.mpl_obj.set_visible(visible)
|
|
@@ -194,11 +196,19 @@ class FieldOfView:
|
|
|
194
196
|
)
|
|
195
197
|
|
|
196
198
|
@property
|
|
197
|
-
def width(self):
|
|
199
|
+
def width(self) -> float:
|
|
200
|
+
if self.xmax is None or self.xmin is None:
|
|
201
|
+
raise ValueError(
|
|
202
|
+
"Can't return width of FOV as either xmin or xmax are undefined"
|
|
203
|
+
)
|
|
198
204
|
return self.xmax - self.xmin
|
|
199
205
|
|
|
200
206
|
@property
|
|
201
|
-
def height(self):
|
|
207
|
+
def height(self) -> float:
|
|
208
|
+
if self.ymax is None or self.ymin is None:
|
|
209
|
+
raise ValueError(
|
|
210
|
+
"Can't return width of FOV as either ymin or ymax are undefined"
|
|
211
|
+
)
|
|
202
212
|
return self.ymax - self.ymin
|
|
203
213
|
|
|
204
214
|
def to_json(self):
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bloqade-circuit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
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
|
|
7
7
|
Requires-Python: >=3.10
|
|
8
|
-
Requires-Dist: kirin-toolchain~=0.
|
|
8
|
+
Requires-Dist: kirin-toolchain~=0.17.0
|
|
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.38.2; sys_platform != 'darwin'
|
|
13
|
+
Requires-Dist: pyqrack>=1.38.2; sys_platform == 'darwin'
|
|
12
14
|
Requires-Dist: rich>=13.9.4
|
|
13
15
|
Requires-Dist: scipy>=1.13.1
|
|
14
16
|
Provides-Extra: cirq
|
|
15
17
|
Requires-Dist: cirq-core>=1.4.1; extra == 'cirq'
|
|
16
18
|
Requires-Dist: cirq-core[contrib]>=1.4.1; extra == 'cirq'
|
|
19
|
+
Provides-Extra: pyqrack-cuda
|
|
20
|
+
Requires-Dist: pyqrack-cuda>=1.38.2; extra == 'pyqrack-cuda'
|
|
21
|
+
Provides-Extra: pyqrack-opencl
|
|
22
|
+
Requires-Dist: pyqrack>=1.38.2; (sys_platform != 'darwin') and extra == 'pyqrack-opencl'
|
|
17
23
|
Provides-Extra: qasm2
|
|
18
24
|
Requires-Dist: lark>=1.2.2; extra == 'qasm2'
|
|
19
25
|
Provides-Extra: qbraid
|