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
@@ -95,8 +95,7 @@ class AlignMeasures(TransformationPass):
95
95
  "Instead, use :class:`~.ConstrainedReschedule`, which performs the same function "
96
96
  "but also supports aligning to additional timing constraints."
97
97
  ),
98
- since="0.21.0",
99
- pending=True,
98
+ since="1.1.0",
100
99
  )
101
100
  def __init__(self, alignment: int = 1):
102
101
  """Create new pass.
@@ -1,6 +1,6 @@
1
1
  # This code is part of Qiskit.
2
2
  #
3
- # (C) Copyright IBM 2021.
3
+ # (C) Copyright IBM 2021, 2024.
4
4
  #
5
5
  # This code is licensed under the Apache License, Version 2.0. You may
6
6
  # obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -14,6 +14,7 @@
14
14
  from qiskit.circuit.delay import Delay
15
15
  from qiskit.dagcircuit import DAGCircuit
16
16
  from qiskit.transpiler.basepasses import AnalysisPass
17
+ from qiskit.transpiler import Target
17
18
 
18
19
 
19
20
  class InstructionDurationCheck(AnalysisPass):
@@ -28,11 +29,7 @@ class InstructionDurationCheck(AnalysisPass):
28
29
  of the hardware alignment constraints, which is true in general.
29
30
  """
30
31
 
31
- def __init__(
32
- self,
33
- acquire_alignment: int = 1,
34
- pulse_alignment: int = 1,
35
- ):
32
+ def __init__(self, acquire_alignment: int = 1, pulse_alignment: int = 1, target: Target = None):
36
33
  """Create new duration validation pass.
37
34
 
38
35
  The alignment values depend on the control electronics of your quantum processor.
@@ -42,10 +39,16 @@ class InstructionDurationCheck(AnalysisPass):
42
39
  trigger acquisition instruction in units of ``dt``.
43
40
  pulse_alignment: Integer number representing the minimum time resolution to
44
41
  trigger gate instruction in units of ``dt``.
42
+ target: The :class:`~.Target` representing the target backend, if
43
+ ``target`` is specified then this argument will take
44
+ precedence and ``acquire_alignment`` and ``pulse_alignment`` will be ignored.
45
45
  """
46
46
  super().__init__()
47
47
  self.acquire_align = acquire_alignment
48
48
  self.pulse_align = pulse_alignment
49
+ if target is not None:
50
+ self.acquire_align = target.acquire_alignment
51
+ self.pulse_align = target.pulse_alignment
49
52
 
50
53
  def run(self, dag: DAGCircuit):
51
54
  """Run duration validation passes.
@@ -16,6 +16,7 @@ from qiskit.dagcircuit import DAGCircuit
16
16
  from qiskit.pulse import Play
17
17
  from qiskit.transpiler.basepasses import AnalysisPass
18
18
  from qiskit.transpiler.exceptions import TranspilerError
19
+ from qiskit.transpiler import Target
19
20
 
20
21
 
21
22
  class ValidatePulseGates(AnalysisPass):
@@ -43,6 +44,7 @@ class ValidatePulseGates(AnalysisPass):
43
44
  self,
44
45
  granularity: int = 1,
45
46
  min_length: int = 1,
47
+ target: Target = None,
46
48
  ):
47
49
  """Create new pass.
48
50
 
@@ -53,10 +55,16 @@ class ValidatePulseGates(AnalysisPass):
53
55
  min_length: Integer number representing the minimum data point length to
54
56
  define the pulse gate in units of ``dt``. This value depends on
55
57
  the control electronics of your quantum processor.
58
+ target: The :class:`~.Target` representing the target backend, if
59
+ ``target`` is specified then this argument will take
60
+ precedence and ``granularity`` and ``min_length`` will be ignored.
56
61
  """
57
62
  super().__init__()
58
63
  self.granularity = granularity
59
64
  self.min_length = min_length
65
+ if target is not None:
66
+ self.granularity = target.granularity
67
+ self.min_length = target.min_length
60
68
 
61
69
  def run(self, dag: DAGCircuit):
62
70
  """Run the pulse gate validation attached to ``dag``.
