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
@@ -23,6 +23,7 @@ Output:
23
23
  """
24
24
 
25
25
  from __future__ import annotations
26
+ import cmath
26
27
  from functools import reduce
27
28
  import math
28
29
  from operator import itemgetter
@@ -55,8 +56,8 @@ def decompose_xxyy_into_xxyy_xx(a_target, b_target, a_source, b_source, interact
55
56
  Returns the 6-tuple (r, s, u, v, x, y).
56
57
  """
57
58
 
58
- cplus, cminus = np.cos(a_source + b_source), np.cos(a_source - b_source)
59
- splus, sminus = np.sin(a_source + b_source), np.sin(a_source - b_source)
59
+ cplus, cminus = math.cos(a_source + b_source), math.cos(a_source - b_source)
60
+ splus, sminus = math.sin(a_source + b_source), math.sin(a_source - b_source)
60
61
  ca, sa = np.cos(interaction), np.sin(interaction)
61
62
 
62
63
  uplusv = (
@@ -117,10 +118,10 @@ def decompose_xxyy_into_xxyy_xx(a_target, b_target, a_source, b_source, interact
117
118
  ]
118
119
  )
119
120
  inner_phases = [
120
- np.angle(middle_matrix[0, 0]),
121
- np.angle(middle_matrix[1, 1]),
122
- np.angle(middle_matrix[1, 2]) + np.pi / 2,
123
- np.angle(middle_matrix[0, 3]) + np.pi / 2,
121
+ cmath.phase(middle_matrix[0, 0]),
122
+ cmath.phase(middle_matrix[1, 1]),
123
+ cmath.phase(middle_matrix[1, 2]) + np.pi / 2,
124
+ cmath.phase(middle_matrix[0, 3]) + np.pi / 2,
124
125
  ]
125
126
  r, s, x, y = np.dot(phase_solver, inner_phases)
126
127
 
@@ -133,8 +134,8 @@ def decompose_xxyy_into_xxyy_xx(a_target, b_target, a_source, b_source, interact
133
134
  np.kron(RZGate(2 * x).to_matrix(), RZGate(2 * y).to_matrix()),
134
135
  ],
135
136
  )
136
- if (abs(np.angle(generated_matrix[3, 0]) - np.pi / 2) < 0.01 and a_target > b_target) or (
137
- abs(np.angle(generated_matrix[3, 0]) + np.pi / 2) < 0.01 and a_target < b_target
137
+ if (abs(cmath.phase(generated_matrix[3, 0]) - np.pi / 2) < 0.01 and a_target > b_target) or (
138
+ abs(cmath.phase(generated_matrix[3, 0]) + np.pi / 2) < 0.01 and a_target < b_target
138
139
  ):
139
140
  x += np.pi / 4
140
141
  y += np.pi / 4
@@ -231,8 +232,8 @@ def xx_circuit_step(source, strength, target, embodiment):
231
232
  # finally conjugated by p_s_f_o.
232
233
  prefix_circuit.compose(permute_source_for_overlap, inplace=True)
233
234
  prefix_circuit.compose(source_reflection, inplace=True)
234
- prefix_circuit.global_phase += -np.log(reflection_phase_shift).imag
235
- prefix_circuit.global_phase += -np.log(shift_phase_shift).imag
235
+ prefix_circuit.global_phase -= cmath.phase(reflection_phase_shift)
236
+ prefix_circuit.global_phase -= cmath.phase(shift_phase_shift)
236
237
 
237
238
  # the affix circuit is constructed in reverse.
238
239
  # first (i.e., innermost), we install the other half of the source transformations and p_s_f_o.
@@ -291,8 +292,8 @@ def canonical_xx_circuit(target, strength_sequence, basis_embodiments):
291
292
  circuit.compose(basis_embodiments[strength_sequence[0]], inplace=True)
292
293
  circuit.compose(source_reflection.inverse(), inplace=True)
293
294
  circuit.compose(source_shift, inplace=True)
294
- circuit.global_phase += -np.log(shift_phase_shift).imag
295
- circuit.global_phase += -np.log(reflection_phase_shift).imag
295
+ circuit.global_phase -= cmath.phase(shift_phase_shift)
296
+ circuit.global_phase -= cmath.phase(reflection_phase_shift)
296
297
 
297
298
  circuit.compose(affix_circuit, inplace=True)
298
299
 
@@ -230,6 +230,7 @@ class XXDecomposer:
230
230
  unitary: Operator | np.ndarray,
231
231
  basis_fidelity: dict | float | None = None,
232
232
  approximate: bool = True,
233
+ use_dag: bool = False,
233
234
  ) -> QuantumCircuit:
