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.
- qiskit/VERSION.txt +1 -1
- qiskit/__init__.py +19 -1
- qiskit/_accelerate.abi3.so +0 -0
- qiskit/circuit/__init__.py +104 -20
- qiskit/circuit/_add_control.py +57 -31
- qiskit/circuit/_classical_resource_map.py +4 -0
- qiskit/circuit/annotation.py +504 -0
- qiskit/circuit/classical/expr/__init__.py +1 -1
- qiskit/circuit/classical/expr/expr.py +104 -446
- qiskit/circuit/classical/expr/visitors.py +6 -0
- qiskit/circuit/classical/types/types.py +7 -130
- qiskit/circuit/controlflow/box.py +32 -7
- qiskit/circuit/delay.py +11 -9
- qiskit/circuit/library/arithmetic/adders/adder.py +4 -4
- qiskit/circuit/library/arithmetic/multipliers/multiplier.py +2 -2
- qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +8 -4
- qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +23 -15
- qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +22 -14
- qiskit/circuit/library/arithmetic/quadratic_form.py +6 -0
- qiskit/circuit/library/arithmetic/weighted_adder.py +43 -24
- qiskit/circuit/library/basis_change/qft.py +2 -2
- qiskit/circuit/library/blueprintcircuit.py +6 -0
- qiskit/circuit/library/boolean_logic/inner_product.py +2 -2
- qiskit/circuit/library/boolean_logic/quantum_and.py +2 -2
- qiskit/circuit/library/boolean_logic/quantum_or.py +3 -3
- qiskit/circuit/library/boolean_logic/quantum_xor.py +2 -2
- qiskit/circuit/library/data_preparation/_z_feature_map.py +2 -2
- qiskit/circuit/library/data_preparation/_zz_feature_map.py +2 -2
- qiskit/circuit/library/data_preparation/pauli_feature_map.py +2 -2
- qiskit/circuit/library/fourier_checking.py +2 -2
- qiskit/circuit/library/generalized_gates/diagonal.py +5 -1
- qiskit/circuit/library/generalized_gates/gms.py +5 -1
- qiskit/circuit/library/generalized_gates/linear_function.py +2 -2
- qiskit/circuit/library/generalized_gates/permutation.py +5 -1
- qiskit/circuit/library/generalized_gates/uc.py +1 -1
- qiskit/circuit/library/generalized_gates/unitary.py +21 -2
- qiskit/circuit/library/graph_state.py +2 -2
- qiskit/circuit/library/grover_operator.py +2 -2
- qiskit/circuit/library/hidden_linear_function.py +2 -2
- qiskit/circuit/library/iqp.py +2 -2
- qiskit/circuit/library/n_local/efficient_su2.py +2 -2
- qiskit/circuit/library/n_local/evolved_operator_ansatz.py +1 -1
- qiskit/circuit/library/n_local/excitation_preserving.py +7 -9
- qiskit/circuit/library/n_local/n_local.py +4 -3
- qiskit/circuit/library/n_local/pauli_two_design.py +2 -2
- qiskit/circuit/library/n_local/real_amplitudes.py +2 -2
- qiskit/circuit/library/n_local/two_local.py +2 -2
- qiskit/circuit/library/overlap.py +2 -2
- qiskit/circuit/library/pauli_evolution.py +3 -2
- qiskit/circuit/library/phase_estimation.py +2 -2
- qiskit/circuit/library/standard_gates/dcx.py +11 -12
- qiskit/circuit/library/standard_gates/ecr.py +21 -24
- qiskit/circuit/library/standard_gates/equivalence_library.py +232 -96
- qiskit/circuit/library/standard_gates/global_phase.py +5 -6
- qiskit/circuit/library/standard_gates/h.py +22 -45
- qiskit/circuit/library/standard_gates/i.py +1 -1
- qiskit/circuit/library/standard_gates/iswap.py +13 -31
- qiskit/circuit/library/standard_gates/p.py +19 -26
- qiskit/circuit/library/standard_gates/r.py +11 -17
- qiskit/circuit/library/standard_gates/rx.py +21 -45
- qiskit/circuit/library/standard_gates/rxx.py +7 -22
- qiskit/circuit/library/standard_gates/ry.py +21 -39
- qiskit/circuit/library/standard_gates/ryy.py +13 -28
- qiskit/circuit/library/standard_gates/rz.py +18 -35
- qiskit/circuit/library/standard_gates/rzx.py +7 -22
- qiskit/circuit/library/standard_gates/rzz.py +7 -19
- qiskit/circuit/library/standard_gates/s.py +44 -39
- qiskit/circuit/library/standard_gates/swap.py +25 -38
- qiskit/circuit/library/standard_gates/sx.py +34 -41
- qiskit/circuit/library/standard_gates/t.py +18 -27
- qiskit/circuit/library/standard_gates/u.py +8 -24
- qiskit/circuit/library/standard_gates/u1.py +28 -52
- qiskit/circuit/library/standard_gates/u2.py +9 -9
- qiskit/circuit/library/standard_gates/u3.py +24 -40
- qiskit/circuit/library/standard_gates/x.py +190 -336
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +12 -50
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +13 -52
- qiskit/circuit/library/standard_gates/y.py +19 -23
- qiskit/circuit/library/standard_gates/z.py +31 -38
- qiskit/circuit/parameter.py +14 -5
- qiskit/circuit/parameterexpression.py +109 -75
- qiskit/circuit/quantumcircuit.py +172 -99
- qiskit/circuit/quantumcircuitdata.py +1 -0
- qiskit/circuit/random/__init__.py +37 -2
- qiskit/circuit/random/utils.py +445 -56
- qiskit/circuit/tools/pi_check.py +5 -13
- qiskit/compiler/transpiler.py +1 -1
- qiskit/converters/circuit_to_instruction.py +2 -2
- qiskit/dagcircuit/dagnode.py +8 -3
- qiskit/primitives/__init__.py +2 -2
- qiskit/primitives/base/base_estimator.py +2 -2
- qiskit/primitives/containers/data_bin.py +0 -3
- qiskit/primitives/containers/observables_array.py +192 -108
- qiskit/primitives/primitive_job.py +29 -10
- qiskit/providers/fake_provider/generic_backend_v2.py +2 -0
- qiskit/qasm3/__init__.py +106 -12
- qiskit/qasm3/ast.py +15 -1
- qiskit/qasm3/exporter.py +59 -36
- qiskit/qasm3/printer.py +12 -0
- qiskit/qpy/__init__.py +182 -6
- qiskit/qpy/binary_io/circuits.py +256 -24
- qiskit/qpy/binary_io/parse_sympy_repr.py +5 -0
- qiskit/qpy/binary_io/schedules.py +12 -32
- qiskit/qpy/binary_io/value.py +36 -18
- qiskit/qpy/common.py +11 -3
- qiskit/qpy/formats.py +17 -1
- qiskit/qpy/interface.py +52 -12
- qiskit/qpy/type_keys.py +7 -1
- qiskit/quantum_info/__init__.py +10 -0
- qiskit/quantum_info/operators/__init__.py +1 -0
- qiskit/quantum_info/operators/symplectic/__init__.py +1 -0
- qiskit/quantum_info/operators/symplectic/clifford_circuits.py +26 -0
- qiskit/quantum_info/operators/symplectic/pauli.py +2 -2
- qiskit/result/sampled_expval.py +3 -1
- qiskit/synthesis/__init__.py +10 -0
- qiskit/synthesis/arithmetic/__init__.py +1 -1
- qiskit/synthesis/arithmetic/adders/__init__.py +1 -0
- qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +6 -2
- qiskit/synthesis/arithmetic/adders/rv_ripple_carry_adder.py +156 -0
- qiskit/synthesis/discrete_basis/generate_basis_approximations.py +14 -126
- qiskit/synthesis/discrete_basis/solovay_kitaev.py +161 -121
- qiskit/synthesis/evolution/lie_trotter.py +10 -7
- qiskit/synthesis/evolution/product_formula.py +10 -7
- qiskit/synthesis/evolution/qdrift.py +10 -7
- qiskit/synthesis/evolution/suzuki_trotter.py +10 -7
- qiskit/synthesis/multi_controlled/__init__.py +4 -0
- qiskit/synthesis/multi_controlled/mcx_synthesis.py +402 -178
- qiskit/synthesis/multi_controlled/multi_control_rotation_gates.py +14 -15
- qiskit/synthesis/qft/qft_decompose_lnn.py +7 -25
- qiskit/synthesis/unitary/qsd.py +80 -9
- qiskit/transpiler/__init__.py +10 -3
- qiskit/transpiler/instruction_durations.py +2 -20
- qiskit/transpiler/passes/__init__.py +5 -2
- qiskit/transpiler/passes/layout/dense_layout.py +26 -6
- qiskit/transpiler/passes/layout/disjoint_utils.py +1 -166
- qiskit/transpiler/passes/layout/sabre_layout.py +22 -3
- qiskit/transpiler/passes/layout/sabre_pre_layout.py +1 -1
- qiskit/transpiler/passes/layout/vf2_layout.py +49 -13
- qiskit/transpiler/passes/layout/vf2_utils.py +10 -0
- qiskit/transpiler/passes/optimization/__init__.py +1 -1
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +2 -1
- qiskit/transpiler/passes/optimization/optimize_clifford_t.py +68 -0
- qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +3 -9
- qiskit/transpiler/passes/routing/sabre_swap.py +4 -2
- qiskit/transpiler/passes/routing/star_prerouting.py +106 -81
- qiskit/transpiler/passes/scheduling/__init__.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
- qiskit/transpiler/passes/scheduling/padding/__init__.py +1 -0
- qiskit/transpiler/passes/scheduling/padding/context_aware_dynamical_decoupling.py +876 -0
- qiskit/transpiler/passes/synthesis/__init__.py +1 -0
- qiskit/transpiler/passes/synthesis/clifford_unitary_synth_plugin.py +123 -0
- qiskit/transpiler/passes/synthesis/hls_plugins.py +494 -93
- qiskit/transpiler/passes/synthesis/plugin.py +4 -0
- qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +27 -22
- qiskit/transpiler/passmanager_config.py +3 -0
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +149 -28
- qiskit/transpiler/preset_passmanagers/common.py +101 -0
- qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +6 -0
- qiskit/transpiler/preset_passmanagers/level3.py +2 -2
- qiskit/transpiler/target.py +15 -2
- qiskit/utils/optionals.py +6 -5
- qiskit/visualization/circuit/_utils.py +5 -3
- qiskit/visualization/circuit/latex.py +9 -2
- qiskit/visualization/circuit/matplotlib.py +26 -4
- qiskit/visualization/circuit/qcstyle.py +9 -157
- qiskit/visualization/dag/__init__.py +13 -0
- qiskit/visualization/dag/dagstyle.py +103 -0
- qiskit/visualization/dag/styles/__init__.py +13 -0
- qiskit/visualization/dag/styles/color.json +10 -0
- qiskit/visualization/dag/styles/plain.json +5 -0
- qiskit/visualization/dag_visualization.py +169 -98
- qiskit/visualization/style.py +223 -0
- {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/METADATA +7 -6
- {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/RECORD +178 -169
- {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/entry_points.txt +6 -0
- qiskit/synthesis/discrete_basis/commutator_decompose.py +0 -265
- qiskit/synthesis/discrete_basis/gate_sequence.py +0 -421
- {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/WHEEL +0 -0
- {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/licenses/LICENSE.txt +0 -0
- {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/top_level.txt +0 -0
@@ -171,30 +171,29 @@ def _mcsu2_real_diagonal(
|
|
171
171
|
k_1 = math.ceil(num_controls / 2.0)
|
172
172
|
k_2 = math.floor(num_controls / 2.0)
|
173
173
|
|
174
|
-
circuit = QuantumCircuit(num_controls + 1, name="MCSU2")
|
175
174
|
controls = list(range(num_controls)) # control indices, defined for code legibility
|
176
175
|
target = num_controls # target index, defined for code legibility
|
177
176
|
|
177
|
+
mcx1 = synth_mcx_n_dirty_i15(num_ctrl_qubits=k_1)
|
178
|
+
mcx1_num_ancillas = mcx1.num_qubits - k_1 - 1
|
179
|
+
mcx1_qubits = controls[:k_1] + [target] + controls[k_1 : k_1 + mcx1_num_ancillas]
|
180
|
+
|
181
|
+
mcx2 = synth_mcx_n_dirty_i15(num_ctrl_qubits=k_2)
|
182
|
+
mcx2_num_ancillas = mcx2.num_qubits - k_2 - 1
|
183
|
+
mcx2_qubits = controls[k_1:] + [target] + controls[k_1 - mcx2_num_ancillas : k_1]
|
184
|
+
|
185
|
+
circuit = QuantumCircuit(num_controls + 1, name="MCSU2")
|
186
|
+
|
178
187
|
if not is_secondary_diag_real:
|
179
188
|
circuit.h(target)
|
180
189
|
|
181
|
-
|
182
|
-
circuit.compose(mcx_1, controls[:k_1] + [target] + controls[k_1 : 2 * k_1 - 2], inplace=True)
|
190
|
+
circuit.compose(mcx1, mcx1_qubits, inplace=True)
|
183
191
|
circuit.append(s_gate, [target])
|
184
|
-
|
185
|
-
# TODO: improve CX count by using action_only=True (based on #9687)
|
186
|
-
mcx_2 = synth_mcx_n_dirty_i15(num_ctrl_qubits=k_2).to_gate()
|
187
|
-
circuit.compose(
|
188
|
-
mcx_2.inverse(), controls[k_1:] + [target] + controls[k_1 - k_2 + 2 : k_1], inplace=True
|
189
|
-
)
|
192
|
+
circuit.compose(mcx2, mcx2_qubits, inplace=True)
|
190
193
|
circuit.append(s_gate.inverse(), [target])
|
191
|
-
|
192
|
-
mcx_3 = synth_mcx_n_dirty_i15(num_ctrl_qubits=k_1).to_gate()
|
193
|
-
circuit.compose(mcx_3, controls[:k_1] + [target] + controls[k_1 : 2 * k_1 - 2], inplace=True)
|
194
|
+
circuit.compose(mcx1, mcx1_qubits, inplace=True)
|
194
195
|
circuit.append(s_gate, [target])
|
195
|
-
|
196
|
-
mcx_4 = synth_mcx_n_dirty_i15(num_ctrl_qubits=k_2).to_gate()
|
197
|
-
circuit.compose(mcx_4, controls[k_1:] + [target] + controls[k_1 - k_2 + 2 : k_1], inplace=True)
|
196
|
+
circuit.compose(mcx2, mcx2_qubits, inplace=True)
|
198
197
|
circuit.append(s_gate.inverse(), [target])
|
199
198
|
|
200
199
|
if not is_secondary_diag_real:
|
@@ -13,9 +13,9 @@
|
|
13
13
|
Circuit synthesis for a QFT circuit.
|
14
14
|
"""
|
15
15
|
|
16
|
-
import numpy as np
|
17
16
|
from qiskit.circuit import QuantumCircuit
|
18
|
-
from qiskit.synthesis.
|
17
|
+
from qiskit._accelerate.synthesis.qft import synth_qft_line as _synth_qft_line
|
18
|
+
|
19
19
|
from .qft_decompose_full import _warn_if_precision_loss
|
20
20
|
|
21
21
|
|
@@ -53,27 +53,9 @@ def synth_qft_line(
|
|
53
53
|
`arXiv:quant-ph/0402196 [quant-ph] <https://arxiv.org/abs/quant-ph/0402196>`_
|
54
54
|
"""
|
55
55
|
_warn_if_precision_loss(num_qubits - approximation_degree - 1)
|
56
|
-
qc = QuantumCircuit(num_qubits)
|
57
|
-
|
58
|
-
for i in range(num_qubits):
|
59
|
-
qc.h(num_qubits - 1)
|
60
|
-
|
61
|
-
for j in range(i, num_qubits - 1):
|
62
|
-
if j - i + 2 < num_qubits - approximation_degree + 1:
|
63
|
-
qc.p(np.pi / 2 ** (j - i + 2), num_qubits - j + i - 1)
|
64
|
-
qc.cx(num_qubits - j + i - 1, num_qubits - j + i - 2)
|
65
|
-
qc.p(-np.pi / 2 ** (j - i + 2), num_qubits - j + i - 2)
|
66
|
-
qc.cx(num_qubits - j + i - 2, num_qubits - j + i - 1)
|
67
|
-
qc.cx(num_qubits - j + i - 1, num_qubits - j + i - 2)
|
68
|
-
qc.p(np.pi / 2 ** (j - i + 2), num_qubits - j + i - 1)
|
69
|
-
else:
|
70
|
-
qc.cx(num_qubits - j + i - 1, num_qubits - j + i - 2)
|
71
|
-
qc.cx(num_qubits - j + i - 2, num_qubits - j + i - 1)
|
72
|
-
qc.cx(num_qubits - j + i - 1, num_qubits - j + i - 2)
|
73
|
-
|
74
|
-
if not do_swaps:
|
75
|
-
# Add a reversal network for LNN connectivity in depth 2*n+2,
|
76
|
-
# based on Kutin at al., https://arxiv.org/abs/quant-ph/0701194, Section 5.
|
77
|
-
_append_reverse_permutation_lnn_kms(qc, num_qubits)
|
78
56
|
|
79
|
-
return
|
57
|
+
return QuantumCircuit._from_circuit_data(
|
58
|
+
# From rust
|
59
|
+
_synth_qft_line(num_qubits, do_swaps, approximation_degree),
|
60
|
+
add_regs=True,
|
61
|
+
)
|
qiskit/synthesis/unitary/qsd.py
CHANGED
@@ -15,7 +15,6 @@ Quantum Shannon Decomposition.
|
|
15
15
|
Method is described in arXiv:quant-ph/0406176.
|
16
16
|
"""
|
17
17
|
from __future__ import annotations
|
18
|
-
import math
|
19
18
|
from typing import Callable
|
20
19
|
import scipy
|
21
20
|
import numpy as np
|
@@ -31,6 +30,7 @@ from qiskit.circuit.library.generalized_gates.uc_pauli_rot import UCPauliRotGate
|
|
31
30
|
from qiskit.circuit.library.generalized_gates.ucry import UCRYGate
|
32
31
|
from qiskit.circuit.library.generalized_gates.ucrz import UCRZGate
|
33
32
|
from qiskit._accelerate.two_qubit_decompose import two_qubit_decompose_up_to_diagonal
|
33
|
+
from qiskit._accelerate.cos_sin_decomp import cossin
|
34
34
|
|
35
35
|
|
36
36
|
def qs_decomposition(
|
@@ -96,7 +96,8 @@ def qs_decomposition(
|
|
96
96
|
"""
|
97
97
|
# _depth (int): Internal use parameter to track recursion depth.
|
98
98
|
dim = mat.shape[0]
|
99
|
-
nqubits =
|
99
|
+
nqubits = dim.bit_length() - 1
|
100
|
+
|
100
101
|
if np.allclose(np.identity(dim), mat):
|
101
102
|
return QuantumCircuit(nqubits)
|
102
103
|
if dim == 2:
|
@@ -121,11 +122,25 @@ def qs_decomposition(
|
|
121
122
|
decomposer_2q = TwoQubitBasisDecomposer(CXGate())
|
122
123
|
circ = decomposer_2q(mat)
|
123
124
|
else:
|
125
|
+
# check whether matrix is equivalent to block diagonal wrt ctrl_index
|
126
|
+
if opt_a2 is False:
|
127
|
+
for ctrl_index in range(nqubits):
|
128
|
+
um00, um11, um01, um10 = _extract_multiplex_blocks(mat, ctrl_index)
|
129
|
+
# the ctrl_index is reversed here
|
130
|
+
if _off_diagonals_are_zero(um01, um10):
|
131
|
+
decirc = _demultiplex(
|
132
|
+
um00,
|
133
|
+
um11,
|
134
|
+
opt_a1=opt_a1,
|
135
|
+
opt_a2=opt_a2,
|
136
|
+
_depth=_depth,
|
137
|
+
_ctrl_index=nqubits - 1 - ctrl_index,
|
138
|
+
)
|
139
|
+
return decirc
|
124
140
|
qr = QuantumRegister(nqubits)
|
125
141
|
circ = QuantumCircuit(qr)
|
126
|
-
dim_o2 = dim // 2
|
127
142
|
# perform cosine-sine decomposition
|
128
|
-
(u1, u2), vtheta, (v1h, v2h) =
|
143
|
+
(u1, u2), vtheta, (v1h, v2h) = cossin(np.asarray(mat, dtype=complex))
|
129
144
|
# left circ
|
130
145
|
left_circ = _demultiplex(v1h, v2h, opt_a1=opt_a1, opt_a2=opt_a2, _depth=_depth)
|
131
146
|
circ.append(left_circ.to_instruction(), qr)
|
@@ -150,7 +165,7 @@ def qs_decomposition(
|
|
150
165
|
return circ
|
151
166
|
|
152
167
|
|
153
|
-
def _demultiplex(um0, um1, opt_a1=False, opt_a2=False, *, _depth=0):
|
168
|
+
def _demultiplex(um0, um1, opt_a1=False, opt_a2=False, *, _depth=0, _ctrl_index=None):
|
154
169
|
"""Decompose a generic multiplexer.
|
155
170
|
|
156
171
|
────□────
|
@@ -183,12 +198,17 @@ def _demultiplex(um0, um1, opt_a1=False, opt_a2=False, *, _depth=0):
|
|
183
198
|
unitaries into a diagonal gate and a two cx unitary and reduces overall cx count by
|
184
199
|
4^(n-2) - 1.
|
185
200
|
_depth (int): This is an internal variable to track the recursion depth.
|
201
|
+
_ctrl_index (int): The index wrt which um0 and um1 are controlled.
|
186
202
|
|
187
203
|
Returns:
|
188
204
|
QuantumCircuit: decomposed circuit
|
189
205
|
"""
|
190
206
|
dim = um0.shape[0] + um1.shape[0] # these should be same dimension
|
191
|
-
nqubits =
|
207
|
+
nqubits = dim.bit_length() - 1
|
208
|
+
if _ctrl_index is None:
|
209
|
+
_ctrl_index = nqubits - 1
|
210
|
+
layout = list(range(0, _ctrl_index)) + list(range(_ctrl_index + 1, nqubits)) + [_ctrl_index]
|
211
|
+
|
192
212
|
um0um1 = um0 @ um1.T.conjugate()
|
193
213
|
if is_hermitian_matrix(um0um1):
|
194
214
|
eigvals, vmat = scipy.linalg.eigh(um0um1)
|
@@ -205,18 +225,18 @@ def _demultiplex(um0, um1, opt_a1=False, opt_a2=False, *, _depth=0):
|
|
205
225
|
left_gate = qs_decomposition(
|
206
226
|
wmat, opt_a1=opt_a1, opt_a2=opt_a2, _depth=_depth + 1
|
207
227
|
).to_instruction()
|
208
|
-
circ.append(left_gate,
|
228
|
+
circ.append(left_gate, layout[: nqubits - 1])
|
209
229
|
|
210
230
|
# multiplexed Rz
|
211
231
|
angles = 2 * np.angle(np.conj(dvals))
|
212
232
|
ucrz = UCRZGate(angles.tolist())
|
213
|
-
circ.append(ucrz, [
|
233
|
+
circ.append(ucrz, [layout[-1]] + layout[: nqubits - 1])
|
214
234
|
|
215
235
|
# right gate
|
216
236
|
right_gate = qs_decomposition(
|
217
237
|
vmat, opt_a1=opt_a1, opt_a2=opt_a2, _depth=_depth + 1
|
218
238
|
).to_instruction()
|
219
|
-
circ.append(right_gate,
|
239
|
+
circ.append(right_gate, layout[: nqubits - 1])
|
220
240
|
|
221
241
|
return circ
|
222
242
|
|
@@ -286,3 +306,54 @@ def _apply_a2(circ):
|
|
286
306
|
qc3 = two_qubit_decompose.two_qubit_cnot_decompose(mat2)
|
287
307
|
ccirc.data[ind2] = ccirc.data[ind2].replace(operation=qc3.to_gate())
|
288
308
|
return ccirc
|
309
|
+
|
310
|
+
|
311
|
+
def _extract_multiplex_blocks(umat, k):
|
312
|
+
"""
|
313
|
+
A block diagonal gate is represented as:
|
314
|
+
[ um00 | um01 ]
|
315
|
+
[ ---- | ---- ]
|
316
|
+
[ um10 | um11 ]
|
317
|
+
Args:
|
318
|
+
umat (ndarray): unitary matrix
|
319
|
+
k (integer): qubit which indicates the ctrl index
|
320
|
+
Returns:
|
321
|
+
um00 (ndarray): upper left block
|
322
|
+
um01 (ndarray): upper right block
|
323
|
+
um10 (ndarray): lower left block
|
324
|
+
um11 (ndarray): lower right block
|
325
|
+
"""
|
326
|
+
dim = umat.shape[0]
|
327
|
+
nqubits = dim.bit_length() - 1
|
328
|
+
halfdim = dim // 2
|
329
|
+
|
330
|
+
utensor = umat.reshape((2,) * (2 * nqubits))
|
331
|
+
|
332
|
+
# Move qubit k to top
|
333
|
+
if k != 0:
|
334
|
+
utensor = np.moveaxis(utensor, k, 0)
|
335
|
+
utensor = np.moveaxis(utensor, k + nqubits, nqubits)
|
336
|
+
|
337
|
+
# reshape for extraction
|
338
|
+
ud4 = utensor.reshape(2, halfdim, 2, halfdim)
|
339
|
+
# block for qubit k = |0>
|
340
|
+
um00 = ud4[0, :, 0, :]
|
341
|
+
# block for qubit k = |1>
|
342
|
+
um11 = ud4[1, :, 1, :]
|
343
|
+
# off diagonal blocks
|
344
|
+
um01 = ud4[0, :, 1, :]
|
345
|
+
um10 = ud4[1, :, 0, :]
|
346
|
+
return um00, um11, um01, um10
|
347
|
+
|
348
|
+
|
349
|
+
def _off_diagonals_are_zero(um01, um10, atol=1e-12):
|
350
|
+
"""
|
351
|
+
Checks whether off-diagonal blocks are zero.
|
352
|
+
Args:
|
353
|
+
um01 (ndarray): upper right block
|
354
|
+
um10 (ndarray): lower left block
|
355
|
+
atol (float): absolute tolerance
|
356
|
+
Returns:
|
357
|
+
bool: whether both blocks are zero within tolerance
|
358
|
+
"""
|
359
|
+
return np.allclose(um01, 0, atol=atol) and np.allclose(um10, 0, atol=atol)
|
qiskit/transpiler/__init__.py
CHANGED
@@ -677,6 +677,9 @@ At a high level, this starts from the set of gates requested by the circuit, and
|
|
677
677
|
given :class:`.EquivalenceLibrary` (typically the :data:`.SessionEquivalenceLibrary`) to move
|
678
678
|
towards the ISA.
|
679
679
|
|
680
|
+
For a Clifford+T basis set, the single-qubit rotation gates are approximated using the
|
681
|
+
:class:`.SolovayKitaevDecomposition` algorithm.
|
682
|
+
|
680
683
|
This is the default translation method.
|
681
684
|
|
682
685
|
The optimization level has no effect on this plugin.
|
@@ -704,7 +707,7 @@ as a fix-up pipeline.
|
|
704
707
|
|
705
708
|
Qiskit's built-in optimization plugins are general, and apply well to most real-world ISAs for
|
706
709
|
non-error-corrected devices. The built-in plugins are less well-suited to ISAs that have no
|
707
|
-
continuously parametrized single-qubit gate
|
710
|
+
continuously parametrized single-qubit gate.
|
708
711
|
|
709
712
|
When writing :ref:`stage plugins <transpiler-preset-stage-plugins>`, the entry point for
|
710
713
|
``optimization`` is ``qiskit.transpiler.optimization``. The built-in plugins are:
|
@@ -724,10 +727,12 @@ When writing :ref:`stage plugins <transpiler-preset-stage-plugins>`, the entry p
|
|
724
727
|
Built-in ``default`` plugin
|
725
728
|
...........................
|
726
729
|
|
727
|
-
This varies significantly
|
730
|
+
This varies significantly depending on the optimization level and whether the basis set is of the
|
731
|
+
form Clifford+T.
|
728
732
|
|
729
733
|
The specifics of this pipeline are subject to change between Qiskit versions. The broad principles
|
730
|
-
are described below.
|
734
|
+
are described below. First, consider the more common case that the basis set is not of the form
|
735
|
+
Clifford+T.
|
731
736
|
|
732
737
|
At optimization level 0, the stage is empty.
|
733
738
|
|
@@ -744,6 +749,8 @@ The optimization loop condition also tries multiple runs and chooses the minimum
|
|
744
749
|
of fluctuating output; this is necessary because matrix-based resynthesis is relatively unstable in
|
745
750
|
terms of concrete gates.
|
746
751
|
|
752
|
+
For a Clifford+T basis set, two-qubit matrix based resynthesis is not applied.
|
753
|
+
|
747
754
|
Optimization level 3 is typically very expensive for large circuits.
|
748
755
|
|
749
756
|
|
@@ -74,30 +74,12 @@ class InstructionDurations:
|
|
74
74
|
|
75
75
|
Raises:
|
76
76
|
TranspilerError: If dt and dtm is different in the backend.
|
77
|
+
TypeError: If the backend is the wrong type
|
77
78
|
"""
|
78
79
|
# All durations in seconds in gate_length
|
79
80
|
if isinstance(backend, BackendV2):
|
80
81
|
return backend.target.durations()
|
81
|
-
|
82
|
-
instruction_durations = []
|
83
|
-
backend_properties = backend.properties()
|
84
|
-
if hasattr(backend_properties, "_gates"):
|
85
|
-
for gate, insts in backend_properties._gates.items():
|
86
|
-
for qubits, props in insts.items():
|
87
|
-
if "gate_length" in props:
|
88
|
-
gate_length = props["gate_length"][0] # Throw away datetime at index 1
|
89
|
-
instruction_durations.append((gate, qubits, gate_length, "s"))
|
90
|
-
for q, props in backend.properties()._qubits.items():
|
91
|
-
if "readout_length" in props:
|
92
|
-
readout_length = props["readout_length"][0] # Throw away datetime at index 1
|
93
|
-
instruction_durations.append(("measure", [q], readout_length, "s"))
|
94
|
-
|
95
|
-
try:
|
96
|
-
dt = backend.configuration().dt
|
97
|
-
except AttributeError:
|
98
|
-
dt = None
|
99
|
-
|
100
|
-
return cls(instruction_durations, dt=dt)
|
82
|
+
raise TypeError("Unsupported backend type: {backend}")
|
101
83
|
|
102
84
|
def update(self, inst_durations: "InstructionDurationsType" | None, dt: float = None):
|
103
85
|
"""Update self with inst_durations (inst_durations overwrite self).
|
@@ -91,7 +91,7 @@ Optimizations
|
|
91
91
|
Split2QUnitaries
|
92
92
|
RemoveIdentityEquivalent
|
93
93
|
ContractIdleWiresInControlFlow
|
94
|
-
|
94
|
+
OptimizeCliffordT
|
95
95
|
|
96
96
|
Scheduling
|
97
97
|
=============
|
@@ -102,6 +102,7 @@ Scheduling
|
|
102
102
|
TimeUnitConversion
|
103
103
|
ALAPScheduleAnalysis
|
104
104
|
ASAPScheduleAnalysis
|
105
|
+
ContextAwareDynamicalDecoupling
|
105
106
|
PadDynamicalDecoupling
|
106
107
|
PadDelay
|
107
108
|
ConstrainedReschedule
|
@@ -226,7 +227,7 @@ from .optimization import OptimizeAnnotated
|
|
226
227
|
from .optimization import RemoveIdentityEquivalent
|
227
228
|
from .optimization import Split2QUnitaries
|
228
229
|
from .optimization import ContractIdleWiresInControlFlow
|
229
|
-
from .optimization import
|
230
|
+
from .optimization import OptimizeCliffordT
|
230
231
|
|
231
232
|
# circuit analysis
|
232
233
|
from .analysis import ResourceEstimation
|
@@ -246,6 +247,7 @@ from .synthesis import HighLevelSynthesis
|
|
246
247
|
from .synthesis import HLSConfig
|
247
248
|
from .synthesis import SolovayKitaev
|
248
249
|
from .synthesis import SolovayKitaevSynthesis
|
250
|
+
from .synthesis import CliffordUnitarySynthesis
|
249
251
|
from .synthesis import AQCSynthesisPlugin
|
250
252
|
|
251
253
|
# circuit scheduling
|
@@ -257,6 +259,7 @@ from .scheduling import PadDelay
|
|
257
259
|
from .scheduling import ConstrainedReschedule
|
258
260
|
from .scheduling import InstructionDurationCheck
|
259
261
|
from .scheduling import SetIOLatency
|
262
|
+
from .scheduling import ContextAwareDynamicalDecoupling
|
260
263
|
|
261
264
|
# additional utility passes
|
262
265
|
from .utils import CheckMap
|
@@ -19,7 +19,8 @@ import rustworkx
|
|
19
19
|
from qiskit.transpiler.layout import Layout
|
20
20
|
from qiskit.transpiler.basepasses import AnalysisPass
|
21
21
|
from qiskit.transpiler.exceptions import TranspilerError
|
22
|
-
from qiskit.transpiler.
|
22
|
+
from qiskit.transpiler.target import Target
|
23
|
+
from qiskit._accelerate import disjoint_utils
|
23
24
|
|
24
25
|
from qiskit._accelerate.dense_layout import best_subset
|
25
26
|
|
@@ -66,11 +67,30 @@ class DenseLayout(AnalysisPass):
|
|
66
67
|
raise TranspilerError(
|
67
68
|
"A coupling_map or target with constrained qargs is necessary to run the pass."
|
68
69
|
)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
70
|
+
if self.target is not None:
|
71
|
+
layout_components = disjoint_utils.run_pass_over_connected_components(
|
72
|
+
dag,
|
73
|
+
self.target,
|
74
|
+
self._inner_run,
|
75
|
+
)
|
76
|
+
if layout_components is None:
|
77
|
+
target = Target.from_configuration(
|
78
|
+
basis_gates=["u", "cx"], coupling_map=self.coupling_map
|
79
|
+
)
|
80
|
+
layout_components = disjoint_utils.run_pass_over_connected_components(
|
81
|
+
dag,
|
82
|
+
target,
|
83
|
+
self._inner_run,
|
84
|
+
)
|
85
|
+
else:
|
86
|
+
target = Target.from_configuration(
|
87
|
+
basis_gates=["u", "cx"], coupling_map=self.coupling_map
|
88
|
+
)
|
89
|
+
layout_components = disjoint_utils.run_pass_over_connected_components(
|
90
|
+
dag,
|
91
|
+
target,
|
92
|
+
self._inner_run,
|
93
|
+
)
|
74
94
|
layout_mapping = {}
|
75
95
|
for component in layout_components:
|
76
96
|
layout_mapping.update(component)
|
@@ -12,143 +12,12 @@
|
|
12
12
|
|
13
13
|
"""This module contains common utils for disjoint coupling maps."""
|
14
14
|
from __future__ import annotations
|
15
|
-
from
|
16
|
-
from typing import List, Callable, TypeVar, Dict, Union
|
17
|
-
import uuid
|
15
|
+
from typing import Union
|
18
16
|
|
19
|
-
import rustworkx as rx
|
20
|
-
from qiskit.dagcircuit import DAGOpNode
|
21
|
-
|
22
|
-
from qiskit.circuit import Qubit, Barrier, Clbit
|
23
17
|
from qiskit.dagcircuit.dagcircuit import DAGCircuit
|
24
|
-
from qiskit.dagcircuit.dagnode import DAGOutNode
|
25
18
|
from qiskit.transpiler.coupling import CouplingMap
|
26
19
|
from qiskit.transpiler.target import Target
|
27
20
|
from qiskit.transpiler.exceptions import TranspilerError
|
28
|
-
from qiskit.transpiler.passes.layout import vf2_utils
|
29
|
-
|
30
|
-
T = TypeVar("T")
|
31
|
-
|
32
|
-
|
33
|
-
def run_pass_over_connected_components(
|
34
|
-
dag: DAGCircuit,
|
35
|
-
components_source: Union[Target, CouplingMap],
|
36
|
-
run_func: Callable[[DAGCircuit, CouplingMap], T],
|
37
|
-
) -> List[T]:
|
38
|
-
"""Run a transpiler pass inner function over mapped components."""
|
39
|
-
if isinstance(components_source, Target):
|
40
|
-
coupling_map = components_source.build_coupling_map(filter_idle_qubits=True)
|
41
|
-
else:
|
42
|
-
coupling_map = components_source
|
43
|
-
cmap_components = coupling_map.connected_components()
|
44
|
-
# If graph is connected we only need to run the pass once
|
45
|
-
if len(cmap_components) == 1:
|
46
|
-
if dag.num_qubits() > cmap_components[0].size():
|
47
|
-
raise TranspilerError(
|
48
|
-
"A connected component of the DAGCircuit is too large for any of the connected "
|
49
|
-
"components in the coupling map."
|
50
|
-
)
|
51
|
-
return [run_func(dag, cmap_components[0])]
|
52
|
-
dag_components = separate_dag(dag)
|
53
|
-
mapped_components = map_components(dag_components, cmap_components)
|
54
|
-
out_component_pairs = []
|
55
|
-
for cmap_index, dags in mapped_components.items():
|
56
|
-
# Take the first dag from the mapped dag components and then
|
57
|
-
# compose it with any other dag components that are operating on the
|
58
|
-
# same coupling map connected component. This results in a subcircuit
|
59
|
-
# of possibly disjoint circuit components which we will run the layout
|
60
|
-
# pass on.
|
61
|
-
out_dag = dag_components[dags.pop()]
|
62
|
-
for dag_index in dags:
|
63
|
-
dag = dag_components[dag_index]
|
64
|
-
out_dag.add_qubits(dag.qubits)
|
65
|
-
out_dag.add_clbits(dag.clbits)
|
66
|
-
for qreg in dag.qregs:
|
67
|
-
out_dag.add_qreg(qreg)
|
68
|
-
for creg in dag.cregs:
|
69
|
-
out_dag.add_creg(creg)
|
70
|
-
out_dag.compose(dag, qubits=dag.qubits, clbits=dag.clbits)
|
71
|
-
out_component_pairs.append((out_dag, cmap_components[cmap_index]))
|
72
|
-
res = [run_func(out_dag, cmap) for out_dag, cmap in out_component_pairs]
|
73
|
-
return res
|
74
|
-
|
75
|
-
|
76
|
-
def map_components(
|
77
|
-
dag_components: List[DAGCircuit], cmap_components: List[CouplingMap]
|
78
|
-
) -> Dict[int, List[int]]:
|
79
|
-
"""Returns a map where the key is the index of each connected component in cmap_components and
|
80
|
-
the value is a list of indices from dag_components which should be placed onto it."""
|
81
|
-
free_qubits = {index: len(cmap.graph) for index, cmap in enumerate(cmap_components)}
|
82
|
-
out_mapping = defaultdict(list)
|
83
|
-
|
84
|
-
for dag_index, dag in sorted(
|
85
|
-
enumerate(dag_components), key=lambda x: x[1].num_qubits(), reverse=True
|
86
|
-
):
|
87
|
-
for cmap_index in sorted(
|
88
|
-
range(len(cmap_components)), key=lambda index: free_qubits[index], reverse=True
|
89
|
-
):
|
90
|
-
# TODO: Improve heuristic to involve connectivity and estimate
|
91
|
-
# swap cost
|
92
|
-
if dag.num_qubits() <= free_qubits[cmap_index]:
|
93
|
-
out_mapping[cmap_index].append(dag_index)
|
94
|
-
free_qubits[cmap_index] -= dag.num_qubits()
|
95
|
-
break
|
96
|
-
else:
|
97
|
-
raise TranspilerError(
|
98
|
-
"A connected component of the DAGCircuit is too large for any of the connected "
|
99
|
-
"components in the coupling map."
|
100
|
-
)
|
101
|
-
return out_mapping
|
102
|
-
|
103
|
-
|
104
|
-
def split_barriers(dag: DAGCircuit):
|
105
|
-
"""Mutate an input dag to split barriers into single qubit barriers."""
|
106
|
-
for node in dag.op_nodes(Barrier):
|
107
|
-
num_qubits = len(node.qargs)
|
108
|
-
if num_qubits == 1:
|
109
|
-
continue
|
110
|
-
if node.label:
|
111
|
-
barrier_uuid = f"{node.op.label}_uuid={uuid.uuid4()}"
|
112
|
-
else:
|
113
|
-
barrier_uuid = f"_none_uuid={uuid.uuid4()}"
|
114
|
-
split_dag = DAGCircuit()
|
115
|
-
split_dag.add_qubits([Qubit() for _ in range(num_qubits)])
|
116
|
-
for i in range(num_qubits):
|
117
|
-
split_dag.apply_operation_back(
|
118
|
-
Barrier(1, label=barrier_uuid),
|
119
|
-
qargs=(split_dag.qubits[i],),
|
120
|
-
check=False,
|
121
|
-
)
|
122
|
-
dag.substitute_node_with_dag(node, split_dag)
|
123
|
-
|
124
|
-
|
125
|
-
def combine_barriers(dag: DAGCircuit, retain_uuid: bool = True):
|
126
|
-
"""Mutate input dag to combine barriers with UUID labels into a single barrier."""
|
127
|
-
qubit_indices = {bit: index for index, bit in enumerate(dag.qubits)}
|
128
|
-
uuid_map: dict[str, DAGOpNode] = {}
|
129
|
-
for node in dag.op_nodes(Barrier):
|
130
|
-
if node.label:
|
131
|
-
if "_uuid=" in node.label:
|
132
|
-
barrier_uuid = node.label
|
133
|
-
else:
|
134
|
-
continue
|
135
|
-
if barrier_uuid in uuid_map:
|
136
|
-
other_node = uuid_map[barrier_uuid]
|
137
|
-
num_qubits = len(other_node.qargs) + len(node.qargs)
|
138
|
-
if not retain_uuid:
|
139
|
-
if isinstance(node.label, str) and node.label.startswith("_none_uuid="):
|
140
|
-
label = None
|
141
|
-
elif isinstance(node.label, str) and "_uuid=" in node.label:
|
142
|
-
label = "_uuid=".join(node.label.split("_uuid=")[:-1])
|
143
|
-
else:
|
144
|
-
label = barrier_uuid
|
145
|
-
else:
|
146
|
-
label = barrier_uuid
|
147
|
-
new_op = Barrier(num_qubits, label=label)
|
148
|
-
new_node = dag.replace_block_with_op([node, other_node], new_op, qubit_indices)
|
149
|
-
uuid_map[barrier_uuid] = new_node
|
150
|
-
else:
|
151
|
-
uuid_map[barrier_uuid] = node
|
152
21
|
|
153
22
|
|
154
23
|
def require_layout_isolated_to_component(
|
@@ -183,37 +52,3 @@ def require_layout_isolated_to_component(
|
|
183
52
|
f"{dag.find_bit(inst.qargs[1]).index} needs to interact with the "
|
184
53
|
f"qubit {dag.find_bit(inst.qargs[0]).index} and they belong to different components"
|
185
54
|
)
|
186
|
-
|
187
|
-
|
188
|
-
def separate_dag(dag: DAGCircuit) -> List[DAGCircuit]:
|
189
|
-
"""Separate a dag circuit into it's connected components."""
|
190
|
-
# Split barriers into single qubit barriers before splitting connected components
|
191
|
-
split_barriers(dag)
|
192
|
-
im_graph, _, qubit_map, __ = vf2_utils.build_interaction_graph(dag)
|
193
|
-
connected_components = rx.weakly_connected_components(im_graph)
|
194
|
-
component_qubits = []
|
195
|
-
for component in connected_components:
|
196
|
-
component_qubits.append({qubit_map[x] for x in component})
|
197
|
-
|
198
|
-
qubits = set(dag.qubits)
|
199
|
-
|
200
|
-
decomposed_dags = []
|
201
|
-
for dag_qubits in component_qubits:
|
202
|
-
new_dag = dag.copy_empty_like()
|
203
|
-
new_dag.remove_qubits(*qubits - dag_qubits)
|
204
|
-
new_dag.global_phase = 0
|
205
|
-
for node in dag.topological_op_nodes():
|
206
|
-
if dag_qubits.issuperset(node.qargs):
|
207
|
-
new_dag.apply_operation_back(node.op, node.qargs, node.cargs, check=False)
|
208
|
-
idle_clbits = []
|
209
|
-
for bit, node in new_dag.input_map.items():
|
210
|
-
succ_node = next(new_dag.successors(node))
|
211
|
-
if isinstance(succ_node, DAGOutNode) and isinstance(succ_node.wire, Clbit):
|
212
|
-
idle_clbits.append(bit)
|
213
|
-
new_dag.remove_clbits(*idle_clbits)
|
214
|
-
combine_barriers(new_dag)
|
215
|
-
decomposed_dags.append(new_dag)
|
216
|
-
# Reverse split barriers on input dag to avoid leaking out internal transformations as
|
217
|
-
# part of splitting
|
218
|
-
combine_barriers(dag, retain_uuid=False)
|
219
|
-
return decomposed_dags
|
@@ -29,11 +29,11 @@ from qiskit.transpiler.passes.layout.set_layout import SetLayout
|
|
29
29
|
from qiskit.transpiler.passes.layout.full_ancilla_allocation import FullAncillaAllocation
|
30
30
|
from qiskit.transpiler.passes.layout.enlarge_with_ancilla import EnlargeWithAncilla
|
31
31
|
from qiskit.transpiler.passes.layout.apply_layout import ApplyLayout
|
32
|
-
from qiskit.transpiler.passes.layout import disjoint_utils
|
33
32
|
from qiskit.transpiler.passmanager import PassManager
|
34
33
|
from qiskit.transpiler.layout import Layout
|
35
34
|
from qiskit.transpiler.basepasses import TransformationPass
|
36
35
|
from qiskit.transpiler.exceptions import TranspilerError
|
36
|
+
from qiskit._accelerate import disjoint_utils
|
37
37
|
from qiskit._accelerate.nlayout import NLayout
|
38
38
|
from qiskit._accelerate.sabre import sabre_layout_and_routing, Heuristic, NeighborTable, SetScaling
|
39
39
|
from qiskit.transpiler.passes.routing.sabre_swap import _build_sabre_dag, _apply_sabre_result
|
@@ -267,7 +267,24 @@ class SabreLayout(TransformationPass):
|
|
267
267
|
inner_run = functools.partial(
|
268
268
|
self._inner_run, starting_layouts=self.property_set["sabre_starting_layouts"]
|
269
269
|
)
|
270
|
-
|
270
|
+
if self.target is not None:
|
271
|
+
components = disjoint_utils.run_pass_over_connected_components(
|
272
|
+
dag, self.target, inner_run
|
273
|
+
)
|
274
|
+
# If components is None we can't build a coupling map from the target so we must have
|
275
|
+
# one provided:
|
276
|
+
if components is None:
|
277
|
+
temp_target = Target.from_configuration(
|
278
|
+
basis_gates=["u", "cx"], coupling_map=target
|
279
|
+
)
|
280
|
+
components = disjoint_utils.run_pass_over_connected_components(
|
281
|
+
dag, temp_target, inner_run
|
282
|
+
)
|
283
|
+
else:
|
284
|
+
temp_target = Target.from_configuration(basis_gates=["u", "cx"], coupling_map=target)
|
285
|
+
components = disjoint_utils.run_pass_over_connected_components(
|
286
|
+
dag, temp_target, inner_run
|
287
|
+
)
|
271
288
|
self.property_set["layout"] = Layout(
|
272
289
|
{
|
273
290
|
component.dag.qubits[logic]: component.coupling_map.graph[phys]
|
@@ -413,9 +430,11 @@ class SabreLayout(TransformationPass):
|
|
413
430
|
coupling_map.size(),
|
414
431
|
original_qubit_indices,
|
415
432
|
)
|
433
|
+
# In our defaults, the basic heuristic shouldn't scale by size; if it does, it's liable to
|
434
|
+
# get the algorithm stuck. See https://github.com/Qiskit/qiskit/pull/14458 for more.
|
416
435
|
heuristic = (
|
417
436
|
Heuristic(attempt_limit=10 * coupling_map.size())
|
418
|
-
.with_basic(1.0, SetScaling.
|
437
|
+
.with_basic(1.0, SetScaling.Constant)
|
419
438
|
.with_lookahead(0.5, 20, SetScaling.Size)
|
420
439
|
.with_decay(0.001, 5)
|
421
440
|
)
|
@@ -116,7 +116,7 @@ class SabrePreLayout(AnalysisPass):
|
|
116
116
|
augmented_map, augmented_error_map = self._add_extra_edges(cur_distance)
|
117
117
|
pass_ = VF2Layout(
|
118
118
|
augmented_map,
|
119
|
-
seed
|
119
|
+
seed=-1,
|
120
120
|
max_trials=self.max_trials_vf2,
|
121
121
|
call_limit=self.call_limit_vf2,
|
122
122
|
)
|