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
qiskit/qpy/type_keys.py CHANGED
@@ -16,6 +16,7 @@
16
16
  QPY Type keys for several namespace.
17
17
  """
18
18
 
19
+ import uuid
19
20
  from abc import abstractmethod
20
21
  from enum import Enum, IntEnum
21
22
 
@@ -456,6 +457,7 @@ class Expression(TypeKeyBase):
456
457
  CAST = b"c"
457
458
  UNARY = b"u"
458
459
  BINARY = b"b"
460
+ INDEX = b"i"
459
461
 
460
462
  @classmethod
461
463
  def assign(cls, obj):
@@ -471,6 +473,22 @@ class Expression(TypeKeyBase):
471
473
  raise NotImplementedError
472
474
 
473
475
 
476
+ class ExprVarDeclaration(TypeKeyBase):
477
+ """Type keys for the ``EXPR_VAR_DECLARATION`` QPY item."""
478
+
479
+ INPUT = b"I"
480
+ CAPTURE = b"C"
481
+ LOCAL = b"L"
482
+
483
+ @classmethod
484
+ def assign(cls, obj):
485
+ raise NotImplementedError
486
+
487
+ @classmethod
488
+ def retrieve(cls, type_key):
489
+ raise NotImplementedError
490
+
491
+
474
492
  class ExprType(TypeKeyBase):
475
493
  """Type keys for the ``EXPR_TYPE`` QPY item."""
476
494
 
@@ -496,9 +514,12 @@ class ExprVar(TypeKeyBase):
496
514
 
497
515
  CLBIT = b"C"
498
516
  REGISTER = b"R"
517
+ UUID = b"U"
499
518
 
500
519
  @classmethod
501
520
  def assign(cls, obj):
521
+ if isinstance(obj, uuid.UUID):
522
+ return cls.UUID
502
523
  if isinstance(obj, Clbit):
503
524
  return cls.CLBIT
504
525
  if isinstance(obj, ClassicalRegister):
@@ -12,7 +12,7 @@
12
12
 
13
13
  """A collection of discrete probability metrics."""
14
14
  from __future__ import annotations
15
- import numpy as np
15
+ import math
16
16
 
17
17
 
18
18
  def hellinger_distance(dist_p: dict, dist_q: dict) -> float:
@@ -43,13 +43,13 @@ def hellinger_distance(dist_p: dict, dist_q: dict) -> float:
43
43
  total = 0
44
44
  for key, val in p_normed.items():
45
45
  if key in q_normed:
46
- total += (np.sqrt(val) - np.sqrt(q_normed[key])) ** 2
46
+ total += (math.sqrt(val) - math.sqrt(q_normed[key])) ** 2
47
47
  del q_normed[key]
48
48
  else:
49
49
  total += val
50
50
  total += sum(q_normed.values())
51
51
 
52
- dist = np.sqrt(total) / np.sqrt(2)
52
+ dist = math.sqrt(total) / math.sqrt(2)
53
53
 
54
54
  return dist
55
55
 
@@ -13,6 +13,7 @@
13
13
  """Helper functions for building dictionaries from matrices and lists."""
14
14
 
15
15
  from __future__ import annotations
16
+ import math
16
17
  import numpy as np
17
18
 
18
19
 
@@ -33,7 +34,7 @@ def make_dict_observable(matrix_observable: list | np.ndarray) -> dict:
33
34
  dict_observable = {}
34
35
  observable = np.array(matrix_observable)
35
36
  observable_size = len(observable)
36
- observable_bits = int(np.ceil(np.log2(observable_size)))
37
+ observable_bits = math.ceil(math.log2(observable_size))
37
38
  binary_formatter = f"0{observable_bits}b"
38
39
  if observable.ndim == 2:
39
40
  observable = observable.diagonal()
@@ -17,6 +17,7 @@ from __future__ import annotations
17
17
  import itertools
18
18
  from collections.abc import Iterable
19
19
  from copy import deepcopy
20
+ import math
20
21
  from typing import Union, cast
21
22
 
22
23
  import numpy as np
@@ -121,7 +122,7 @@ class Z2Symmetries:
121
122
  A list of unitaries used to diagonalize the Hamiltonian.
122
123
  """