234
235
  r"""
235
236
  Fashions a circuit which (perhaps approximately) models the special unitary operation
@@ -246,6 +247,8 @@ class XXDecomposer:
246
247
  interpreted as ``{pi: f, pi/2: f/2, pi/3: f/3}``.
247
248
  If given, overrides the basis_fidelity given at init.
248
249
  approximate (bool): Approximates if basis fidelities are less than 1.0 .
250
+ use_dag (bool): If true a :class:`.DAGCircuit` is returned instead of a
251
+ :class:`QuantumCircuit` when this class is called.
249
252
 
250
253
  Returns:
251
254
  QuantumCircuit: Synthesized circuit.
@@ -279,7 +282,7 @@ class XXDecomposer:
279
282
  and self.backup_optimizer is not None
280
283
  ):
281
284
  pi2_fidelity = 1 - strength_to_infidelity[np.pi / 2]
282
- return self.backup_optimizer(unitary, basis_fidelity=pi2_fidelity)
285
+ return self.backup_optimizer(unitary, basis_fidelity=pi2_fidelity, use_dag=use_dag)
283
286
 
284
287
  # change to positive canonical coordinates
285
288
  if weyl_decomposition.c >= -EPSILON:
@@ -314,5 +317,8 @@ class XXDecomposer:
314
317
  circ.append(UnitaryGate(weyl_decomposition.K1l), [1])
315
318
 
316
319
  circ = self._decomposer1q(circ)
320
+ if use_dag:
321
+ from qiskit.converters import circuit_to_dag
317
322
 
323
+ return circuit_to_dag(circ, copy_operations=False)
318
324
  return circ
@@ -108,7 +108,7 @@ A basic usage of the AQC algorithm should consist of the following steps::
108
108
  unitary = ...
109
109
 
110
110
  # Define a number of qubits for the algorithm, at least 3 qubits
111
- num_qubits = int(round(np.log2(unitary.shape[0])))
111
+ num_qubits = round(math.log2(unitary.shape[0]))
112
112
 
113
113
  # Choose a layout of the CNOT structure for the approximate circuit, e.g. ``spin`` for
114
114
  # a linear layout.
@@ -13,6 +13,7 @@
13
13
  These are the CNOT structure methods: anything that you need for creating CNOT structures.
14
14
  """
15
15
  import logging
16
+ import math
16
17
 
17
18
  import numpy as np
18
19
 
@@ -34,7 +35,7 @@ def _lower_limit(num_qubits: int) -> int:
34
35
  Returns:
35
36
  lower limit on the number of CNOT units.
36
37
  """
37
- num_cnots = round(np.ceil((4**num_qubits - 3 * num_qubits - 1) / 4.0))
38
+ num_cnots = math.ceil((4**num_qubits - 3 * num_qubits - 1) / 4.0)
38
39
  return num_cnots
39
40
 
40
41
 
@@ -14,6 +14,7 @@
14
14
  Implementation of the fast objective function class.
15
15
  """
16
16
 
17
+ import math
17
18
  import warnings
18
19
  import numpy as np
19
20
 
@@ -110,7 +111,7 @@ class FastCNOTUnitObjective(CNOTUnitObjective):
110
111
  # If thetas are the same as used for objective value calculation
111
112
  # before calling this function, then we re-use the computations,
112
113
  # otherwise we have to re-compute the objective.
113
- tol = float(np.sqrt(np.finfo(float).eps))
114
+ tol = math.sqrt(np.finfo(float).eps)
114
115
  if not np.allclose(param_values, self._circ_thetas, atol=tol, rtol=tol):
115
116
  self.objective(param_values)
116
117
  warnings.warn("gradient is computed before the objective")