@@ -1,6 +1,6 @@
1
1
  # This code is part of Qiskit.
2
2
  #
3
- # (C) Copyright IBM 2022.
3
+ # (C) Copyright IBM 2022, 2024.
4
4
  #
5
5
  # This code is licensed under the Apache License, Version 2.0. You may
6
6
  # obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -17,9 +17,11 @@ from collections.abc import Generator
17
17
  from qiskit.circuit.gate import Gate
18
18
  from qiskit.circuit.delay import Delay
19
19
  from qiskit.circuit.measure import Measure
20
+ from qiskit.circuit.reset import Reset
20
21
  from qiskit.dagcircuit import DAGCircuit, DAGOpNode, DAGOutNode
21
22
  from qiskit.transpiler.basepasses import AnalysisPass
22
23
  from qiskit.transpiler.exceptions import TranspilerError
24
+ from qiskit.transpiler import Target
23
25
 
24
26
 
25
27
  class ConstrainedReschedule(AnalysisPass):
@@ -63,6 +65,7 @@ class ConstrainedReschedule(AnalysisPass):
63
65
  self,
64
66
  acquire_alignment: int = 1,
65
67
  pulse_alignment: int = 1,
68
+ target: Target = None,
66
69
  ):
67
70
  """Create new rescheduler pass.
68
71
 
@@ -73,10 +76,16 @@ class ConstrainedReschedule(AnalysisPass):
73
76
  trigger acquisition instruction in units of ``dt``.
74
77
  pulse_alignment: Integer number representing the minimum time resolution to
75
78
  trigger gate instruction in units of ``dt``.
79
+ target: The :class:`~.Target` representing the target backend, if
80
+ ``target`` is specified then this argument will take
81
+ precedence and ``acquire_alignment`` and ``pulse_alignment`` will be ignored.
76
82
  """
77
83
  super().__init__()
78
84
  self.acquire_align = acquire_alignment
79
85
  self.pulse_align = pulse_alignment
86
+ if target is not None:
87
+ self.acquire_align = target.acquire_alignment
88
+ self.pulse_align = target.pulse_alignment
80
89
 
81
90
  @classmethod
82
91
  def _get_next_gate(cls, dag: DAGCircuit, node: DAGOpNode) -> Generator[DAGOpNode, None, None]:
@@ -113,7 +122,7 @@ class ConstrainedReschedule(AnalysisPass):
113
122
 
114
123
  if isinstance(node.op, Gate):
115
124
  alignment = self.pulse_align
116
- elif isinstance(node.op, Measure):
125
+ elif isinstance(node.op, (Measure, Reset)):
117
126
  alignment = self.acquire_align
118
127
  elif isinstance(node.op, Delay) or getattr(node.op, "_directive", False):
119
128
  # Directive or delay. These can start at arbitrary time.
@@ -135,7 +144,7 @@ class ConstrainedReschedule(AnalysisPass):
135
144
  # Compute shifted t1 of this node separately for qreg and creg
136
145
  new_t1q = this_t0 + node.op.duration
137
146
  this_qubits = set(node.qargs)
138
- if isinstance(node.op, Measure):
147
+ if isinstance(node.op, (Measure, Reset)):
139
148
  # creg access ends at the end of instruction
140
149
  new_t1c = new_t1q
141
150
  this_clbits = set(node.cargs)
@@ -153,7 +162,7 @@ class ConstrainedReschedule(AnalysisPass):
153
162
  # Compute next node start time separately for qreg and creg
154
163
  next_t0q = node_start_time[next_node]
155
164
  next_qubits = set(next_node.qargs)
156
- if isinstance(next_node.op, Measure):
165
+ if isinstance(next_node.op, (Measure, Reset)):
157
166
  # creg access starts after write latency
158
167
  next_t0c = next_t0q + clbit_write_latency
