bloqade-circuit 0.7.13__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 +96 -51
  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.13.dist-info → bloqade_circuit-0.8.0.dist-info}/METADATA +2 -2
  94. {bloqade_circuit-0.7.13.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.13.dist-info → bloqade_circuit-0.8.0.dist-info}/WHEEL +0 -0
  136. {bloqade_circuit-0.7.13.dist-info → bloqade_circuit-0.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,41 +0,0 @@
1
- from . import stmts as stmts, types as types, rewrite as rewrite
2
- from .stdlib import (
3
- ch as ch,
4
- cx as cx,
5
- cy as cy,
6
- cz as cz,
7
- rx as rx,
8
- ry as ry,
9
- rz as rz,
10
- cphase as cphase,
11
- )
12
- from .traits import Unitary as Unitary, MaybeUnitary as MaybeUnitary
13
- from ._dialect import dialect as dialect
14
- from ._wrapper import (
15
- h as h,
16
- s as s,
17
- t as t,
18
- u as u,
19
- x as x,
20
- y as y,
21
- z as z,
22
- p0 as p0,
23
- p1 as p1,
24
- rot as rot,
25
- kron as kron,
26
- mult as mult,
27
- phase as phase,
28
- reset as reset,
29
- scale as scale,
30
- shift as shift,
31
- spin_n as spin_n,
32
- spin_p as spin_p,
33
- sqrt_x as sqrt_x,
34
- sqrt_y as sqrt_y,
35
- sqrt_z as sqrt_z,
36
- adjoint as adjoint,
37
- control as control,
38
- identity as identity,
39
- pauli_string as pauli_string,
40
- reset_to_one as reset_to_one,
41
- )
@@ -1,3 +0,0 @@
1
- from kirin import ir
2
-
3
- dialect = ir.Dialect("squin.op")
@@ -1,121 +0,0 @@
1
- from kirin.lowering import wraps
2
-
3
- from . import stmts, types
4
-
5
-
6
- @wraps(stmts.Kron)
7
- def kron(lhs: types.Op, rhs: types.Op) -> types.Op: ...
8
-
9
-
10
- @wraps(stmts.Mult)
11
- def mult(lhs: types.Op, rhs: types.Op) -> types.Op: ...
12
-
13
-
14
- @wraps(stmts.Scale)
15
- def scale(op: types.Op, factor: complex) -> types.Op: ...
16
-
17
-
18
- @wraps(stmts.Adjoint)
19
- def adjoint(op: types.Op) -> types.Op: ...
20
-
21
-
22
- @wraps(stmts.Control)
23
- def control(op: types.Op, *, n_controls: int) -> types.Op:
24
- """
25
- Create a controlled operator.
26
-
27
- Note, that when considering atom loss, the operator will not be applied if
28
- any of the controls has been lost.
29
-
30
- Args:
31
- operator: The operator to apply under the control.
32
- n_controls: The number qubits to be used as control.
33
-
34
- Returns:
35
- Operator
36
- """
37
- ...
38
-
39
-
40
- @wraps(stmts.Reset)
41
- def reset() -> types.Op: ...
42
-
43
-
44
- @wraps(stmts.ResetToOne)
45
- def reset_to_one() -> types.Op: ...
46
-
47
-
48
- @wraps(stmts.Identity)
49
- def identity(*, sites: int) -> types.Op: ...
50
-
51
-
52
- @wraps(stmts.Rot)
53
- def rot(axis: types.Op, angle: float) -> types.Op: ...
54
-
55
-
56
- @wraps(stmts.ShiftOp)
57
- def shift(theta: float) -> types.Op: ...
58
-
59
-
60
- @wraps(stmts.PhaseOp)
61
- def phase(theta: float) -> types.Op: ...
62
-
63
-
64
- @wraps(stmts.X)
65
- def x() -> types.PauliOp: ...
66
-
67
-
68
- @wraps(stmts.Y)
69
- def y() -> types.PauliOp: ...
70
-
71
-
72
- @wraps(stmts.Z)
73
- def z() -> types.PauliOp: ...
74
-
75
-
76
- @wraps(stmts.SqrtX)
77
- def sqrt_x() -> types.Op: ...
78
-
79
-
80
- @wraps(stmts.SqrtY)
81
- def sqrt_y() -> types.Op: ...
82
-
83
-
84
- @wraps(stmts.S)
85
- def sqrt_z() -> types.Op: ...
86
-
87
-
88
- @wraps(stmts.H)
89
- def h() -> types.Op: ...
90
-
91
-
92
- @wraps(stmts.S)
93
- def s() -> types.Op: ...
94
-
95
-
96
- @wraps(stmts.T)
97
- def t() -> types.Op: ...
98
-
99
-
100
- @wraps(stmts.P0)
101
- def p0() -> types.Op: ...
102
-
103
-
104
- @wraps(stmts.P1)
105
- def p1() -> types.Op: ...
106
-
107
-
108
- @wraps(stmts.Sn)
109
- def spin_n() -> types.Op: ...
110
-
111
-
112
- @wraps(stmts.Sp)
113
- def spin_p() -> types.Op: ...
114
-
115
-
116
- @wraps(stmts.U3)
117
- def u(theta: float, phi: float, lam: float) -> types.Op: ...
118
-
119
-
120
- @wraps(stmts.PauliString)
121
- def pauli_string(*, string: str) -> types.PauliStringOp: ...
@@ -1,5 +0,0 @@
1
- import numbers
2
-
3
- from kirin.ir.attrs.types import PyClass
4
-
5
- NumberType = PyClass(numbers.Number)
@@ -1,46 +0,0 @@
1
- """Rewrite py.binop.mult to Mult stmt"""
2
-
3
- from kirin import ir
4
- from kirin.passes import Pass
5
- from kirin.rewrite import Walk
6
- from kirin.dialects import py
7
- from kirin.rewrite.abc import RewriteRule, RewriteResult
8
-
9
- from .stmts import Mult, Scale
10
- from .types import OpType
11
-
12
-
13
- class _PyMultToSquinMult(RewriteRule):
14
-
15
- def rewrite_Statement(self, node: ir.Statement) -> RewriteResult:
16
- if not isinstance(node, py.Mult):
17
- return RewriteResult()
18
-
19
- lhs_is_op = node.lhs.type.is_subseteq(OpType)
20
- rhs_is_op = node.rhs.type.is_subseteq(OpType)
21
-
22
- if not lhs_is_op and not rhs_is_op:
23
- return RewriteResult()
24
-
25
- if lhs_is_op and rhs_is_op:
26
- mult = Mult(node.lhs, node.rhs)
27
- node.replace_by(mult)
28
- return RewriteResult(has_done_something=True)
29
-
30
- if lhs_is_op:
31
- scale = Scale(node.lhs, node.rhs)
32
- node.replace_by(scale)
33
- return RewriteResult(has_done_something=True)
34
-
35
- if rhs_is_op:
36
- scale = Scale(node.rhs, node.lhs)
37
- node.replace_by(scale)
38
- return RewriteResult(has_done_something=True)
39
-
40
- return RewriteResult()
41
-
42
-
43
- class PyMultToSquinMult(Pass):
44
-
45
- def unsafe_run(self, mt: ir.Method) -> RewriteResult:
46
- return Walk(_PyMultToSquinMult()).rewrite(mt.code)
@@ -1,62 +0,0 @@
1
- from kirin import ir
2
- from kirin.prelude import structural_no_opt
3
-
4
- from . import types
5
- from ._dialect import dialect
6
- from ._wrapper import h, x, y, z, rot, phase, control
7
-
8
-
9
- @ir.dialect_group(structural_no_opt.add(dialect))
10
- def op(self):
11
- def run_pass(method):
12
- pass
13
-
14
- return run_pass
15
-
16
-
17
- @op
18
- def rx(theta: float) -> types.Op:
19
- """Rotation X gate."""
20
- return rot(x(), theta)
21
-
22
-
23
- @op
24
- def ry(theta: float) -> types.Op:
25
- """Rotation Y gate."""
26
- return rot(y(), theta)
27
-
28
-
29
- @op
30
- def rz(theta: float) -> types.Op:
31
- """Rotation Z gate."""
32
- return rot(z(), theta)
33
-
34
-
35
- @op
36
- def cx() -> types.Op:
37
- """Controlled X gate."""
38
- return control(x(), n_controls=1)
39
-
40
-
41
- @op
42
- def cy() -> types.Op:
43
- """Controlled Y gate."""
44
- return control(y(), n_controls=1)
45
-
46
-
47
- @op
48
- def cz() -> types.Op:
49
- """Control Z gate."""
50
- return control(z(), n_controls=1)
51
-
52
-
53
- @op
54
- def ch() -> types.Op:
55
- """Control H gate."""
56
- return control(h(), n_controls=1)
57
-
58
-
59
- @op
60
- def cphase(theta: float) -> types.Op:
61
- """Control Phase gate."""
62
- return control(phase(theta), n_controls=1)
bloqade/squin/op/stmts.py DELETED
@@ -1,300 +0,0 @@
1
- from kirin import ir, types, lowering
2
- from kirin.decl import info, statement
3
-
4
- from .types import (
5
- OpType,
6
- ROpType,
7
- XOpType,
8
- YOpType,
9
- ZOpType,
10
- KronType,
11
- MultType,
12
- PauliOpType,
13
- ControlOpType,
14
- PauliStringType,
15
- ControlledOpType,
16
- )
17
- from .number import NumberType
18
- from .traits import Unitary, HasSites, FixedSites, MaybeUnitary
19
- from ._dialect import dialect
20
-
21
-
22
- @statement
23
- class Operator(ir.Statement):
24
- result: ir.ResultValue = info.result(OpType)
25
-
26
-
27
- @statement
28
- class PrimitiveOp(Operator):
29
- pass
30
-
31
-
32
- @statement
33
- class CompositeOp(Operator):
34
- pass
35
-
36
-
37
- LhsType = types.TypeVar("Lhs", bound=OpType)
38
- RhsType = types.TypeVar("Rhs", bound=OpType)
39
-
40
-
41
- @statement
42
- class BinaryOp(CompositeOp):
43
- lhs: ir.SSAValue = info.argument(LhsType)
44
- rhs: ir.SSAValue = info.argument(RhsType)
45
-
46
-
47
- @statement(dialect=dialect)
48
- class Kron(BinaryOp):
49
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), MaybeUnitary()})
50
- is_unitary: bool = info.attribute(default=False)
51
- result: ir.ResultValue = info.result(KronType[LhsType, RhsType])
52
-
53
-
54
- @statement(dialect=dialect)
55
- class Mult(BinaryOp):
56
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), MaybeUnitary()})
57
- is_unitary: bool = info.attribute(default=False)
58
- result: ir.ResultValue = info.result(MultType[LhsType, RhsType])
59
-
60
-
61
- @statement(dialect=dialect)
62
- class Adjoint(CompositeOp):
63
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), MaybeUnitary()})
64
- is_unitary: bool = info.attribute(default=False)
65
- op: ir.SSAValue = info.argument(OpType)
66
-
67
-
68
- @statement(dialect=dialect)
69
- class Scale(CompositeOp):
70
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), MaybeUnitary()})
71
- is_unitary: bool = info.attribute(default=False)
72
- op: ir.SSAValue = info.argument(OpType)
73
- factor: ir.SSAValue = info.argument(NumberType)
74
-
75
-
76
- @statement(dialect=dialect)
77
- class Control(CompositeOp):
78
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), MaybeUnitary()})
79
- is_unitary: bool = info.attribute(default=False)
80
- op: ir.SSAValue = info.argument(ControlledOpType)
81
- n_controls: int = info.attribute()
82
- result: ir.ResultValue = info.result(ControlOpType[ControlledOpType])
83
-
84
-
85
- RotationAxisType = types.TypeVar("RotationAxis", bound=OpType)
86
-
87
-
88
- @statement(dialect=dialect)
89
- class Rot(CompositeOp):
90
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), Unitary()})
91
- axis: ir.SSAValue = info.argument(RotationAxisType)
92
- angle: ir.SSAValue = info.argument(types.Float)
93
- result: ir.ResultValue = info.result(ROpType[RotationAxisType])
94
-
95
-
96
- @statement(dialect=dialect)
97
- class Identity(CompositeOp):
98
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), Unitary(), HasSites()})
99
- sites: int = info.attribute()
100
-
101
-
102
- @statement
103
- class ConstantOp(PrimitiveOp):
104
- traits = frozenset(
105
- {ir.Pure(), lowering.FromPythonCall(), ir.ConstantLike(), FixedSites(1)}
106
- )
107
-
108
-
109
- @statement
110
- class ConstantUnitary(ConstantOp):
111
- traits = frozenset(
112
- {
113
- ir.Pure(),
114
- lowering.FromPythonCall(),
115
- ir.ConstantLike(),
116
- Unitary(),
117
- FixedSites(1),
118
- }
119
- )
120
-
121
-
122
- @statement(dialect=dialect)
123
- class U3(PrimitiveOp):
124
- """
125
- The rotation operator U3(theta, phi, lam).
126
- Note that we use the convention from the QASM2 specification, namely
127
-
128
- $$
129
- U_3(\\theta, \\phi, \\lambda) = R_z(\\phi) R_y(\\theta) R_z(\\lambda)
130
- $$
131
- """
132
-
133
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), Unitary(), FixedSites(1)})
134
- theta: ir.SSAValue = info.argument(types.Float)
135
- phi: ir.SSAValue = info.argument(types.Float)
136
- lam: ir.SSAValue = info.argument(types.Float)
137
-
138
-
139
- @statement(dialect=dialect)
140
- class PhaseOp(PrimitiveOp):
141
- """
142
- A phase operator.
143
-
144
- $$
145
- \\text{PhaseOp}(\\theta) = e^{i \\theta} I
146
- $$
147
- """
148
-
149
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), Unitary(), FixedSites(1)})
150
- theta: ir.SSAValue = info.argument(types.Float)
151
-
152
-
153
- @statement(dialect=dialect)
154
- class ShiftOp(PrimitiveOp):
155
- """
156
- A phase shift operator.
157
-
158
- $$
159
- \\text{Shift}(\\theta) = \\begin{bmatrix} 1 & 0 \\\\ 0 & e^{i \\theta} \\end{bmatrix}
160
- $$
161
- """
162
-
163
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), Unitary(), FixedSites(1)})
164
- theta: ir.SSAValue = info.argument(types.Float)
165
-
166
-
167
- @statement(dialect=dialect)
168
- class Reset(PrimitiveOp):
169
- """
170
- Reset operator for qubits and wires.
171
- """
172
-
173
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), FixedSites(1)})
174
-
175
-
176
- @statement(dialect=dialect)
177
- class ResetToOne(PrimitiveOp):
178
- """
179
- Reset qubits to the one state. Mainly needed to accommodate cirq's GeneralizedAmplitudeDampingChannel
180
- """
181
-
182
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), FixedSites(1)})
183
-
184
-
185
- @statement
186
- class CliffordOp(ConstantUnitary):
187
- pass
188
-
189
-
190
- @statement
191
- class PauliOp(CliffordOp):
192
- result: ir.ResultValue = info.result(type=PauliOpType)
193
-
194
-
195
- @statement(dialect=dialect)
196
- class PauliString(ConstantUnitary):
197
- traits = frozenset({ir.Pure(), lowering.FromPythonCall(), Unitary(), HasSites()})
198
- string: str = info.attribute()
199
- result: ir.ResultValue = info.result(type=PauliStringType)
200
-
201
- def verify(self) -> None:
202
- if not set("XYZ").issuperset(self.string):
203
- raise ValueError(
204
- f"Invalid Pauli string: {self.string}. Must be a combination of 'X', 'Y', and 'Z'."
205
- )
206
-
207
-
208
- @statement(dialect=dialect)
209
- class X(PauliOp):
210
- result: ir.ResultValue = info.result(XOpType)
211
-
212
-
213
- @statement(dialect=dialect)
214
- class Y(PauliOp):
215
- result: ir.ResultValue = info.result(YOpType)
216
-
217
-
218
- @statement(dialect=dialect)
219
- class Z(PauliOp):
220
- result: ir.ResultValue = info.result(ZOpType)
221
-
222
-
223
- @statement(dialect=dialect)
224
- class SqrtX(ConstantUnitary):
225
- pass
226
-
227
-
228
- @statement(dialect=dialect)
229
- class SqrtY(ConstantUnitary):
230
- pass
231
-
232
-
233
- # NOTE no SqrtZ since its equal to S
234
-
235
-
236
- @statement(dialect=dialect)
237
- class H(ConstantUnitary):
238
- pass
239
-
240
-
241
- @statement(dialect=dialect)
242
- class S(ConstantUnitary):
243
- pass
244
-
245
-
246
- @statement(dialect=dialect)
247
- class T(ConstantUnitary):
248
- pass
249
-
250
-
251
- @statement(dialect=dialect)
252
- class P0(ConstantOp):
253
- """
254
- The $P_0$ projection operator.
255
-
256
- $$
257
- P0 = \\begin{bmatrix} 1 & 0 \\\\ 0 & 0 \\end{bmatrix}
258
- $$
259
- """
260
-
261
- pass
262
-
263
-
264
- @statement(dialect=dialect)
265
- class P1(ConstantOp):
266
- """
267
- The $P_1$ projection operator.
268
-
269
- $$
270
- P1 = \\begin{bmatrix} 0 & 0 \\\\ 0 & 1 \\end{bmatrix}
271
- $$
272
- """
273
-
274
- pass
275
-
276
-
277
- @statement(dialect=dialect)
278
- class Sn(ConstantOp):
279
- """
280
- $S_{-}$ operator.
281
-
282
- $$
283
- Sn = \\frac{1}{2} (S_x - i S_y) = \\frac{1}{2} \\begin{bmatrix} 0 & 0 \\\\ 1 & 0 \\end{bmatrix}
284
- $$
285
- """
286
-
287
- pass
288
-
289
-
290
- @statement(dialect=dialect)
291
- class Sp(ConstantOp):
292
- """
293
- $S_{+}$ operator.
294
-
295
- $$
296
- Sp = \\frac{1}{2} (S_x + i S_y) = \\frac{1}{2}\\begin{bmatrix} 0 & 1 \\\\ 0 & 0 \\end{bmatrix}
297
- $$
298
- """
299
-
300
- pass
@@ -1,43 +0,0 @@
1
- from typing import cast
2
- from dataclasses import dataclass
3
-
4
- from kirin import ir
5
-
6
-
7
- @dataclass(frozen=True)
8
- class FixedSites(ir.StmtTrait):
9
- data: int
10
-
11
-
12
- @dataclass(frozen=True)
13
- class HasSites(ir.StmtTrait):
14
- """An operator with a `sites` attribute."""
15
-
16
- def get_sites(self, stmt: ir.Statement):
17
- attr = stmt.get_attr_or_prop("sites")
18
- if attr is None:
19
- raise ValueError(f"Missing sites attribute in {stmt}")
20
- return cast(ir.PyAttr[int], attr).data
21
-
22
- def set_sites(self, stmt: ir.Statement, value: int):
23
- stmt.attributes["sites"] = ir.PyAttr(value)
24
- return
25
-
26
-
27
- @dataclass(frozen=True)
28
- class Unitary(ir.StmtTrait):
29
- pass
30
-
31
-
32
- @dataclass(frozen=True)
33
- class MaybeUnitary(ir.StmtTrait):
34
-
35
- def is_unitary(self, stmt: ir.Statement):
36
- attr = stmt.get_attr_or_prop("is_unitary")
37
- if attr is None:
38
- return False
39
- return cast(ir.PyAttr[bool], attr).data
40
-
41
- def set_unitary(self, stmt: ir.Statement, value: bool):
42
- stmt.attributes["is_unitary"] = ir.PyAttr(value)
43
- return