@@ -15,6 +15,7 @@ Quantum Shannon Decomposition.
15
15
  Method is described in arXiv:quant-ph/0406176.
16
16
  """
17
17
  from __future__ import annotations
18
+ import math
18
19
  from typing import Callable
19
20
  import scipy
20
21
  import numpy as np
@@ -93,7 +94,7 @@ def qs_decomposition(
93
94
  """
94
95
  # _depth (int): Internal use parameter to track recursion depth.
95
96
  dim = mat.shape[0]
96
- nqubits = int(np.log2(dim))
97
+ nqubits = int(math.log2(dim))
97
98
  if np.allclose(np.identity(dim), mat):
98
99
  return QuantumCircuit(nqubits)
99
100
  if dim == 2:
@@ -185,7 +186,7 @@ def _demultiplex(um0, um1, opt_a1=False, opt_a2=False, *, _depth=0):
185
186
  QuantumCircuit: decomposed circuit
186
187
  """
187
188
  dim = um0.shape[0] + um1.shape[0] # these should be same dimension
188
- nqubits = int(np.log2(dim))
189
+ nqubits = int(math.log2(dim))
189
190
  um0um1 = um0 @ um1.T.conjugate()
190
191
  if is_hermitian_matrix(um0um1):
191
192
  eigvals, vmat = scipy.linalg.eigh(um0um1)
@@ -799,7 +799,7 @@ circuit repeatedly will in general result in a distribution of circuit depths an
799
799
  at the output.
800
800
 
801
801
  In order to highlight this, we run a GHZ circuit 100 times, using a "bad" (disconnected)
802
- `initial_layout`:
802
+ ``initial_layout`` in a heavy hex coupling map:
803
803
 
804
804
  .. plot::
805
805
 
@@ -816,18 +816,22 @@ In order to highlight this, we run a GHZ circuit 100 times, using a "bad" (disco
816
816
  import matplotlib.pyplot as plt
817
817
  from qiskit import QuantumCircuit, transpile
818
818
  from qiskit.providers.fake_provider import GenericBackendV2
819
- backend = GenericBackendV2(16)
819
+ from qiskit.transpiler import CouplingMap
820
+
821
+ coupling_map = CouplingMap.from_heavy_hex(3)
822
+ backend = GenericBackendV2(coupling_map.size(), coupling_map=coupling_map)
820
823
 
821
824
  ghz = QuantumCircuit(15)
822
825
  ghz.h(0)
823
826
  ghz.cx(0, range(1, 15))
824
827
 
825
828
  depths = []
826
- for _ in range(100):
829
+ for i in range(100):
827
830
  depths.append(
828
831
  transpile(
829
832
  ghz,
830
833
  backend,
834
+ seed_transpiler=i,
831
835
  layout_method='trivial' # Fixed layout mapped in circuit order
832
836
  ).depth()
833
837
  )
@@ -368,22 +368,91 @@ class Layout:
368
368
  out.add_register(qreg)
369
369
  return out
370
370
 
371
+ def compose(self, other: Layout, qubits: List[Qubit]) -> Layout:
372
+ """Compose this layout with another layout.
373
+
374
+ If this layout represents a mapping from the P-qubits to the positions of the Q-qubits,
375
+ and the other layout represents a mapping from the Q-qubits to the positions of
376
+ the R-qubits, then the composed layout represents a mapping from the P-qubits to the
377
+ positions of the R-qubits.
378
+
379
+ Args:
380
+ other: The existing :class:`.Layout` to compose this :class:`.Layout` with.
381
+ qubits: A list of :class:`.Qubit` objects over which ``other`` is defined,
382
+ used to establish the correspondence between the positions of the ``other``
383
+ qubits and the actual qubits.
384
+
385
+ Returns:
386
+ A new layout object the represents this layout composed with the ``other`` layout.
387
+ """
388
+ other_v2p = other.get_virtual_bits()
389
+ return Layout({virt: other_v2p[qubits[phys]] for virt, phys in self._v2p.items()})
390
+
391
+ def inverse(self, source_qubits: List[Qubit], target_qubits: List[Qubit]):
392
+ """Finds the inverse of this layout.
393
+
394
+ This is possible when the layout is a bijective mapping, however the input
395
+ and the output qubits may be different (in particular, this layout may be
396
+ the mapping from the extended-with-ancillas virtual qubits to physical qubits).
397
+ Thus, if this layout represents a mapping from the P-qubits to the positions
398
+ of the Q-qubits, the inverse layout represents a mapping from the Q-qubits
399
+ to the positions of the P-qubits.
400
+
401
+ Args:
402
+ source_qubits: A list of :class:`.Qubit` objects representing the domain
403
+ of the layout.
404
+ target_qubits: A list of :class:`.Qubit` objects representing the image
405
+ of the layout.
406
+
407
+ Returns:
408
+ A new layout object the represents the inverse of this layout.
409
+ """
410
+ source_qubit_to_position = {q: p for p, q in enumerate(source_qubits)}
411
+ return Layout(
412
+ {
413
+ target_qubits[pos_phys]: source_qubit_to_position[virt]
414
+ for virt, pos_phys in self._v2p.items()
415
+ }
416
+ )
417
+
418
+ def to_permutation(self, qubits: List[Qubit]):
419
+ """Creates a permutation corresponding to this layout.
420
+
421
+ This is possible when the layout is a bijective mapping with the same
422
+ source and target qubits (for instance, a "final_layout" corresponds
423
+ to a permutation of the physical circuit qubits). If this layout is
424
+ a mapping from qubits to their new positions, the resulting permutation
425
+ describes which qubits occupy the positions 0, 1, 2, etc. after
426
+ applying the permutation.
427
+
428
+ For example, suppose that the list of qubits is ``[qr_0, qr_1, qr_2]``,
429
+ and the layout maps ``qr_0`` to ``2``, ``qr_1`` to ``0``, and
430
+ ``qr_2`` to ``1``. In terms of positions in ``qubits``, this maps ``0``
431
+ to ``2``, ``1`` to ``0`` and ``2`` to ``1``, with the corresponding
432
+ permutation being ``[1, 2, 0]``.
433
+ """
434
+
435
+ perm = [None] * len(qubits)
436
+ for i, q in enumerate(qubits):
437
+ pos = self._v2p[q]
438
+ perm[pos] = i
439
+ return perm
440
+
371
441
 
372
442
  @dataclass
373
443
  class TranspileLayout:
374
- r"""Layout attributes from output circuit from transpiler.
444
+ r"""Layout attributes for the output circuit from transpiler.
375
445
 
376
- The transpiler in general is unitary-perserving up to permutations caused
377
- by setting and applying initial layout during the :ref:`layout_stage`
378
- and :class:`~.SwapGate` insertion during the :ref:`routing_stage`. To
379
- provide an interface to reason about these permutations caused by
380
- the :mod:`~qiskit.transpiler`. In general the normal interface to access
381
- and reason about the layout transformations made by the transpiler is to
382
- use the helper methods defined on this class.
446
+ The :mod:`~qiskit.transpiler` is unitary-preserving up to the "initial layout"
447
+ and "final layout" permutations. The initial layout permutation is caused by
448
+ setting and applying the initial layout during the :ref:`layout_stage`.
449
+ The final layout permutation is caused by :class:`~.SwapGate` insertion during
450
+ the :ref:`routing_stage`. This class provides an interface to reason about these
451
+ permutations using a variety of helper methods.
383
452
 
384
- For example, looking at the initial layout, the transpiler can potentially
385
- remap the order of the qubits in your circuit as it fits the circuit to
386
- the target backend. If the input circuit was:
453
+ During the layout stage, the transpiler can potentially remap the order of the
454
+ qubits in the circuit as it fits the circuit to the target backend. For example,
455
+ let the input circuit be:
387
456
 
388
457
  .. plot:
389
458
  :include-source:
@@ -397,7 +466,8 @@ class TranspileLayout:
397
466
  qc.cx(0, 2)
398
467
  qc.draw("mpl")
399
468
 
400
- Then during the layout stage the transpiler reorders the qubits to be:
469
+
470
+ Suppose that during the layout stage the transpiler reorders the qubits to be:
401
471
 
402
472
  .. plot:
403
473
  :include-source:
@@ -410,7 +480,7 @@ class TranspileLayout:
410
480
  qc.cx(2, 0)
411
481
  qc.draw("mpl")
412
482
 
413
- then the output of the :meth:`.initial_virtual_layout` would be
483
+ Then the output of the :meth:`.initial_virtual_layout` method is
414
484
  equivalent to::
415
485
 
416
486
  Layout({
@@ -421,10 +491,11 @@ class TranspileLayout:
421
491
 
422
492
  (it is also this attribute in the :meth:`.QuantumCircuit.draw` and
423
493
  :func:`.circuit_drawer` which is used to display the mapping of qubits to
424
- positions in circuit visualizations post-transpilation)
494
+ positions in circuit visualizations post-transpilation).
425
495
 
426
- Building on this above example for final layout, if the transpiler needed to
427
- insert swap gates during routing so the output circuit became:
496
+ Building on the above example, suppose that during the routing stage
497
+ the transpiler needs to insert swap gates, and the output circuit
498
+ becomes:
428
499
 
429
500
  .. plot:
430
501
  :include-source:
@@ -438,19 +509,19 @@ class TranspileLayout:
438
509
  qc.cx(2, 1)
439
510
  qc.draw("mpl")
440
511
 
441
- then the output of the :meth:`routing_permutation` method would be::
512
+ Then the output of the :meth:`routing_permutation` method is::
442
513
 
443
514
  [1, 0, 2]
444
515
 
445
- which maps the qubits at each position to their final position after any swap
446
- insertions caused by routing.
516
+ which maps positions of qubits before routing to their final positions
517
+ after routing.
447
518
 
448
519
  There are three public attributes associated with the class, however these
449
520
  are mostly provided for backwards compatibility and represent the internal
450
521
  state from the transpiler. They are defined as:
451
522
 
452
523
  * :attr:`initial_layout` - This attribute is used to model the
453
- permutation caused by the :ref:`layout_stage` it contains a
524
+ permutation caused by the :ref:`layout_stage`. It is a
454
525
  :class:`~.Layout` object that maps the input :class:`~.QuantumCircuit`\s
455
526
  :class:`~.circuit.Qubit` objects to the position in the output
456
527
  :class:`.QuantumCircuit.qubits` list.
@@ -461,18 +532,19 @@ class TranspileLayout:
461
532
  :attr:`.QuantumCircuit.qubits` in the original circuit. This
462
533
  is needed when computing the permutation of the :class:`Operator` of
463
534
  the circuit (and used by :meth:`.Operator.from_circuit`).
464
- * :attr:`final_layout` - This is a :class:`~.Layout` object used to
465
- model the output permutation caused ny any :class:`~.SwapGate`\s
466
- inserted into the :class:`~.QuantumCircuit` during the
467
- :ref:`routing_stage`. It maps the output circuit's qubits from
468
- :class:`.QuantumCircuit.qubits` in the output circuit to the final
469
- position after routing. It is **not** a mapping from the original
470
- input circuit's position to the final position at the end of the
471
- transpiled circuit. If you need this you can use the
472
- :meth:`.final_index_layout` to generate this. If this is set to ``None``
473
- this indicates that routing was not run and it can be considered
474
- equivalent to a trivial layout with the qubits from the output circuit's
475
- :attr:`~.QuantumCircuit.qubits` list.
535
+ * :attr:`final_layout` - This attribute is used to model the
536
+ permutation caused by the :ref:`routing_stage`. It is a
537
+ :class:`~.Layout` object that maps the output circuit's qubits from
538
+ :class:`.QuantumCircuit.qubits` in the output circuit to their final
539
+ positions after routing. Importantly, this only represents the
540
+ permutation caused by inserting :class:`~.SwapGate`\s into
541
+ the :class:`~.QuantumCircuit` during the :ref:`routing_stage`.
542
+ It is **not** a mapping from the original input circuit's position
543
+ to the final position at the end of the transpiled circuit.
544
+ If you need this, you can use the :meth:`.final_index_layout` to generate this.
545
+ If :attr:`final_layout` is set to ``None``, this indicates that routing was not
546
+ run, and can be considered equivalent to a trivial layout with the qubits from
547
+ the output circuit's :attr:`~.QuantumCircuit.qubits` list.
476
548
  """