159
168
  next_clbits = set(next_node.cargs)
@@ -38,8 +38,7 @@ class ASAPSchedule(BaseSchedulerTransform):
38
38
  "Instead, use :class:`~.ASAPScheduleAnalysis`, which is an "
39
39
  "analysis pass that requires a padding pass to later modify the circuit."
40
40
  ),
41
- since="0.21.0",
42
- pending=True,
41
+ since="1.1.0",
43
42
  )
44
43
  def __init__(self, *args, **kwargs):
45
44
  super().__init__(*args, **kwargs)
@@ -11,11 +11,13 @@
11
11
  # that they have been altered from the originals.
12
12
 
13
13
  """Base circuit scheduling pass."""
14
+ import warnings
15
+
14
16
  from qiskit.transpiler import InstructionDurations
15
17
  from qiskit.transpiler.basepasses import TransformationPass
16
18
  from qiskit.transpiler.passes.scheduling.time_unit_conversion import TimeUnitConversion
17
- from qiskit.dagcircuit import DAGOpNode, DAGCircuit
18
- from qiskit.circuit import Delay, Gate
19
+ from qiskit.dagcircuit import DAGOpNode, DAGCircuit, DAGOutNode
20
+ from qiskit.circuit import Delay, Gate, Measure, Reset
19
21
  from qiskit.circuit.parameterexpression import ParameterExpression
20
22
  from qiskit.transpiler.exceptions import TranspilerError
21
23
  from qiskit.transpiler.target import Target
@@ -269,6 +271,23 @@ class BaseSchedulerTransform(TransformationPass):
269
271
  else:
270
272
  duration = node.op.duration
271
273
 
274
+ if isinstance(node.op, Reset):
275
+ warnings.warn(
276
+ "Qiskit scheduler assumes Reset works similarly to Measure instruction. "
277
+ "Actual behavior depends on the control system of your quantum backend. "
278
+ "Your backend may provide a plugin scheduler pass."
279
+ )
280
+ elif isinstance(node.op, Measure):
281
+ is_mid_circuit = not any(
282
+ isinstance(x, DAGOutNode) for x in dag.quantum_successors(node)
283
+ )
284
+ if is_mid_circuit:
285
+ warnings.warn(
286
+ "Qiskit scheduler assumes mid-circuit measurement works as a standard instruction. "
287
+ "Actual backend may apply custom scheduling. "
288
+ "Your backend may provide a plugin scheduler pass."
289
+ )
290
+
272
291
  if isinstance(duration, ParameterExpression):
273
292
  raise TranspilerError(
274
293
  f"Parameterized duration ({duration}) "
@@ -1,6 +1,6 @@
1
1
  # This code is part of Qiskit.
2
2
  #
3
- # (C) Copyright IBM 2021.
3
+ # (C) Copyright IBM 2021, 2024.
4
4
  #
5
5
  # This code is licensed under the Apache License, Version 2.0. You may
6
6
  # obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -20,6 +20,7 @@ from qiskit.circuit.library.standard_gates import IGate, UGate, U3Gate
20
20
  from qiskit.dagcircuit import DAGOpNode, DAGInNode
21
21
  from qiskit.quantum_info.operators.predicates import matrix_equal
22
22
  from qiskit.synthesis.one_qubit import OneQubitEulerDecomposer
23
+ from qiskit.transpiler import InstructionDurations
23
24
  from qiskit.transpiler.passes.optimization import Optimize1qGates
24
25
  from qiskit.transpiler.basepasses import TransformationPass
25
26
  from qiskit.transpiler.exceptions import TranspilerError
@@ -109,8 +110,7 @@ class DynamicalDecoupling(TransformationPass):
109
110
  "Instead, use :class:`~.PadDynamicalDecoupling`, which performs the same "
110
111
  "function but requires scheduling and alignment analysis passes to run prior to it."
111
112
  ),
112
- since="0.21.0",
113
- pending=True,
113
+ since="1.1.0",
114
114
  )
