qiskit 2.0.3__cp39-abi3-macosx_11_0_arm64.whl → 2.1.0__cp39-abi3-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. qiskit/VERSION.txt +1 -1
  2. qiskit/__init__.py +19 -1
  3. qiskit/_accelerate.abi3.so +0 -0
  4. qiskit/circuit/__init__.py +104 -20
  5. qiskit/circuit/_add_control.py +57 -31
  6. qiskit/circuit/_classical_resource_map.py +4 -0
  7. qiskit/circuit/annotation.py +504 -0
  8. qiskit/circuit/classical/expr/__init__.py +1 -1
  9. qiskit/circuit/classical/expr/expr.py +104 -446
  10. qiskit/circuit/classical/expr/visitors.py +6 -0
  11. qiskit/circuit/classical/types/types.py +7 -130
  12. qiskit/circuit/controlflow/box.py +32 -7
  13. qiskit/circuit/delay.py +11 -9
  14. qiskit/circuit/library/arithmetic/adders/adder.py +4 -4
  15. qiskit/circuit/library/arithmetic/multipliers/multiplier.py +2 -2
  16. qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +8 -4
  17. qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +23 -15
  18. qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +22 -14
  19. qiskit/circuit/library/arithmetic/quadratic_form.py +6 -0
  20. qiskit/circuit/library/arithmetic/weighted_adder.py +43 -24
  21. qiskit/circuit/library/basis_change/qft.py +2 -2
  22. qiskit/circuit/library/blueprintcircuit.py +6 -0
  23. qiskit/circuit/library/boolean_logic/inner_product.py +2 -2
  24. qiskit/circuit/library/boolean_logic/quantum_and.py +2 -2
  25. qiskit/circuit/library/boolean_logic/quantum_or.py +3 -3
  26. qiskit/circuit/library/boolean_logic/quantum_xor.py +2 -2
  27. qiskit/circuit/library/data_preparation/_z_feature_map.py +2 -2
  28. qiskit/circuit/library/data_preparation/_zz_feature_map.py +2 -2
  29. qiskit/circuit/library/data_preparation/pauli_feature_map.py +2 -2
  30. qiskit/circuit/library/fourier_checking.py +2 -2
  31. qiskit/circuit/library/generalized_gates/diagonal.py +5 -1
  32. qiskit/circuit/library/generalized_gates/gms.py +5 -1
  33. qiskit/circuit/library/generalized_gates/linear_function.py +2 -2
  34. qiskit/circuit/library/generalized_gates/permutation.py +5 -1
  35. qiskit/circuit/library/generalized_gates/uc.py +1 -1
  36. qiskit/circuit/library/generalized_gates/unitary.py +21 -2
  37. qiskit/circuit/library/graph_state.py +2 -2
  38. qiskit/circuit/library/grover_operator.py +2 -2
  39. qiskit/circuit/library/hidden_linear_function.py +2 -2
  40. qiskit/circuit/library/iqp.py +2 -2
  41. qiskit/circuit/library/n_local/efficient_su2.py +2 -2
  42. qiskit/circuit/library/n_local/evolved_operator_ansatz.py +1 -1
  43. qiskit/circuit/library/n_local/excitation_preserving.py +7 -9
  44. qiskit/circuit/library/n_local/n_local.py +4 -3
  45. qiskit/circuit/library/n_local/pauli_two_design.py +2 -2
  46. qiskit/circuit/library/n_local/real_amplitudes.py +2 -2
  47. qiskit/circuit/library/n_local/two_local.py +2 -2
  48. qiskit/circuit/library/overlap.py +2 -2
  49. qiskit/circuit/library/pauli_evolution.py +3 -2
  50. qiskit/circuit/library/phase_estimation.py +2 -2
  51. qiskit/circuit/library/standard_gates/dcx.py +11 -12
  52. qiskit/circuit/library/standard_gates/ecr.py +21 -24
  53. qiskit/circuit/library/standard_gates/equivalence_library.py +232 -96
  54. qiskit/circuit/library/standard_gates/global_phase.py +5 -6
  55. qiskit/circuit/library/standard_gates/h.py +22 -45
  56. qiskit/circuit/library/standard_gates/i.py +1 -1
  57. qiskit/circuit/library/standard_gates/iswap.py +13 -31
  58. qiskit/circuit/library/standard_gates/p.py +19 -26
  59. qiskit/circuit/library/standard_gates/r.py +11 -17
  60. qiskit/circuit/library/standard_gates/rx.py +21 -45
  61. qiskit/circuit/library/standard_gates/rxx.py +7 -22
  62. qiskit/circuit/library/standard_gates/ry.py +21 -39
  63. qiskit/circuit/library/standard_gates/ryy.py +13 -28
  64. qiskit/circuit/library/standard_gates/rz.py +18 -35
  65. qiskit/circuit/library/standard_gates/rzx.py +7 -22
  66. qiskit/circuit/library/standard_gates/rzz.py +7 -19
  67. qiskit/circuit/library/standard_gates/s.py +44 -39
  68. qiskit/circuit/library/standard_gates/swap.py +25 -38
  69. qiskit/circuit/library/standard_gates/sx.py +34 -41
  70. qiskit/circuit/library/standard_gates/t.py +18 -27
  71. qiskit/circuit/library/standard_gates/u.py +8 -24
  72. qiskit/circuit/library/standard_gates/u1.py +28 -52
  73. qiskit/circuit/library/standard_gates/u2.py +9 -9
  74. qiskit/circuit/library/standard_gates/u3.py +24 -40
  75. qiskit/circuit/library/standard_gates/x.py +190 -336
  76. qiskit/circuit/library/standard_gates/xx_minus_yy.py +12 -50
  77. qiskit/circuit/library/standard_gates/xx_plus_yy.py +13 -52
  78. qiskit/circuit/library/standard_gates/y.py +19 -23
  79. qiskit/circuit/library/standard_gates/z.py +31 -38
  80. qiskit/circuit/parameter.py +14 -5
  81. qiskit/circuit/parameterexpression.py +109 -75
  82. qiskit/circuit/quantumcircuit.py +172 -99
  83. qiskit/circuit/quantumcircuitdata.py +1 -0
  84. qiskit/circuit/random/__init__.py +37 -2
  85. qiskit/circuit/random/utils.py +445 -56
  86. qiskit/circuit/tools/pi_check.py +5 -13
  87. qiskit/compiler/transpiler.py +1 -1
  88. qiskit/converters/circuit_to_instruction.py +2 -2
  89. qiskit/dagcircuit/dagnode.py +8 -3
  90. qiskit/primitives/__init__.py +2 -2
  91. qiskit/primitives/base/base_estimator.py +2 -2
  92. qiskit/primitives/containers/data_bin.py +0 -3
  93. qiskit/primitives/containers/observables_array.py +192 -108
  94. qiskit/primitives/primitive_job.py +29 -10
  95. qiskit/providers/fake_provider/generic_backend_v2.py +2 -0
  96. qiskit/qasm3/__init__.py +106 -12
  97. qiskit/qasm3/ast.py +15 -1
  98. qiskit/qasm3/exporter.py +59 -36
  99. qiskit/qasm3/printer.py +12 -0
  100. qiskit/qpy/__init__.py +182 -6
  101. qiskit/qpy/binary_io/circuits.py +256 -24
  102. qiskit/qpy/binary_io/parse_sympy_repr.py +5 -0
  103. qiskit/qpy/binary_io/schedules.py +12 -32
  104. qiskit/qpy/binary_io/value.py +36 -18
  105. qiskit/qpy/common.py +11 -3
  106. qiskit/qpy/formats.py +17 -1
  107. qiskit/qpy/interface.py +52 -12
  108. qiskit/qpy/type_keys.py +7 -1
  109. qiskit/quantum_info/__init__.py +10 -0
  110. qiskit/quantum_info/operators/__init__.py +1 -0
  111. qiskit/quantum_info/operators/symplectic/__init__.py +1 -0
  112. qiskit/quantum_info/operators/symplectic/clifford_circuits.py +26 -0
  113. qiskit/quantum_info/operators/symplectic/pauli.py +2 -2
  114. qiskit/result/sampled_expval.py +3 -1
  115. qiskit/synthesis/__init__.py +10 -0
  116. qiskit/synthesis/arithmetic/__init__.py +1 -1
  117. qiskit/synthesis/arithmetic/adders/__init__.py +1 -0
  118. qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +6 -2
  119. qiskit/synthesis/arithmetic/adders/rv_ripple_carry_adder.py +156 -0
  120. qiskit/synthesis/discrete_basis/generate_basis_approximations.py +14 -126
  121. qiskit/synthesis/discrete_basis/solovay_kitaev.py +161 -121
  122. qiskit/synthesis/evolution/lie_trotter.py +10 -7
  123. qiskit/synthesis/evolution/product_formula.py +10 -7
  124. qiskit/synthesis/evolution/qdrift.py +10 -7
  125. qiskit/synthesis/evolution/suzuki_trotter.py +10 -7
  126. qiskit/synthesis/multi_controlled/__init__.py +4 -0
  127. qiskit/synthesis/multi_controlled/mcx_synthesis.py +402 -178
  128. qiskit/synthesis/multi_controlled/multi_control_rotation_gates.py +14 -15
  129. qiskit/synthesis/qft/qft_decompose_lnn.py +7 -25
  130. qiskit/synthesis/unitary/qsd.py +80 -9
  131. qiskit/transpiler/__init__.py +10 -3
  132. qiskit/transpiler/instruction_durations.py +2 -20
  133. qiskit/transpiler/passes/__init__.py +5 -2
  134. qiskit/transpiler/passes/layout/dense_layout.py +26 -6
  135. qiskit/transpiler/passes/layout/disjoint_utils.py +1 -166
  136. qiskit/transpiler/passes/layout/sabre_layout.py +22 -3
  137. qiskit/transpiler/passes/layout/sabre_pre_layout.py +1 -1
  138. qiskit/transpiler/passes/layout/vf2_layout.py +49 -13
  139. qiskit/transpiler/passes/layout/vf2_utils.py +10 -0
  140. qiskit/transpiler/passes/optimization/__init__.py +1 -1
  141. qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +2 -1
  142. qiskit/transpiler/passes/optimization/optimize_clifford_t.py +68 -0
  143. qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +3 -9
  144. qiskit/transpiler/passes/routing/sabre_swap.py +4 -2
  145. qiskit/transpiler/passes/routing/star_prerouting.py +106 -81
  146. qiskit/transpiler/passes/scheduling/__init__.py +1 -1
  147. qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
  148. qiskit/transpiler/passes/scheduling/padding/__init__.py +1 -0
  149. qiskit/transpiler/passes/scheduling/padding/context_aware_dynamical_decoupling.py +876 -0
  150. qiskit/transpiler/passes/synthesis/__init__.py +1 -0
  151. qiskit/transpiler/passes/synthesis/clifford_unitary_synth_plugin.py +123 -0
  152. qiskit/transpiler/passes/synthesis/hls_plugins.py +494 -93
  153. qiskit/transpiler/passes/synthesis/plugin.py +4 -0
  154. qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +27 -22
  155. qiskit/transpiler/passmanager_config.py +3 -0
  156. qiskit/transpiler/preset_passmanagers/builtin_plugins.py +149 -28
  157. qiskit/transpiler/preset_passmanagers/common.py +101 -0
  158. qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +6 -0
  159. qiskit/transpiler/preset_passmanagers/level3.py +2 -2
  160. qiskit/transpiler/target.py +15 -2
  161. qiskit/utils/optionals.py +6 -5
  162. qiskit/visualization/circuit/_utils.py +5 -3
  163. qiskit/visualization/circuit/latex.py +9 -2
  164. qiskit/visualization/circuit/matplotlib.py +26 -4
  165. qiskit/visualization/circuit/qcstyle.py +9 -157
  166. qiskit/visualization/dag/__init__.py +13 -0
  167. qiskit/visualization/dag/dagstyle.py +103 -0
  168. qiskit/visualization/dag/styles/__init__.py +13 -0
  169. qiskit/visualization/dag/styles/color.json +10 -0
  170. qiskit/visualization/dag/styles/plain.json +5 -0
  171. qiskit/visualization/dag_visualization.py +169 -98
  172. qiskit/visualization/style.py +223 -0
  173. {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/METADATA +7 -6
  174. {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/RECORD +178 -169
  175. {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/entry_points.txt +6 -0
  176. qiskit/synthesis/discrete_basis/commutator_decompose.py +0 -265
  177. qiskit/synthesis/discrete_basis/gate_sequence.py +0 -421
  178. {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/WHEEL +0 -0
  179. {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/licenses/LICENSE.txt +0 -0
  180. {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,156 @@
1
+ # This code is part of Qiskit.
2
+ #
3
+ # (C) Copyright IBM 2025.
4
+ #
5
+ # This code is licensed under the Apache License, Version 2.0. You may
6
+ # obtain a copy of this license in the LICENSE.txt file in the root directory
7
+ # of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
8
+ #
9
+ # Any modifications or derivative works of this code must retain this
10
+ # copyright notice, and modified files need to carry a notice indicating
11
+ # that they have been altered from the originals.
12
+
13
+ """Compute the sum of two qubit registers without any ancillary qubits."""
14
+
15
+ from __future__ import annotations
16
+ from math import ceil
17
+ from qiskit.circuit.quantumcircuit import QuantumCircuit
18
+ from qiskit.circuit import QuantumRegister
19
+
20
+
21
+ def _mcx_ladder(n_mcx: int, alpha: int):
22
+ r"""Implements a log-depth MCX ladder circuit as outlined in Algorithm 2 of [1]. The circuit
23
+ relies on log-depth decomposition of MCX gate that uses conditionally clean ancillae of [2].
24
+ Selecting :math:`\alpha=1` creates a CX ladder as shown in Fig. 2 of [1] and selecting
25
+ :math:`\alpha=2` creates a Toffoli ladder as shown in Fig. 3 of [1].
26
+
27
+ Args:
28
+ n_mcx: Number of MCX gates in the ladder.
29
+ alpha: Number of controls per MCX gate.
30
+
31
+ Returns:
32
+ QuantumCircuit: The MCX ladder circuit.
33
+
34
+ References:
35
+ 1. Remaud and Vandaele, Ancilla-free Quantum Adder with Sublinear Depth, 2025.
36
+ `arXiv:2501.16802 <https://arxiv.org/abs/2501.16802>`__
37
+
38
+ 2. Khattar and Gidney, Rise of conditionally clean ancillae for optimizing quantum circuits
39
+ `arXiv:2407.17966 <https://arxiv.org/abs/2407.17966>`__
40
+ """
41
+
42
+ def helper(qubit_indices, alphas) -> list[list[int]]:
43
+ k = len(alphas) + 1
44
+ if k == 1:
45
+ return []
46
+ if k == 2:
47
+ return [qubit_indices[: alphas[0] + 1]]
48
+
49
+ x_bar = [qubit_indices[alphas[0]]]
50
+ alpha_bar = []
51
+ right_pairs = [qubit_indices[0 : alphas[0] + 1]]
52
+ left_pairs = [qubit_indices[alphas[k - 3] : alphas[-1] + 1]]
53
+
54
+ for i in range(1, ceil(k / 2) - 1):
55
+ left_pairs += [qubit_indices[alphas[2 * i - 2] : alphas[2 * i - 1] + 1]]
56
+ right_pairs += [qubit_indices[alphas[2 * i - 1] : alphas[2 * i] + 1]]
57
+ x_bar += (
58
+ qubit_indices[alphas[2 * i - 2] + 1 : alphas[2 * i - 1]]
59
+ + qubit_indices[alphas[2 * i - 1] + 1 : alphas[2 * i] + 1]
60
+ )
61
+ alpha_bar.append(alphas[2 * i] - alphas[0] - i)
62
+
63
+ if k % 2 == 0:
64
+ x_bar += qubit_indices[alphas[k - 4] + 1 : alphas[k - 3] + 1]
65
+ alpha_bar.append(alphas[k - 3] - alphas[0] - int(k / 2) + 2)
66
+
67
+ return left_pairs + helper(x_bar, alpha_bar) + right_pairs
68
+
69
+ n = n_mcx * alpha + 1
70
+ qc = QuantumCircuit(n)
71
+ qubit_indices, alphas = list(range(n)), list(range(alpha, n, alpha))
72
+ mcxs = helper(qubit_indices, alphas)
73
+ for mcx in mcxs:
74
+ qc.mcx(mcx[:-1], mcx[-1])
75
+
76
+ return qc
77
+
78
+
79
+ def adder_ripple_r25(num_qubits: int) -> QuantumCircuit:
80
+ # pylint: disable=line-too-long
81
+ r"""The RV ripple carry adder [1].
82
+ Construct an ancilla-free quantum adder circuit with sublinear depth based on the RV ripple-carry
83
+ adder shown in [1]. The implementation has a depth of :math:`O(\log^2 n)` and uses
84
+ math:`O(n \log n)` gates.
85
+
86
+ As an example, a ripple-carry adder circuit that performs addition on two 4-qubit sized
87
+ registers is as follows:
88
+
89
+ .. parsed-literal::
90
+
91
+ ┌───────────┐ ┌────────┐
92
+ a_0: ─────────────────────────┤0 ├────────────────────┤0 ├───────────────■─────────────────
93
+ ┌────────┐│ │ │ │┌───────────┐ │
94
+ a_1: ──■────────────┤0 ├┤2 ├──■─────────────────┤2 ├┤0 ├──┼────■────────────
95
+ │ │ ││ │ │ │ ││ │ │ │
96
+ a_2: ──┼────■───────┤1 ├┤4 ├──┼────■────────────┤4 ├┤1 LAD_1_dg ├──┼────┼────■───────
97
+ │ │ │ ││ │ │ │ │ ││ │ │ │ │
98
+ a_3: ──┼────┼────■──┤2 ├┤6 ├──┼────┼────■───────┤6 LAD_2 ├┤2 ├──┼────┼────┼────■──
99
+ │ │ │ │ ││ │ │ │ │ │ │└───────────┘┌─┴─┐ │ │ │
100
+ b_0: ──┼────┼────┼──┤ ├┤1 LAD_2_dg ├──┼────┼────┼───────┤1 ├─────────────┤ X ├──┼────┼────┼──
101
+ ┌─┴─┐ │ │ │ LAD_1 ││ │┌─┴─┐ │ │ ┌───┐│ │ ┌───┐ └───┘┌─┴─┐ │ │
102
+ b_1: ┤ X ├──┼────┼──┤ ├┤3 ├┤ X ├──┼────┼──┤ X ├┤3 ├────┤ X ├─────────┤ X ├──┼────┼──
103
+ └───┘┌─┴─┐ │ │ ││ │└───┘┌─┴─┐ │ ├───┤│ │ ├───┤ └───┘┌─┴─┐ │
104
+ b_2: ─────┤ X ├──┼──┤ ├┤5 ├─────┤ X ├──┼──┤ X ├┤5 ├────┤ X ├──────────────┤ X ├──┼──
105
+ └───┘┌─┴─┐│ ││ │ └───┘┌─┴─┐└───┘└────────┘ └───┘ └───┘┌─┴─┐
106
+ b_3: ──────────┤ X ├┤ ├┤7 ├──────────┤ X ├───────────────────────────────────────────┤ X ├
107
+ └───┘│ ││ │ └───┘ └───┘
108
+ cout: ───────────────┤3 ├┤8 ├───────────────────────────────────────────────────────────────
109
+ └────────┘└───────────┘
110
+
111
+ Here *LAD_1* and *LAD_2* are the CX and CCX ladders respectively introduced in [1]. Note that
112
+ in this implementation the input register qubits are ordered as all qubits from
113
+ the first input register, followed by all qubits from the second input register.
114
+
115
+ Args:
116
+ num_qubits: The size of the register.
117
+
118
+ Returns:
119
+ The quantum circuit implementing the RV ripple carry adder.
120
+
121
+ Raises:
122
+ ValueError: If ``num_state_qubits`` is lower than 1.
123
+
124
+ **References:**
125
+
126
+ 1. Remaud and Vandaele, Ancilla-free Quantum Adder with Sublinear Depth, 2025.
127
+ `arXiv:2501.16802 <https://arxiv.org/abs/2501.16802>`__
128
+
129
+ """
130
+
131
+ if num_qubits < 1:
132
+ raise ValueError("The number of qubits must be at least 1.")
133
+
134
+ qr_a = QuantumRegister(num_qubits, "a")
135
+ qr_b = QuantumRegister(num_qubits, "b")
136
+ qr_z = QuantumRegister(1, "cout")
137
+ qc = QuantumCircuit(qr_a, qr_b, qr_z)
138
+
139
+ if num_qubits == 1:
140
+ qc.ccx(qr_a[0], qr_b[0], qr_z[0])
141
+ qc.cx(qr_a[0], qr_b[0])
142
+ return qc
143
+
144
+ ab_interleaved = [q for pair in zip(qr_a, qr_b) for q in pair]
145
+
146
+ qc.cx(qr_a[1:], qr_b[1:])
147
+ qc.compose(_mcx_ladder(num_qubits - 1, 1), qr_a[1:] + qr_z[:], inplace=True)
148
+ qc.compose(_mcx_ladder(num_qubits, 2).inverse(), ab_interleaved + qr_z[:], inplace=True)
149
+ qc.cx(qr_a[1:], qr_b[1:])
150
+ qc.x(qr_b[1 : max(2, num_qubits - 1)])
151
+ qc.compose(_mcx_ladder(num_qubits - 1, 2), ab_interleaved[:-1], inplace=True)
152
+ qc.x(qr_b[1 : max(2, num_qubits - 1)])
153
+ qc.compose(_mcx_ladder(num_qubits - 2, 1).inverse(), qr_a[1:], inplace=True)
154
+ qc.cx(qr_a, qr_b)
155
+
156
+ return qc
@@ -14,112 +14,21 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
- import warnings
18
- import collections
19
- import numpy as np
20
-
21
- import qiskit.circuit.library.standard_gates as gates
22
17
  from qiskit.circuit import Gate
23
- from qiskit.quantum_info.operators.predicates import matrix_equal
24
- from qiskit.utils import optionals
25
-
26
- from .gate_sequence import GateSequence
27
-
28
- Node = collections.namedtuple("Node", ("labels", "sequence", "children"))
29
-
30
- _1q_inverses = {
31
- "i": "i",
32
- "x": "x",
33
- "y": "y",
34
- "z": "z",
35
- "h": "h",
36
- "t": "tdg",
37
- "tdg": "t",
38
- "s": "sdg",
39
- "sdg": "s",
40
- "sx": "sxdg",
41
- "sxdg": "sx",
42
- }
43
-
44
- _1q_gates = {
45
- "i": gates.IGate(),
46
- "x": gates.XGate(),
47
- "y": gates.YGate(),
48
- "z": gates.ZGate(),
49
- "h": gates.HGate(),
50
- "t": gates.TGate(),
51
- "tdg": gates.TdgGate(),
52
- "s": gates.SGate(),
53
- "sdg": gates.SdgGate(),
54
- "sx": gates.SXGate(),
55
- "sxdg": gates.SXdgGate(),
56
- }
57
-
58
-
59
- def _check_candidate(candidate, existing_sequences, tol=1e-10):
60
- if optionals.HAS_SKLEARN:
61
- return _check_candidate_kdtree(candidate, existing_sequences, tol)
62
-
63
- warnings.warn(
64
- "The SolovayKitaev algorithm relies on scikit-learn's KDTree for a "
65
- "fast search over the basis approximations. Without this, we fallback onto a "
66
- "greedy search with is significantly slower. We highly suggest to install "
67
- "scikit-learn to use this feature.",
68
- category=RuntimeWarning,
69
- )
70
- return _check_candidate_greedy(candidate, existing_sequences, tol)
71
-
72
-
73
- def _check_candidate_greedy(candidate, existing_sequences, tol=1e-10):
74
- # do a quick, string-based check if the same sequence already exists
75
- if any(candidate.name == existing.name for existing in existing_sequences):
76
- return False
77
-
78
- for existing in existing_sequences:
79
- if matrix_equal(existing.product, candidate.product, ignore_phase=True, atol=tol):
80
- # is the new sequence less or more efficient?
81
- return len(candidate.gates) < len(existing.gates)
82
- return True
83
-
84
-
85
- @optionals.HAS_SKLEARN.require_in_call
86
- def _check_candidate_kdtree(candidate, existing_sequences, tol=1e-10):
87
- """Check if there's a candidate implementing the same matrix up to ``tol``.
18
+ from qiskit.utils.deprecation import deprecate_func
19
+ from qiskit._accelerate.synthesis.discrete_basis import GateSequence
88
20
 
89
- This uses a k-d tree search and is much faster than the greedy, list-based search.
90
- """
91
- from sklearn.neighbors import KDTree
92
-
93
- # do a quick, string-based check if the same sequence already exists
94
- if any(candidate.name == existing.name for existing in existing_sequences):
95
- return False
96
-
97
- points = np.array([sequence.product.flatten() for sequence in existing_sequences])
98
- candidate = np.array([candidate.product.flatten()])
99
-
100
- kdtree = KDTree(points)
101
- dist, _ = kdtree.query(candidate)
102
-
103
- return dist[0][0] > tol
104
-
105
-
106
- def _process_node(node: Node, basis: list[str], sequences: list[GateSequence]):
107
- inverse_last = _1q_inverses[node.labels[-1]] if node.labels else None
108
-
109
- for label in basis:
110
- if label == inverse_last:
111
- continue
112
-
113
- sequence = node.sequence.copy()
114
- sequence.append(_1q_gates[label])
115
-
116
- if _check_candidate(sequence, sequences):
117
- sequences.append(sequence)
118
- node.children.append(Node(node.labels + (label,), sequence, []))
119
-
120
- return node.children
21
+ from .solovay_kitaev import SolovayKitaevDecomposition
121
22
 
122
23
 
24
+ @deprecate_func(
25
+ since="2.1",
26
+ additional_msg=(
27
+ "Use the SolovayKitaevDecomposition class directly, to generate, store, and load the "
28
+ "basic approximations."
29
+ ),
30
+ pending=True,
31
+ )
123
32
  def generate_basic_approximations(
124
33
  basis_gates: list[str | Gate], depth: int, filename: str | None = None
125
34
  ) -> list[GateSequence]:
@@ -136,30 +45,9 @@ def generate_basic_approximations(
136
45
  Raises:
137
46
  ValueError: If ``basis_gates`` contains an invalid gate identifier.
138
47
  """
139
- basis = []
140
- for gate in basis_gates:
141
- if isinstance(gate, str):
142
- if gate not in _1q_gates:
143
- raise ValueError(f"Invalid gate identifier: {gate}")
144
- basis.append(gate)
145
- else: # gate is a qiskit.circuit.Gate
146
- basis.append(gate.name)
147
-
148
- tree = Node((), GateSequence(), [])
149
- cur_level = [tree]
150
- sequences = [tree.sequence]
151
- for _ in [None] * depth:
152
- next_level = []
153
- for node in cur_level:
154
- next_level.extend(_process_node(node, basis, sequences))
155
- cur_level = next_level
48
+ sk = SolovayKitaevDecomposition(basis_gates=basis_gates, depth=depth)
156
49
 
157
50
  if filename is not None:
158
- data = {}
159
- for sequence in sequences:
160
- gatestring = sequence.name
161
- data[gatestring] = (sequence.product, sequence.global_phase)
162
-
163
- np.save(filename, data)
51
+ sk.save_basic_approximations(filename)
164
52
 
165
- return sequences
53
+ return sk._sk.get_gate_sequences()