477
549
 
478
550
  initial_layout: Layout
@@ -485,8 +557,8 @@ class TranspileLayout:
485
557
  """Return a :class:`.Layout` object for the initial layout.
486
558
 
487
559
  This returns a mapping of virtual :class:`~.circuit.Qubit` objects in the input
488
- circuit to the physical qubit selected during layout. This is analogous
489
- to the :attr:`.initial_layout` attribute.
560
+ circuit to the positions of the physical qubits selected during layout.
561
+ This is analogous to the :attr:`.initial_layout` attribute.
490
562
 
491
563
  Args:
492
564
  filter_ancillas: If set to ``True`` only qubits in the input circuit
@@ -494,7 +566,7 @@ class TranspileLayout:
494
566
  output circuit will be filtered from the returned object.
495
567
  Returns:
496
568
  A layout object mapping the input circuit's :class:`~.circuit.Qubit`
497
- objects to the selected physical qubits.
569
+ objects to the positions of the selected physical qubits.
498
570
  """
499
571
  if not filter_ancillas:
500
572
  return self.initial_layout
@@ -507,7 +579,7 @@ class TranspileLayout:
507
579
  )
508
580
 
509
581
  def initial_index_layout(self, filter_ancillas: bool = False) -> List[int]:
510
- """Generate an initial layout as an array of integers
582
+ """Generate an initial layout as an array of integers.
511
583
 