115
115
  def __init__(
116
116
  self, durations, dd_sequence, qubits=None, spacing=None, skip_reset_qubits=True, target=None
@@ -169,6 +169,8 @@ class DynamicalDecoupling(TransformationPass):
169
169
  if dag.duration is None:
170
170
  raise TranspilerError("DD runs after circuit is scheduled.")
171
171
 
172
+ durations = self._update_inst_durations(dag)
173
+
172
174
  num_pulses = len(self._dd_sequence)
173
175
  sequence_gphase = 0
174
176
  if num_pulses != 1:
@@ -209,7 +211,7 @@ class DynamicalDecoupling(TransformationPass):
209
211
  for index, gate in enumerate(self._dd_sequence):
210
212
  gate = gate.to_mutable()
211
213
  self._dd_sequence[index] = gate
212
- gate.duration = self._durations.get(gate, physical_qubit)
214
+ gate.duration = durations.get(gate, physical_qubit)
213
215
 
214
216
  dd_sequence_duration += gate.duration
215
217
  index_sequence_duration_map[physical_qubit] = dd_sequence_duration
@@ -278,6 +280,26 @@ class DynamicalDecoupling(TransformationPass):
278
280
 
279
281
  return new_dag
280
282
 
283
+ def _update_inst_durations(self, dag):
284
+ """Update instruction durations with circuit information. If the dag contains gate
285
+ calibrations and no instruction durations were provided through the target or as a
286
+ standalone input, the circuit calibration durations will be used.
287
+ The priority order for instruction durations is: target > standalone > circuit.
288
+ """
289
+ circ_durations = InstructionDurations()
290
+
291
+ if dag.calibrations:
292
+ cal_durations = []
293
+ for gate, gate_cals in dag.calibrations.items():
294
+ for (qubits, parameters), schedule in gate_cals.items():
295
+ cal_durations.append((gate, qubits, parameters, schedule.duration))
296
+ circ_durations.update(cal_durations, circ_durations.dt)
297
+
298
+ if self._durations is not None:
299
+ circ_durations.update(self._durations, getattr(self._durations, "dt", None))
300
+
301
+ return circ_durations
302
+
281
303
  def __gate_supported(self, gate: Gate, qarg: int) -> bool:
282
304
  """A gate is supported on the qubit (qarg) or not."""
283
305
  if self._target is None or self._target.instruction_supported(gate.name, qargs=(qarg,)):
@@ -1,6 +1,6 @@
1
1
  # This code is part of Qiskit.
2
2
  #
3
- # (C) Copyright IBM 2021.
3
+ # (C) Copyright IBM 2021, 2024.
4
4
  #
5
5
  # This code is licensed under the Apache License, Version 2.0. You may
6
6
  # obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -179,9 +179,31 @@ class PadDynamicalDecoupling(BasePadding):
179
179
  f"{gate.name} in dd_sequence is not supported in the target"
180
180
  )
181
181
 
182
+ def _update_inst_durations(self, dag):
183
+ """Update instruction durations with circuit information. If the dag contains gate
184
+ calibrations and no instruction durations were provided through the target or as a
185
+ standalone input, the circuit calibration durations will be used.
186
+ The priority order for instruction durations is: target > standalone > circuit.
187
+ """
188
+ circ_durations = InstructionDurations()
189
+
190
+ if dag.calibrations:
191
+ cal_durations = []
192
+ for gate, gate_cals in dag.calibrations.items():
193
+ for (qubits, parameters), schedule in gate_cals.items():
194
+ cal_durations.append((gate, qubits, parameters, schedule.duration))
195
+ circ_durations.update(cal_durations, circ_durations.dt)
196
+
197
+ if self._durations is not None:
198
+ circ_durations.update(self._durations, getattr(self._durations, "dt", None))
199
+
200
+ return circ_durations
201
+
182
202
  def _pre_runhook(self, dag: DAGCircuit):
183
203
  super()._pre_runhook(dag)
184
204
 
