qiskit 1.0.2__cp38-abi3-win32.whl → 1.1.0__cp38-abi3-win32.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 (263) hide show
  1. qiskit/VERSION.txt +1 -1
  2. qiskit/__init__.py +27 -16
  3. qiskit/_accelerate.pyd +0 -0
  4. qiskit/_numpy_compat.py +73 -0
  5. qiskit/assembler/__init__.py +5 -10
  6. qiskit/assembler/disassemble.py +5 -6
  7. qiskit/circuit/__init__.py +1061 -232
  8. qiskit/circuit/_classical_resource_map.py +10 -6
  9. qiskit/circuit/_utils.py +18 -8
  10. qiskit/circuit/annotated_operation.py +21 -0
  11. qiskit/circuit/barrier.py +10 -13
  12. qiskit/circuit/bit.py +0 -1
  13. qiskit/circuit/classical/__init__.py +2 -2
  14. qiskit/circuit/classical/expr/__init__.py +39 -5
  15. qiskit/circuit/classical/expr/constructors.py +84 -1
  16. qiskit/circuit/classical/expr/expr.py +83 -13
  17. qiskit/circuit/classical/expr/visitors.py +83 -0
  18. qiskit/circuit/classical/types/__init__.py +5 -4
  19. qiskit/circuit/classicalfunction/__init__.py +1 -0
  20. qiskit/circuit/commutation_checker.py +86 -51
  21. qiskit/circuit/controlflow/_builder_utils.py +9 -1
  22. qiskit/circuit/controlflow/break_loop.py +8 -22
  23. qiskit/circuit/controlflow/builder.py +116 -1
  24. qiskit/circuit/controlflow/continue_loop.py +8 -22
  25. qiskit/circuit/controlflow/control_flow.py +47 -8
  26. qiskit/circuit/controlflow/for_loop.py +8 -23
  27. qiskit/circuit/controlflow/if_else.py +13 -27
  28. qiskit/circuit/controlflow/switch_case.py +14 -21
  29. qiskit/circuit/controlflow/while_loop.py +9 -23
  30. qiskit/circuit/controlledgate.py +2 -2
  31. qiskit/circuit/delay.py +7 -5
  32. qiskit/circuit/gate.py +20 -7
  33. qiskit/circuit/instruction.py +31 -30
  34. qiskit/circuit/instructionset.py +9 -22
  35. qiskit/circuit/library/__init__.py +3 -13
  36. qiskit/circuit/library/arithmetic/integer_comparator.py +2 -2
  37. qiskit/circuit/library/arithmetic/quadratic_form.py +3 -2
  38. qiskit/circuit/library/blueprintcircuit.py +29 -7
  39. qiskit/circuit/library/data_preparation/state_preparation.py +6 -5
  40. qiskit/circuit/library/generalized_gates/diagonal.py +5 -4
  41. qiskit/circuit/library/generalized_gates/isometry.py +51 -254
  42. qiskit/circuit/library/generalized_gates/pauli.py +2 -2
  43. qiskit/circuit/library/generalized_gates/permutation.py +4 -1
  44. qiskit/circuit/library/generalized_gates/rv.py +15 -11
  45. qiskit/circuit/library/generalized_gates/uc.py +2 -98
  46. qiskit/circuit/library/generalized_gates/unitary.py +9 -4
  47. qiskit/circuit/library/hamiltonian_gate.py +11 -5
  48. qiskit/circuit/library/n_local/efficient_su2.py +5 -5
  49. qiskit/circuit/library/n_local/n_local.py +100 -49
  50. qiskit/circuit/library/n_local/two_local.py +3 -59
  51. qiskit/circuit/library/overlap.py +3 -3
  52. qiskit/circuit/library/phase_oracle.py +1 -1
  53. qiskit/circuit/library/quantum_volume.py +39 -38
  54. qiskit/circuit/library/standard_gates/equivalence_library.py +50 -0
  55. qiskit/circuit/library/standard_gates/global_phase.py +4 -2
  56. qiskit/circuit/library/standard_gates/i.py +1 -2
  57. qiskit/circuit/library/standard_gates/iswap.py +1 -2
  58. qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +11 -5
  59. qiskit/circuit/library/standard_gates/p.py +31 -15
  60. qiskit/circuit/library/standard_gates/r.py +4 -3
  61. qiskit/circuit/library/standard_gates/rx.py +7 -4
  62. qiskit/circuit/library/standard_gates/rxx.py +4 -3
  63. qiskit/circuit/library/standard_gates/ry.py +7 -4
  64. qiskit/circuit/library/standard_gates/ryy.py +4 -3
  65. qiskit/circuit/library/standard_gates/rz.py +7 -4
  66. qiskit/circuit/library/standard_gates/rzx.py +4 -3
  67. qiskit/circuit/library/standard_gates/rzz.py +4 -3
  68. qiskit/circuit/library/standard_gates/s.py +4 -8
  69. qiskit/circuit/library/standard_gates/t.py +2 -4
  70. qiskit/circuit/library/standard_gates/u.py +16 -11
  71. qiskit/circuit/library/standard_gates/u1.py +6 -2
  72. qiskit/circuit/library/standard_gates/u2.py +4 -2
  73. qiskit/circuit/library/standard_gates/u3.py +9 -5
  74. qiskit/circuit/library/standard_gates/x.py +22 -11
  75. qiskit/circuit/library/standard_gates/xx_minus_yy.py +4 -3
  76. qiskit/circuit/library/standard_gates/xx_plus_yy.py +7 -5
  77. qiskit/circuit/library/standard_gates/z.py +1 -2
  78. qiskit/circuit/measure.py +4 -1
  79. qiskit/circuit/operation.py +13 -8
  80. qiskit/circuit/parameter.py +11 -6
  81. qiskit/circuit/quantumcircuit.py +1910 -260
  82. qiskit/circuit/quantumcircuitdata.py +2 -2
  83. qiskit/circuit/reset.py +5 -2
  84. qiskit/circuit/store.py +95 -0
  85. qiskit/compiler/assembler.py +22 -22
  86. qiskit/compiler/transpiler.py +63 -112
  87. qiskit/converters/__init__.py +17 -2
  88. qiskit/converters/circuit_to_dag.py +7 -0
  89. qiskit/converters/circuit_to_dagdependency_v2.py +47 -0
  90. qiskit/converters/circuit_to_gate.py +2 -0
  91. qiskit/converters/circuit_to_instruction.py +22 -0
  92. qiskit/converters/dag_to_circuit.py +4 -0
  93. qiskit/converters/dag_to_dagdependency_v2.py +44 -0
  94. qiskit/dagcircuit/collect_blocks.py +15 -10
  95. qiskit/dagcircuit/dagcircuit.py +434 -124
  96. qiskit/dagcircuit/dagdependency.py +19 -12
  97. qiskit/dagcircuit/dagdependency_v2.py +641 -0
  98. qiskit/dagcircuit/dagdepnode.py +19 -16
  99. qiskit/dagcircuit/dagnode.py +14 -4
  100. qiskit/passmanager/passmanager.py +11 -11
  101. qiskit/primitives/__init__.py +22 -12
  102. qiskit/primitives/backend_estimator.py +3 -5
  103. qiskit/primitives/backend_estimator_v2.py +410 -0
  104. qiskit/primitives/backend_sampler_v2.py +287 -0
  105. qiskit/primitives/base/base_estimator.py +4 -9
  106. qiskit/primitives/base/base_sampler.py +2 -2
  107. qiskit/primitives/containers/__init__.py +6 -4
  108. qiskit/primitives/containers/bit_array.py +293 -2
  109. qiskit/primitives/containers/data_bin.py +123 -50
  110. qiskit/primitives/containers/estimator_pub.py +10 -3
  111. qiskit/primitives/containers/observables_array.py +2 -2
  112. qiskit/primitives/containers/pub_result.py +1 -1
  113. qiskit/primitives/containers/sampler_pub.py +19 -3
  114. qiskit/primitives/containers/sampler_pub_result.py +74 -0
  115. qiskit/primitives/containers/shape.py +4 -4
  116. qiskit/primitives/statevector_estimator.py +4 -4
  117. qiskit/primitives/statevector_sampler.py +7 -12
  118. qiskit/providers/__init__.py +65 -34
  119. qiskit/providers/backend.py +2 -2
  120. qiskit/providers/backend_compat.py +8 -10
  121. qiskit/providers/basic_provider/__init__.py +2 -23
  122. qiskit/providers/basic_provider/basic_provider_tools.py +67 -31
  123. qiskit/providers/basic_provider/basic_simulator.py +81 -21
  124. qiskit/providers/fake_provider/__init__.py +1 -1
  125. qiskit/providers/fake_provider/fake_1q.py +1 -1
  126. qiskit/providers/fake_provider/fake_backend.py +3 -408
  127. qiskit/providers/fake_provider/generic_backend_v2.py +26 -14
  128. qiskit/providers/models/__init__.py +2 -2
  129. qiskit/providers/provider.py +16 -0
  130. qiskit/pulse/builder.py +4 -1
  131. qiskit/pulse/parameter_manager.py +60 -4
  132. qiskit/pulse/schedule.py +29 -13
  133. qiskit/pulse/utils.py +61 -20
  134. qiskit/qasm2/__init__.py +1 -5
  135. qiskit/qasm2/parse.py +1 -4
  136. qiskit/qasm3/__init__.py +42 -5
  137. qiskit/qasm3/ast.py +19 -0
  138. qiskit/qasm3/exporter.py +178 -106
  139. qiskit/qasm3/printer.py +27 -5
  140. qiskit/qobj/converters/pulse_instruction.py +6 -6
  141. qiskit/qpy/__init__.py +299 -67
  142. qiskit/qpy/binary_io/circuits.py +216 -47
  143. qiskit/qpy/binary_io/schedules.py +42 -36
  144. qiskit/qpy/binary_io/value.py +201 -22
  145. qiskit/qpy/common.py +1 -1
  146. qiskit/qpy/exceptions.py +20 -0
  147. qiskit/qpy/formats.py +29 -0
  148. qiskit/qpy/type_keys.py +21 -0
  149. qiskit/quantum_info/analysis/distance.py +3 -3
  150. qiskit/quantum_info/analysis/make_observable.py +2 -1
  151. qiskit/quantum_info/analysis/z2_symmetries.py +2 -1
  152. qiskit/quantum_info/operators/channel/chi.py +9 -8
  153. qiskit/quantum_info/operators/channel/choi.py +10 -9
  154. qiskit/quantum_info/operators/channel/kraus.py +2 -1
  155. qiskit/quantum_info/operators/channel/ptm.py +10 -9
  156. qiskit/quantum_info/operators/channel/quantum_channel.py +2 -1
  157. qiskit/quantum_info/operators/channel/stinespring.py +2 -1
  158. qiskit/quantum_info/operators/channel/superop.py +12 -11
  159. qiskit/quantum_info/operators/channel/transformations.py +12 -11
  160. qiskit/quantum_info/operators/dihedral/dihedral.py +5 -4
  161. qiskit/quantum_info/operators/operator.py +43 -30
  162. qiskit/quantum_info/operators/scalar_op.py +10 -9
  163. qiskit/quantum_info/operators/symplectic/base_pauli.py +70 -59
  164. qiskit/quantum_info/operators/symplectic/clifford.py +36 -9
  165. qiskit/quantum_info/operators/symplectic/pauli.py +53 -6
  166. qiskit/quantum_info/operators/symplectic/pauli_list.py +36 -14
  167. qiskit/quantum_info/operators/symplectic/random.py +3 -2
  168. qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +61 -36
  169. qiskit/quantum_info/states/densitymatrix.py +13 -13
  170. qiskit/quantum_info/states/stabilizerstate.py +3 -3
  171. qiskit/quantum_info/states/statevector.py +14 -13
  172. qiskit/quantum_info/states/utils.py +5 -3
  173. qiskit/result/__init__.py +6 -0
  174. qiskit/result/mitigation/correlated_readout_mitigator.py +3 -2
  175. qiskit/result/mitigation/local_readout_mitigator.py +2 -1
  176. qiskit/result/mitigation/utils.py +3 -2
  177. qiskit/scheduler/__init__.py +10 -1
  178. qiskit/scheduler/methods/__init__.py +1 -8
  179. qiskit/synthesis/__init__.py +3 -6
  180. qiskit/synthesis/discrete_basis/commutator_decompose.py +2 -2
  181. qiskit/synthesis/evolution/lie_trotter.py +7 -14
  182. qiskit/synthesis/evolution/qdrift.py +3 -4
  183. qiskit/synthesis/linear/cnot_synth.py +1 -3
  184. qiskit/synthesis/linear/linear_circuits_utils.py +1 -1
  185. qiskit/synthesis/linear_phase/cz_depth_lnn.py +4 -18
  186. qiskit/synthesis/permutation/__init__.py +1 -0
  187. qiskit/synthesis/permutation/permutation_reverse_lnn.py +90 -0
  188. qiskit/synthesis/qft/qft_decompose_lnn.py +2 -6
  189. qiskit/synthesis/two_qubit/two_qubit_decompose.py +165 -954
  190. qiskit/synthesis/two_qubit/xx_decompose/circuits.py +13 -12
  191. qiskit/synthesis/two_qubit/xx_decompose/decomposer.py +7 -1
  192. qiskit/synthesis/unitary/aqc/__init__.py +1 -1
  193. qiskit/synthesis/unitary/aqc/cnot_structures.py +2 -1
  194. qiskit/synthesis/unitary/aqc/fast_gradient/fast_gradient.py +2 -1
  195. qiskit/synthesis/unitary/qsd.py +3 -2
  196. qiskit/transpiler/__init__.py +7 -3
  197. qiskit/transpiler/layout.py +140 -61
  198. qiskit/transpiler/passes/__init__.py +10 -2
  199. qiskit/transpiler/passes/basis/basis_translator.py +9 -4
  200. qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
  201. qiskit/transpiler/passes/basis/unroll_custom_definitions.py +1 -1
  202. qiskit/transpiler/passes/calibration/rzx_builder.py +2 -1
  203. qiskit/transpiler/passes/layout/apply_layout.py +8 -3
  204. qiskit/transpiler/passes/layout/sabre_layout.py +15 -3
  205. qiskit/transpiler/passes/layout/set_layout.py +1 -1
  206. qiskit/transpiler/passes/optimization/__init__.py +2 -0
  207. qiskit/transpiler/passes/optimization/commutation_analysis.py +2 -2
  208. qiskit/transpiler/passes/optimization/commutative_cancellation.py +1 -1
  209. qiskit/transpiler/passes/optimization/consolidate_blocks.py +1 -1
  210. qiskit/transpiler/passes/optimization/cx_cancellation.py +10 -0
  211. qiskit/transpiler/passes/optimization/elide_permutations.py +114 -0
  212. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +9 -3
  213. qiskit/transpiler/passes/optimization/optimize_annotated.py +248 -12
  214. qiskit/transpiler/passes/optimization/remove_final_reset.py +37 -0
  215. qiskit/transpiler/passes/optimization/template_matching/forward_match.py +1 -3
  216. qiskit/transpiler/passes/routing/__init__.py +1 -0
  217. qiskit/transpiler/passes/routing/basic_swap.py +13 -2
  218. qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +8 -1
  219. qiskit/transpiler/passes/routing/lookahead_swap.py +7 -1
  220. qiskit/transpiler/passes/routing/sabre_swap.py +10 -6
  221. qiskit/transpiler/passes/routing/star_prerouting.py +417 -0
  222. qiskit/transpiler/passes/routing/stochastic_swap.py +24 -8
  223. qiskit/transpiler/passes/scheduling/__init__.py +1 -1
  224. qiskit/transpiler/passes/scheduling/alap.py +1 -2
  225. qiskit/transpiler/passes/scheduling/alignments/align_measures.py +1 -2
  226. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +9 -6
  227. qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +8 -0
  228. qiskit/transpiler/passes/scheduling/alignments/reschedule.py +13 -4
  229. qiskit/transpiler/passes/scheduling/asap.py +1 -2
  230. qiskit/transpiler/passes/scheduling/base_scheduler.py +21 -2
  231. qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +26 -4
  232. qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +24 -2
  233. qiskit/transpiler/passes/scheduling/time_unit_conversion.py +28 -4
  234. qiskit/transpiler/passes/synthesis/aqc_plugin.py +2 -2
  235. qiskit/transpiler/passes/synthesis/high_level_synthesis.py +120 -13
  236. qiskit/transpiler/passes/synthesis/unitary_synthesis.py +162 -55
  237. qiskit/transpiler/passes/utils/gates_basis.py +3 -3
  238. qiskit/transpiler/passmanager.py +44 -1
  239. qiskit/transpiler/preset_passmanagers/__init__.py +3 -3
  240. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +34 -16
  241. qiskit/transpiler/preset_passmanagers/common.py +4 -6
  242. qiskit/transpiler/preset_passmanagers/plugin.py +9 -1
  243. qiskit/utils/__init__.py +3 -2
  244. qiskit/utils/optionals.py +6 -2
  245. qiskit/utils/parallel.py +24 -15
  246. qiskit/visualization/array.py +1 -1
  247. qiskit/visualization/bloch.py +2 -3
  248. qiskit/visualization/circuit/matplotlib.py +44 -14
  249. qiskit/visualization/circuit/text.py +38 -18
  250. qiskit/visualization/counts_visualization.py +3 -6
  251. qiskit/visualization/dag_visualization.py +6 -7
  252. qiskit/visualization/gate_map.py +9 -1
  253. qiskit/visualization/pulse_v2/interface.py +8 -3
  254. qiskit/visualization/state_visualization.py +3 -2
  255. qiskit/visualization/timeline/interface.py +18 -8
  256. {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/METADATA +12 -8
  257. {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/RECORD +261 -251
  258. {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/WHEEL +1 -1
  259. qiskit/_qasm2.pyd +0 -0
  260. qiskit/_qasm3.pyd +0 -0
  261. {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/LICENSE.txt +0 -0
  262. {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/entry_points.txt +0 -0
  263. {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/top_level.txt +0 -0
@@ -15,78 +15,151 @@ Dataclass tools for data namespaces (bins)
15
15
  """
16
16
  from __future__ import annotations
17
17
 
18
- from collections.abc import Iterable
19
- from dataclasses import make_dataclass
18
+ from typing import Any, ItemsView, Iterable, KeysView, ValuesView
20
19
 
20
+ import numpy as np
21
21
 
22
- class DataBinMeta(type):
23
- """Metaclass for :class:`DataBin` that adds the shape to the type name.
22
+ from .shape import ShapedMixin, ShapeInput, shape_tuple
23
+
24
+
25
+ def _value_repr(value: Any) -> str:
26
+ """Helper function for :meth:`DataBin.__repr__`."""
27
+ if isinstance(value, np.ndarray):
28
+ return f"np.ndarray(<shape={value.shape}, dtype={value.dtype}>)"
29
+ return repr(value)
24
30
 
25
- This is so that the class has a custom repr with DataBin<*shape> notation.
26
- """
27
31
 
28
- def __repr__(cls):
29
- name = cls.__name__
30
- if cls._SHAPE is None:
31
- return name
32
- shape = ",".join(map(str, cls._SHAPE))
33
- return f"{name}<{shape}>"
32
+ class DataBin(ShapedMixin):
33
+ """Namespace for storing data.
34
34
 
35
+ .. code-block:: python
36
+
37
+ data = DataBin(
38
+ alpha=BitArray.from_bitstrings(["0010"]),
39
+ beta=np.array([1.2])
40
+ )
35
41
 
36
- class DataBin(metaclass=DataBinMeta):
37
- """Base class for data bin containers.
42
+ print("alpha data:", data.alpha)
43
+ print("beta data:", data.beta)
38
44
 
39
- Subclasses are typically made via :class:`~make_data_bin`, which is a specialization of
40
- :class:`make_dataclass`.
41
45
  """
42
46
 
43
- _RESTRICTED_NAMES = ("_RESTRICTED_NAMES", "_SHAPE", "_FIELDS", "_FIELD_TYPES")
44
- _SHAPE: tuple[int, ...] | None = None
45
- _FIELDS: tuple[str, ...] = ()
46
- """The fields allowed in this data bin."""
47
- _FIELD_TYPES: tuple[type, ...] = ()
48
- """The types of each field."""
47
+ __slots__ = ("_data", "_shape")
48
+
49
+ _RESTRICTED_NAMES = frozenset(
50
+ {
51
+ "_RESTRICTED_NAMES",
52
+ "_SHAPE",
53
+ "_FIELDS",
54
+ "_FIELD_TYPES",
55
+ "_data",
56
+ "_shape",
57
+ "keys",
58
+ "values",
59
+ "items",
60
+ "shape",
61
+ "ndim",
62
+ "size",
63
+ }
64
+ )
65
+
66
+ def __init__(self, *, shape: ShapeInput = (), **data):
67
+ """
68
+ Args:
69
+ data: Name/value data to place in the data bin.
70
+ shape: The leading shape common to all entries in the data bin. This defaults to
71
+ the trivial leading shape of ``()`` that is compatible with all objects.
72
+
73
+ Raises:
74
+ ValueError: If a name overlaps with a method name on this class.
75
+ ValueError: If some value is inconsistent with the provided shape.
76
+ """
77
+ if not self._RESTRICTED_NAMES.isdisjoint(data):
78
+ bad_names = sorted(self._RESTRICTED_NAMES.intersection(data))
79
+ raise ValueError(f"Cannot assign with these field names: {bad_names}")
80
+
81
+ _setattr = super().__setattr__
82
+ _setattr("_shape", shape_tuple(shape))
83
+ _setattr("_data", data)
84
+
85
+ ndim = len(self._shape)
86
+ for name, value in data.items():
87
+ if getattr(value, "shape", shape)[:ndim] != shape:
88
+ raise ValueError(f"The value of '{name}' does not lead with the shape {shape}.")
89
+ _setattr(name, value)
90
+
91
+ super().__init__()
49
92
 
50
93
  def __len__(self):
51
- return len(self._FIELDS)
94
+ return len(self._data)
95
+
96
+ def __setattr__(self, *_):
97
+ raise NotImplementedError
52
98
 
53
99
  def __repr__(self):
54
- vals = (f"{name}={getattr(self, name)}" for name in self._FIELDS if hasattr(self, name))
55
- return f"{type(self)}({', '.join(vals)})"
100
+ vals = [f"{name}={_value_repr(val)}" for name, val in self.items()]
101
+ if self.ndim:
102
+ vals.append(f"shape={self.shape}")
103
+ return f"{type(self).__name__}({', '.join(vals)})"
56
104
 
105
+ def __getitem__(self, key: str) -> Any:
106
+ try:
107
+ return self._data[key]
108
+ except KeyError as ex:
109
+ raise KeyError(f"Key ({key}) does not exist in this data bin.") from ex
57
110
 
58
- def make_data_bin(
59
- fields: Iterable[tuple[str, type]], shape: tuple[int, ...] | None = None
60
- ) -> DataBinMeta:
61
- """Return a new subclass of :class:`~DataBin` with the provided fields and shape.
111
+ def __contains__(self, key: str) -> bool:
112
+ return key in self._data
62
113
 
63
- .. code-block:: python
114
+ def __iter__(self) -> Iterable[str]:
115
+ return iter(self._data)
64
116
 
65
- my_bin = make_data_bin([("alpha", np.NDArray[np.float64])], shape=(20, 30))
117
+ def keys(self) -> KeysView[str]:
118
+ """Return a view of field names."""
119
+ return self._data.keys()
66
120
 
67
- # behaves like a dataclass
68
- my_bin(alpha=np.empty((20, 30)))
121
+ def values(self) -> ValuesView[Any]:
122
+ """Return a view of values."""
123
+ return self._data.values()
124
+
125
+ def items(self) -> ItemsView[str, Any]:
126
+ """Return a view of field names and values"""
127
+ return self._data.items()
128
+
129
+ # The following properties exist to provide support to legacy private class attributes which
130
+ # gained widespread prior to qiskit 1.1. These properties will be removed once the internal
131
+ # projects have made the appropriate changes.
132
+
133
+ @property
134
+ def _FIELDS(self) -> tuple[str, ...]: # pylint: disable=invalid-name
135
+ return tuple(self._data)
136
+
137
+ @property
138
+ def _FIELD_TYPES(self) -> tuple[Any, ...]: # pylint: disable=invalid-name
139
+ return tuple(map(type, self.values()))
140
+
141
+ @property
142
+ def _SHAPE(self) -> tuple[int, ...]: # pylint: disable=invalid-name
143
+ return self.shape
144
+
145
+
146
+ # pylint: disable=unused-argument
147
+ def make_data_bin(
148
+ fields: Iterable[tuple[str, type]], shape: tuple[int, ...] | None = None
149
+ ) -> type[DataBin]:
150
+ """Return the :class:`~DataBin` type.
151
+
152
+ .. note::
153
+ This class used to return a subclass of :class:`~DataBin`. However, that caused confusion
154
+ and didn't have a useful purpose. Several internal projects made use of this internal
155
+ function prior to qiskit 1.1. This function will be removed once these internal projects
156
+ have made the appropriate changes.
69
157
 
70
158
  Args:
71
159
  fields: Tuples ``(name, type)`` specifying the attributes of the returned class.
72
160
  shape: The intended shape of every attribute of this class.
73
161
 
74
162
  Returns:
75
- A new class.
163
+ The :class:`DataBin` type.
76
164
  """
77
- field_names, field_types = zip(*fields) if fields else ([], [])
78
- for name in field_names:
79
- if name in DataBin._RESTRICTED_NAMES:
80
- raise ValueError(f"'{name}' is a restricted name for a DataBin.")
81
- cls = make_dataclass(
82
- "DataBin",
83
- dict(zip(field_names, field_types)),
84
- bases=(DataBin,),
85
- frozen=True,
86
- unsafe_hash=True,
87
- repr=False,
88
- )
89
- cls._SHAPE = shape
90
- cls._FIELDS = field_names
91
- cls._FIELD_TYPES = field_types
92
- return cls
165
+ return DataBin
@@ -132,6 +132,15 @@ class EstimatorPub(ShapedMixin):
132
132
  validate=False, # Assume Pub is already validated
133
133
  )
134
134
  return pub
135
+
136
+ if isinstance(pub, QuantumCircuit):
137
+ raise ValueError(
138
+ f"An invalid Estimator pub-like was given ({type(pub)}). "
139
+ "If you want to run a single pub, you need to wrap it with `[]` like "
140
+ "`estimator.run([(circuit, observables, param_values)])` "
141
+ "instead of `estimator.run((circuit, observables, param_values))`."
142
+ )
143
+
135
144
  if len(pub) not in [2, 3, 4]:
136
145
  raise ValueError(
137
146
  f"The length of pub must be 2, 3 or 4, but length {len(pub)} is given."
@@ -208,8 +217,6 @@ estimator, if ``precision=None`` the estimator will determine the target precisi
208
217
  An Estimator Pub can also be initialized in the following formats which
209
218
  will be converted to the full Pub tuple:
210
219
 
211
- * ``circuit
212
- * ``(circuit,)``
213
220
  * ``(circuit, observables)``
214
- * ``(circuit, observalbes, parameter_values)``
221
+ * ``(circuit, observables, parameter_values)``
215
222
  """
@@ -101,10 +101,10 @@ class ObservablesArray(ShapedMixin):
101
101
  """Convert to a nested list"""
102
102
  return self._array.tolist()
103
103
 
104
- def __array__(self, dtype=None):
104
+ def __array__(self, dtype=None, copy=None):
105
105
  """Convert to an Numpy.ndarray"""
106
106
  if dtype is None or dtype == object:
107
- return self._array
107
+ return self._array.copy() if copy else self._array
108
108
  raise ValueError("Type must be 'None' or 'object'")
109
109
 
110
110
  @overload
@@ -11,7 +11,7 @@
11
11
  # that they have been altered from the originals.
12
12
 
13
13
  """
14
- Base Pub class
14
+ Base Pub result class
15
15
  """
16
16
 
17
17
  from __future__ import annotations
@@ -18,10 +18,11 @@ Sampler Pub class
18
18
  from __future__ import annotations
19
19
 
20
20
  from collections.abc import Mapping
21
- from typing import Tuple, Union
22
21
  from numbers import Integral
22
+ from typing import Tuple, Union
23
23
 
24
24
  from qiskit import QuantumCircuit
25
+ from qiskit.circuit import CircuitInstruction
25
26
 
26
27
  from .bindings_array import BindingsArray, BindingsArrayLike
27
28
  from .shape import ShapedMixin
@@ -113,6 +114,14 @@ class SamplerPub(ShapedMixin):
113
114
  if isinstance(pub, QuantumCircuit):
114
115
  return cls(circuit=pub, shots=shots, validate=True)
115
116
 
117
+ if isinstance(pub, CircuitInstruction):
118
+ raise ValueError(
119
+ f"An invalid Sampler pub-like was given ({type(pub)}). "
120
+ "If you want to run a single circuit, "
121
+ "you need to wrap it with `[]` like `sampler.run([circuit])` "
122
+ "instead of `sampler.run(circuit)`."
123
+ )
124
+
116
125
  if len(pub) not in [1, 2, 3]:
117
126
  raise ValueError(
118
127
  f"The length of pub must be 1, 2 or 3, but length {len(pub)} is given."
@@ -147,10 +156,17 @@ class SamplerPub(ShapedMixin):
147
156
  # Cross validate circuits and parameter values
148
157
  num_parameters = self.parameter_values.num_parameters
149
158
  if num_parameters != self.circuit.num_parameters:
150
- raise ValueError(
159
+ message = (
151
160
  f"The number of values ({num_parameters}) does not match "
152
161
  f"the number of parameters ({self.circuit.num_parameters}) for the circuit."
153
162
  )
163
+ if num_parameters == 0:
164
+ message += (
165
+ " Note that if you want to run a single pub, you need to wrap it with `[]` like "
166
+ "`sampler.run([(circuit, param_values)])` instead of "
167
+ "`sampler.run((circuit, param_values))`."
168
+ )
169
+ raise ValueError(message)
154
170
 
155
171
 
156
172
  SamplerPubLike = Union[
@@ -171,7 +187,7 @@ if ``shots=None`` the number of run shots is determined by the sampler.
171
187
  A Sampler Pub can also be initialized in the following formats which
172
188
  will be converted to the full Pub tuple:
173
189
 
174
- * ``circuit
190
+ * ``circuit``
175
191
  * ``(circuit,)``
176
192
  * ``(circuit, parameter_values)``
177
193
  """
@@ -0,0 +1,74 @@
1
+ # This code is part of Qiskit.
2
+ #
3
+ # (C) Copyright IBM 2024.
4
+ #
5
+ # This code is licensed under the Apache License, Version 2.0. You may
6
+ # obtain a copy of this license in the LICENSE.txt file in the root directory
7
+ # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8
+ #
9
+ # Any modifications or derivative works of this code must retain this
10
+ # copyright notice, and modified files need to carry a notice indicating
11
+ # that they have been altered from the originals.
12
+
13
+ """
14
+ Sampler Pub result class
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from typing import Iterable
20
+
21
+ import numpy as np
22
+
23
+ from .bit_array import BitArray
24
+ from .pub_result import PubResult
25
+
26
+
27
+ class SamplerPubResult(PubResult):
28
+ """Result of Sampler Pub."""
29
+
30
+ def join_data(self, names: Iterable[str] | None = None) -> BitArray | np.ndarray:
31
+ """Join data from many registers into one data container.
32
+
33
+ Data is joined along the bits axis. For example, for :class:`~.BitArray` data, this corresponds
34
+ to bitstring concatenation.
35
+
36
+ Args:
37
+ names: Which registers to join. Their order is maintained, for example, given
38
+ ``["alpha", "beta"]``, the data from register ``alpha`` is placed to the left of the
39
+ data from register ``beta``. When ``None`` is given, this value is set to the
40
+ ordered list of register names, which will have been preserved from the input circuit
41
+ order.
42
+
43
+ Returns:
44
+ Joint data.
45
+
46
+ Raises:
47
+ ValueError: If specified names are empty.
48
+ ValueError: If specified name does not exist.
49
+ TypeError: If specified data comes from incompatible types.
50
+ """
51
+ if names is None:
52
+ names = list(self.data)
53
+ if not names:
54
+ raise ValueError("No entry exists in the data bin.")
55
+ else:
56
+ names = list(names)
57
+ if not names:
58
+ raise ValueError("An empty name list is given.")
59
+ for name in names:
60
+ if name not in self.data:
61
+ raise ValueError(f"Name '{name}' does not exist.")
62
+
63
+ data = [self.data[name] for name in names]
64
+ if isinstance(data[0], BitArray):
65
+ if not all(isinstance(datum, BitArray) for datum in data):
66
+ raise TypeError("Data comes from incompatible types.")
67
+ joint_data = BitArray.concatenate_bits(data)
68
+ elif isinstance(data[0], np.ndarray):
69
+ if not all(isinstance(datum, np.ndarray) for datum in data):
70
+ raise TypeError("Data comes from incompatible types.")
71
+ joint_data = np.concatenate(data, axis=-1)
72
+ else:
73
+ raise TypeError("Data comes from incompatible types.")
74
+ return joint_data
@@ -59,15 +59,15 @@ class ShapedMixin(Shaped):
59
59
  return f"{type(self).__name__}(<{self.shape}>)"
60
60
 
61
61
  @property
62
- def shape(self):
62
+ def shape(self) -> tuple[int, ...]:
63
63
  return self._shape
64
64
 
65
65
  @property
66
- def ndim(self):
66
+ def ndim(self) -> int:
67
67
  return len(self._shape)
68
68
 
69
69
  @property
70
- def size(self):
70
+ def size(self) -> int:
71
71
  return int(np.prod(self._shape, dtype=int))
72
72
 
73
73
 
@@ -85,7 +85,7 @@ def array_coerce(arr: ArrayLike | Shaped) -> NDArray | Shaped:
85
85
  """
86
86
  if isinstance(arr, Shaped):
87
87
  return arr
88
- return np.array(arr, copy=False)
88
+ return np.asarray(arr)
89
89
 
90
90
 
91
91
  def _flatten_to_ints(arg: ShapeInput) -> Iterable[int]:
@@ -22,7 +22,7 @@ import numpy as np
22
22
  from qiskit.quantum_info import SparsePauliOp, Statevector
23
23
 
24
24
  from .base import BaseEstimatorV2
25
- from .containers import EstimatorPubLike, PrimitiveResult, PubResult
25
+ from .containers import DataBin, EstimatorPubLike, PrimitiveResult, PubResult
26
26
  from .containers.estimator_pub import EstimatorPub
27
27
  from .primitive_job import PrimitiveJob
28
28
  from .utils import bound_circuit_to_instruction
@@ -160,6 +160,6 @@ class StatevectorEstimator(BaseEstimatorV2):
160
160
  raise ValueError("Given operator is not Hermitian and noise cannot be added.")
161
161
  expectation_value = rng.normal(expectation_value, precision)
162
162
  evs[index] = expectation_value
163
- data_bin_cls = self._make_data_bin(pub)
164
- data_bin = data_bin_cls(evs=evs, stds=stds)
165
- return PubResult(data_bin, metadata={"precision": precision})
163
+
164
+ data = DataBin(evs=evs, stds=stds, shape=evs.shape)
165
+ return PubResult(data, metadata={"precision": precision})
@@ -15,9 +15,9 @@ Statevector Sampler class
15
15
 
16
16
  from __future__ import annotations
17
17
 
18
+ import warnings
18
19
  from dataclasses import dataclass
19
20
  from typing import Iterable
20
- import warnings
21
21
 
22
22
  import numpy as np
23
23
  from numpy.typing import NDArray
@@ -30,10 +30,10 @@ from .base import BaseSamplerV2
30
30
  from .base.validation import _has_measure
31
31
  from .containers import (
32
32
  BitArray,
33
+ DataBin,
33
34
  PrimitiveResult,
34
- PubResult,
35
+ SamplerPubResult,
35
36
  SamplerPubLike,
36
- make_data_bin,
37
37
  )
38
38
  from .containers.sampler_pub import SamplerPub
39
39
  from .containers.bit_array import _min_num_bytes
@@ -154,7 +154,7 @@ class StatevectorSampler(BaseSamplerV2):
154
154
 
155
155
  def run(
156
156
  self, pubs: Iterable[SamplerPubLike], *, shots: int | None = None
157
- ) -> PrimitiveJob[PrimitiveResult[PubResult]]:
157
+ ) -> PrimitiveJob[PrimitiveResult[SamplerPubResult]]:
158
158
  if shots is None:
159
159
  shots = self._default_shots
160
160
  coerced_pubs = [SamplerPub.coerce(pub, shots) for pub in pubs]
@@ -169,11 +169,11 @@ class StatevectorSampler(BaseSamplerV2):
169
169
  job._submit()
170
170
  return job
171
171
 
172
- def _run(self, pubs: Iterable[SamplerPub]) -> PrimitiveResult[PubResult]:
172
+ def _run(self, pubs: Iterable[SamplerPub]) -> PrimitiveResult[SamplerPubResult]:
173
173
  results = [self._run_pub(pub) for pub in pubs]
174
174
  return PrimitiveResult(results)
175
175
 
176
- def _run_pub(self, pub: SamplerPub) -> PubResult:
176
+ def _run_pub(self, pub: SamplerPub) -> SamplerPubResult:
177
177
  circuit, qargs, meas_info = _preprocess_circuit(pub.circuit)
178
178
  bound_circuits = pub.parameter_values.bind_all(circuit)
179
179
  arrays = {
@@ -194,15 +194,10 @@ class StatevectorSampler(BaseSamplerV2):
194
194
  ary = _samples_to_packed_array(samples_array, item.num_bits, item.qreg_indices)
195
195
  arrays[item.creg_name][index] = ary
196
196
 
197
- data_bin_cls = make_data_bin(
198
- [(item.creg_name, BitArray) for item in meas_info],
199
- shape=bound_circuits.shape,
200
- )
201
197
  meas = {
202
198
  item.creg_name: BitArray(arrays[item.creg_name], item.num_bits) for item in meas_info
203
199
  }
204
- data_bin = data_bin_cls(**meas)
205
- return PubResult(data_bin, metadata={"shots": pub.shots})
200
+ return SamplerPubResult(DataBin(**meas, shape=pub.shape), metadata={"shots": pub.shots})
206
201
 
207
202
 
208
203
  def _preprocess_circuit(circuit: QuantumCircuit):