512
584
  Args:
513
585
  filter_ancillas: If set to ``True`` any ancilla qubits added
@@ -531,16 +603,15 @@ class TranspileLayout:
531
603
  return output
532
604
 
533
605
  def routing_permutation(self) -> List[int]:
534
- """Generate a final layout as an array of integers
606
+ """Generate a final layout as an array of integers.
535
607
 
536
608
  If there is no :attr:`.final_layout` attribute present then that indicates
537
609
  there was no output permutation caused by routing or other transpiler
538
- transforms. In this case the function will return a list of ``[0, 1, 2, .., n]``
539
- to indicate this
610
+ transforms. In this case the function will return a list of ``[0, 1, 2, .., n]``.
540
611
 
541
612
  Returns:
542
613
  A layout array that maps a position in the array to its new position in the output
543
- circuit
614
+ circuit.
544
615
  """
545
616
  if self.final_layout is None:
546
617
  return list(range(len(self._output_qubit_list)))
@@ -548,9 +619,9 @@ class TranspileLayout:
548
619
  return [virtual_map[virt] for virt in self._output_qubit_list]
549
620
 
550
621
  def final_index_layout(self, filter_ancillas: bool = True) -> List[int]:
551
- """Generate the final layout as an array of integers
622
+ """Generate the final layout as an array of integers.
552
623
 
553
- This method will generate an array of final positions for each qubit in the output circuit.
624
+ This method will generate an array of final positions for each qubit in the input circuit.
554
625
  For example, if you had an input circuit like::
555
626
 
556
627
  qc = QuantumCircuit(3)
@@ -561,18 +632,22 @@ class TranspileLayout:
561
632
  and the output from the transpiler was::
562
633
 
563
634
  tqc = QuantumCircuit(3)
564
- qc.h(2)
565
- qc.cx(2, 1)
566
- qc.swap(0, 1)
567
- qc.cx(2, 1)
635
+ tqc.h(2)
636
+ tqc.cx(2, 1)
637
+ tqc.swap(0, 1)
638
+ tqc.cx(2, 1)
568
639
 
569
- then the return from this function would be a list of::
640
+ then the :meth:`.final_index_layout` method returns::
570
641
 
571
642
  [2, 0, 1]
572
643
 
573
- because qubit 0 in the original circuit's final state is on qubit 3 in the output circuit,
574
- qubit 1 in the original circuit's final state is on qubit 0, and qubit 2's final state is
575
- on qubit. The output list length will be as wide as the input circuit's number of qubits,
644
+ This can be seen as follows. Qubit 0 in the original circuit is mapped to qubit 2
645
+ in the output circuit during the layout stage, which is mapped to qubit 2 during the
646
+ routing stage. Qubit 1 in the original circuit is mapped to qubit 1 in the output
647
+ circuit during the layout stage, which is mapped to qubit 0 during the routing
648
+ stage. Qubit 2 in the original circuit is mapped to qubit 0 in the output circuit
649
+ during the layout stage, which is mapped to qubit 1 during the routing stage.
650
+ The output list length will be as wide as the input circuit's number of qubits,
576
651
  as the output list from this method is for tracking the permutation of qubits in the
577
652
  original circuit caused by the transpiler.
578
653
 
@@ -581,7 +656,7 @@ class TranspileLayout:
581
656
  included in the layout.
582
657
 
583
658
  Returns:
584
- A list of final positions for each input circuit qubit
659
+ A list of final positions for each input circuit qubit.
585
660
  """