205
+ durations = self._update_inst_durations(dag)
206
+
185
207
  num_pulses = len(self._dd_sequence)
186
208
 
187
209
  # Check if physical circuit is given
@@ -245,7 +267,7 @@ class PadDynamicalDecoupling(BasePadding):
245
267
  f"is not acceptable in {self.__class__.__name__} pass."
246
268
  )
247
269
  except KeyError:
248
- gate_length = self._durations.get(gate, physical_index)
270
+ gate_length = durations.get(gate, physical_index)
249
271
  sequence_lengths.append(gate_length)
250
272
  # Update gate duration. This is necessary for current timeline drawer, i.e. scheduled.
251
273
  gate = gate.to_mutable()
@@ -1,6 +1,6 @@
1
1
  # This code is part of Qiskit.
2
2
  #
3
- # (C) Copyright IBM 2021.
3
+ # (C) Copyright IBM 2021, 2024.
4
4
  #
5
5
  # This code is licensed under the Apache License, Version 2.0. You may
6
6
  # obtain a copy of this license in the LICENSE.txt file in the root directory
@@ -51,6 +51,7 @@ class TimeUnitConversion(TransformationPass):
51
51
  self.inst_durations = inst_durations or InstructionDurations()
52
52
  if target is not None:
53
53
  self.inst_durations = target.durations()
54
+ self._durations_provided = inst_durations is not None or target is not None
54
55
 
55
56
  def run(self, dag: DAGCircuit):
56
57
  """Run the TimeUnitAnalysis pass on `dag`.
@@ -64,8 +65,11 @@ class TimeUnitConversion(TransformationPass):
64
65
  Raises:
65
66
  TranspilerError: if the units are not unifiable
66
67
  """
68
+
69
+ inst_durations = self._update_inst_durations(dag)
70
+
67
71
  # Choose unit
68
- if self.inst_durations.dt is not None:
72
+ if inst_durations.dt is not None:
69
73
  time_unit = "dt"
70
74
  else:
71
75
  # Check what units are used in delays and other instructions: dt or SI or mixed
@@ -75,7 +79,7 @@ class TimeUnitConversion(TransformationPass):
75
79
  "Fail to unify time units in delays. SI units "
76
80
  "and dt unit must not be mixed when dt is not supplied."
77
81
  )
78
- units_other = self.inst_durations.units_used()
82
+ units_other = inst_durations.units_used()
79
83
  if self._unified(units_other) == "mixed":