123
124
  cliffords = [
124
- (SparsePauliOp(pauli_symm) + SparsePauliOp(sq_pauli)) / np.sqrt(2)
125
+ (SparsePauliOp(pauli_symm) + SparsePauliOp(sq_pauli)) / math.sqrt(2)
125
126
  for pauli_symm, sq_pauli in zip(self._symmetries, self._sq_paulis)
126
127
  ]
127
128
  return cliffords
@@ -16,9 +16,11 @@ Chi-matrix representation of a Quantum Channel.
16
16
  """
17
17
 
18
18
  from __future__ import annotations
19
- import copy
19
+ import copy as _copy
20
+ import math
20
21
  import numpy as np
21
22
 
23
+ from qiskit import _numpy_compat
22
24
  from qiskit.circuit.quantumcircuit import QuantumCircuit
23
25
  from qiskit.circuit.instruction import Instruction
24
26
  from qiskit.exceptions import QiskitError
@@ -96,7 +98,7 @@ class Chi(QuantumChannel):
96
98
  if output_dims:
97
99
  output_dim = np.prod(input_dims)
98
100
  if output_dims is None and input_dims is None:
99
- output_dim = int(np.sqrt(dim_l))
101
+ output_dim = int(math.sqrt(dim_l))
100
102
  input_dim = dim_l // output_dim
101
103
  elif input_dims is None:
102
104
  input_dim = dim_l // output_dim
@@ -125,15 +127,14 @@ class Chi(QuantumChannel):
125
127
  if output_dims is None:
126
128
  output_dims = data.output_dims()
127
129
  # Check input is N-qubit channel
128
- num_qubits = int(np.log2(input_dim))
130
+ num_qubits = int(math.log2(input_dim))
129
131
  if 2**num_qubits != input_dim or input_dim != output_dim:
130
132
  raise QiskitError("Input is not an n-qubit Chi matrix.")
131
133
  super().__init__(chi_mat, num_qubits=num_qubits)
132
134
 
133
- def __array__(self, dtype=None):
134
- if dtype:
135
- return np.asarray(self.data, dtype=dtype)
136
- return self.data
135
+ def __array__(self, dtype=None, copy=_numpy_compat.COPY_ONLY_IF_NEEDED):
136
+ dtype = self.data.dtype
137
+ return np.array(self.data, dtype=dtype, copy=copy)
137
138
 
138
139
  @property
139
140
  def _bipartite_shape(self):
@@ -180,7 +181,7 @@ class Chi(QuantumChannel):
180
181
 
181
182
  @classmethod
182
183
  def _tensor(cls, a, b):
183
- ret = copy.copy(a)
184
+ ret = _copy.copy(a)
184
185
  ret._op_shape = a._op_shape.tensor(b._op_shape)
185
186
  ret._data = np.kron(a._data, b.data)
186
187
  return ret
@@ -16,9 +16,11 @@ Choi-matrix representation of a Quantum Channel.
16
16
  """
17
17
 
18
18
  from __future__ import annotations
19
- import copy
19
+ import copy as _copy
20
+ import math
20
21
  import numpy as np
21
22
 
23
+ from qiskit import _numpy_compat
22
24
  from qiskit.circuit.quantumcircuit import QuantumCircuit
23
25
  from qiskit.circuit.instruction import Instruction
24
26
  from qiskit.exceptions import QiskitError
@@ -103,7 +105,7 @@ class Choi(QuantumChannel):
103
105
  if output_dims:
104
106
  output_dim = np.prod(output_dims)
105
107
  if output_dims is None and input_dims is None:
106
- output_dim = int(np.sqrt(dim_l))
108
+ output_dim = int(math.sqrt(dim_l))
107
109
  input_dim = dim_l // output_dim
108
110
  elif input_dims is None:
109
111
  input_dim = dim_l // output_dim
@@ -133,10 +135,9 @@ class Choi(QuantumChannel):
133
135
  choi_mat = _to_choi(rep, data._data, input_dim, output_dim)
134
136
  super().__init__(choi_mat, op_shape=op_shape)
135
137
 
136
- def __array__(self, dtype=None):
137
- if dtype:
138
- return np.asarray(self.data, dtype=dtype)
139
- return self.data
138
+ def __array__(self, dtype=None, copy=_numpy_compat.COPY_ONLY_IF_NEEDED):
139
+ dtype = self.data.dtype if dtype is None else dtype
140
+ return np.array(self.data, dtype=dtype, copy=copy)
140
141
 
141
142
  @property