586
661
  if self._input_qubit_count is None:
587
662
  # TODO: After there is a way to differentiate the ancilla qubits added by the transpiler
@@ -614,9 +689,9 @@ class TranspileLayout:
614
689
  return qubit_indices
615
690
 
616
691
  def final_virtual_layout(self, filter_ancillas: bool = True) -> Layout:
617
- """Generate the final layout as a :class:`.Layout` object
692
+ """Generate the final layout as a :class:`.Layout` object.
618
693
 
619
- This method will generate an array of final positions for each qubit in the output circuit.
694
+ This method will generate an array of final positions for each qubit in the input circuit.
620
695
  For example, if you had an input circuit like::
621
696
 
622
697
  qc = QuantumCircuit(3)
@@ -627,10 +702,10 @@ class TranspileLayout:
627
702
  and the output from the transpiler was::
628
703
 
629
704
  tqc = QuantumCircuit(3)
630
- qc.h(2)
631
- qc.cx(2, 1)
632
- qc.swap(0, 1)
633
- qc.cx(2, 1)
705
+ tqc.h(2)
706
+ tqc.cx(2, 1)
707
+ tqc.swap(0, 1)
708
+ tqc.cx(2, 1)
634
709
 
635
710
  then the return from this function would be a layout object::
636
711
 
