bloqade-circuit 0.7.12__py3-none-any.whl → 0.8.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 (136) hide show
  1. bloqade/analysis/address/__init__.py +8 -4
  2. bloqade/analysis/address/analysis.py +119 -29
  3. bloqade/analysis/address/impls.py +290 -87
  4. bloqade/analysis/address/lattice.py +209 -24
  5. bloqade/analysis/fidelity/analysis.py +2 -2
  6. bloqade/analysis/measure_id/impls.py +3 -27
  7. bloqade/cirq_utils/__init__.py +3 -1
  8. bloqade/cirq_utils/emit/__init__.py +3 -0
  9. bloqade/cirq_utils/emit/base.py +243 -0
  10. bloqade/cirq_utils/emit/gate.py +104 -0
  11. bloqade/cirq_utils/emit/noise.py +90 -0
  12. bloqade/cirq_utils/emit/qubit.py +35 -0
  13. bloqade/cirq_utils/lowering.py +664 -0
  14. bloqade/native/__init__.py +0 -1
  15. bloqade/native/_prelude.py +3 -3
  16. bloqade/native/dialects/gate/__init__.py +2 -0
  17. bloqade/native/dialects/gate/_dialect.py +3 -0
  18. bloqade/native/dialects/{gates → gate}/_interface.py +5 -5
  19. bloqade/native/dialects/{gates → gate}/stmts.py +5 -5
  20. bloqade/native/stdlib/broadcast.py +19 -19
  21. bloqade/native/stdlib/simple.py +14 -13
  22. bloqade/native/upstream/__init__.py +5 -0
  23. bloqade/native/upstream/squin2native.py +136 -0
  24. bloqade/pyqrack/__init__.py +1 -2
  25. bloqade/pyqrack/device.py +6 -17
  26. bloqade/pyqrack/native.py +17 -17
  27. bloqade/pyqrack/reg.py +1 -6
  28. bloqade/pyqrack/squin/gate/__init__.py +1 -0
  29. bloqade/pyqrack/squin/gate/gate.py +136 -0
  30. bloqade/pyqrack/squin/noise/native.py +120 -54
  31. bloqade/pyqrack/squin/qubit.py +25 -41
  32. bloqade/pyqrack/target.py +2 -2
  33. bloqade/qasm2/dialects/core/address.py +21 -12
  34. bloqade/qasm2/dialects/noise/fidelity.py +2 -6
  35. bloqade/qasm2/dialects/noise/model.py +2 -1
  36. bloqade/qasm2/passes/parallel.py +3 -1
  37. bloqade/qasm2/rewrite/__init__.py +0 -1
  38. bloqade/qasm2/rewrite/noise/heuristic_noise.py +7 -17
  39. bloqade/qasm2/rewrite/parallel_to_glob.py +28 -15
  40. bloqade/qasm2/rewrite/parallel_to_uop.py +2 -8
  41. bloqade/qubit/__init__.py +12 -0
  42. bloqade/qubit/_dialect.py +3 -0
  43. bloqade/qubit/_interface.py +49 -0
  44. bloqade/qubit/_prelude.py +45 -0
  45. bloqade/qubit/analysis/__init__.py +1 -0
  46. bloqade/qubit/analysis/address_impl.py +40 -0
  47. bloqade/qubit/stdlib/__init__.py +2 -0
  48. bloqade/qubit/stdlib/_new.py +34 -0
  49. bloqade/qubit/stdlib/broadcast.py +62 -0
  50. bloqade/qubit/stdlib/simple.py +59 -0
  51. bloqade/qubit/stmts.py +60 -0
  52. bloqade/rewrite/passes/aggressive_unroll.py +2 -1
  53. bloqade/squin/__init__.py +44 -17
  54. bloqade/squin/analysis/__init__.py +0 -1
  55. bloqade/squin/analysis/schedule.py +2 -2
  56. bloqade/squin/gate/__init__.py +2 -0
  57. bloqade/squin/gate/_dialect.py +3 -0
  58. bloqade/squin/gate/_interface.py +98 -0
  59. bloqade/squin/gate/stmts.py +119 -0
  60. bloqade/squin/groups.py +4 -21
  61. bloqade/squin/noise/__init__.py +1 -9
  62. bloqade/squin/noise/_dialect.py +1 -1
  63. bloqade/squin/noise/_interface.py +45 -0
  64. bloqade/squin/noise/stmts.py +65 -29
  65. bloqade/squin/rewrite/U3_to_clifford.py +70 -51
  66. bloqade/squin/rewrite/__init__.py +0 -2
  67. bloqade/squin/rewrite/remove_dangling_qubits.py +2 -2
  68. bloqade/squin/rewrite/wrap_analysis.py +4 -35
  69. bloqade/squin/stdlib/broadcast/__init__.py +34 -0
  70. bloqade/squin/stdlib/broadcast/_qubit.py +4 -0
  71. bloqade/squin/stdlib/broadcast/gate.py +260 -0
  72. bloqade/squin/stdlib/broadcast/noise.py +144 -0
  73. bloqade/squin/stdlib/simple/__init__.py +33 -0
  74. bloqade/squin/stdlib/simple/gate.py +242 -0
  75. bloqade/squin/stdlib/simple/noise.py +126 -0
  76. bloqade/stim/__init__.py +1 -0
  77. bloqade/stim/_wrappers.py +6 -0
  78. bloqade/stim/dialects/noise/emit.py +6 -1
  79. bloqade/stim/dialects/noise/stmts.py +5 -3
  80. bloqade/stim/emit/stim_str.py +2 -0
  81. bloqade/stim/parse/lowering.py +12 -17
  82. bloqade/stim/passes/__init__.py +0 -1
  83. bloqade/stim/passes/flatten.py +26 -0
  84. bloqade/stim/passes/simplify_ifs.py +6 -1
  85. bloqade/stim/passes/squin_to_stim.py +4 -70
  86. bloqade/stim/rewrite/__init__.py +0 -4
  87. bloqade/stim/rewrite/ifs_to_stim.py +23 -29
  88. bloqade/stim/rewrite/qubit_to_stim.py +90 -41
  89. bloqade/stim/rewrite/squin_measure.py +9 -18
  90. bloqade/stim/rewrite/squin_noise.py +132 -108
  91. bloqade/stim/rewrite/util.py +5 -204
  92. bloqade/types.py +10 -0
  93. {bloqade_circuit-0.7.12.dist-info → bloqade_circuit-0.8.0.dist-info}/METADATA +2 -2
  94. {bloqade_circuit-0.7.12.dist-info → bloqade_circuit-0.8.0.dist-info}/RECORD +96 -100
  95. bloqade/native/dialects/gates/__init__.py +0 -3
  96. bloqade/native/dialects/gates/_dialect.py +0 -3
  97. bloqade/pyqrack/squin/op.py +0 -180
  98. bloqade/pyqrack/squin/runtime.py +0 -543
  99. bloqade/pyqrack/squin/wire.py +0 -51
  100. bloqade/squin/_typeinfer.py +0 -20
  101. bloqade/squin/analysis/address_impl.py +0 -71
  102. bloqade/squin/analysis/nsites/__init__.py +0 -9
  103. bloqade/squin/analysis/nsites/analysis.py +0 -50
  104. bloqade/squin/analysis/nsites/impls.py +0 -99
  105. bloqade/squin/analysis/nsites/lattice.py +0 -49
  106. bloqade/squin/cirq/__init__.py +0 -306
  107. bloqade/squin/cirq/emit/emit_circuit.py +0 -129
  108. bloqade/squin/cirq/emit/noise.py +0 -49
  109. bloqade/squin/cirq/emit/op.py +0 -176
  110. bloqade/squin/cirq/emit/qubit.py +0 -58
  111. bloqade/squin/cirq/emit/runtime.py +0 -242
  112. bloqade/squin/cirq/lowering.py +0 -439
  113. bloqade/squin/lowering.py +0 -80
  114. bloqade/squin/noise/_wrapper.py +0 -36
  115. bloqade/squin/noise/rewrite.py +0 -129
  116. bloqade/squin/op/__init__.py +0 -41
  117. bloqade/squin/op/_dialect.py +0 -3
  118. bloqade/squin/op/_wrapper.py +0 -121
  119. bloqade/squin/op/number.py +0 -5
  120. bloqade/squin/op/rewrite.py +0 -46
  121. bloqade/squin/op/stdlib.py +0 -62
  122. bloqade/squin/op/stmts.py +0 -300
  123. bloqade/squin/op/traits.py +0 -43
  124. bloqade/squin/op/types.py +0 -128
  125. bloqade/squin/parallel.py +0 -200
  126. bloqade/squin/qubit.py +0 -194
  127. bloqade/squin/rewrite/canonicalize.py +0 -60
  128. bloqade/squin/rewrite/desugar.py +0 -102
  129. bloqade/squin/stdlib/channel.py +0 -86
  130. bloqade/squin/stdlib/gate.py +0 -201
  131. bloqade/squin/types.py +0 -8
  132. bloqade/squin/wire.py +0 -201
  133. bloqade/stim/rewrite/wire_identity_elimination.py +0 -24
  134. bloqade/stim/rewrite/wire_to_stim.py +0 -57
  135. {bloqade_circuit-0.7.12.dist-info → bloqade_circuit-0.8.0.dist-info}/WHEEL +0 -0
  136. {bloqade_circuit-0.7.12.dist-info → bloqade_circuit-0.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,260 @@
1
+ import math
2
+ from typing import Any, TypeVar
3
+
4
+ from kirin.dialects import ilist
5
+
6
+ from bloqade.types import Qubit
7
+
8
+ from ...gate import _interface as gate
9
+ from ...groups import kernel
10
+
11
+
12
+ @kernel
13
+ def _radian_to_turn(angle: float) -> float:
14
+ """Convert an angle from radians to turns.
15
+
16
+ Args:
17
+ angle (float): Angle in radians.
18
+ Returns:
19
+ float: Equivalent angle in turns.
20
+ """
21
+ return angle / (2 * math.pi)
22
+
23
+
24
+ @kernel
25
+ def x(qubits: ilist.IList[Qubit, Any]) -> None:
26
+ """Apply a Pauli-X gate to a group of qubits.
27
+
28
+ Args:
29
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
30
+ """
31
+ gate.x(qubits)
32
+
33
+
34
+ @kernel
35
+ def y(qubits: ilist.IList[Qubit, Any]) -> None:
36
+ """Apply a Pauli-Y gate to a group of qubits.
37
+
38
+ Args:
39
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
40
+ """
41
+ gate.y(qubits)
42
+
43
+
44
+ @kernel
45
+ def z(qubits: ilist.IList[Qubit, Any]) -> None:
46
+ """Apply a Pauli-Z gate to a group of qubits.
47
+
48
+ Args:
49
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
50
+ """
51
+ gate.z(qubits)
52
+
53
+
54
+ @kernel
55
+ def h(qubits: ilist.IList[Qubit, Any]) -> None:
56
+ """Apply a Hadamard gate to a group of qubits.
57
+
58
+ Args:
59
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
60
+ """
61
+ gate.h(qubits)
62
+
63
+
64
+ @kernel
65
+ def t(qubits: ilist.IList[Qubit, Any]) -> None:
66
+ """Apply a T gate to a group of qubits.
67
+
68
+ Args:
69
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
70
+ """
71
+ gate.t(qubits, adjoint=False)
72
+
73
+
74
+ @kernel
75
+ def s(qubits: ilist.IList[Qubit, Any]) -> None:
76
+ """Apply an S gate to a group of qubits.
77
+
78
+ Args:
79
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
80
+ """
81
+ gate.s(qubits, adjoint=False)
82
+
83
+
84
+ @kernel
85
+ def sqrt_x(qubits: ilist.IList[Qubit, Any]) -> None:
86
+ """Apply a Sqrt(X) gate to a group of qubits.
87
+
88
+ Args:
89
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
90
+ """
91
+ gate.sqrt_x(qubits, adjoint=False)
92
+
93
+
94
+ @kernel
95
+ def sqrt_y(qubits: ilist.IList[Qubit, Any]) -> None:
96
+ """Apply a sqrt(Y) gate to a group of qubits.
97
+
98
+ Args:
99
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
100
+ """
101
+ gate.sqrt_y(qubits, adjoint=False)
102
+
103
+
104
+ @kernel
105
+ def sqrt_z(qubits: ilist.IList[Qubit, Any]) -> None:
106
+ """Apply a Sqrt(Z) gate to a group of qubits.
107
+
108
+ Args:
109
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
110
+ """
111
+ gate.s(qubits, adjoint=False)
112
+
113
+
114
+ @kernel
115
+ def t_adj(qubits: ilist.IList[Qubit, Any]) -> None:
116
+ """Apply the adjoint of a T gate to a group of qubits.
117
+
118
+ Args:
119
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
120
+ """
121
+ gate.t(qubits, adjoint=True)
122
+
123
+
124
+ @kernel
125
+ def s_adj(qubits: ilist.IList[Qubit, Any]) -> None:
126
+ """Apply the adjoint of an S gate to a group of qubits.
127
+
128
+ Args:
129
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
130
+ """
131
+ gate.s(qubits, adjoint=True)
132
+
133
+
134
+ @kernel
135
+ def sqrt_x_adj(qubits: ilist.IList[Qubit, Any]) -> None:
136
+ """Apply the adjoint of a Sqrt(X) gate to a group of qubits.
137
+
138
+ Args:
139
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
140
+ """
141
+ gate.sqrt_x(qubits, adjoint=True)
142
+
143
+
144
+ @kernel
145
+ def sqrt_y_adj(qubits: ilist.IList[Qubit, Any]) -> None:
146
+ """Apply the adjoint of a Sqrt(Y) gate to a group of qubits.
147
+
148
+ Args:
149
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
150
+ """
151
+ gate.sqrt_y(qubits, adjoint=True)
152
+
153
+
154
+ @kernel
155
+ def sqrt_z_adj(qubits: ilist.IList[Qubit, Any]) -> None:
156
+ """Apply the adjoint of a Sqrt(Z) gate to a group of qubits.
157
+
158
+ Args:
159
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
160
+ """
161
+ gate.s(qubits, adjoint=True)
162
+
163
+
164
+ @kernel
165
+ def rx(angle: float, qubits: ilist.IList[Qubit, Any]) -> None:
166
+ """Apply an RX rotation gate to a group of qubits.
167
+
168
+ Args:
169
+ angle (float): Rotation angle in radians.
170
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
171
+ """
172
+ gate.rx(_radian_to_turn(angle), qubits)
173
+
174
+
175
+ @kernel
176
+ def ry(angle: float, qubits: ilist.IList[Qubit, Any]) -> None:
177
+ """Apply an RY rotation gate to a group of qubits.
178
+
179
+ Args:
180
+ angle (float): Rotation angle in radians.
181
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
182
+ """
183
+ gate.ry(_radian_to_turn(angle), qubits)
184
+
185
+
186
+ @kernel
187
+ def rz(angle: float, qubits: ilist.IList[Qubit, Any]) -> None:
188
+ """Apply an RZ rotation gate to a group of qubits.
189
+
190
+ Args:
191
+ angle (float): Rotation angle in radians.
192
+ qubits (ilist.IList[Qubit, Any]): Target qubits.
193
+ """
194
+ gate.rz(_radian_to_turn(angle), qubits)
195
+
196
+
197
+ Len = TypeVar("Len", bound=int)
198
+
199
+
200
+ @kernel
201
+ def cx(controls: ilist.IList[Qubit, Len], targets: ilist.IList[Qubit, Len]) -> None:
202
+ """Apply a controlled-X gate to pairs of qubits.
203
+
204
+ Args:
205
+ controls (ilist.IList[Qubit, N]): Control qubits.
206
+ targets (ilist.IList[Qubit, N]): Target qubits.
207
+ """
208
+ gate.cx(controls, targets)
209
+
210
+
211
+ @kernel
212
+ def cy(controls: ilist.IList[Qubit, Len], targets: ilist.IList[Qubit, Len]) -> None:
213
+ """Apply a controlled-Y gate to pairs of qubits.
214
+
215
+ Args:
216
+ controls (ilist.IList[Qubit, N]): Control qubits.
217
+ targets (ilist.IList[Qubit, N]): Target qubits.
218
+ """
219
+ gate.cy(controls, targets)
220
+
221
+
222
+ @kernel
223
+ def cz(controls: ilist.IList[Qubit, Len], targets: ilist.IList[Qubit, Len]) -> None:
224
+ """Apply a controlled-Z gate to pairs of qubits.
225
+
226
+ Args:
227
+ controls (ilist.IList[Qubit, N]): Control qubits.
228
+ targets (ilist.IList[Qubit, N]): Target qubits.
229
+ """
230
+ gate.cz(controls, targets)
231
+
232
+
233
+ @kernel
234
+ def u3(theta: float, phi: float, lam: float, qubits: ilist.IList[Qubit, Any]):
235
+ """Apply the U3 gate to a group of qubits.
236
+
237
+ The applied gate is represented by the unitary matrix given by:
238
+
239
+ $$ U3(\\theta, \\phi, \\lambda) = R_z(\\phi)R_y(\\theta)R_z(\\lambda) $$
240
+
241
+ Args:
242
+ theta (float): Rotation around Y axis (radians).
243
+ phi (float): Global phase shift component (radians).
244
+ lam (float): Z rotations in decomposition (radians).
245
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
246
+ """
247
+ gate.u3(_radian_to_turn(theta), _radian_to_turn(phi), _radian_to_turn(lam), qubits)
248
+
249
+
250
+ # NOTE: stdlib not wrapping statements starts here
251
+
252
+
253
+ @kernel
254
+ def shift(angle: float, qubits: ilist.IList[Qubit, Any]) -> None:
255
+ """Apply a phase shift to the |1> state to a group of qubits.
256
+ Args:
257
+ angle (float): Phase shift angle in radians.
258
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
259
+ """
260
+ rz(angle / 2.0, qubits)
@@ -0,0 +1,144 @@
1
+ from typing import Any, Literal, TypeVar
2
+
3
+ from kirin.dialects import ilist
4
+
5
+ from bloqade.types import Qubit
6
+
7
+ from ...noise import _interface as noise
8
+ from ...groups import kernel
9
+
10
+
11
+ @kernel
12
+ def depolarize(p: float, qubits: ilist.IList[Qubit, Any]) -> None:
13
+ """
14
+ Apply a depolarizing noise channel to a list of qubits with probability `p`.
15
+
16
+ For each qubit, this will randomly select one of the Pauli operators X, Y, Z
17
+ with a probability `p / 3` and apply it to the qubit. No operator is applied
18
+ with a probability of `1 - p`.
19
+
20
+ Args:
21
+ p (float): The probability with which a Pauli operator is applied.
22
+ qubits (IList[Qubit, Any]): The list of qubits to which the noise channel is applied.
23
+ """
24
+ noise.depolarize(p, qubits)
25
+
26
+
27
+ N = TypeVar("N", bound=int)
28
+
29
+
30
+ @kernel
31
+ def depolarize2(
32
+ p: float, controls: ilist.IList[Qubit, N], targets: ilist.IList[Qubit, N]
33
+ ) -> None:
34
+ """
35
+ Symmetric two-qubit depolarization channel applied to a set of control and target qubits.
36
+
37
+ For each pair of qubits from the `controls` and `targets` lists, this will randomly select one
38
+ of the pauli products
39
+
40
+ `{IX, IY, IZ, XI, XX, XY, XZ, YI, YX, YY, YZ, ZI, ZX, ZY, ZZ}`
41
+
42
+ each with a probability `p / 15`. No noise is applied with a probability of `1 - p`.
43
+
44
+ Args:
45
+ p (float): The probability with which a Pauli product is applied.
46
+ controls (IList[Qubit, N]): The list of control qubits.
47
+ targets (IList[Qubit, N]): The list of target qubits.
48
+ """
49
+ noise.depolarize2(p, controls, targets)
50
+
51
+
52
+ @kernel
53
+ def single_qubit_pauli_channel(
54
+ px: float, py: float, pz: float, qubits: ilist.IList[Qubit, Any]
55
+ ) -> None:
56
+ """
57
+ Apply a Pauli error channel with weighted `px, py, pz`. No error is applied with a probability
58
+ `1 - (px + py + pz)`.
59
+
60
+ This randomly selects one of the three Pauli operators X, Y, Z, weighted with the given probabilities in that order.
61
+
62
+ Args:
63
+ probabilities (IList[float, Literal[3]]): A list of 3 probabilities corresponding to the probabilities `(p_x, p_y, p_z)` in that order.
64
+ qubits (IList[Qubit, Any]): The list of qubits to which the noise channel is applied.
65
+ """
66
+ noise.single_qubit_pauli_channel(px, py, pz, qubits)
67
+
68
+
69
+ @kernel
70
+ def two_qubit_pauli_channel(
71
+ probabilities: ilist.IList[float, Literal[15]],
72
+ controls: ilist.IList[Qubit, N],
73
+ targets: ilist.IList[Qubit, N],
74
+ ) -> None:
75
+ """
76
+ Apply a Pauli product error with weighted `probabilities` to the set of control and target qubits.
77
+
78
+ No error is applied with the probability `1 - sum(probabilities)`.
79
+
80
+ For each pair of qubits from the `controls` and `targets` lists, this will randomly select one
81
+ of the pauli products
82
+
83
+ `{IX, IY, IZ, XI, XX, XY, XZ, YI, YX, YY, YZ, ZI, ZX, ZY, ZZ}`
84
+
85
+ weighted with the corresponding list of probabilities.
86
+
87
+ **NOTE**: The order of the given probabilities must match the order of the list of Pauli products above!
88
+ """
89
+ noise.two_qubit_pauli_channel(probabilities, controls, targets)
90
+
91
+
92
+ @kernel
93
+ def qubit_loss(p: float, qubits: ilist.IList[Qubit, Any]) -> None:
94
+ """
95
+ Apply a qubit loss channel to each of the qubits in the given list.
96
+
97
+ Each qubit in the list is lost with a probability `p`.
98
+
99
+ Args:
100
+ p (float): Probability of the atom being lost.
101
+ qubits (IList[Qubit, Any]): The list of qubits to which the noise channel is applied.
102
+ """
103
+ noise.qubit_loss(p, qubits)
104
+
105
+
106
+ @kernel
107
+ def correlated_qubit_loss(
108
+ p: float, qubits: ilist.IList[ilist.IList[Qubit, N], Any]
109
+ ) -> None:
110
+ """
111
+ Apply correlated qubit loss channels to groups of qubits.
112
+
113
+ For each group of qubits, applies a correlated loss channel where all qubits
114
+ within the group are lost together with probability `p`. Loss events are independent
115
+ between different groups.
116
+
117
+ Args:
118
+ p (float): Loss probability for each group.
119
+ qubits (IList[IList[Qubit, N], Any]): List of qubit groups. Each sublist
120
+ represents a group of qubits to which a correlated loss channel is applied.
121
+
122
+ Example:
123
+ >>> q1 = squin.qalloc(3) # First group: qubits 0, 1, 2
124
+ >>> q2 = squin.qalloc(3) # Second group: qubits 3, 4, 5
125
+ >>> squin.broadcast.correlated_qubit_loss(0.5, [q1, q2])
126
+ # Each group has 50% chance: either all qubits lost or none lost.
127
+ # Group 1 and Group 2 outcomes are independent.
128
+ """
129
+ noise.correlated_qubit_loss(p, qubits)
130
+
131
+
132
+ # NOTE: actual stdlib that doesn't wrap statements starts here
133
+
134
+
135
+ @kernel
136
+ def bit_flip(p: float, qubits: ilist.IList[Qubit, Any]) -> None:
137
+ """
138
+ Apply a bit flip error channel to the qubits in the given list with probability `p`.
139
+
140
+ Args:
141
+ p (float): Probability of a bit flip error being applied.
142
+ qubits (IList[Qubit, Any]): The list of qubits to which the noise channel is applied.
143
+ """
144
+ single_qubit_pauli_channel(p, 0, 0, qubits)
@@ -0,0 +1,33 @@
1
+ from .gate import (
2
+ h as h,
3
+ s as s,
4
+ t as t,
5
+ x as x,
6
+ y as y,
7
+ z as z,
8
+ cx as cx,
9
+ cy as cy,
10
+ cz as cz,
11
+ rx as rx,
12
+ ry as ry,
13
+ rz as rz,
14
+ u3 as u3,
15
+ s_adj as s_adj,
16
+ shift as shift,
17
+ t_adj as t_adj,
18
+ sqrt_x as sqrt_x,
19
+ sqrt_y as sqrt_y,
20
+ sqrt_z as sqrt_z,
21
+ sqrt_x_adj as sqrt_x_adj,
22
+ sqrt_y_adj as sqrt_y_adj,
23
+ sqrt_z_adj as sqrt_z_adj,
24
+ )
25
+ from .noise import (
26
+ bit_flip as bit_flip,
27
+ depolarize as depolarize,
28
+ qubit_loss as qubit_loss,
29
+ depolarize2 as depolarize2,
30
+ correlated_qubit_loss as correlated_qubit_loss,
31
+ two_qubit_pauli_channel as two_qubit_pauli_channel,
32
+ single_qubit_pauli_channel as single_qubit_pauli_channel,
33
+ )
@@ -0,0 +1,242 @@
1
+ from kirin.dialects import ilist
2
+
3
+ from bloqade.types import Qubit
4
+
5
+ from .. import broadcast
6
+ from ...groups import kernel
7
+
8
+
9
+ @kernel
10
+ def x(qubit: Qubit) -> None:
11
+ """Apply a Pauli-X gate to a qubit.
12
+
13
+ Args:
14
+ qubit (Qubit): Target qubit.
15
+ """
16
+ broadcast.x(ilist.IList([qubit]))
17
+
18
+
19
+ @kernel
20
+ def y(qubit: Qubit) -> None:
21
+ """Apply a Pauli-Y gate to a qubit.
22
+
23
+ Args:
24
+ qubit (Qubit): Target qubit.
25
+ """
26
+ broadcast.y(ilist.IList([qubit]))
27
+
28
+
29
+ @kernel
30
+ def z(qubit: Qubit) -> None:
31
+ """Apply a Pauli-Z gate to a qubit.
32
+
33
+ Args:
34
+ qubit (Qubit): Target qubit.
35
+ """
36
+ broadcast.z(ilist.IList([qubit]))
37
+
38
+
39
+ @kernel
40
+ def h(qubit: Qubit) -> None:
41
+ """Apply a Hadamard gate to a qubit.
42
+
43
+ Args:
44
+ qubit (Qubit): Target qubit.
45
+ """
46
+ broadcast.h(ilist.IList([qubit]))
47
+
48
+
49
+ @kernel
50
+ def t(qubit: Qubit) -> None:
51
+ """Apply a T gate to a qubit.
52
+
53
+ Args:
54
+ qubit (Qubit): Target qubit.
55
+ """
56
+ broadcast.t(ilist.IList([qubit]))
57
+
58
+
59
+ @kernel
60
+ def s(qubit: Qubit) -> None:
61
+ """Apply an S gate to a qubit.
62
+
63
+ Args:
64
+ qubit (Qubit): Target qubit.
65
+ """
66
+ broadcast.s(ilist.IList([qubit]))
67
+
68
+
69
+ @kernel
70
+ def sqrt_x(qubit: Qubit) -> None:
71
+ """Apply a Sqrt(X) gate to a qubit.
72
+
73
+ Args:
74
+ qubit (Qubit): Target qubit.
75
+ """
76
+ broadcast.sqrt_x(ilist.IList([qubit]))
77
+
78
+
79
+ @kernel
80
+ def sqrt_y(qubit: Qubit) -> None:
81
+ """Apply a Sqrt(Y) gate to a qubit.
82
+
83
+ Args:
84
+ qubit (Qubit): Target qubit.
85
+ """
86
+ broadcast.sqrt_y(ilist.IList([qubit]))
87
+
88
+
89
+ @kernel
90
+ def sqrt_z(qubit: Qubit) -> None:
91
+ """Apply a Sqrt(Z) gate to a qubit.
92
+
93
+ Args:
94
+ qubit (Qubit): Target qubit.
95
+ """
96
+ broadcast.s(ilist.IList([qubit]))
97
+
98
+
99
+ @kernel
100
+ def t_adj(qubit: Qubit) -> None:
101
+ """Apply the adjoint of a T gate to a qubit.
102
+
103
+ Args:
104
+ qubit (Qubit): Target qubit.
105
+ """
106
+ broadcast.t_adj(ilist.IList([qubit]))
107
+
108
+
109
+ @kernel
110
+ def s_adj(qubit: Qubit) -> None:
111
+ """Apply the adjoint of an S gate to a qubit.
112
+
113
+ Args:
114
+ qubit (Qubit): Target qubit.
115
+ """
116
+ broadcast.s_adj(ilist.IList([qubit]))
117
+
118
+
119
+ @kernel
120
+ def sqrt_x_adj(qubit: Qubit) -> None:
121
+ """Apply the adjoint of a Sqrt(X) gate to a qubit.
122
+
123
+ Args:
124
+ qubit (Qubit): Target qubit.
125
+ """
126
+ broadcast.sqrt_x_adj(ilist.IList([qubit]))
127
+
128
+
129
+ @kernel
130
+ def sqrt_y_adj(qubit: Qubit) -> None:
131
+ """Apply the adjoint of a Sqrt(Y) gate to a qubit.
132
+
133
+ Args:
134
+ qubit (Qubit): Target qubit.
135
+ """
136
+ broadcast.sqrt_y_adj(ilist.IList([qubit]))
137
+
138
+
139
+ @kernel
140
+ def sqrt_z_adj(qubit: Qubit) -> None:
141
+ """Apply the adjoint of a Sqrt(Z) gate to a qubit.
142
+
143
+ Args:
144
+ qubit (Qubit): Target qubit.
145
+ """
146
+ broadcast.s_adj(ilist.IList([qubit]))
147
+
148
+
149
+ @kernel
150
+ def rx(angle: float, qubit: Qubit) -> None:
151
+ """Apply an RX rotation gate to a qubit.
152
+
153
+ Args:
154
+ angle (float): Rotation angle in radians.
155
+ qubit (Qubit): Target qubit.
156
+ """
157
+ broadcast.rx(angle, ilist.IList([qubit]))
158
+
159
+
160
+ @kernel
161
+ def ry(angle: float, qubit: Qubit) -> None:
162
+ """Apply an RY rotation gate to a qubit.
163
+
164
+ Args:
165
+ angle (float): Rotation angle in radians.
166
+ qubit (Qubit): Target qubit.
167
+ """
168
+ broadcast.ry(angle, ilist.IList([qubit]))
169
+
170
+
171
+ @kernel
172
+ def rz(angle: float, qubit: Qubit) -> None:
173
+ """Apply an RZ rotation gate to a qubit.
174
+
175
+ Args:
176
+ angle (float): Rotation angle in radians.
177
+ qubit (Qubit): Target qubit.
178
+ """
179
+ broadcast.rz(angle, ilist.IList([qubit]))
180
+
181
+
182
+ @kernel
183
+ def cx(control: Qubit, target: Qubit) -> None:
184
+ """Apply a controlled-X gate to a pair of qubits.
185
+
186
+ Args:
187
+ controls (Qubit): Control qubit.
188
+ targets (Qubit): Target qubit.
189
+ """
190
+ broadcast.cx(ilist.IList([control]), ilist.IList([target]))
191
+
192
+
193
+ @kernel
194
+ def cy(control: Qubit, target: Qubit) -> None:
195
+ """Apply a controlled-Y gate to a pair of qubits.
196
+
197
+ Args:
198
+ controls (Qubit): Control qubit.
199
+ targets (Qubit): Target qubit.
200
+ """
201
+ broadcast.cy(ilist.IList([control]), ilist.IList([target]))
202
+
203
+
204
+ @kernel
205
+ def cz(control: Qubit, target: Qubit) -> None:
206
+ """Apply a controlled-Z gate to a pair of qubits.
207
+
208
+ Args:
209
+ controls (Qubit): Control qubit.
210
+ targets (Qubit): Target qubit.
211
+ """
212
+ broadcast.cz(ilist.IList([control]), ilist.IList([target]))
213
+
214
+
215
+ @kernel
216
+ def u3(theta: float, phi: float, lam: float, qubit: Qubit):
217
+ """Apply the U3 gate of a qubit.
218
+
219
+ The applied gate is represented by the unitary matrix given by:
220
+
221
+ $$ U3(\\theta, \\phi, \\lambda) = R_z(\\phi)R_y(\\theta)R_z(\\lambda) $$
222
+
223
+ Args:
224
+ theta (float): Rotation around Y axis (radians).
225
+ phi (float): Global phase shift component (radians).
226
+ lam (float): Z rotations in decomposition (radians).
227
+ qubit (Qubit): Target qubit.
228
+ """
229
+ broadcast.u3(theta, phi, lam, ilist.IList([qubit]))
230
+
231
+
232
+ # NOTE: stdlib not wrapping statements starts here
233
+
234
+
235
+ @kernel
236
+ def shift(angle: float, qubit: Qubit) -> None:
237
+ """Apply a phase shift to the |1> state of a qubit.
238
+ Args:
239
+ angle (float): Phase shift angle in radians.
240
+ qubit (Qubit): Target qubit.
241
+ """
242
+ broadcast.shift(angle, ilist.IList([qubit]))