142
143
  def _bipartite_shape(self):
@@ -151,12 +152,12 @@ class Choi(QuantumChannel):
151
152
  # ---------------------------------------------------------------------
152
153
 
153
154
  def conjugate(self):
154
- ret = copy.copy(self)
155
+ ret = _copy.copy(self)
155
156
  ret._data = np.conj(self._data)
156
157
  return ret
157
158
 
158
159
  def transpose(self):
159
- ret = copy.copy(self)
160
+ ret = _copy.copy(self)
160
161
  ret._op_shape = self._op_shape.transpose()
161
162
  # Make bipartite matrix
162
163
  d_in, d_out = self.dim
@@ -205,7 +206,7 @@ class Choi(QuantumChannel):
205
206
 
206
207
  @classmethod
207
208
  def _tensor(cls, a, b):
208
- ret = copy.copy(a)
209
+ ret = _copy.copy(a)
209
210
  ret._op_shape = a._op_shape.tensor(b._op_shape)
210
211
  ret._data = _bipartite_tensor(
211
212
  a._data, b.data, shape1=a._bipartite_shape, shape2=b._bipartite_shape
@@ -16,6 +16,7 @@ Kraus representation of a Quantum Channel.
16
16
 
17
17
  from __future__ import annotations
18
18
  import copy
19
+ import math
19
20
  from numbers import Number
20
21
  import numpy as np
21
22
 
@@ -315,7 +316,7 @@ class Kraus(QuantumChannel):
315
316
  return ret
316
317
  # If the number is real we can update the Kraus operators
317
318
  # directly
318
- val = np.sqrt(other)
319
+ val = math.sqrt(other)
319
320
  kraus_r = None
320
321
  kraus_l = [val * k for k in self._data[0]]
321
322
  if self._data[1] is not None:
@@ -16,9 +16,11 @@ Pauli Transfer Matrix (PTM) representation of a Quantum Channel.
16
16
  """
17
17
 
18
18
  from __future__ import annotations
19
- import copy
19
+ import copy as _copy
20
+ import math
20
21
  import numpy as np
21
22
 
23
+ from qiskit import _numpy_compat
22
24
  from qiskit.circuit.quantumcircuit import QuantumCircuit
23
25
  from qiskit.circuit.instruction import Instruction
24
26
  from qiskit.exceptions import QiskitError
@@ -100,11 +102,11 @@ class PTM(QuantumChannel):
100
102
  if input_dims:
101
103
  input_dim = np.prod(input_dims)
102
104
  else:
103
- input_dim = int(np.sqrt(din))
105
+ input_dim = int(math.sqrt(din))
104
106
  if output_dims:
105
107
  output_dim = np.prod(input_dims)
106
108
  else:
107
- output_dim = int(np.sqrt(dout))
109
+ output_dim = int(math.sqrt(dout))
108
110
  if output_dim**2 != dout or input_dim**2 != din or input_dim != output_dim:
109
111
  raise QiskitError("Invalid shape for PTM matrix.")
110
112
  else:
@@ -127,15 +129,14 @@ class PTM(QuantumChannel):
127
129
  if output_dims is None:
128
130
  output_dims = data.output_dims()
129
131
  # Check input is N-qubit channel
130
- num_qubits = int(np.log2(input_dim))
132
+ num_qubits = int(math.log2(input_dim))
131
133
  if 2**num_qubits != input_dim or input_dim != output_dim:
132
134
  raise QiskitError("Input is not an n-qubit Pauli transfer matrix.")
133
135
  super().__init__(ptm, num_qubits=num_qubits)
134
136
 
135
- def __array__(self, dtype=None):
136
- if dtype:
137
- np.asarray(self.data, dtype=dtype)
138
- return self.data
137
+ def __array__(self, dtype=None, copy=_numpy_compat.COPY_ONLY_IF_NEEDED):
138
+ dtype = self.data.dtype if dtype is None else dtype
139
+ return np.array(self.data, dtype=dtype, copy=copy)
139
140
 
140
141
  @property
141
142
  def _bipartite_shape(self):
@@ -193,7 +194,7 @@ class PTM(QuantumChannel):
193
194
 
194
195
  @classmethod
195
196
  def _tensor(cls, a, b):
196
- ret = copy.copy(a)
197
+ ret = _copy.copy(a)
197
198
  ret._op_shape = a._op_shape.tensor(b._op_shape)
198
199
  ret._data = np.kron(a._data, b.data)
199
200
  return ret
@@ -16,6 +16,7 @@ Abstract base class for Quantum Channels.
16
16
 
17
17
  from __future__ import annotations
18
18
  import copy
19
+ import math
19
20
  import sys
20
21
  from abc import abstractmethod
21
22
  from numbers import Number, Integral
@@ -249,7 +250,7 @@ class QuantumChannel(LinearOp):
249
250
  """
250
251
 
251
252
  # Check if input is an N-qubit CPTP channel.
252
- num_qubits = int(np.log2(self._input_dim))
253
+ num_qubits = int(math.log2(self._input_dim))
253
254
  if self._input_dim != self._output_dim or 2**num_qubits != self._input_dim:
254
255
  raise QiskitError(
255
256
  "Cannot convert QuantumChannel to Instruction: channel is not an N-qubit channel."
@@ -15,6 +15,7 @@ Stinespring representation of a Quantum Channel.
15
15
 
16
16
  from __future__ import annotations
17
17
  import copy
18
+ import math
18
19
  from numbers import Number
19
20
  import numpy as np
20
21
 
@@ -281,7 +282,7 @@ class Stinespring(QuantumChannel):
281
282
  return ret
282
283
  # If the number is real we can update the Kraus operators
283
284
  # directly
284
- num = np.sqrt(other)
285
+ num = math.sqrt(other)
285
286
  stine_l, stine_r = self._data
286
287
  stine_l = num * self._data[0]
287
288
  stine_r = None
@@ -15,11 +15,13 @@ Superoperator representation of a Quantum Channel."""
15
15
 
16
16
  from __future__ import annotations
17
17
 
18
- import copy
18
+ import copy as _copy
19
+ import math
19
20
  from typing import TYPE_CHECKING
20
21
 
21
22
  import numpy as np
22
23
 
24
+ from qiskit import _numpy_compat
23
25
  from qiskit.circuit.instruction import Instruction
24
26
  from qiskit.circuit.quantumcircuit import QuantumCircuit
25
27
  from qiskit.exceptions import QiskitError
@@ -94,8 +96,8 @@ class SuperOp(QuantumChannel):
94
96
  super_mat = np.asarray(data, dtype=complex)
95
97
  # Determine total input and output dimensions
96
98
  dout, din = super_mat.shape
97
- input_dim = int(np.sqrt(din))
98
- output_dim = int(np.sqrt(dout))
99
+ input_dim = int(math.sqrt(din))
100
+ output_dim = int(math.sqrt(dout))
99
101
  if output_dim**2 != dout or input_dim**2 != din:
100
102
  raise QiskitError("Invalid shape for SuperOp matrix.")
101
103
  op_shape = OpShape.auto(
@@ -126,10 +128,9 @@ class SuperOp(QuantumChannel):
126
128
  # Initialize QuantumChannel
127
129
  super().__init__(super_mat, op_shape=op_shape)
128
130
 
129
- def __array__(self, dtype=None):
130
- if dtype:
131
- return np.asarray(self.data, dtype=dtype)
132
- return self.data
131
+ def __array__(self, dtype=None, copy=_numpy_compat.COPY_ONLY_IF_NEEDED):
132
+ dtype = self.data.dtype if dtype is None else dtype
133
+ return np.array(self.data, dtype=dtype, copy=copy)
133
134
 
134
135
  @property
135
136
  def _tensor_shape(self):
@@ -148,18 +149,18 @@ class SuperOp(QuantumChannel):
148
149
  # ---------------------------------------------------------------------
149
150
 
150
151
  def conjugate(self):
151
- ret = copy.copy(self)
152
+ ret = _copy.copy(self)
152
153
  ret._data = np.conj(self._data)
153
154
  return ret
154
155
 
155
156
  def transpose(self):
156
- ret = copy.copy(self)
157
+ ret = _copy.copy(self)
157
158
  ret._data = np.transpose(self._data)
158
159
  ret._op_shape = self._op_shape.transpose()
159
160
  return ret
160
161
 
161
162
  def adjoint(self):
162
- ret = copy.copy(self)
163
+ ret = _copy.copy(self)
163
164
  ret._data = np.conj(np.transpose(self._data))
164
165
  ret._op_shape = self._op_shape.transpose()
165
166
  return ret
@@ -176,7 +177,7 @@ class SuperOp(QuantumChannel):
176
177
 
177
178
  @classmethod
178
179
  def _tensor(cls, a, b):
179
- ret = copy.copy(a)
180
+ ret = _copy.copy(a)
180
181
  ret._op_shape = a._op_shape.tensor(b._op_shape)
181
182
  ret._data = _bipartite_tensor(
182
183
  a._data, b.data, shape1=a._bipartite_shape, shape2=b._bipartite_shape
@@ -18,6 +18,7 @@ Transformations between QuantumChannel representations.
18
18
  """
19
19
 
20
20
  from __future__ import annotations
21
+ import math
21
22
  import numpy as np
22
23
 
23
24
  from qiskit.exceptions import QiskitError
@@ -328,25 +329,25 @@ def _kraus_to_superop(data):
328
329
 
329
330
  def _chi_to_choi(data, input_dim):
330
331
  """Transform Chi representation to a Choi representation."""
331
- num_qubits = int(np.log2(input_dim))
332
+ num_qubits = int(math.log2(input_dim))
332
333
  return _transform_from_pauli(data, num_qubits)
333
334
 
334
335
 
335
336
  def _choi_to_chi(data, input_dim):
336
337
  """Transform Choi representation to the Chi representation."""
337
- num_qubits = int(np.log2(input_dim))
338
+ num_qubits = int(math.log2(input_dim))
338
339
  return _transform_to_pauli(data, num_qubits)
339
340
 
340
341
 
341
342
  def _ptm_to_superop(data, input_dim):
342
343
  """Transform PTM representation to SuperOp representation."""
343
- num_qubits = int(np.log2(input_dim))
344
+ num_qubits = int(math.log2(input_dim))
344
345
  return _transform_from_pauli(data, num_qubits)
345
346
 
346
347
 
347
348
  def _superop_to_ptm(data, input_dim):
348
349
  """Transform SuperOp representation to PTM representation."""
349
- num_qubits = int(np.log2(input_dim))
350
+ num_qubits = int(math.log2(input_dim))
350
351
  return _transform_to_pauli(data, num_qubits)
351
352
 
352
353
 
@@ -375,12 +376,12 @@ def _bipartite_tensor(mat1, mat2, shape1=None, shape2=None):
375
376
  dim_a0, dim_a1 = mat1.shape
376
377
  dim_b0, dim_b1 = mat2.shape
377
378
  if shape1 is None:
378
- sdim_a0 = int(np.sqrt(dim_a0))
379
- sdim_a1 = int(np.sqrt(dim_a1))
379
+ sdim_a0 = int(math.sqrt(dim_a0))
380
+ sdim_a1 = int(math.sqrt(dim_a1))
380
381
  shape1 = (sdim_a0, sdim_a0, sdim_a1, sdim_a1)
381
382
  if shape2 is None:
382
- sdim_b0 = int(np.sqrt(dim_b0))
383
- sdim_b1 = int(np.sqrt(dim_b1))
383
+ sdim_b0 = int(math.sqrt(dim_b0))
384
+ sdim_b1 = int(math.sqrt(dim_b1))
384
385
  shape2 = (sdim_b0, sdim_b0, sdim_b1, sdim_b1)
385
386
  # Check dimensions
386
387
  if len(shape1) != 4 or shape1[0] * shape1[1] != dim_a0 or shape1[2] * shape1[3] != dim_a1:
@@ -416,7 +417,7 @@ def _transform_to_pauli(data, num_qubits):
416
417
  # to avoid rounding errors from square-roots of 2.
417
418
  cob = basis_mat
418
419
  for _ in range(num_qubits - 1):
419
- dim = int(np.sqrt(len(cob)))
420
+ dim = int(math.sqrt(len(cob)))
420
421
  cob = np.reshape(
421
422
  np.transpose(
422
423
  np.reshape(np.kron(basis_mat, cob), (4, dim * dim, 2, 2, dim, dim)),
@@ -437,7 +438,7 @@ def _transform_from_pauli(data, num_qubits):
437
438
  # to avoid rounding errors from square-roots of 2.
438
439
  cob = basis_mat
439
440
  for _ in range(num_qubits - 1):
440
- dim = int(np.sqrt(len(cob)))
441
+ dim = int(math.sqrt(len(cob)))
441
442
  cob = np.reshape(
442
443
  np.transpose(
443
444
  np.reshape(np.kron(basis_mat, cob), (2, 2, dim, dim, 4, dim * dim)),
@@ -462,6 +463,6 @@ def _check_nqubit_dim(input_dim, output_dim):
462
463
  raise QiskitError(
463
464
  f"Not an n-qubit channel: input_dim ({input_dim}) != output_dim ({output_dim})"
464
465
  )
465
- num_qubits = int(np.log2(input_dim))
466
+ num_qubits = int(math.log2(input_dim))
466
467
  if 2**num_qubits != input_dim:
467
468
  raise QiskitError("Not an n-qubit channel: input_dim != 2 ** n")
@@ -357,10 +357,11 @@ class CNOTDihedral(BaseOperator, AdjointMixin):
357
357
  _append_circuit(elem, circuit)
358
358
  return elem
359
359
 
360
- def __array__(self, dtype=None):
361
- if dtype:
362
- return np.asarray(self.to_matrix(), dtype=dtype)
363
- return self.to_matrix()
360
+ def __array__(self, dtype=None, copy=None):
361
+ if copy is False:
362
+ raise ValueError("unable to avoid copy while creating an array as requested")
363
+ arr = self.to_matrix()
364
+ return arr if dtype is None else arr.astype(dtype, copy=False)
364
365
 
365
366
  def to_matrix(self):
366
367
  """Convert operator to Numpy matrix."""
@@ -16,13 +16,14 @@ Matrix Operator class.
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
- import copy
19
+ import copy as _copy
20
20
  import re
21
21
  from numbers import Number
22
22
  from typing import TYPE_CHECKING
23
23
 
24
24
  import numpy as np
25
25
 
26
+ from qiskit import _numpy_compat
26
27
  from qiskit.circuit.instruction import Instruction
27
28
  from qiskit.circuit.library.standard_gates import HGate, IGate, SGate, TGate, XGate, YGate, ZGate
28
29
  from qiskit.circuit.operation import Operation
@@ -81,6 +82,9 @@ class Operator(LinearOp):
81
82
  a Numpy array of shape (2**N, 2**N) qubit systems will be used. If
82
83
  the input operator is not an N-qubit operator, it will assign a
83
84
  single subsystem with dimension specified by the shape of the input.
85
+ Note that two operators initialized via this method are only considered equivalent if they
86
+ match up to their canonical qubit order (or: permutation). See :meth:`.Operator.from_circuit`
87
+ to specify a different qubit permutation.
84
88
  """
85
89
  op_shape = None
86
90
  if isinstance(data, (list, np.ndarray)):
@@ -117,10 +121,9 @@ class Operator(LinearOp):
117
121
  shape=self._data.shape,
118
122
  )
119
123
 
120
- def __array__(self, dtype=None):
121
- if dtype:
122
- return np.asarray(self.data, dtype=dtype)
123
- return self.data
124
+ def __array__(self, dtype=None, copy=_numpy_compat.COPY_ONLY_IF_NEEDED):
125
+ dtype = self.data.dtype if dtype is None else dtype
126
+ return np.array(self.data, dtype=dtype, copy=copy)
124
127
 
125
128
  def __repr__(self):
126
129
  prefix = "Operator("
@@ -391,8 +394,7 @@ class Operator(LinearOp):
391
394
  Returns:
392
395
  Operator: An operator representing the input circuit
393
396
  """
394
- dimension = 2**circuit.num_qubits
395
- op = cls(np.eye(dimension))
397
+
396
398
  if layout is None:
397
399
  if not ignore_set_layout:
398
400
  layout = getattr(circuit, "_layout", None)
@@ -403,27 +405,38 @@ class Operator(LinearOp):
403
405
  initial_layout=layout,
404
406
  input_qubit_mapping={qubit: index for index, qubit in enumerate(circuit.qubits)},
405
407
  )
408
+
409
+ initial_layout = layout.initial_layout if layout is not None else None
410
+
406
411
  if final_layout is None:
407
412
  if not ignore_set_layout and layout is not None:
408
413
  final_layout = getattr(layout, "final_layout", None)
409
414
 
410
- qargs = None
411
- # If there was a layout specified (either from the circuit
412
- # or via user input) use that to set qargs to permute qubits
413
- # based on that layout
414
- if layout is not None:
415
- physical_to_virtual = layout.initial_layout.get_physical_bits()
416
- qargs = [
417
- layout.input_qubit_mapping[physical_to_virtual[physical_bit]]
418
- for physical_bit in range(len(physical_to_virtual))
419
- ]
420
- # Convert circuit to an instruction
421
- instruction = circuit.to_instruction()
422
- op._append_instruction(instruction, qargs=qargs)
423
- # If final layout is set permute output indices based on layout
415
+ from qiskit.synthesis.permutation.permutation_utils import _inverse_pattern
416
+
417
+ if initial_layout is not None:
418
+ input_qubits = [None] * len(layout.input_qubit_mapping)
419
+ for q, p in layout.input_qubit_mapping.items():
420
+ input_qubits[p] = q
421
+
422
+ initial_permutation = initial_layout.to_permutation(input_qubits)
423
+ initial_permutation_inverse = _inverse_pattern(initial_permutation)
424
+
424
425
  if final_layout is not None:
425
- perm_pattern = [final_layout._v2p[v] for v in circuit.qubits]
426
- op = op.apply_permutation(perm_pattern, front=False)
426
+ final_permutation = final_layout.to_permutation(circuit.qubits)
427
+ final_permutation_inverse = _inverse_pattern(final_permutation)
428
+
429
+ op = Operator(circuit)
430
+
431
+ if initial_layout:
432
+ op = op.apply_permutation(initial_permutation, True)
433
+
434
+ if final_layout:
435
+ op = op.apply_permutation(final_permutation_inverse, False)
436
+
437
+ if initial_layout:
438
+ op = op.apply_permutation(initial_permutation_inverse, False)
439
+
427
440
  return op
428
441
 
429
442
  def is_unitary(self, atol=None, rtol=None):
@@ -447,13 +460,13 @@ class Operator(LinearOp):
447
460
 
448
461
  def conjugate(self):
449
462
  # Make a shallow copy and update array
450
- ret = copy.copy(self)
463
+ ret = _copy.copy(self)
451
464
  ret._data = np.conj(self._data)
452
465
  return ret
453
466
 
454
467
  def transpose(self):
455
468
  # Make a shallow copy and update array
456
- ret = copy.copy(self)
469
+ ret = _copy.copy(self)
457
470
  ret._data = np.transpose(self._data)
458
471
  ret._op_shape = self._op_shape.transpose()
459
472
  return ret
@@ -523,7 +536,7 @@ class Operator(LinearOp):
523
536
  """
524
537
  if self.input_dims() != self.output_dims():
525
538
  raise QiskitError("Can only power with input_dims = output_dims.")
526
- ret = copy.copy(self)
539
+ ret = _copy.copy(self)
527
540
  if isinstance(n, int):
528
541
  ret._data = np.linalg.matrix_power(self.data, n)
529
542
  else:
@@ -550,7 +563,7 @@ class Operator(LinearOp):
550
563
 
551
564
  @classmethod
552
565
  def _tensor(cls, a, b):
553
- ret = copy.copy(a)
566
+ ret = _copy.copy(a)
554
567
  ret._op_shape = a._op_shape.tensor(b._op_shape)
555
568
  ret._data = np.kron(a.data, b.data)
556
569
  return ret
@@ -585,7 +598,7 @@ class Operator(LinearOp):
585
598
  self._op_shape._validate_add(other._op_shape, qargs)
586
599
  other = ScalarOp._pad_with_identity(self, other, qargs)
587
600
 
588
- ret = copy.copy(self)
601
+ ret = _copy.copy(self)
589
602
  ret._data = self.data + other.data
590
603
  return ret
591
604
 
@@ -603,7 +616,7 @@ class Operator(LinearOp):
603
616
  """
604
617
  if not isinstance(other, Number):
605
618
  raise QiskitError("other is not a number")
606
- ret = copy.copy(self)
619
+ ret = _copy.copy(self)
607
620
  ret._data = other * self._data
608
621
  return ret
609
622
 
@@ -643,7 +656,7 @@ class Operator(LinearOp):
643
656
  Returns:
644
657
  Operator: the operator with reversed subsystem order.
645
658
  """
646
- ret = copy.copy(self)
659
+ ret = _copy.copy(self)
647
660
  axes = tuple(range(self._op_shape._num_qargs_l - 1, -1, -1))
648
661
  axes = axes + tuple(len(axes) + i for i in axes)
649
662
  ret._data = np.reshape(