80
84
  raise TranspilerError(
81
85
  "Fail to unify time units in instruction_durations. SI units "
@@ -96,7 +100,7 @@ class TimeUnitConversion(TransformationPass):
96
100
  # Make units consistent
97
101
  for node in dag.op_nodes():
98
102
  try:
99
- duration = self.inst_durations.get(
103
+ duration = inst_durations.get(
100
104
  node.op, [dag.find_bit(qarg).index for qarg in node.qargs], unit=time_unit
101
105
  )
102
106
  except TranspilerError:
@@ -108,6 +112,26 @@ class TimeUnitConversion(TransformationPass):
108
112
  self.property_set["time_unit"] = time_unit
109
113
  return dag
110
114
 
115
+ def _update_inst_durations(self, dag):
116
+ """Update instruction durations with circuit information. If the dag contains gate
117
+ calibrations and no instruction durations were provided through the target or as a
118
+ standalone input, the circuit calibration durations will be used.
119
+ The priority order for instruction durations is: target > standalone > circuit.
120
+ """
121
+ circ_durations = InstructionDurations()
122
+
123
+ if dag.calibrations:
124
+ cal_durations = []
125
+ for gate, gate_cals in dag.calibrations.items():
126
+ for (qubits, parameters), schedule in gate_cals.items():
127
+ cal_durations.append((gate, qubits, parameters, schedule.duration))
128
+ circ_durations.update(cal_durations, circ_durations.dt)
129
+
130
+ if self._durations_provided:
131
+ circ_durations.update(self.inst_durations, getattr(self.inst_durations, "dt", None))
132
+
133
+ return circ_durations
134
+
111
135
  @staticmethod
112
136
  def _units_used_in_delays(dag: DAGCircuit) -> Set[str]:
113
137
  units_used = set()
@@ -20,7 +20,7 @@ AQC Synthesis Plugin (in :mod:`qiskit.transpiler.passes.synthesis.aqc_plugin`)
20
20
  AQCSynthesisPlugin
21
21
  """
22
22
  from functools import partial
23
- import numpy as np
23
+ import math
24
24
 
25
25
  from qiskit.converters import circuit_to_dag
26
26
  from qiskit.transpiler.passes.synthesis.plugin import UnitarySynthesisPlugin
@@ -118,7 +118,7 @@ class AQCSynthesisPlugin(UnitarySynthesisPlugin):
118
118
  from qiskit.synthesis.unitary.aqc.cnot_unit_circuit import CNOTUnitCircuit
119
119
  from qiskit.synthesis.unitary.aqc.fast_gradient.fast_gradient import FastCNOTUnitObjective
120
120
 
121
- num_qubits = int(round(np.log2(unitary.shape[0])))
121
+ num_qubits = round(math.log2(unitary.shape[0]))
122
122
 
123
123
  config = options.get("config") or {}
124
124
 
@@ -133,8 +133,9 @@ Permutation Synthesis
133
133
  TokenSwapperSynthesisPermutation
134
134
  """
135
135
 
136
- from typing import Optional, Union, List, Tuple
136
+ from typing import Optional, Union, List, Tuple, Callable
137
137
 
138
+ import numpy as np
138
139
  import rustworkx as rx
139
140
 
140
141
  from qiskit.circuit.operation import Operation
@@ -142,6 +143,7 @@ from qiskit.converters import circuit_to_dag, dag_to_circuit
142
143
  from qiskit.transpiler.basepasses import TransformationPass
143
144
  from qiskit.circuit.quantumcircuit import QuantumCircuit
144
145
  from qiskit.circuit import ControlFlowOp, ControlledGate, EquivalenceLibrary
146
+ from qiskit.circuit.library import LinearFunction
145
147
  from qiskit.transpiler.passes.utils import control_flow
146
148
  from qiskit.transpiler.target import Target
147
149
  from qiskit.transpiler.coupling import CouplingMap
@@ -163,7 +165,12 @@ from qiskit.synthesis.clifford import (
163
165
  synth_clifford_ag,
164
166
  synth_clifford_bm,
165
167
  )
166
- from qiskit.synthesis.linear import synth_cnot_count_full_pmh, synth_cnot_depth_line_kms
168
+ from qiskit.synthesis.linear import (
169
+ synth_cnot_count_full_pmh,
170
+ synth_cnot_depth_line_kms,
171
+ calc_inverse_matrix,
172
+ )
173
+ from qiskit.synthesis.linear.linear_circuits_utils import transpose_cx_circ
167
174
  from qiskit.synthesis.permutation import (
168
175
  synth_permutation_basic,
169
176
  synth_permutation_acg,
@@ -220,16 +227,34 @@ class HLSConfig:
220
227
  :ref:`using-high-level-synthesis-plugins`.
221
228
  """
222
229
 
223
- def __init__(self, use_default_on_unspecified=True, **kwargs):
230
+ def __init__(
231
+ self,
232
+ use_default_on_unspecified: bool = True,
233
+ plugin_selection: str = "sequential",
234
+ plugin_evaluation_fn: Optional[Callable[[QuantumCircuit], int]] = None,
235
+ **kwargs,
236
+ ):
224
237
  """Creates a high-level-synthesis config.
225
238
 
226
239
  Args:
227
- use_default_on_unspecified (bool): if True, every higher-level-object without an
240
+ use_default_on_unspecified: if True, every higher-level-object without an
228
241
  explicitly specified list of methods will be synthesized using the "default"
229
242
  algorithm if it exists.
243
+ plugin_selection: if set to ``"sequential"`` (default), for every higher-level-object
244
+ the synthesis pass will consider the specified methods sequentially, stopping
245
+ at the first method that is able to synthesize the object. If set to ``"all"``,
246
+ all the specified methods will be considered, and the best synthesized circuit,
247
+ according to ``plugin_evaluation_fn`` will be chosen.
248
+ plugin_evaluation_fn: a callable that evaluates the quality of the synthesized
249
+ quantum circuit; a smaller value means a better circuit. If ``None``, the
250
+ quality of the circuit its size (i.e. the number of gates that it contains).
230
251
  kwargs: a dictionary mapping higher-level-objects to lists of synthesis methods.
231
252
  """
232
253
  self.use_default_on_unspecified = use_default_on_unspecified
254
+ self.plugin_selection = plugin_selection
255
+ self.plugin_evaluation_fn = (
256
+ plugin_evaluation_fn if plugin_evaluation_fn is not None else lambda qc: qc.size()
257
+ )
233
258
  self.methods = {}
234
259
 
235
260
  for key, value in kwargs.items():
@@ -241,9 +266,6 @@ class HLSConfig:
241
266
  self.methods[hls_name] = hls_methods
242
267
 
243
268
 
244
- # ToDo: Do we have a way to specify optimization criteria (e.g., 2q gate count vs. depth)?
245
-
246
-
247
269
  class HighLevelSynthesis(TransformationPass):
248
270
  """Synthesize higher-level objects and unroll custom definitions.
249
271
 
@@ -341,7 +363,7 @@ class HighLevelSynthesis(TransformationPass):
341
363
 
342
364
  # include path for when target exists but target.num_qubits is None (BasicSimulator)
343
365
  if not self._top_level_only and (self._target is None or self._target.num_qubits is None):
344
- basic_insts = {"measure", "reset", "barrier", "snapshot", "delay"}
366
+ basic_insts = {"measure", "reset", "barrier", "snapshot", "delay", "store"}
345
367
  self._device_insts = basic_insts | set(self._basis_gates)
346
368
 
347
369
  def run(self, dag: DAGCircuit) -> DAGCircuit:
@@ -493,6 +515,9 @@ class HighLevelSynthesis(TransformationPass):
493
515
  else:
494
516
  methods = []
495
517
 
518
+ best_decomposition = None
519
+ best_score = np.inf
520
+
496
521
  for method in methods:
497
522
  # There are two ways to specify a synthesis method. The more explicit
498
523
  # way is to specify it as a tuple consisting of a synthesis algorithm and a
@@ -531,11 +556,22 @@ class HighLevelSynthesis(TransformationPass):
531
556
  )
532
557
 
533
558
  # The synthesis methods that are not suited for the given higher-level-object
534
- # will return None, in which case the next method in the list will be used.
559
+ # will return None.
535
560
  if decomposition is not None:
536
- return decomposition
561
+ if self.hls_config.plugin_selection == "sequential":
562
+ # In the "sequential" mode the first successful decomposition is
563
+ # returned.
564
+ best_decomposition = decomposition
565
+ break
537
566
 
538
- return None
567
+ # In the "run everything" mode we update the best decomposition
568
+ # discovered
569
+ current_score = self.hls_config.plugin_evaluation_fn(decomposition)
570
+ if current_score < best_score:
571
+ best_decomposition = decomposition
572
+ best_score = current_score
573
+
574
+ return best_decomposition
539
575
 
540
576
  def _synthesize_annotated_op(self, op: Operation) -> Union[Operation, None]:
541
577
  """
@@ -720,11 +756,43 @@ class KMSSynthesisLinearFunction(HighLevelSynthesisPlugin):
720
756
 
721
757
  This plugin name is :``linear_function.kms`` which can be used as the key on
722
758
  an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
759
+
760
+ The plugin supports the following plugin-specific options:
761
+
762
+ * use_inverted: Indicates whether to run the algorithm on the inverse matrix
763
+ and to invert the synthesized circuit.
764
+ In certain cases this provides a better decomposition than the direct approach.
765
+ * use_transposed: Indicates whether to run the algorithm on the transposed matrix
766
+ and to invert the order of CX gates in the synthesized circuit.
767
+ In certain cases this provides a better decomposition than the direct approach.
768
+
723
769
  """
724
770
 
725
771
  def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
726
772
  """Run synthesis for the given LinearFunction."""
727
- decomposition = synth_cnot_depth_line_kms(high_level_object.linear)
773
+
774
+ if not isinstance(high_level_object, LinearFunction):
775
+ raise TranspilerError(
776
+ "PMHSynthesisLinearFunction only accepts objects of type LinearFunction"
777
+ )
778
+
779
+ use_inverted = options.get("use_inverted", False)
780
+ use_transposed = options.get("use_transposed", False)
781
+
782
+ mat = high_level_object.linear.astype(int)
783
+
784
+ if use_transposed:
785
+ mat = np.transpose(mat)
786
+ if use_inverted:
787
+ mat = calc_inverse_matrix(mat)
788
+
789
+ decomposition = synth_cnot_depth_line_kms(mat)
790
+
791
+ if use_transposed:
792
+ decomposition = transpose_cx_circ(decomposition)
793
+ if use_inverted:
794
+ decomposition = decomposition.inverse()
795
+
728
796
  return decomposition
729
797
 
730
798
 
@@ -733,11 +801,50 @@ class PMHSynthesisLinearFunction(HighLevelSynthesisPlugin):
733
801
 
734
802
  This plugin name is :``linear_function.pmh`` which can be used as the key on
735
803
  an :class:`~.HLSConfig` object to use this method with :class:`~.HighLevelSynthesis`.
804
+
805
+ The plugin supports the following plugin-specific options:
806
+
807
+ * section size: The size of each section used in the Patel–Markov–Hayes algorithm [1].
808
+ * use_inverted: Indicates whether to run the algorithm on the inverse matrix
809
+ and to invert the synthesized circuit.
810
+ In certain cases this provides a better decomposition than the direct approach.
811
+ * use_transposed: Indicates whether to run the algorithm on the transposed matrix
812
+ and to invert the order of CX gates in the synthesized circuit.
813
+ In certain cases this provides a better decomposition than the direct approach.
814
+
815
+ References:
816
+ 1. Patel, Ketan N., Igor L. Markov, and John P. Hayes,
817
+ *Optimal synthesis of linear reversible circuits*,
818
+ Quantum Information & Computation 8.3 (2008): 282-294.
819
+ `arXiv:quant-ph/0302002 [quant-ph] <https://arxiv.org/abs/quant-ph/0302002>`_
736
820
  """
737
821
 
738
822
  def run(self, high_level_object, coupling_map=None, target=None, qubits=None, **options):
739
823
  """Run synthesis for the given LinearFunction."""
740
- decomposition = synth_cnot_count_full_pmh(high_level_object.linear)
824
+
825
+ if not isinstance(high_level_object, LinearFunction):
826
+ raise TranspilerError(
827
+ "PMHSynthesisLinearFunction only accepts objects of type LinearFunction"
828
+ )
829
+
830
+ section_size = options.get("section_size", 2)
831
+ use_inverted = options.get("use_inverted", False)
832
+ use_transposed = options.get("use_transposed", False)
833
+
834
+ mat = high_level_object.linear.astype(int)
835
+
836
+ if use_transposed:
837
+ mat = np.transpose(mat)
838
+ if use_inverted:
839
+ mat = calc_inverse_matrix(mat)
840
+
841
+ decomposition = synth_cnot_count_full_pmh(mat, section_size=section_size)
842
+
843
+ if use_transposed:
844
+ decomposition = transpose_cx_circ(decomposition)
845
+ if use_inverted:
846
+ decomposition = decomposition.inverse()
847
+
741
848
  return decomposition
742
849
 
743
850