@@ -640,9 +715,13 @@ class TranspileLayout:
640
715
  qc.qubits[2]: 1,
641
716
  })
642
717
 
643
- because qubit 0 in the original circuit's final state is on qubit 3 in the output circuit,
644
- qubit 1 in the original circuit's final state is on qubit 0, and qubit 2's final state is
645
- on qubit. The output list length will be as wide as the input circuit's number of qubits,
718
+ This can be seen as follows. Qubit 0 in the original circuit is mapped to qubit 2
719
+ in the output circuit during the layout stage, which is mapped to qubit 2 during the
720
+ routing stage. Qubit 1 in the original circuit is mapped to qubit 1 in the output
721
+ circuit during the layout stage, which is mapped to qubit 0 during the routing
722
+ stage. Qubit 2 in the original circuit is mapped to qubit 0 in the output circuit
723
+ during the layout stage, which is mapped to qubit 1 during the routing stage.
724
+ The output list length will be as wide as the input circuit's number of qubits,
646
725
  as the output list from this method is for tracking the permutation of qubits in the
647
726
  original circuit caused by the transpiler.
648
727
 
@@ -651,7 +730,7 @@ class TranspileLayout:
651
730
  included in the layout.
652
731
 
653
732
  Returns:
654
- A layout object mapping to the final positions for each qubit
733
+ A layout object mapping to the final positions for each qubit.
655
734
  """
656
735
  res = self.final_index_layout(filter_ancillas=filter_ancillas)
657
736
  pos_to_virt = {v: k for k, v in self.input_qubit_mapping.items()}
@@ -46,6 +46,7 @@ Routing
46
46
  StochasticSwap
47
47
  SabreSwap
48
48
  Commuting2qGateRouter
49
+ StarPreRouting
49
50
 
50
51
  Basis Change
51
52
  ============
@@ -81,11 +82,13 @@ Optimizations
81
82
  Optimize1qGatesSimpleCommutation
82
83
  RemoveDiagonalGatesBeforeMeasure
83
84
  RemoveResetInZeroState
85
+ RemoveFinalReset
84
86
  HoareOptimizer
85
87
  TemplateOptimization
86
88
  EchoRZXWeylDecomposition
87
89
  ResetAfterMeasureSimplification
88
90
  OptimizeCliffords
91
+ ElidePermutations
89
92
  NormalizeRXAngle
90
93
  OptimizeAnnotated
91
94
 
@@ -151,8 +154,10 @@ The synthesis transpiler plugin documentation can be found in the
151
154
  HLSConfig
152
155
  SolovayKitaev
153
156
 
154
- Post Layout (Post transpile qubit selection)
155
- ============================================
157
+ Post Layout
158
+ ===========
159
+
160
+ These are post qubit selection.
156
161
 
157
162
  .. autosummary::
158
163
  :toctree: ../stubs/
@@ -203,6 +208,7 @@ from .routing import LookaheadSwap
203
208
  from .routing import StochasticSwap
204
209
  from .routing import SabreSwap
205
210
  from .routing import Commuting2qGateRouter
211
+ from .routing import StarPreRouting
206
212
 
207
213
  # basis change
208
214
  from .basis import Decompose
@@ -225,6 +231,7 @@ from .optimization import CXCancellation
225
231
  from .optimization import Optimize1qGatesSimpleCommutation
226
232
  from .optimization import OptimizeSwapBeforeMeasure
227
233
  from .optimization import RemoveResetInZeroState
234
+ from .optimization import RemoveFinalReset
228
235
  from .optimization import RemoveDiagonalGatesBeforeMeasure
229
236
  from .optimization import HoareOptimizer
230
237
  from .optimization import TemplateOptimization
@@ -234,6 +241,7 @@ from .optimization import CollectLinearFunctions
234
241
  from .optimization import CollectCliffords
235
242
  from .optimization import ResetAfterMeasureSimplification
236
243
  from .optimization import OptimizeCliffords
244
+ from .optimization import ElidePermutations
237
245
  from .optimization import NormalizeRXAngle
238
246
  from .optimization import OptimizeAnnotated
239
247
 
@@ -97,8 +97,8 @@ class BasisTranslator(TransformationPass):
97
97
 
98
98
  When this error occurs it typically means that either the target basis
99
99
  is not universal or there are additional equivalence rules needed in the
100
- :clas:~.EquivalenceLibrary` instance being used by the
101
- :class:~.BasisTranslator` pass. You can refer to
100
+ :class:`~.EquivalenceLibrary` instance being used by the
101
+ :class:`~.BasisTranslator` pass. You can refer to
102
102
  :ref:`custom_basis_gates` for details on adding custom equivalence rules.
103
103
  """
