bloqade-circuit 0.6.2__py3-none-any.whl → 0.9.1__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.
Files changed (192) hide show
  1. bloqade/analysis/address/__init__.py +8 -4
  2. bloqade/analysis/address/analysis.py +123 -33
  3. bloqade/analysis/address/impls.py +293 -90
  4. bloqade/analysis/address/lattice.py +209 -24
  5. bloqade/analysis/fidelity/analysis.py +11 -23
  6. bloqade/analysis/measure_id/__init__.py +4 -1
  7. bloqade/analysis/measure_id/analysis.py +29 -20
  8. bloqade/analysis/measure_id/impls.py +72 -31
  9. bloqade/annotate/__init__.py +6 -0
  10. bloqade/annotate/_dialect.py +3 -0
  11. bloqade/annotate/_interface.py +22 -0
  12. bloqade/annotate/stmts.py +29 -0
  13. bloqade/annotate/types.py +13 -0
  14. bloqade/cirq_utils/__init__.py +4 -2
  15. bloqade/cirq_utils/emit/__init__.py +3 -0
  16. bloqade/cirq_utils/emit/base.py +246 -0
  17. bloqade/cirq_utils/emit/gate.py +104 -0
  18. bloqade/cirq_utils/emit/noise.py +90 -0
  19. bloqade/cirq_utils/emit/qubit.py +35 -0
  20. bloqade/cirq_utils/lowering.py +660 -0
  21. bloqade/cirq_utils/noise/__init__.py +0 -2
  22. bloqade/cirq_utils/noise/_two_zone_utils.py +7 -15
  23. bloqade/cirq_utils/noise/model.py +151 -191
  24. bloqade/cirq_utils/noise/transform.py +2 -2
  25. bloqade/cirq_utils/parallelize.py +9 -6
  26. bloqade/gemini/__init__.py +1 -0
  27. bloqade/gemini/analysis/__init__.py +3 -0
  28. bloqade/gemini/analysis/logical_validation/__init__.py +1 -0
  29. bloqade/gemini/analysis/logical_validation/analysis.py +17 -0
  30. bloqade/gemini/analysis/logical_validation/impls.py +101 -0
  31. bloqade/gemini/groups.py +67 -0
  32. bloqade/native/__init__.py +23 -0
  33. bloqade/native/_prelude.py +45 -0
  34. bloqade/native/dialects/__init__.py +0 -0
  35. bloqade/native/dialects/gate/__init__.py +2 -0
  36. bloqade/native/dialects/gate/_dialect.py +3 -0
  37. bloqade/native/dialects/gate/_interface.py +32 -0
  38. bloqade/native/dialects/gate/stmts.py +31 -0
  39. bloqade/native/stdlib/__init__.py +0 -0
  40. bloqade/native/stdlib/broadcast.py +246 -0
  41. bloqade/native/stdlib/simple.py +220 -0
  42. bloqade/native/upstream/__init__.py +4 -0
  43. bloqade/native/upstream/squin2native.py +79 -0
  44. bloqade/pyqrack/__init__.py +2 -2
  45. bloqade/pyqrack/base.py +7 -1
  46. bloqade/pyqrack/device.py +190 -4
  47. bloqade/pyqrack/native.py +49 -0
  48. bloqade/pyqrack/reg.py +6 -6
  49. bloqade/pyqrack/squin/gate/__init__.py +1 -0
  50. bloqade/pyqrack/squin/gate/gate.py +136 -0
  51. bloqade/pyqrack/squin/noise/native.py +120 -54
  52. bloqade/pyqrack/squin/qubit.py +39 -36
  53. bloqade/pyqrack/target.py +5 -4
  54. bloqade/pyqrack/task.py +114 -7
  55. bloqade/qasm2/_qasm_loading.py +3 -3
  56. bloqade/qasm2/dialects/core/address.py +21 -12
  57. bloqade/qasm2/dialects/expr/_emit.py +19 -8
  58. bloqade/qasm2/dialects/expr/stmts.py +7 -7
  59. bloqade/qasm2/dialects/noise/fidelity.py +4 -8
  60. bloqade/qasm2/dialects/noise/model.py +2 -1
  61. bloqade/qasm2/emit/base.py +16 -11
  62. bloqade/qasm2/emit/gate.py +11 -8
  63. bloqade/qasm2/emit/main.py +103 -3
  64. bloqade/qasm2/emit/target.py +9 -5
  65. bloqade/qasm2/groups.py +3 -2
  66. bloqade/qasm2/parse/lowering.py +0 -1
  67. bloqade/qasm2/passes/fold.py +14 -73
  68. bloqade/qasm2/passes/glob.py +2 -2
  69. bloqade/qasm2/passes/noise.py +1 -1
  70. bloqade/qasm2/passes/parallel.py +7 -5
  71. bloqade/qasm2/rewrite/__init__.py +0 -1
  72. bloqade/qasm2/rewrite/noise/heuristic_noise.py +7 -17
  73. bloqade/qasm2/rewrite/parallel_to_glob.py +28 -15
  74. bloqade/qasm2/rewrite/parallel_to_uop.py +2 -8
  75. bloqade/qasm2/rewrite/register.py +2 -2
  76. bloqade/qasm2/rewrite/uop_to_parallel.py +4 -2
  77. bloqade/qbraid/lowering.py +1 -0
  78. bloqade/qbraid/schema.py +2 -2
  79. bloqade/qubit/__init__.py +12 -0
  80. bloqade/qubit/_dialect.py +3 -0
  81. bloqade/qubit/_interface.py +49 -0
  82. bloqade/qubit/_prelude.py +45 -0
  83. bloqade/qubit/analysis/__init__.py +1 -0
  84. bloqade/qubit/analysis/address_impl.py +40 -0
  85. bloqade/qubit/stdlib/__init__.py +2 -0
  86. bloqade/qubit/stdlib/_new.py +34 -0
  87. bloqade/qubit/stdlib/broadcast.py +62 -0
  88. bloqade/qubit/stdlib/simple.py +59 -0
  89. bloqade/qubit/stmts.py +60 -0
  90. bloqade/rewrite/passes/__init__.py +6 -0
  91. bloqade/rewrite/passes/aggressive_unroll.py +103 -0
  92. bloqade/rewrite/passes/callgraph.py +116 -0
  93. bloqade/rewrite/passes/canonicalize_ilist.py +20 -14
  94. bloqade/rewrite/rules/split_ifs.py +18 -1
  95. bloqade/squin/__init__.py +47 -14
  96. bloqade/squin/analysis/__init__.py +0 -1
  97. bloqade/squin/analysis/schedule.py +10 -11
  98. bloqade/squin/gate/__init__.py +2 -0
  99. bloqade/squin/gate/_dialect.py +3 -0
  100. bloqade/squin/gate/_interface.py +98 -0
  101. bloqade/squin/gate/stmts.py +125 -0
  102. bloqade/squin/groups.py +5 -22
  103. bloqade/squin/noise/__init__.py +1 -10
  104. bloqade/squin/noise/_dialect.py +1 -1
  105. bloqade/squin/noise/_interface.py +45 -0
  106. bloqade/squin/noise/stmts.py +66 -28
  107. bloqade/squin/rewrite/U3_to_clifford.py +70 -51
  108. bloqade/squin/rewrite/__init__.py +0 -2
  109. bloqade/squin/rewrite/remove_dangling_qubits.py +2 -2
  110. bloqade/squin/rewrite/wrap_analysis.py +4 -35
  111. bloqade/squin/stdlib/__init__.py +0 -0
  112. bloqade/squin/stdlib/broadcast/__init__.py +34 -0
  113. bloqade/squin/stdlib/broadcast/_qubit.py +4 -0
  114. bloqade/squin/stdlib/broadcast/gate.py +260 -0
  115. bloqade/squin/stdlib/broadcast/noise.py +144 -0
  116. bloqade/squin/stdlib/simple/__init__.py +33 -0
  117. bloqade/squin/stdlib/simple/gate.py +242 -0
  118. bloqade/squin/stdlib/simple/noise.py +126 -0
  119. bloqade/stim/__init__.py +1 -0
  120. bloqade/stim/_wrappers.py +6 -0
  121. bloqade/stim/dialects/auxiliary/emit.py +19 -18
  122. bloqade/stim/dialects/collapse/emit_str.py +7 -8
  123. bloqade/stim/dialects/gate/emit.py +9 -10
  124. bloqade/stim/dialects/noise/emit.py +17 -13
  125. bloqade/stim/dialects/noise/stmts.py +5 -3
  126. bloqade/stim/emit/__init__.py +1 -0
  127. bloqade/stim/emit/impls.py +16 -0
  128. bloqade/stim/emit/stim_str.py +48 -31
  129. bloqade/stim/groups.py +12 -2
  130. bloqade/stim/parse/lowering.py +14 -17
  131. bloqade/stim/passes/__init__.py +3 -1
  132. bloqade/stim/passes/flatten.py +26 -0
  133. bloqade/stim/passes/simplify_ifs.py +16 -2
  134. bloqade/stim/passes/squin_to_stim.py +18 -60
  135. bloqade/stim/rewrite/__init__.py +3 -4
  136. bloqade/stim/rewrite/get_record_util.py +24 -0
  137. bloqade/stim/rewrite/ifs_to_stim.py +29 -31
  138. bloqade/stim/rewrite/qubit_to_stim.py +90 -41
  139. bloqade/stim/rewrite/set_detector_to_stim.py +68 -0
  140. bloqade/stim/rewrite/set_observable_to_stim.py +52 -0
  141. bloqade/stim/rewrite/squin_measure.py +11 -79
  142. bloqade/stim/rewrite/squin_noise.py +134 -108
  143. bloqade/stim/rewrite/util.py +5 -192
  144. bloqade/test_utils.py +1 -1
  145. bloqade/types.py +10 -0
  146. bloqade/validation/__init__.py +2 -0
  147. bloqade/validation/analysis/__init__.py +5 -0
  148. bloqade/validation/analysis/analysis.py +41 -0
  149. bloqade/validation/analysis/lattice.py +58 -0
  150. bloqade/validation/kernel_validation.py +77 -0
  151. {bloqade_circuit-0.6.2.dist-info → bloqade_circuit-0.9.1.dist-info}/METADATA +5 -6
  152. bloqade_circuit-0.9.1.dist-info/RECORD +265 -0
  153. bloqade/pyqrack/squin/op.py +0 -166
  154. bloqade/pyqrack/squin/runtime.py +0 -535
  155. bloqade/pyqrack/squin/wire.py +0 -51
  156. bloqade/rewrite/rules/flatten_ilist.py +0 -51
  157. bloqade/rewrite/rules/inline_getitem_ilist.py +0 -31
  158. bloqade/squin/_typeinfer.py +0 -20
  159. bloqade/squin/analysis/address_impl.py +0 -71
  160. bloqade/squin/analysis/nsites/__init__.py +0 -9
  161. bloqade/squin/analysis/nsites/analysis.py +0 -50
  162. bloqade/squin/analysis/nsites/impls.py +0 -92
  163. bloqade/squin/analysis/nsites/lattice.py +0 -49
  164. bloqade/squin/cirq/__init__.py +0 -265
  165. bloqade/squin/cirq/emit/emit_circuit.py +0 -109
  166. bloqade/squin/cirq/emit/noise.py +0 -49
  167. bloqade/squin/cirq/emit/op.py +0 -125
  168. bloqade/squin/cirq/emit/qubit.py +0 -60
  169. bloqade/squin/cirq/emit/runtime.py +0 -242
  170. bloqade/squin/cirq/lowering.py +0 -440
  171. bloqade/squin/lowering.py +0 -54
  172. bloqade/squin/noise/_wrapper.py +0 -40
  173. bloqade/squin/noise/rewrite.py +0 -111
  174. bloqade/squin/op/__init__.py +0 -41
  175. bloqade/squin/op/_dialect.py +0 -3
  176. bloqade/squin/op/_wrapper.py +0 -121
  177. bloqade/squin/op/number.py +0 -5
  178. bloqade/squin/op/rewrite.py +0 -46
  179. bloqade/squin/op/stdlib.py +0 -62
  180. bloqade/squin/op/stmts.py +0 -276
  181. bloqade/squin/op/traits.py +0 -43
  182. bloqade/squin/op/types.py +0 -26
  183. bloqade/squin/qubit.py +0 -184
  184. bloqade/squin/rewrite/canonicalize.py +0 -60
  185. bloqade/squin/rewrite/desugar.py +0 -124
  186. bloqade/squin/types.py +0 -8
  187. bloqade/squin/wire.py +0 -201
  188. bloqade/stim/rewrite/wire_identity_elimination.py +0 -24
  189. bloqade/stim/rewrite/wire_to_stim.py +0 -57
  190. bloqade_circuit-0.6.2.dist-info/RECORD +0 -234
  191. {bloqade_circuit-0.6.2.dist-info → bloqade_circuit-0.9.1.dist-info}/WHEEL +0 -0
  192. {bloqade_circuit-0.6.2.dist-info → bloqade_circuit-0.9.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,67 @@
1
+ from typing import Annotated
2
+
3
+ from kirin import ir
4
+ from kirin.passes import Default
5
+ from kirin.prelude import structural_no_opt
6
+ from kirin.dialects import py, func, ilist
7
+ from typing_extensions import Doc
8
+ from kirin.passes.inline import InlinePass
9
+
10
+ from bloqade.squin import gate, qubit
11
+ from bloqade.validation import KernelValidation
12
+ from bloqade.rewrite.passes import AggressiveUnroll
13
+
14
+ from .analysis import GeminiLogicalValidationAnalysis
15
+
16
+
17
+ @ir.dialect_group(structural_no_opt.union([gate, py.constant, qubit, func, ilist]))
18
+ def logical(self):
19
+ """Compile a function to a Gemini logical kernel."""
20
+
21
+ def run_pass(
22
+ mt,
23
+ *,
24
+ verify: Annotated[
25
+ bool, Doc("run `verify` before running passes, default is `True`")
26
+ ] = True,
27
+ typeinfer: Annotated[
28
+ bool,
29
+ Doc("run type inference and apply the inferred type to IR, default `True`"),
30
+ ] = True,
31
+ fold: Annotated[bool, Doc("run folding passes")] = True,
32
+ aggressive: Annotated[
33
+ bool, Doc("run aggressive folding passes if `fold=True`")
34
+ ] = False,
35
+ inline: Annotated[bool, Doc("inline function calls, default `True`")] = True,
36
+ aggressive_unroll: Annotated[
37
+ bool,
38
+ Doc(
39
+ "Run aggressive inlining and unrolling pass on the IR, default `False`"
40
+ ),
41
+ ] = False,
42
+ no_raise: Annotated[bool, Doc("do not raise exception during analysis")] = True,
43
+ ) -> None:
44
+
45
+ if inline and not aggressive_unroll:
46
+ InlinePass(mt.dialects, no_raise=no_raise).fixpoint(mt)
47
+
48
+ if aggressive_unroll:
49
+ AggressiveUnroll(mt.dialects, no_raise=no_raise).fixpoint(mt)
50
+ else:
51
+ default_pass = Default(
52
+ self,
53
+ verify=verify,
54
+ fold=fold,
55
+ aggressive=aggressive,
56
+ typeinfer=typeinfer,
57
+ no_raise=no_raise,
58
+ )
59
+
60
+ default_pass.fixpoint(mt)
61
+
62
+ if verify:
63
+ validator = KernelValidation(GeminiLogicalValidationAnalysis)
64
+ validator.run(mt, no_raise=no_raise)
65
+ mt.verify()
66
+
67
+ return run_pass
@@ -0,0 +1,23 @@
1
+ from .stdlib import broadcast as broadcast
2
+ from ._prelude import kernel as kernel
3
+ from .stdlib.simple import (
4
+ h as h,
5
+ s as s,
6
+ t as t,
7
+ x as x,
8
+ y as y,
9
+ z as z,
10
+ cx as cx,
11
+ cy as cy,
12
+ cz as cz,
13
+ rx as rx,
14
+ ry as ry,
15
+ rz as rz,
16
+ u3 as u3,
17
+ s_dag as s_dag,
18
+ shift as shift,
19
+ sqrt_x as sqrt_x,
20
+ sqrt_y as sqrt_y,
21
+ sqrt_x_adj as sqrt_x_adj,
22
+ sqrt_y_adj as sqrt_y_adj,
23
+ )
@@ -0,0 +1,45 @@
1
+ from typing import Annotated
2
+
3
+ from kirin import ir
4
+ from kirin.passes import Default
5
+ from kirin.prelude import structural_no_opt
6
+ from typing_extensions import Doc
7
+
8
+ from bloqade import qubit
9
+
10
+ from .dialects import gate
11
+
12
+
13
+ @ir.dialect_group(structural_no_opt.union([gate, qubit]))
14
+ def kernel(self):
15
+ """Compile a function to a native kernel."""
16
+
17
+ def run_pass(
18
+ mt,
19
+ *,
20
+ verify: Annotated[
21
+ bool, Doc("run `verify` before running passes, default is `True`")
22
+ ] = True,
23
+ typeinfer: Annotated[
24
+ bool,
25
+ Doc(
26
+ "run type inference and apply the inferred type to IR, default `False`"
27
+ ),
28
+ ] = False,
29
+ fold: Annotated[bool, Doc("run folding passes")] = True,
30
+ aggressive: Annotated[
31
+ bool, Doc("run aggressive folding passes if `fold=True`")
32
+ ] = False,
33
+ no_raise: Annotated[bool, Doc("do not raise exception during analysis")] = True,
34
+ ) -> None:
35
+ default_pass = Default(
36
+ self,
37
+ verify=verify,
38
+ fold=fold,
39
+ aggressive=aggressive,
40
+ typeinfer=typeinfer,
41
+ no_raise=no_raise,
42
+ )
43
+ default_pass.fixpoint(mt)
44
+
45
+ return run_pass
File without changes
@@ -0,0 +1,2 @@
1
+ from . import stmts as stmts
2
+ from ._dialect import dialect as dialect
@@ -0,0 +1,3 @@
1
+ from kirin import ir
2
+
3
+ dialect = ir.Dialect("native.gate")
@@ -0,0 +1,32 @@
1
+ import typing
2
+
3
+ from kirin import lowering
4
+ from kirin.dialects import ilist
5
+
6
+ from bloqade import qubit
7
+
8
+ from .stmts import CZ, R, Rz
9
+
10
+ Len = typing.TypeVar("Len")
11
+
12
+
13
+ @lowering.wraps(CZ)
14
+ def cz(
15
+ controls: ilist.IList[qubit.Qubit, Len],
16
+ targets: ilist.IList[qubit.Qubit, Len],
17
+ ): ...
18
+
19
+
20
+ @lowering.wraps(R)
21
+ def r(
22
+ axis_angle: float,
23
+ rotation_angle: float,
24
+ qubits: ilist.IList[qubit.Qubit, typing.Any],
25
+ ): ...
26
+
27
+
28
+ @lowering.wraps(Rz)
29
+ def rz(
30
+ rotation_angle: float,
31
+ qubits: ilist.IList[qubit.Qubit, typing.Any],
32
+ ): ...
@@ -0,0 +1,31 @@
1
+ from kirin import ir, types, lowering
2
+ from kirin.decl import info, statement
3
+ from kirin.dialects import ilist
4
+
5
+ from bloqade.types import QubitType
6
+
7
+ from ._dialect import dialect
8
+
9
+ N = types.TypeVar("N")
10
+
11
+
12
+ @statement(dialect=dialect)
13
+ class CZ(ir.Statement):
14
+ traits = frozenset({lowering.FromPythonCall()})
15
+ controls: ir.SSAValue = info.argument(ilist.IListType[QubitType, N])
16
+ targets: ir.SSAValue = info.argument(ilist.IListType[QubitType, N])
17
+
18
+
19
+ @statement(dialect=dialect)
20
+ class R(ir.Statement):
21
+ traits = frozenset({lowering.FromPythonCall()})
22
+ axis_angle: ir.SSAValue = info.argument(types.Float)
23
+ rotation_angle: ir.SSAValue = info.argument(types.Float)
24
+ qubits: ir.SSAValue = info.argument(ilist.IListType[QubitType, types.Any])
25
+
26
+
27
+ @statement(dialect=dialect)
28
+ class Rz(ir.Statement):
29
+ traits = frozenset({lowering.FromPythonCall()})
30
+ rotation_angle: ir.SSAValue = info.argument(types.Float)
31
+ qubits: ir.SSAValue = info.argument(ilist.IListType[QubitType, types.Any])
File without changes
@@ -0,0 +1,246 @@
1
+ import math
2
+ from typing import Any, TypeVar
3
+
4
+ from kirin.dialects import ilist
5
+
6
+ from bloqade import qubit
7
+ from bloqade.native._prelude import kernel
8
+ from bloqade.native.dialects.gate import _interface as native
9
+
10
+
11
+ @kernel
12
+ def _radian_to_turn(angle: float) -> float:
13
+ """Convert an angle from radians to turns.
14
+
15
+ Args:
16
+ angle (float): Angle in radians.
17
+
18
+ Returns:
19
+ float: Equivalent angle in turns.
20
+ """
21
+ return angle / (2 * math.pi)
22
+
23
+
24
+ @kernel
25
+ def rx(angle: float, qubits: ilist.IList[qubit.Qubit, Any]):
26
+ """Apply an RX rotation gate on a group of qubits.
27
+
28
+ Args:
29
+ angle (float): Rotation angle in radians.
30
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
31
+ """
32
+ native.r(0.0, _radian_to_turn(angle), qubits)
33
+
34
+
35
+ @kernel
36
+ def x(qubits: ilist.IList[qubit.Qubit, Any]):
37
+ """Apply a Pauli-X gate on a group of qubits.
38
+
39
+ Args:
40
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
41
+ """
42
+ rx(math.pi, qubits)
43
+
44
+
45
+ @kernel
46
+ def sqrt_x(qubits: ilist.IList[qubit.Qubit, Any]):
47
+ """Apply a sqrt(X) gate on a group of qubits.
48
+
49
+ Args:
50
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
51
+ """
52
+ rx(math.pi / 2.0, qubits)
53
+
54
+
55
+ @kernel
56
+ def sqrt_x_adj(qubits: ilist.IList[qubit.Qubit, Any]):
57
+ """Apply the adjoint of sqrt(X) on a group of qubits.
58
+
59
+ Args:
60
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
61
+ """
62
+ rx(-math.pi / 2.0, qubits)
63
+
64
+
65
+ @kernel
66
+ def ry(angle: float, qubits: ilist.IList[qubit.Qubit, Any]):
67
+ """Apply an RY rotation gate on a group of qubits.
68
+
69
+ Args:
70
+ angle (float): Rotation angle in radians.
71
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
72
+ """
73
+ native.r(0.25, _radian_to_turn(angle), qubits)
74
+
75
+
76
+ @kernel
77
+ def y(qubits: ilist.IList[qubit.Qubit, Any]):
78
+ """Apply a Pauli-Y gate on a group of qubits.
79
+
80
+ Args:
81
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
82
+ """
83
+ ry(math.pi, qubits)
84
+
85
+
86
+ @kernel
87
+ def sqrt_y(qubits: ilist.IList[qubit.Qubit, Any]):
88
+ """Apply a sqrt(Y) gate on a group of qubits.
89
+
90
+ Args:
91
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
92
+ """
93
+ ry(-math.pi / 2.0, qubits)
94
+
95
+
96
+ @kernel
97
+ def sqrt_y_adj(qubits: ilist.IList[qubit.Qubit, Any]):
98
+ """Apply the adjoint of sqrt(Y) on a group of qubits.
99
+
100
+ Args:
101
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
102
+ """
103
+ ry(math.pi / 2.0, qubits)
104
+
105
+
106
+ @kernel
107
+ def rz(angle: float, qubits: ilist.IList[qubit.Qubit, Any]):
108
+ """Apply an RZ rotation gate on a group of qubits.
109
+
110
+ Args:
111
+ angle (float): Rotation angle in radians.
112
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
113
+ """
114
+ native.rz(_radian_to_turn(angle), qubits)
115
+
116
+
117
+ @kernel
118
+ def z(qubits: ilist.IList[qubit.Qubit, Any]):
119
+ """Apply a Pauli-Z gate on a group of qubits.
120
+
121
+ Args:
122
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
123
+ """
124
+ rz(math.pi, qubits)
125
+
126
+
127
+ @kernel
128
+ def s(qubits: ilist.IList[qubit.Qubit, Any]):
129
+ """Apply an S gate on a group of qubits.
130
+
131
+ Args:
132
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
133
+ """
134
+ rz(math.pi / 2.0, qubits)
135
+
136
+
137
+ @kernel
138
+ def s_adj(qubits: ilist.IList[qubit.Qubit, Any]):
139
+ """Apply the adjoint of the S gate on a group of qubits.
140
+
141
+ Args:
142
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
143
+ """
144
+ rz(-math.pi / 2.0, qubits)
145
+
146
+
147
+ @kernel
148
+ def h(qubits: ilist.IList[qubit.Qubit, Any]):
149
+ """Apply a Hadamard gate on a group of qubits.
150
+
151
+ Args:
152
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
153
+ """
154
+ s(qubits)
155
+ sqrt_x(qubits)
156
+ s(qubits)
157
+
158
+
159
+ @kernel
160
+ def t(qubits: ilist.IList[qubit.Qubit, Any]):
161
+ """Apply a T gate on a group of qubits.
162
+
163
+ Args:
164
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
165
+ """
166
+ rz(math.pi / 4.0, qubits)
167
+
168
+
169
+ @kernel
170
+ def t_adj(qubits: ilist.IList[qubit.Qubit, Any]):
171
+ """Apply the adjoint of aT gate on a group of qubits.
172
+
173
+ Args:
174
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
175
+ """
176
+ rz(-math.pi / 4.0, qubits)
177
+
178
+
179
+ @kernel
180
+ def shift(angle: float, qubits: ilist.IList[qubit.Qubit, Any]):
181
+ """Apply a phase shift to the |1> state on a group of qubits.
182
+
183
+ Args:
184
+ angle (float): Phase shift angle in radians.
185
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
186
+ """
187
+ rz(angle / 2.0, qubits)
188
+
189
+
190
+ @kernel
191
+ def u3(theta: float, phi: float, lam: float, qubits: ilist.IList[qubit.Qubit, Any]):
192
+ """Apply the U3 gate on a group of qubits.
193
+
194
+ The applied gate is represented by the unitary matrix given by:
195
+
196
+ $$ U3(\\theta, \\phi, \\lambda) = R_z(\\phi)R_y(\\theta)R_z(\\lambda) $$
197
+
198
+ Args:
199
+ theta (float): Rotation around Y axis (radians).
200
+ phi (float): Global phase shift component (radians).
201
+ lam (float): Z rotations in decomposition (radians).
202
+ qubits (ilist.IList[qubit.Qubit, Any]): Target qubits.
203
+ """
204
+ rz(lam, qubits)
205
+ ry(theta, qubits)
206
+ rz(phi, qubits)
207
+
208
+
209
+ N = TypeVar("N")
210
+
211
+
212
+ @kernel
213
+ def cz(controls: ilist.IList[qubit.Qubit, N], qubits: ilist.IList[qubit.Qubit, N]):
214
+ """Apply a controlled-Z gate on a pairs of qubits.
215
+
216
+ Args:
217
+ controls (ilist.IList[qubit.Qubit, N]): Control qubits.
218
+ qubits (ilist.IList[qubit.Qubit, N]): Target qubits.
219
+ """
220
+ native.cz(controls, qubits)
221
+
222
+
223
+ @kernel
224
+ def cx(controls: ilist.IList[qubit.Qubit, N], targets: ilist.IList[qubit.Qubit, N]):
225
+ """Apply a controlled-X gate on a pairs of qubits.
226
+
227
+ Args:
228
+ controls (ilist.IList[qubit.Qubit, N]): Control qubits.
229
+ targets (ilist.IList[qubit.Qubit, N]): Target qubits.
230
+ """
231
+ sqrt_y_adj(targets)
232
+ cz(controls, targets)
233
+ sqrt_y(targets)
234
+
235
+
236
+ @kernel
237
+ def cy(controls: ilist.IList[qubit.Qubit, N], targets: ilist.IList[qubit.Qubit, N]):
238
+ """Apply a controlled-Y gate on a pairs of qubits.
239
+
240
+ Args:
241
+ controls (ilist.IList[qubit.Qubit, N]): Control qubits.
242
+ targets (ilist.IList[qubit.Qubit, N]): Target qubits.
243
+ """
244
+ sqrt_x(targets)
245
+ cz(controls, targets)
246
+ sqrt_x_adj(targets)
@@ -0,0 +1,220 @@
1
+ from kirin.dialects import ilist
2
+
3
+ from bloqade import qubit
4
+
5
+ from . import broadcast
6
+ from .._prelude import kernel
7
+
8
+
9
+ @kernel
10
+ def rx(angle: float, qubit: qubit.Qubit):
11
+ """Apply an RX rotation gate on a single qubit.
12
+
13
+ Args:
14
+ angle (float): Rotation angle in radians.
15
+ qubit (qubit.Qubit): The qubit to apply the rotation to.
16
+ """
17
+ broadcast.rx(angle, ilist.IList([qubit]))
18
+
19
+
20
+ @kernel
21
+ def x(qubit: qubit.Qubit):
22
+ """Apply a Pauli-X gate on a single qubit.
23
+
24
+ Args:
25
+ qubit (qubit.Qubit): The qubit to apply the X gate to.
26
+ """
27
+ broadcast.x(ilist.IList([qubit]))
28
+
29
+
30
+ @kernel
31
+ def sqrt_x(qubit: qubit.Qubit):
32
+ """Apply a sqrt(X) gate on a single qubit.
33
+
34
+ Args:
35
+ qubit (qubit.Qubit): The qubit to apply the sqrt(X) gate to.
36
+ """
37
+ broadcast.sqrt_x(ilist.IList([qubit]))
38
+
39
+
40
+ @kernel
41
+ def sqrt_x_adj(qubit: qubit.Qubit):
42
+ """Apply the adjoint of sqrt(X) on a single qubit.
43
+
44
+ Args:
45
+ qubit (qubit.Qubit): The qubit to apply the adjoint sqrt(X) gate to.
46
+ """
47
+ broadcast.sqrt_x_adj(ilist.IList([qubit]))
48
+
49
+
50
+ @kernel
51
+ def ry(angle: float, qubit: qubit.Qubit):
52
+ """Apply an RY rotation gate on a single qubit.
53
+
54
+ Args:
55
+ angle (float): Rotation angle in radians.
56
+ qubit (qubit.Qubit): The qubit to apply the rotation to.
57
+ """
58
+ broadcast.ry(angle, ilist.IList([qubit]))
59
+
60
+
61
+ @kernel
62
+ def y(qubit: qubit.Qubit):
63
+ """Apply a Pauli-Y gate on a single qubit.
64
+
65
+ Args:
66
+ qubit (qubit.Qubit): The qubit to apply the Y gate to.
67
+ """
68
+ broadcast.y(ilist.IList([qubit]))
69
+
70
+
71
+ @kernel
72
+ def sqrt_y(qubit: qubit.Qubit):
73
+ """Apply a sqrt(Y) gate on a single qubit.
74
+
75
+ Args:
76
+ qubit (qubit.Qubit): The qubit to apply the sqrt(Y) gate to.
77
+ """
78
+ broadcast.sqrt_y(ilist.IList([qubit]))
79
+
80
+
81
+ @kernel
82
+ def sqrt_y_adj(qubit: qubit.Qubit):
83
+ """Apply the adjoint of sqrt(Y) on a single qubit.
84
+
85
+ Args:
86
+ qubit (qubit.Qubit): The qubit to apply the adjoint sqrt(Y) gate to.
87
+ """
88
+ broadcast.sqrt_y_adj(ilist.IList([qubit]))
89
+
90
+
91
+ @kernel
92
+ def rz(angle: float, qubit: qubit.Qubit):
93
+ """Apply an RZ rotation gate on a single qubit.
94
+
95
+ Args:
96
+ angle (float): Rotation angle in radians.
97
+ qubit (qubit.Qubit): The qubit to apply the rotation to.
98
+ """
99
+ broadcast.rz(angle, ilist.IList([qubit]))
100
+
101
+
102
+ @kernel
103
+ def z(qubit: qubit.Qubit):
104
+ """Apply a Pauli-Z gate on a single qubit.
105
+
106
+ Args:
107
+ qubit (qubit.Qubit): The qubit to apply the Z gate to.
108
+ """
109
+ broadcast.z(ilist.IList([qubit]))
110
+
111
+
112
+ @kernel
113
+ def s(qubit: qubit.Qubit):
114
+ """Apply an S gate on a single qubit.
115
+
116
+ Args:
117
+ qubit (qubit.Qubit): The qubit to apply the S gate to.
118
+ """
119
+ broadcast.s(ilist.IList([qubit]))
120
+
121
+
122
+ @kernel
123
+ def s_dag(qubit: qubit.Qubit):
124
+ """Apply the adjoint of the S gate on a single qubit.
125
+
126
+ Args:
127
+ qubit (qubit.Qubit): The qubit to apply the adjoint S gate to.
128
+ """
129
+ broadcast.s_adj(ilist.IList([qubit]))
130
+
131
+
132
+ @kernel
133
+ def h(qubit: qubit.Qubit):
134
+ """Apply a Hadamard gate on a single qubit.
135
+
136
+ Args:
137
+ qubit (qubit.Qubit): The qubit to apply the Hadamard gate to.
138
+ """
139
+ broadcast.h(ilist.IList([qubit]))
140
+
141
+
142
+ @kernel
143
+ def t(qubit: qubit.Qubit):
144
+ """Apply a T gate on a single qubit.
145
+
146
+ Args:
147
+ qubit (qubit.Qubit): The qubit to apply the T gate to.
148
+ """
149
+ broadcast.t(ilist.IList([qubit]))
150
+
151
+
152
+ @kernel
153
+ def t_adj(qubit: qubit.Qubit):
154
+ """Apply the adjoint of the T gate on a single qubit.
155
+
156
+ Args:
157
+ qubit (qubit.Qubit): The qubit to apply the adjoint T gate to.
158
+ """
159
+ broadcast.t_adj(ilist.IList([qubit]))
160
+
161
+
162
+ @kernel
163
+ def shift(angle: float, qubit: qubit.Qubit):
164
+ """Apply a phase shift on the |1> state of a single qubit.
165
+
166
+ Args:
167
+ angle (float): Shift angle in radians.
168
+ qubit (qubit.Qubit): The qubit to apply the shift to.
169
+ """
170
+ broadcast.shift(angle, ilist.IList([qubit]))
171
+
172
+
173
+ @kernel
174
+ def u3(theta: float, phi: float, lam: float, qubit: qubit.Qubit):
175
+ """Apply the U3 gate on a single qubit.
176
+
177
+ The applied gate is represented by the unitary matrix given by:
178
+
179
+ $$ U3(\\theta, \\phi, \\lambda) = R_z(\\phi)R_y(\\theta)R_z(\\lambda) $$
180
+
181
+ Args:
182
+ theta (float): Rotation angle around the Y axis in radians.
183
+ phi (float): Rotation angle around the Z axis in radians.
184
+ lam (float): Rotation angle around the Z axis in radians.
185
+ qubit (qubit.Qubit): The qubit to apply the U3 gate to.
186
+ """
187
+ broadcast.u3(theta, phi, lam, ilist.IList([qubit]))
188
+
189
+
190
+ @kernel
191
+ def cz(control: qubit.Qubit, target: qubit.Qubit):
192
+ """Apply a controlled-Z gate on two qubits.
193
+
194
+ Args:
195
+ control (qubit.Qubit): The control qubit.
196
+ target (qubit.Qubit): The target qubit.
197
+ """
198
+ broadcast.cz(ilist.IList([control]), ilist.IList([target]))
199
+
200
+
201
+ @kernel
202
+ def cx(control: qubit.Qubit, target: qubit.Qubit):
203
+ """Apply a controlled-X gate on two qubits.
204
+
205
+ Args:
206
+ control (qubit.Qubit): The control qubit.
207
+ target (qubit.Qubit): The target qubit.
208
+ """
209
+ broadcast.cx(ilist.IList([control]), ilist.IList([target]))
210
+
211
+
212
+ @kernel
213
+ def cy(control: qubit.Qubit, targets: qubit.Qubit):
214
+ """Apply a controlled-Y gate on two qubits.
215
+
216
+ Args:
217
+ control (qubit.Qubit): The control qubit.
218
+ targets (qubit.Qubit): The target qubit.
219
+ """
220
+ broadcast.cy(ilist.IList([control]), ilist.IList([targets]))
@@ -0,0 +1,4 @@
1
+ from .squin2native import (
2
+ GateRule as GateRule,
3
+ SquinToNative as SquinToNative,
4
+ )