qiskit 2.0.2__cp39-abi3-macosx_11_0_arm64.whl → 2.1.0rc1__cp39-abi3-macosx_11_0_arm64.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 (179) hide show
  1. qiskit/VERSION.txt +1 -1
  2. qiskit/__init__.py +19 -1
  3. qiskit/_accelerate.abi3.so +0 -0
  4. qiskit/circuit/__init__.py +13 -21
  5. qiskit/circuit/_add_control.py +57 -31
  6. qiskit/circuit/_classical_resource_map.py +4 -0
  7. qiskit/circuit/annotation.py +404 -0
  8. qiskit/circuit/classical/expr/__init__.py +1 -1
  9. qiskit/circuit/classical/expr/expr.py +104 -446
  10. qiskit/circuit/classical/expr/visitors.py +6 -0
  11. qiskit/circuit/classical/types/types.py +7 -130
  12. qiskit/circuit/controlflow/box.py +32 -7
  13. qiskit/circuit/delay.py +11 -9
  14. qiskit/circuit/library/arithmetic/adders/adder.py +5 -5
  15. qiskit/circuit/library/arithmetic/multipliers/multiplier.py +3 -3
  16. qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +7 -3
  17. qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +23 -15
  18. qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +22 -14
  19. qiskit/circuit/library/arithmetic/quadratic_form.py +6 -0
  20. qiskit/circuit/library/arithmetic/weighted_adder.py +43 -24
  21. qiskit/circuit/library/basis_change/qft.py +2 -2
  22. qiskit/circuit/library/blueprintcircuit.py +6 -0
  23. qiskit/circuit/library/boolean_logic/inner_product.py +2 -2
  24. qiskit/circuit/library/boolean_logic/quantum_and.py +2 -2
  25. qiskit/circuit/library/boolean_logic/quantum_or.py +3 -3
  26. qiskit/circuit/library/boolean_logic/quantum_xor.py +2 -2
  27. qiskit/circuit/library/data_preparation/_z_feature_map.py +2 -2
  28. qiskit/circuit/library/data_preparation/_zz_feature_map.py +2 -2
  29. qiskit/circuit/library/data_preparation/pauli_feature_map.py +2 -2
  30. qiskit/circuit/library/fourier_checking.py +2 -2
  31. qiskit/circuit/library/generalized_gates/diagonal.py +5 -1
  32. qiskit/circuit/library/generalized_gates/gms.py +5 -1
  33. qiskit/circuit/library/generalized_gates/linear_function.py +2 -2
  34. qiskit/circuit/library/generalized_gates/permutation.py +5 -1
  35. qiskit/circuit/library/generalized_gates/uc.py +1 -1
  36. qiskit/circuit/library/generalized_gates/unitary.py +21 -2
  37. qiskit/circuit/library/graph_state.py +2 -2
  38. qiskit/circuit/library/grover_operator.py +2 -2
  39. qiskit/circuit/library/hidden_linear_function.py +2 -2
  40. qiskit/circuit/library/iqp.py +2 -2
  41. qiskit/circuit/library/n_local/efficient_su2.py +2 -2
  42. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +1 -1
  43. qiskit/circuit/library/n_local/excitation_preserving.py +7 -9
  44. qiskit/circuit/library/n_local/n_local.py +4 -3
  45. qiskit/circuit/library/n_local/pauli_two_design.py +2 -2
  46. qiskit/circuit/library/n_local/real_amplitudes.py +2 -2
  47. qiskit/circuit/library/n_local/two_local.py +2 -2
  48. qiskit/circuit/library/overlap.py +2 -2
  49. qiskit/circuit/library/pauli_evolution.py +3 -2
  50. qiskit/circuit/library/phase_estimation.py +2 -2
  51. qiskit/circuit/library/standard_gates/dcx.py +11 -12
  52. qiskit/circuit/library/standard_gates/ecr.py +21 -24
  53. qiskit/circuit/library/standard_gates/equivalence_library.py +232 -96
  54. qiskit/circuit/library/standard_gates/global_phase.py +5 -6
  55. qiskit/circuit/library/standard_gates/h.py +22 -45
  56. qiskit/circuit/library/standard_gates/i.py +1 -1
  57. qiskit/circuit/library/standard_gates/iswap.py +13 -31
  58. qiskit/circuit/library/standard_gates/p.py +19 -26
  59. qiskit/circuit/library/standard_gates/r.py +11 -17
  60. qiskit/circuit/library/standard_gates/rx.py +21 -45
  61. qiskit/circuit/library/standard_gates/rxx.py +7 -22
  62. qiskit/circuit/library/standard_gates/ry.py +21 -39
  63. qiskit/circuit/library/standard_gates/ryy.py +13 -28
  64. qiskit/circuit/library/standard_gates/rz.py +18 -35
  65. qiskit/circuit/library/standard_gates/rzx.py +7 -22
  66. qiskit/circuit/library/standard_gates/rzz.py +7 -19
  67. qiskit/circuit/library/standard_gates/s.py +44 -39
  68. qiskit/circuit/library/standard_gates/swap.py +25 -38
  69. qiskit/circuit/library/standard_gates/sx.py +34 -41
  70. qiskit/circuit/library/standard_gates/t.py +18 -27
  71. qiskit/circuit/library/standard_gates/u.py +8 -24
  72. qiskit/circuit/library/standard_gates/u1.py +28 -52
  73. qiskit/circuit/library/standard_gates/u2.py +9 -9
  74. qiskit/circuit/library/standard_gates/u3.py +24 -40
  75. qiskit/circuit/library/standard_gates/x.py +190 -336
  76. qiskit/circuit/library/standard_gates/xx_minus_yy.py +12 -50
  77. qiskit/circuit/library/standard_gates/xx_plus_yy.py +13 -52
  78. qiskit/circuit/library/standard_gates/y.py +19 -23
  79. qiskit/circuit/library/standard_gates/z.py +31 -38
  80. qiskit/circuit/parameter.py +14 -5
  81. qiskit/circuit/parameterexpression.py +109 -75
  82. qiskit/circuit/quantumcircuit.py +168 -98
  83. qiskit/circuit/quantumcircuitdata.py +1 -0
  84. qiskit/circuit/random/__init__.py +37 -2
  85. qiskit/circuit/random/utils.py +445 -56
  86. qiskit/circuit/tools/pi_check.py +5 -13
  87. qiskit/compiler/transpiler.py +1 -1
  88. qiskit/converters/circuit_to_instruction.py +2 -2
  89. qiskit/dagcircuit/dagnode.py +8 -3
  90. qiskit/primitives/__init__.py +2 -2
  91. qiskit/primitives/base/base_estimator.py +2 -2
  92. qiskit/primitives/containers/data_bin.py +0 -3
  93. qiskit/primitives/containers/observables_array.py +192 -108
  94. qiskit/primitives/primitive_job.py +29 -10
  95. qiskit/providers/fake_provider/generic_backend_v2.py +2 -0
  96. qiskit/qasm3/__init__.py +106 -12
  97. qiskit/qasm3/ast.py +15 -1
  98. qiskit/qasm3/exporter.py +59 -36
  99. qiskit/qasm3/printer.py +12 -0
  100. qiskit/qpy/__init__.py +183 -7
  101. qiskit/qpy/binary_io/circuits.py +256 -24
  102. qiskit/qpy/binary_io/parse_sympy_repr.py +5 -0
  103. qiskit/qpy/binary_io/schedules.py +12 -32
  104. qiskit/qpy/binary_io/value.py +36 -18
  105. qiskit/qpy/common.py +11 -3
  106. qiskit/qpy/formats.py +17 -1
  107. qiskit/qpy/interface.py +52 -12
  108. qiskit/qpy/type_keys.py +7 -1
  109. qiskit/quantum_info/__init__.py +10 -0
  110. qiskit/quantum_info/operators/__init__.py +1 -0
  111. qiskit/quantum_info/operators/symplectic/__init__.py +1 -0
  112. qiskit/quantum_info/operators/symplectic/clifford_circuits.py +26 -0
  113. qiskit/quantum_info/operators/symplectic/pauli.py +2 -2
  114. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +1 -1
  115. qiskit/result/sampled_expval.py +3 -1
  116. qiskit/synthesis/__init__.py +10 -0
  117. qiskit/synthesis/arithmetic/__init__.py +1 -1
  118. qiskit/synthesis/arithmetic/adders/__init__.py +1 -0
  119. qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +6 -2
  120. qiskit/synthesis/arithmetic/adders/rv_ripple_carry_adder.py +156 -0
  121. qiskit/synthesis/discrete_basis/generate_basis_approximations.py +14 -126
  122. qiskit/synthesis/discrete_basis/solovay_kitaev.py +161 -121
  123. qiskit/synthesis/evolution/lie_trotter.py +10 -7
  124. qiskit/synthesis/evolution/product_formula.py +10 -7
  125. qiskit/synthesis/evolution/qdrift.py +10 -7
  126. qiskit/synthesis/evolution/suzuki_trotter.py +10 -7
  127. qiskit/synthesis/multi_controlled/__init__.py +4 -0
  128. qiskit/synthesis/multi_controlled/mcx_synthesis.py +402 -178
  129. qiskit/synthesis/multi_controlled/multi_control_rotation_gates.py +14 -15
  130. qiskit/synthesis/qft/qft_decompose_lnn.py +7 -25
  131. qiskit/synthesis/unitary/qsd.py +80 -9
  132. qiskit/transpiler/__init__.py +19 -8
  133. qiskit/transpiler/instruction_durations.py +2 -20
  134. qiskit/transpiler/passes/__init__.py +4 -2
  135. qiskit/transpiler/passes/layout/dense_layout.py +26 -6
  136. qiskit/transpiler/passes/layout/disjoint_utils.py +1 -166
  137. qiskit/transpiler/passes/layout/sabre_layout.py +22 -3
  138. qiskit/transpiler/passes/layout/sabre_pre_layout.py +1 -1
  139. qiskit/transpiler/passes/layout/vf2_layout.py +49 -13
  140. qiskit/transpiler/passes/layout/vf2_utils.py +13 -1
  141. qiskit/transpiler/passes/optimization/__init__.py +1 -1
  142. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +2 -1
  143. qiskit/transpiler/passes/optimization/optimize_clifford_t.py +68 -0
  144. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +3 -9
  145. qiskit/transpiler/passes/routing/sabre_swap.py +12 -2
  146. qiskit/transpiler/passes/routing/star_prerouting.py +106 -81
  147. qiskit/transpiler/passes/scheduling/__init__.py +1 -1
  148. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
  149. qiskit/transpiler/passes/scheduling/padding/__init__.py +1 -0
  150. qiskit/transpiler/passes/scheduling/padding/context_aware_dynamical_decoupling.py +876 -0
  151. qiskit/transpiler/passes/synthesis/__init__.py +1 -0
  152. qiskit/transpiler/passes/synthesis/clifford_unitary_synth_plugin.py +123 -0
  153. qiskit/transpiler/passes/synthesis/hls_plugins.py +472 -92
  154. qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +27 -22
  155. qiskit/transpiler/passmanager_config.py +3 -0
  156. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +149 -28
  157. qiskit/transpiler/preset_passmanagers/common.py +101 -0
  158. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +6 -0
  159. qiskit/transpiler/preset_passmanagers/level3.py +2 -2
  160. qiskit/utils/optionals.py +6 -5
  161. qiskit/visualization/circuit/_utils.py +5 -3
  162. qiskit/visualization/circuit/latex.py +9 -2
  163. qiskit/visualization/circuit/matplotlib.py +26 -4
  164. qiskit/visualization/circuit/qcstyle.py +9 -157
  165. qiskit/visualization/dag/__init__.py +13 -0
  166. qiskit/visualization/dag/dagstyle.py +103 -0
  167. qiskit/visualization/dag/styles/__init__.py +13 -0
  168. qiskit/visualization/dag/styles/color.json +10 -0
  169. qiskit/visualization/dag/styles/plain.json +5 -0
  170. qiskit/visualization/dag_visualization.py +169 -98
  171. qiskit/visualization/style.py +223 -0
  172. {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/METADATA +14 -13
  173. {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/RECORD +177 -168
  174. {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/entry_points.txt +6 -0
  175. qiskit/synthesis/discrete_basis/commutator_decompose.py +0 -265
  176. qiskit/synthesis/discrete_basis/gate_sequence.py +0 -421
  177. {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/WHEEL +0 -0
  178. {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/licenses/LICENSE.txt +0 -0
  179. {qiskit-2.0.2.dist-info → qiskit-2.1.0rc1.dist-info}/top_level.txt +0 -0
@@ -12,12 +12,6 @@
12
12
 
13
13
  """Expression-tree nodes."""
14
14
 
15
- # Given the nature of the tree representation and that there are helper functions associated with
16
- # many of the classes whose arguments naturally share names with themselves, it's inconvenient to
17
- # use synonyms everywhere. This goes for the builtin 'type' as well.
18
- # pylint: disable=redefined-builtin,redefined-outer-name
19
-
20
- from __future__ import annotations
21
15
 
22
16
  __all__ = [
23
17
  "Expr",
@@ -30,469 +24,133 @@ __all__ = [
30
24
  "Index",
31
25
  ]
32
26
 
33
- import abc
34
27
  import enum
35
- import typing
36
- import uuid
37
-
38
- from .. import types
39
-
40
- if typing.TYPE_CHECKING:
41
- import qiskit
42
-
43
-
44
- _T_co = typing.TypeVar("_T_co", covariant=True)
45
-
46
-
47
- # If adding nodes, remember to update `visitors.ExprVisitor` as well.
48
-
49
-
50
- class Expr(abc.ABC):
51
- """Root base class of all nodes in the expression tree. The base case should never be
52
- instantiated directly.
53
-
54
- This must not be subclassed by users; subclasses form the internal data of the representation of
55
- expressions, and it does not make sense to add more outside of Qiskit library code.
56
-
57
- All subclasses are responsible for setting their ``type`` attribute in their ``__init__``, and
58
- should not call the parent initializer."""
59
-
60
- __slots__ = ("type", "const")
61
28
 
62
- type: types.Type
63
- const: bool
29
+ from qiskit._accelerate.circuit.classical.expr import (
30
+ Expr,
31
+ Var,
32
+ Stretch,
33
+ Value,
34
+ Cast,
35
+ Unary,
36
+ Binary,
37
+ Index,
38
+ ) # pylint: disable=unused-import
64
39
 
65
- # Sentinel to prevent instantiation of the base class.
66
- @abc.abstractmethod
67
- def __init__(self): # pragma: no cover
68
- pass
69
-
70
- def accept(
71
- self, visitor: qiskit.circuit.classical.expr.ExprVisitor[_T_co], /
72
- ) -> _T_co: # pragma: no cover
73
- """Call the relevant ``visit_*`` method on the given :class:`ExprVisitor`. The usual entry
74
- point for a simple visitor is to construct it, and then call :meth:`accept` on the root
75
- object to be visited. For example::
76
-
77
- expr = ...
78
- visitor = MyVisitor()
79
- visitor.accept(expr)
80
-
81
- Subclasses of :class:`Expr` should override this to call the correct virtual method on the
82
- visitor. This implements double dispatch with the visitor."""
83
- return visitor.visit_generic(self)
84
-
85
-
86
- @typing.final
87
- class Cast(Expr):
88
- """A cast from one type to another, implied by the use of an expression in a different
89
- context."""
90
-
91
- __slots__ = ("operand", "implicit")
92
-
93
- def __init__(self, operand: Expr, type: types.Type, implicit: bool = False):
94
- self.type = type
95
- self.const = operand.const
96
- self.operand = operand
97
- self.implicit = implicit
98
-
99
- def accept(self, visitor, /):
100
- return visitor.visit_cast(self)
101
-
102
- def __eq__(self, other):
103
- return (
104
- isinstance(other, Cast)
105
- and self.type == other.type
106
- and self.const == other.const
107
- and self.operand == other.operand
108
- and self.implicit == other.implicit
109
- )
110
-
111
- def __repr__(self):
112
- return f"Cast({self.operand}, {self.type}, implicit={self.implicit})"
113
40
 
41
+ class _UnaryOp(enum.Enum):
42
+ """Enumeration of the opcodes for unary operations.
114
43
 
115
- @typing.final
116
- class Var(Expr):
117
- """A classical variable.
44
+ The bitwise negation :data:`BIT_NOT` takes a single bit or an unsigned integer of known
45
+ width, and returns a value of the same type.
118
46
 
119
- These variables take two forms: a new-style variable that owns its storage location and has an
120
- associated name; and an old-style variable that wraps a :class:`.Clbit` or
121
- :class:`.ClassicalRegister` instance that is owned by some containing circuit. In general,
122
- construction of variables for use in programs should use :meth:`Var.new` or
123
- :meth:`.QuantumCircuit.add_var`.
124
-
125
- Variables are immutable after construction, so they can be used as dictionary keys."""
126
-
127
- __slots__ = ("var", "name")
128
-
129
- var: qiskit.circuit.Clbit | qiskit.circuit.ClassicalRegister | uuid.UUID
130
- """A reference to the backing data storage of the :class:`Var` instance. When lifting
131
- old-style :class:`.Clbit` or :class:`.ClassicalRegister` instances into a :class:`Var`,
132
- this is exactly the :class:`.Clbit` or :class:`.ClassicalRegister`. If the variable is a
133
- new-style classical variable (one that owns its own storage separate to the old
134
- :class:`.Clbit`/:class:`.ClassicalRegister` model), this field will be a :class:`~uuid.UUID`
135
- to uniquely identify it."""
136
- name: str | None
137
- """The name of the variable. This is required to exist if the backing :attr:`var` attribute
138
- is a :class:`~uuid.UUID`, i.e. if it is a new-style variable, and must be ``None`` if it is
139
- an old-style variable."""
140
-
141
- def __init__(
142
- self,
143
- var: qiskit.circuit.Clbit | qiskit.circuit.ClassicalRegister | uuid.UUID,
144
- type: types.Type,
145
- *,
146
- name: str | None = None,
147
- ):
148
- super().__setattr__("type", type)
149
- super().__setattr__("const", False)
150
- super().__setattr__("var", var)
151
- super().__setattr__("name", name)
152
-
153
- @classmethod
154
- def new(cls, name: str, type: types.Type) -> typing.Self:
155
- """Generate a new named variable that owns its own backing storage."""
156
- return cls(uuid.uuid4(), type, name=name)
157
-
158
- @property
159
- def standalone(self) -> bool:
160
- """Whether this :class:`Var` is a standalone variable that owns its storage
161
- location, if applicable. If false, this is a wrapper :class:`Var` around a
162
- pre-existing circuit object."""
163
- return isinstance(self.var, uuid.UUID)
164
-
165
- def accept(self, visitor, /):
166
- return visitor.visit_var(self)
167
-
168
- def __setattr__(self, key, value):
169
- if hasattr(self, key):
170
- raise AttributeError(f"'Var' object attribute '{key}' is read-only")
171
- raise AttributeError(f"'Var' object has no attribute '{key}'")
172
-
173
- def __hash__(self):
174
- return hash((self.type, self.var, self.name))
175
-
176
- def __eq__(self, other):
177
- return (
178
- isinstance(other, Var)
179
- and self.type == other.type
180
- and self.var == other.var
181
- and self.name == other.name
182
- )
183
-
184
- def __repr__(self):
185
- if self.name is None:
186
- return f"Var({self.var}, {self.type})"
187
- return f"Var({self.var}, {self.type}, name='{self.name}')"
188
-
189
- def __getstate__(self):
190
- return (self.var, self.type, self.name)
191
-
192
- def __setstate__(self, state):
193
- var, type, name = state
194
- super().__setattr__("type", type)
195
- super().__setattr__("const", False)
196
- super().__setattr__("var", var)
197
- super().__setattr__("name", name)
198
-
199
- def __copy__(self):
200
- # I am immutable...
201
- return self
202
-
203
- def __deepcopy__(self, memo):
204
- # ... as are all my constituent parts.
205
- return self
206
-
207
-
208
- @typing.final
209
- class Stretch(Expr):
210
- """A stretch variable.
211
-
212
- In general, construction of stretch variables for use in programs should use :meth:`Stretch.new`
213
- or :meth:`.QuantumCircuit.add_stretch`.
47
+ The logical negation :data:`LOGIC_NOT` takes an input that is implicitly coerced to a
48
+ Boolean, and returns a Boolean.
214
49
  """
215
50
 
216
- __slots__ = (
217
- "var",
218
- "name",
219
- )
220
-
221
- var: uuid.UUID
222
- """A :class:`~uuid.UUID` to uniquely identify this stretch."""
223
- name: str
224
- """The name of the stretch variable."""
225
-
226
- def __init__(
227
- self,
228
- var: uuid.UUID,
229
- name: str,
230
- ):
231
- super().__setattr__("type", types.Duration())
232
- super().__setattr__("const", True)
233
- super().__setattr__("var", var)
234
- super().__setattr__("name", name)
235
-
236
- @classmethod
237
- def new(cls, name: str) -> typing.Self:
238
- """Generate a new named stretch variable."""
239
- return cls(uuid.uuid4(), name)
51
+ # If adding opcodes, remember to add helper constructor functions in `constructors.py`.
52
+ # The opcode integers should be considered a public interface; they are used by
53
+ # serialization formats that may transfer data between different versions of Qiskit.
54
+ #
55
+ # !!! YOU MUST ALSO UPDATE the underlying Rust enum if you touch this.
56
+ BIT_NOT = 1
57
+ """Bitwise negation. ``~operand``."""
58
+ LOGIC_NOT = 2
59
+ """Logical negation. ``!operand``."""
240
60
 
241
- def accept(self, visitor, /):
242
- return visitor.visit_stretch(self)
243
-
244
- def __setattr__(self, key, value):
245
- if hasattr(self, key):
246
- raise AttributeError(f"'Stretch' object attribute '{key}' is read-only")
247
- raise AttributeError(f"'Stretch' object has no attribute '{key}'")
248
-
249
- def __hash__(self):
250
- return hash((self.var, self.name))
251
-
252
- def __eq__(self, other):
253
- return isinstance(other, Stretch) and self.var == other.var and self.name == other.name
61
+ def __str__(self):
62
+ return f"Unary.{super().__str__()}"
254
63
 
255
64
  def __repr__(self):
256
- return f"Stretch({self.var}, {self.name})"
257
-
258
- def __getstate__(self):
259
- return (self.var, self.name)
260
-
261
- def __setstate__(self, state):
262
- var, name = state
263
- super().__setattr__("type", types.Duration())
264
- super().__setattr__("const", True)
265
- super().__setattr__("var", var)
266
- super().__setattr__("name", name)
267
-
268
- def __copy__(self):
269
- # I am immutable...
270
- return self
65
+ return f"Unary.{super().__repr__()}"
271
66
 
272
- def __deepcopy__(self, memo):
273
- # ... as are all my constituent parts.
274
- return self
275
67
 
68
+ # Setting these tricks Sphinx into thinking that this enum is actually
69
+ # defined as an inner class of the Rust pyclass.
70
+ _UnaryOp.__module__ = "qiskit._accelerate.circuit.classical.expr"
71
+ _UnaryOp.__name__ = "Op"
72
+ _UnaryOp.__qualname__ = "Unary.Op"
276
73
 
277
- @typing.final
278
- class Value(Expr):
279
- """A single scalar value."""
280
74
 
281
- __slots__ = ("value",)
75
+ class _BinaryOp(enum.Enum):
76
+ """Enumeration of the opcodes for binary operations.
282
77
 
283
- def __init__(self, value: typing.Any, type: types.Type):
284
- self.type = type
285
- self.value = value
286
- self.const = True
78
+ The bitwise operations :data:`BIT_AND`, :data:`BIT_OR` and :data:`BIT_XOR` apply to two
79
+ operands of the same type, which must be a single bit or an unsigned integer of fixed width.
80
+ The resultant type is the same as the two input types.
287
81
 
288
- def accept(self, visitor, /):
289
- return visitor.visit_value(self)
82
+ The logical operations :data:`LOGIC_AND` and :data:`LOGIC_OR` first implicitly coerce their
83
+ arguments to Booleans, and then apply the logical operation. The resultant type is always
84
+ Boolean.
290
85
 
291
- def __eq__(self, other):
292
- return isinstance(other, Value) and self.type == other.type and self.value == other.value
86
+ The binary mathematical relations :data:`EQUAL`, :data:`NOT_EQUAL`, :data:`LESS`,
87
+ :data:`LESS_EQUAL`, :data:`GREATER` and :data:`GREATER_EQUAL` take unsigned integers
88
+ (with an implicit cast to make them the same width), and return a Boolean.
293
89
 
294
- def __repr__(self):
295
- return f"Value({self.value}, {self.type})"
296
-
297
-
298
- @typing.final
299
- class Unary(Expr):
300
- """A unary expression.
90
+ The bitshift operations :data:`SHIFT_LEFT` and :data:`SHIFT_RIGHT` can take bit-like
91
+ container types (e.g. unsigned integers) as the left operand, and any integer type as the
92
+ right-hand operand. In all cases, the output bit width is the same as the input, and zeros
93
+ fill in the "exposed" spaces.
301
94
 
302
- Args:
303
- op: The opcode describing which operation is being done.
304
- operand: The operand of the operation.
305
- type: The resolved type of the result.
95
+ The binary arithmetic operators :data:`ADD`, :data:`SUB:, :data:`MUL`, and :data:`DIV`
96
+ can be applied to two floats or two unsigned integers, which should be made to be of
97
+ the same width during construction via a cast.
98
+ The :data:`ADD`, :data:`SUB`, and :data:`DIV` operators can be applied on two durations
99
+ yielding another duration, or a float in the case of :data:`DIV`. The :data:`MUL` operator
100
+ can also be applied to a duration and a numeric type, yielding another duration. Finally,
101
+ the :data:`DIV` operator can be used to divide a duration by a numeric type, yielding a
102
+ duration.
306
103
  """
307
104
 
308
- __slots__ = ("op", "operand")
309
-
310
- class Op(enum.Enum):
311
- """Enumeration of the opcodes for unary operations.
312
-
313
- The bitwise negation :data:`BIT_NOT` takes a single bit or an unsigned integer of known
314
- width, and returns a value of the same type.
315
-
316
- The logical negation :data:`LOGIC_NOT` takes an input that is implicitly coerced to a
317
- Boolean, and returns a Boolean.
318
- """
319
-
320
- # If adding opcodes, remember to add helper constructor functions in `constructors.py`.
321
- # The opcode integers should be considered a public interface; they are used by
322
- # serialization formats that may transfer data between different versions of Qiskit.
323
- BIT_NOT = 1
324
- """Bitwise negation. ``~operand``."""
325
- LOGIC_NOT = 2
326
- """Logical negation. ``!operand``."""
327
-
328
- def __str__(self):
329
- return f"Unary.{super().__str__()}"
330
-
331
- def __repr__(self):
332
- return f"Unary.{super().__repr__()}"
333
-
334
- def __init__(self, op: Unary.Op, operand: Expr, type: types.Type):
335
- self.op = op
336
- self.operand = operand
337
- self.type = type
338
- self.const = operand.const
339
-
340
- def accept(self, visitor, /):
341
- return visitor.visit_unary(self)
342
-
343
- def __eq__(self, other):
344
- return (
345
- isinstance(other, Unary)
346
- and self.type == other.type
347
- and self.const == other.const
348
- and self.op is other.op
349
- and self.operand == other.operand
350
- )
105
+ # If adding opcodes, remember to add helper constructor functions in `constructors.py`
106
+ # The opcode integers should be considered a public interface; they are used by
107
+ # serialization formats that may transfer data between different versions of Qiskit.
108
+ #
109
+ # !!! YOU MUST ALSO UPDATE the underlying Rust enum if you touch this.
110
+ BIT_AND = 1
111
+ """Bitwise "and". ``lhs & rhs``."""
112
+ BIT_OR = 2
113
+ """Bitwise "or". ``lhs | rhs``."""
114
+ BIT_XOR = 3
115
+ """Bitwise "exclusive or". ``lhs ^ rhs``."""
116
+ LOGIC_AND = 4
117
+ """Logical "and". ``lhs && rhs``."""
118
+ LOGIC_OR = 5
119
+ """Logical "or". ``lhs || rhs``."""
120
+ EQUAL = 6
121
+ """Numeric equality. ``lhs == rhs``."""
122
+ NOT_EQUAL = 7
123
+ """Numeric inequality. ``lhs != rhs``."""
124
+ LESS = 8
125
+ """Numeric less than. ``lhs < rhs``."""
126
+ LESS_EQUAL = 9
127
+ """Numeric less than or equal to. ``lhs <= rhs``"""
128
+ GREATER = 10
129
+ """Numeric greater than. ``lhs > rhs``."""
130
+ GREATER_EQUAL = 11
131
+ """Numeric greater than or equal to. ``lhs >= rhs``."""
132
+ SHIFT_LEFT = 12
133
+ """Zero-padding bitshift to the left. ``lhs << rhs``."""
134
+ SHIFT_RIGHT = 13
135
+ """Zero-padding bitshift to the right. ``lhs >> rhs``."""
136
+ ADD = 14
137
+ """Addition. ``lhs + rhs``."""
138
+ SUB = 15
139
+ """Subtraction. ``lhs - rhs``."""
140
+ MUL = 16
141
+ """Multiplication. ``lhs * rhs``."""
142
+ DIV = 17
143
+ """Division. ``lhs / rhs``."""
144
+
145
+ def __str__(self):
146
+ return f"Binary.{super().__str__()}"
351
147
 
352
148
  def __repr__(self):
353
- return f"Unary({self.op}, {self.operand}, {self.type})"
354
-
355
-
356
- @typing.final
357
- class Binary(Expr):
358
- """A binary expression.
359
-
360
- Args:
361
- op: The opcode describing which operation is being done.
362
- left: The left-hand operand.
363
- right: The right-hand operand.
364
- type: The resolved type of the result.
365
- """
366
-
367
- __slots__ = ("op", "left", "right")
149
+ return f"Binary.{super().__repr__()}"
368
150
 
369
- class Op(enum.Enum):
370
- """Enumeration of the opcodes for binary operations.
371
151
 
372
- The bitwise operations :data:`BIT_AND`, :data:`BIT_OR` and :data:`BIT_XOR` apply to two
373
- operands of the same type, which must be a single bit or an unsigned integer of fixed width.
374
- The resultant type is the same as the two input types.
375
-
376
- The logical operations :data:`LOGIC_AND` and :data:`LOGIC_OR` first implicitly coerce their
377
- arguments to Booleans, and then apply the logical operation. The resultant type is always
378
- Boolean.
379
-
380
- The binary mathematical relations :data:`EQUAL`, :data:`NOT_EQUAL`, :data:`LESS`,
381
- :data:`LESS_EQUAL`, :data:`GREATER` and :data:`GREATER_EQUAL` take unsigned integers
382
- (with an implicit cast to make them the same width), and return a Boolean.
383
-
384
- The bitshift operations :data:`SHIFT_LEFT` and :data:`SHIFT_RIGHT` can take bit-like
385
- container types (e.g. unsigned integers) as the left operand, and any integer type as the
386
- right-hand operand. In all cases, the output bit width is the same as the input, and zeros
387
- fill in the "exposed" spaces.
388
-
389
- The binary arithmetic operators :data:`ADD`, :data:`SUB:, :data:`MUL`, and :data:`DIV`
390
- can be applied to two floats or two unsigned integers, which should be made to be of
391
- the same width during construction via a cast.
392
- The :data:`ADD`, :data:`SUB`, and :data:`DIV` operators can be applied on two durations
393
- yielding another duration, or a float in the case of :data:`DIV`. The :data:`MUL` operator
394
- can also be applied to a duration and a numeric type, yielding another duration. Finally,
395
- the :data:`DIV` operator can be used to divide a duration by a numeric type, yielding a
396
- duration.
397
- """
398
-
399
- # If adding opcodes, remember to add helper constructor functions in `constructors.py`
400
- # The opcode integers should be considered a public interface; they are used by
401
- # serialization formats that may transfer data between different versions of Qiskit.
402
- BIT_AND = 1
403
- """Bitwise "and". ``lhs & rhs``."""
404
- BIT_OR = 2
405
- """Bitwise "or". ``lhs | rhs``."""
406
- BIT_XOR = 3
407
- """Bitwise "exclusive or". ``lhs ^ rhs``."""
408
- LOGIC_AND = 4
409
- """Logical "and". ``lhs && rhs``."""
410
- LOGIC_OR = 5
411
- """Logical "or". ``lhs || rhs``."""
412
- EQUAL = 6
413
- """Numeric equality. ``lhs == rhs``."""
414
- NOT_EQUAL = 7
415
- """Numeric inequality. ``lhs != rhs``."""
416
- LESS = 8
417
- """Numeric less than. ``lhs < rhs``."""
418
- LESS_EQUAL = 9
419
- """Numeric less than or equal to. ``lhs <= rhs``"""
420
- GREATER = 10
421
- """Numeric greater than. ``lhs > rhs``."""
422
- GREATER_EQUAL = 11
423
- """Numeric greater than or equal to. ``lhs >= rhs``."""
424
- SHIFT_LEFT = 12
425
- """Zero-padding bitshift to the left. ``lhs << rhs``."""
426
- SHIFT_RIGHT = 13
427
- """Zero-padding bitshift to the right. ``lhs >> rhs``."""
428
- ADD = 14
429
- """Addition. ``lhs + rhs``."""
430
- SUB = 15
431
- """Subtraction. ``lhs - rhs``."""
432
- MUL = 16
433
- """Multiplication. ``lhs * rhs``."""
434
- DIV = 17
435
- """Division. ``lhs / rhs``."""
436
-
437
- def __str__(self):
438
- return f"Binary.{super().__str__()}"
439
-
440
- def __repr__(self):
441
- return f"Binary.{super().__repr__()}"
442
-
443
- def __init__(self, op: Binary.Op, left: Expr, right: Expr, type: types.Type):
444
- self.op = op
445
- self.left = left
446
- self.right = right
447
- self.type = type
448
- self.const = left.const and right.const
449
-
450
- def accept(self, visitor, /):
451
- return visitor.visit_binary(self)
452
-
453
- def __eq__(self, other):
454
- return (
455
- isinstance(other, Binary)
456
- and self.type == other.type
457
- and self.const == other.const
458
- and self.op is other.op
459
- and self.left == other.left
460
- and self.right == other.right
461
- )
462
-
463
- def __repr__(self):
464
- return f"Binary({self.op}, {self.left}, {self.right}, {self.type})"
465
-
466
-
467
- @typing.final
468
- class Index(Expr):
469
- """An indexing expression.
470
-
471
- Args:
472
- target: The object being indexed.
473
- index: The expression doing the indexing.
474
- type: The resolved type of the result.
475
- """
476
-
477
- __slots__ = ("target", "index")
478
-
479
- def __init__(self, target: Expr, index: Expr, type: types.Type):
480
- self.target = target
481
- self.index = index
482
- self.type = type
483
- self.const = target.const and index.const
484
-
485
- def accept(self, visitor, /):
486
- return visitor.visit_index(self)
487
-
488
- def __eq__(self, other):
489
- return (
490
- isinstance(other, Index)
491
- and self.type == other.type
492
- and self.const == other.const
493
- and self.target == other.target
494
- and self.index == other.index
495
- )
496
-
497
- def __repr__(self):
498
- return f"Index({self.target}, {self.index}, {self.type})"
152
+ # Setting these tricks Sphinx into thinking that this enum is actually
153
+ # defined as an inner class of the Rust pyclass.
154
+ _BinaryOp.__module__ = "qiskit._accelerate.circuit.classical.expr"
155
+ _BinaryOp.__name__ = "Op"
156
+ _BinaryOp.__qualname__ = "Binary.Op"
@@ -65,15 +65,21 @@ class ExprVisitor(typing.Generic[_T_co]):
65
65
 
66
66
 
67
67
  class _VarWalkerImpl(ExprVisitor[typing.Iterable[expr.Var]]):
68
+ # We don't want docstrings for the inherited visitor methods, which are self-explanatory and
69
+ # would just be noise.
70
+ # pylint: disable=missing-function-docstring
71
+
68
72
  __slots__ = ()
69
73
 
70
74
  def visit_var(self, node, /):
71
75
  yield node
72
76
 
73
77
  def visit_stretch(self, node, /):
78
+ # pylint: disable=unused-argument
74
79
  yield from ()
75
80
 
76
81
  def visit_value(self, node, /):
82
+ # pylint: disable=unused-argument
77
83
  yield from ()
78
84
 
79
85
  def visit_unary(self, node, /):