qiskit 2.0.1__cp39-abi3-macosx_11_0_arm64.whl → 2.1.0rc1__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 +13 -21
- qiskit/circuit/_add_control.py +57 -31
- qiskit/circuit/_classical_resource_map.py +4 -0
- qiskit/circuit/annotation.py +404 -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 +5 -5
- qiskit/circuit/library/arithmetic/multipliers/multiplier.py +3 -3
- qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +7 -3
- 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 +5 -5
- 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 +4 -2
- 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 +168 -98
- 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 +183 -7
- 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/quantum_info/operators/symplectic/sparse_pauli_op.py +1 -1
- 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 +19 -8
- qiskit/transpiler/instruction_durations.py +2 -20
- qiskit/transpiler/passes/__init__.py +4 -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 +13 -1
- qiskit/transpiler/passes/optimization/__init__.py +1 -1
- qiskit/transpiler/passes/optimization/consolidate_blocks.py +6 -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 +12 -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 +472 -92
- 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/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.1.dist-info → qiskit-2.1.0rc1.dist-info}/METADATA +14 -13
- {qiskit-2.0.1.dist-info → qiskit-2.1.0rc1.dist-info}/RECORD +178 -169
- {qiskit-2.0.1.dist-info → qiskit-2.1.0rc1.dist-info}/WHEEL +1 -1
- {qiskit-2.0.1.dist-info → qiskit-2.1.0rc1.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.1.dist-info → qiskit-2.1.0rc1.dist-info}/licenses/LICENSE.txt +0 -0
- {qiskit-2.0.1.dist-info → qiskit-2.1.0rc1.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
@@ -237,7 +237,7 @@ Initialization stage
|
|
237
237
|
--------------------
|
238
238
|
|
239
239
|
.. seealso::
|
240
|
-
`Init stage explanation <https://
|
240
|
+
`Init stage explanation <https://quantum.cloud.ibm.com/docs/guides/transpiler-stages#init-stage>`__
|
241
241
|
Higher-level user-facing explanation of the init stage in the IBM Quantum guide.
|
242
242
|
|
243
243
|
The ``init`` stage is responsible for high-level, logical optimizations on abstract circuits, and
|
@@ -291,9 +291,11 @@ Layout stage
|
|
291
291
|
------------
|
292
292
|
|
293
293
|
.. seealso::
|
294
|
-
`Layout stage explanation
|
294
|
+
`Layout stage explanation`__
|
295
295
|
Higher-level user-facing explanation of the layout stage in the IBM Quantum guide.
|
296
296
|
|
297
|
+
__ https://quantum.cloud.ibm.com/docs/guides/transpiler-stages#layout-stage
|
298
|
+
|
297
299
|
The layout stage is responsible for making an initial mapping between the virtual qubits of the
|
298
300
|
input circuit, and the hardware qubits of the target. This includes expanding the input circuit
|
299
301
|
with explicit ancillas so it has as many qubits as the target has, and rewriting all operations in
|
@@ -452,9 +454,11 @@ Routing stage
|
|
452
454
|
-------------
|
453
455
|
|
454
456
|
.. seealso::
|
455
|
-
`Routing stage explanation
|
457
|
+
`Routing stage explanation`__
|
456
458
|
Higher-level user-facing explanation of the routing stage in the IBM Quantum guide.
|
457
459
|
|
460
|
+
__ https://quantum.cloud.ibm.com/docs/guides/transpiler-stages#routing-stage
|
461
|
+
|
458
462
|
The routing stage ensures that the virtual connectivity graph of the circuit is compatible with the
|
459
463
|
hardware connectivity graph of the target. In simpler terms, the routing stage makes sure that all
|
460
464
|
two-qubit gates in the circuit are mapped to hardware qubits that have a defined two-qubit operation
|
@@ -598,7 +602,7 @@ Translation stage
|
|
598
602
|
`Translation stage explanation`__
|
599
603
|
Higher-level user-facing explanation of the translation stage in the IBM Quantum guide.
|
600
604
|
|
601
|
-
.. __: https://
|
605
|
+
.. __: https://quantum.cloud.ibm.com/docs/guides/transpiler-stages#translation-stage
|
602
606
|
|
603
607
|
The translation stage is responsible for rewriting all gates in the circuit into ones that are
|
604
608
|
supported by the target ISA. For example, if a ``cx`` is requested on hardware qubits 0 and 1, but
|
@@ -673,6 +677,9 @@ At a high level, this starts from the set of gates requested by the circuit, and
|
|
673
677
|
given :class:`.EquivalenceLibrary` (typically the :data:`.SessionEquivalenceLibrary`) to move
|
674
678
|
towards the ISA.
|
675
679
|
|
680
|
+
For a Clifford+T basis set, the single-qubit rotation gates are approximated using the
|
681
|
+
:class:`.SolovayKitaevDecomposition` algorithm.
|
682
|
+
|
676
683
|
This is the default translation method.
|
677
684
|
|
678
685
|
The optimization level has no effect on this plugin.
|
@@ -687,7 +694,7 @@ Optimization stage
|
|
687
694
|
`Optimization stage explanation`__
|
688
695
|
Higher-level user-facing explanation of the optimization stage in the IBM Quantum guide.
|
689
696
|
|
690
|
-
.. __: https://
|
697
|
+
.. __: https://quantum.cloud.ibm.com/docs/guides/transpiler-stages#optimization-stage
|
691
698
|
|
692
699
|
The optimization stage is for low-level hardware-aware optimizations. Unlike :ref:`the init stage
|
693
700
|
<transpiler-preset-stage-init>`, the input to this stage is a circuit that is already
|
@@ -700,7 +707,7 @@ as a fix-up pipeline.
|
|
700
707
|
|
701
708
|
Qiskit's built-in optimization plugins are general, and apply well to most real-world ISAs for
|
702
709
|
non-error-corrected devices. The built-in plugins are less well-suited to ISAs that have no
|
703
|
-
continuously parametrized single-qubit gate
|
710
|
+
continuously parametrized single-qubit gate.
|
704
711
|
|
705
712
|
When writing :ref:`stage plugins <transpiler-preset-stage-plugins>`, the entry point for
|
706
713
|
``optimization`` is ``qiskit.transpiler.optimization``. The built-in plugins are:
|
@@ -720,10 +727,12 @@ When writing :ref:`stage plugins <transpiler-preset-stage-plugins>`, the entry p
|
|
720
727
|
Built-in ``default`` plugin
|
721
728
|
...........................
|
722
729
|
|
723
|
-
This varies significantly
|
730
|
+
This varies significantly depending on the optimization level and whether the basis set is of the
|
731
|
+
form Clifford+T.
|
724
732
|
|
725
733
|
The specifics of this pipeline are subject to change between Qiskit versions. The broad principles
|
726
|
-
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.
|
727
736
|
|
728
737
|
At optimization level 0, the stage is empty.
|
729
738
|
|
@@ -740,6 +749,8 @@ The optimization loop condition also tries multiple runs and chooses the minimum
|
|
740
749
|
of fluctuating output; this is necessary because matrix-based resynthesis is relatively unstable in
|
741
750
|
terms of concrete gates.
|
742
751
|
|
752
|
+
For a Clifford+T basis set, two-qubit matrix based resynthesis is not applied.
|
753
|
+
|
743
754
|
Optimization level 3 is typically very expensive for large circuits.
|
744
755
|
|
745
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,6 @@ Optimizations
|
|
91
91
|
Split2QUnitaries
|
92
92
|
RemoveIdentityEquivalent
|
93
93
|
ContractIdleWiresInControlFlow
|
94
|
-
LightCone
|
95
94
|
|
96
95
|
Scheduling
|
97
96
|
=============
|
@@ -102,6 +101,7 @@ Scheduling
|
|
102
101
|
TimeUnitConversion
|
103
102
|
ALAPScheduleAnalysis
|
104
103
|
ASAPScheduleAnalysis
|
104
|
+
ContextAwareDynamicalDecoupling
|
105
105
|
PadDynamicalDecoupling
|
106
106
|
PadDelay
|
107
107
|
ConstrainedReschedule
|
@@ -226,7 +226,7 @@ from .optimization import OptimizeAnnotated
|
|
226
226
|
from .optimization import RemoveIdentityEquivalent
|
227
227
|
from .optimization import Split2QUnitaries
|
228
228
|
from .optimization import ContractIdleWiresInControlFlow
|
229
|
-
from .optimization import
|
229
|
+
from .optimization import OptimizeCliffordT
|
230
230
|
|
231
231
|
# circuit analysis
|
232
232
|
from .analysis import ResourceEstimation
|
@@ -246,6 +246,7 @@ from .synthesis import HighLevelSynthesis
|
|
246
246
|
from .synthesis import HLSConfig
|
247
247
|
from .synthesis import SolovayKitaev
|
248
248
|
from .synthesis import SolovayKitaevSynthesis
|
249
|
+
from .synthesis import CliffordUnitarySynthesis
|
249
250
|
from .synthesis import AQCSynthesisPlugin
|
250
251
|
|
251
252
|
# circuit scheduling
|
@@ -257,6 +258,7 @@ from .scheduling import PadDelay
|
|
257
258
|
from .scheduling import ConstrainedReschedule
|
258
259
|
from .scheduling import InstructionDurationCheck
|
259
260
|
from .scheduling import SetIOLatency
|
261
|
+
from .scheduling import ContextAwareDynamicalDecoupling
|
260
262
|
|
261
263
|
# additional utility passes
|
262
264
|
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
|