104
104
 
@@ -148,16 +148,21 @@ class BasisTranslator(TransformationPass):
148
148
 
149
149
  # Names of instructions assumed to supported by any backend.
150
150
  if self._target is None:
151
- basic_instrs = ["measure", "reset", "barrier", "snapshot", "delay"]
151
+ basic_instrs = ["measure", "reset", "barrier", "snapshot", "delay", "store"]
152
152
  target_basis = set(self._target_basis)
153
153
  source_basis = set(self._extract_basis(dag))
154
154
  qargs_local_source_basis = {}
155
155
  else:
156
- basic_instrs = ["barrier", "snapshot"]
156
+ basic_instrs = ["barrier", "snapshot", "store"]
157
157
  target_basis = self._target.keys() - set(self._non_global_operations)
158
158
  source_basis, qargs_local_source_basis = self._extract_basis_target(dag, qarg_indices)
159
159
 
160
160
  target_basis = set(target_basis).union(basic_instrs)
161
+ # If the source basis is a subset of the target basis and we have no circuit
162
+ # instructions on qargs that have non-global operations there is nothing to
163
+ # translate and we can exit early.
164
+ if source_basis.issubset(target_basis) and not qargs_local_source_basis:
165
+ return dag
161
166
 
162
167
  logger.info(
163
168
  "Begin BasisTranslator from source basis %s to target basis %s.",
@@ -63,7 +63,7 @@ class Unroll3qOrMore(TransformationPass):
63
63
 
64
64
  if self.target is not None:
65
65
  # Treat target instructions as global since this pass can be run
66
- # prior to layout and routing we don't have phsyical qubits from
66
+ # prior to layout and routing we don't have physical qubits from
67
67
  # the circuit yet
68
68
  if node.name in self.target:
69
69
  continue