qiskit 1.0.2__cp38-abi3-win32.whl → 1.1.0__cp38-abi3-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qiskit/VERSION.txt +1 -1
- qiskit/__init__.py +27 -16
- qiskit/_accelerate.pyd +0 -0
- qiskit/_numpy_compat.py +73 -0
- qiskit/assembler/__init__.py +5 -10
- qiskit/assembler/disassemble.py +5 -6
- qiskit/circuit/__init__.py +1061 -232
- qiskit/circuit/_classical_resource_map.py +10 -6
- qiskit/circuit/_utils.py +18 -8
- qiskit/circuit/annotated_operation.py +21 -0
- qiskit/circuit/barrier.py +10 -13
- qiskit/circuit/bit.py +0 -1
- qiskit/circuit/classical/__init__.py +2 -2
- qiskit/circuit/classical/expr/__init__.py +39 -5
- qiskit/circuit/classical/expr/constructors.py +84 -1
- qiskit/circuit/classical/expr/expr.py +83 -13
- qiskit/circuit/classical/expr/visitors.py +83 -0
- qiskit/circuit/classical/types/__init__.py +5 -4
- qiskit/circuit/classicalfunction/__init__.py +1 -0
- qiskit/circuit/commutation_checker.py +86 -51
- qiskit/circuit/controlflow/_builder_utils.py +9 -1
- qiskit/circuit/controlflow/break_loop.py +8 -22
- qiskit/circuit/controlflow/builder.py +116 -1
- qiskit/circuit/controlflow/continue_loop.py +8 -22
- qiskit/circuit/controlflow/control_flow.py +47 -8
- qiskit/circuit/controlflow/for_loop.py +8 -23
- qiskit/circuit/controlflow/if_else.py +13 -27
- qiskit/circuit/controlflow/switch_case.py +14 -21
- qiskit/circuit/controlflow/while_loop.py +9 -23
- qiskit/circuit/controlledgate.py +2 -2
- qiskit/circuit/delay.py +7 -5
- qiskit/circuit/gate.py +20 -7
- qiskit/circuit/instruction.py +31 -30
- qiskit/circuit/instructionset.py +9 -22
- qiskit/circuit/library/__init__.py +3 -13
- qiskit/circuit/library/arithmetic/integer_comparator.py +2 -2
- qiskit/circuit/library/arithmetic/quadratic_form.py +3 -2
- qiskit/circuit/library/blueprintcircuit.py +29 -7
- qiskit/circuit/library/data_preparation/state_preparation.py +6 -5
- qiskit/circuit/library/generalized_gates/diagonal.py +5 -4
- qiskit/circuit/library/generalized_gates/isometry.py +51 -254
- qiskit/circuit/library/generalized_gates/pauli.py +2 -2
- qiskit/circuit/library/generalized_gates/permutation.py +4 -1
- qiskit/circuit/library/generalized_gates/rv.py +15 -11
- qiskit/circuit/library/generalized_gates/uc.py +2 -98
- qiskit/circuit/library/generalized_gates/unitary.py +9 -4
- qiskit/circuit/library/hamiltonian_gate.py +11 -5
- qiskit/circuit/library/n_local/efficient_su2.py +5 -5
- qiskit/circuit/library/n_local/n_local.py +100 -49
- qiskit/circuit/library/n_local/two_local.py +3 -59
- qiskit/circuit/library/overlap.py +3 -3
- qiskit/circuit/library/phase_oracle.py +1 -1
- qiskit/circuit/library/quantum_volume.py +39 -38
- qiskit/circuit/library/standard_gates/equivalence_library.py +50 -0
- qiskit/circuit/library/standard_gates/global_phase.py +4 -2
- qiskit/circuit/library/standard_gates/i.py +1 -2
- qiskit/circuit/library/standard_gates/iswap.py +1 -2
- qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +11 -5
- qiskit/circuit/library/standard_gates/p.py +31 -15
- qiskit/circuit/library/standard_gates/r.py +4 -3
- qiskit/circuit/library/standard_gates/rx.py +7 -4
- qiskit/circuit/library/standard_gates/rxx.py +4 -3
- qiskit/circuit/library/standard_gates/ry.py +7 -4
- qiskit/circuit/library/standard_gates/ryy.py +4 -3
- qiskit/circuit/library/standard_gates/rz.py +7 -4
- qiskit/circuit/library/standard_gates/rzx.py +4 -3
- qiskit/circuit/library/standard_gates/rzz.py +4 -3
- qiskit/circuit/library/standard_gates/s.py +4 -8
- qiskit/circuit/library/standard_gates/t.py +2 -4
- qiskit/circuit/library/standard_gates/u.py +16 -11
- qiskit/circuit/library/standard_gates/u1.py +6 -2
- qiskit/circuit/library/standard_gates/u2.py +4 -2
- qiskit/circuit/library/standard_gates/u3.py +9 -5
- qiskit/circuit/library/standard_gates/x.py +22 -11
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +4 -3
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +7 -5
- qiskit/circuit/library/standard_gates/z.py +1 -2
- qiskit/circuit/measure.py +4 -1
- qiskit/circuit/operation.py +13 -8
- qiskit/circuit/parameter.py +11 -6
- qiskit/circuit/quantumcircuit.py +1910 -260
- qiskit/circuit/quantumcircuitdata.py +2 -2
- qiskit/circuit/reset.py +5 -2
- qiskit/circuit/store.py +95 -0
- qiskit/compiler/assembler.py +22 -22
- qiskit/compiler/transpiler.py +63 -112
- qiskit/converters/__init__.py +17 -2
- qiskit/converters/circuit_to_dag.py +7 -0
- qiskit/converters/circuit_to_dagdependency_v2.py +47 -0
- qiskit/converters/circuit_to_gate.py +2 -0
- qiskit/converters/circuit_to_instruction.py +22 -0
- qiskit/converters/dag_to_circuit.py +4 -0
- qiskit/converters/dag_to_dagdependency_v2.py +44 -0
- qiskit/dagcircuit/collect_blocks.py +15 -10
- qiskit/dagcircuit/dagcircuit.py +434 -124
- qiskit/dagcircuit/dagdependency.py +19 -12
- qiskit/dagcircuit/dagdependency_v2.py +641 -0
- qiskit/dagcircuit/dagdepnode.py +19 -16
- qiskit/dagcircuit/dagnode.py +14 -4
- qiskit/passmanager/passmanager.py +11 -11
- qiskit/primitives/__init__.py +22 -12
- qiskit/primitives/backend_estimator.py +3 -5
- qiskit/primitives/backend_estimator_v2.py +410 -0
- qiskit/primitives/backend_sampler_v2.py +287 -0
- qiskit/primitives/base/base_estimator.py +4 -9
- qiskit/primitives/base/base_sampler.py +2 -2
- qiskit/primitives/containers/__init__.py +6 -4
- qiskit/primitives/containers/bit_array.py +293 -2
- qiskit/primitives/containers/data_bin.py +123 -50
- qiskit/primitives/containers/estimator_pub.py +10 -3
- qiskit/primitives/containers/observables_array.py +2 -2
- qiskit/primitives/containers/pub_result.py +1 -1
- qiskit/primitives/containers/sampler_pub.py +19 -3
- qiskit/primitives/containers/sampler_pub_result.py +74 -0
- qiskit/primitives/containers/shape.py +4 -4
- qiskit/primitives/statevector_estimator.py +4 -4
- qiskit/primitives/statevector_sampler.py +7 -12
- qiskit/providers/__init__.py +65 -34
- qiskit/providers/backend.py +2 -2
- qiskit/providers/backend_compat.py +8 -10
- qiskit/providers/basic_provider/__init__.py +2 -23
- qiskit/providers/basic_provider/basic_provider_tools.py +67 -31
- qiskit/providers/basic_provider/basic_simulator.py +81 -21
- qiskit/providers/fake_provider/__init__.py +1 -1
- qiskit/providers/fake_provider/fake_1q.py +1 -1
- qiskit/providers/fake_provider/fake_backend.py +3 -408
- qiskit/providers/fake_provider/generic_backend_v2.py +26 -14
- qiskit/providers/models/__init__.py +2 -2
- qiskit/providers/provider.py +16 -0
- qiskit/pulse/builder.py +4 -1
- qiskit/pulse/parameter_manager.py +60 -4
- qiskit/pulse/schedule.py +29 -13
- qiskit/pulse/utils.py +61 -20
- qiskit/qasm2/__init__.py +1 -5
- qiskit/qasm2/parse.py +1 -4
- qiskit/qasm3/__init__.py +42 -5
- qiskit/qasm3/ast.py +19 -0
- qiskit/qasm3/exporter.py +178 -106
- qiskit/qasm3/printer.py +27 -5
- qiskit/qobj/converters/pulse_instruction.py +6 -6
- qiskit/qpy/__init__.py +299 -67
- qiskit/qpy/binary_io/circuits.py +216 -47
- qiskit/qpy/binary_io/schedules.py +42 -36
- qiskit/qpy/binary_io/value.py +201 -22
- qiskit/qpy/common.py +1 -1
- qiskit/qpy/exceptions.py +20 -0
- qiskit/qpy/formats.py +29 -0
- qiskit/qpy/type_keys.py +21 -0
- qiskit/quantum_info/analysis/distance.py +3 -3
- qiskit/quantum_info/analysis/make_observable.py +2 -1
- qiskit/quantum_info/analysis/z2_symmetries.py +2 -1
- qiskit/quantum_info/operators/channel/chi.py +9 -8
- qiskit/quantum_info/operators/channel/choi.py +10 -9
- qiskit/quantum_info/operators/channel/kraus.py +2 -1
- qiskit/quantum_info/operators/channel/ptm.py +10 -9
- qiskit/quantum_info/operators/channel/quantum_channel.py +2 -1
- qiskit/quantum_info/operators/channel/stinespring.py +2 -1
- qiskit/quantum_info/operators/channel/superop.py +12 -11
- qiskit/quantum_info/operators/channel/transformations.py +12 -11
- qiskit/quantum_info/operators/dihedral/dihedral.py +5 -4
- qiskit/quantum_info/operators/operator.py +43 -30
- qiskit/quantum_info/operators/scalar_op.py +10 -9
- qiskit/quantum_info/operators/symplectic/base_pauli.py +70 -59
- qiskit/quantum_info/operators/symplectic/clifford.py +36 -9
- qiskit/quantum_info/operators/symplectic/pauli.py +53 -6
- qiskit/quantum_info/operators/symplectic/pauli_list.py +36 -14
- qiskit/quantum_info/operators/symplectic/random.py +3 -2
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +61 -36
- qiskit/quantum_info/states/densitymatrix.py +13 -13
- qiskit/quantum_info/states/stabilizerstate.py +3 -3
- qiskit/quantum_info/states/statevector.py +14 -13
- qiskit/quantum_info/states/utils.py +5 -3
- qiskit/result/__init__.py +6 -0
- qiskit/result/mitigation/correlated_readout_mitigator.py +3 -2
- qiskit/result/mitigation/local_readout_mitigator.py +2 -1
- qiskit/result/mitigation/utils.py +3 -2
- qiskit/scheduler/__init__.py +10 -1
- qiskit/scheduler/methods/__init__.py +1 -8
- qiskit/synthesis/__init__.py +3 -6
- qiskit/synthesis/discrete_basis/commutator_decompose.py +2 -2
- qiskit/synthesis/evolution/lie_trotter.py +7 -14
- qiskit/synthesis/evolution/qdrift.py +3 -4
- qiskit/synthesis/linear/cnot_synth.py +1 -3
- qiskit/synthesis/linear/linear_circuits_utils.py +1 -1
- qiskit/synthesis/linear_phase/cz_depth_lnn.py +4 -18
- qiskit/synthesis/permutation/__init__.py +1 -0
- qiskit/synthesis/permutation/permutation_reverse_lnn.py +90 -0
- qiskit/synthesis/qft/qft_decompose_lnn.py +2 -6
- qiskit/synthesis/two_qubit/two_qubit_decompose.py +165 -954
- qiskit/synthesis/two_qubit/xx_decompose/circuits.py +13 -12
- qiskit/synthesis/two_qubit/xx_decompose/decomposer.py +7 -1
- qiskit/synthesis/unitary/aqc/__init__.py +1 -1
- qiskit/synthesis/unitary/aqc/cnot_structures.py +2 -1
- qiskit/synthesis/unitary/aqc/fast_gradient/fast_gradient.py +2 -1
- qiskit/synthesis/unitary/qsd.py +3 -2
- qiskit/transpiler/__init__.py +7 -3
- qiskit/transpiler/layout.py +140 -61
- qiskit/transpiler/passes/__init__.py +10 -2
- qiskit/transpiler/passes/basis/basis_translator.py +9 -4
- qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
- qiskit/transpiler/passes/basis/unroll_custom_definitions.py +1 -1
- qiskit/transpiler/passes/calibration/rzx_builder.py +2 -1
- qiskit/transpiler/passes/layout/apply_layout.py +8 -3
- qiskit/transpiler/passes/layout/sabre_layout.py +15 -3
- qiskit/transpiler/passes/layout/set_layout.py +1 -1
- qiskit/transpiler/passes/optimization/__init__.py +2 -0
- qiskit/transpiler/passes/optimization/commutation_analysis.py +2 -2
- qiskit/transpiler/passes/optimization/commutative_cancellation.py +1 -1
- qiskit/transpiler/passes/optimization/consolidate_blocks.py +1 -1
- qiskit/transpiler/passes/optimization/cx_cancellation.py +10 -0
- qiskit/transpiler/passes/optimization/elide_permutations.py +114 -0
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +9 -3
- qiskit/transpiler/passes/optimization/optimize_annotated.py +248 -12
- qiskit/transpiler/passes/optimization/remove_final_reset.py +37 -0
- qiskit/transpiler/passes/optimization/template_matching/forward_match.py +1 -3
- qiskit/transpiler/passes/routing/__init__.py +1 -0
- qiskit/transpiler/passes/routing/basic_swap.py +13 -2
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +8 -1
- qiskit/transpiler/passes/routing/lookahead_swap.py +7 -1
- qiskit/transpiler/passes/routing/sabre_swap.py +10 -6
- qiskit/transpiler/passes/routing/star_prerouting.py +417 -0
- qiskit/transpiler/passes/routing/stochastic_swap.py +24 -8
- qiskit/transpiler/passes/scheduling/__init__.py +1 -1
- qiskit/transpiler/passes/scheduling/alap.py +1 -2
- qiskit/transpiler/passes/scheduling/alignments/align_measures.py +1 -2
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +9 -6
- qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +8 -0
- qiskit/transpiler/passes/scheduling/alignments/reschedule.py +13 -4
- qiskit/transpiler/passes/scheduling/asap.py +1 -2
- qiskit/transpiler/passes/scheduling/base_scheduler.py +21 -2
- qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +26 -4
- qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +24 -2
- qiskit/transpiler/passes/scheduling/time_unit_conversion.py +28 -4
- qiskit/transpiler/passes/synthesis/aqc_plugin.py +2 -2
- qiskit/transpiler/passes/synthesis/high_level_synthesis.py +120 -13
- qiskit/transpiler/passes/synthesis/unitary_synthesis.py +162 -55
- qiskit/transpiler/passes/utils/gates_basis.py +3 -3
- qiskit/transpiler/passmanager.py +44 -1
- qiskit/transpiler/preset_passmanagers/__init__.py +3 -3
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +34 -16
- qiskit/transpiler/preset_passmanagers/common.py +4 -6
- qiskit/transpiler/preset_passmanagers/plugin.py +9 -1
- qiskit/utils/__init__.py +3 -2
- qiskit/utils/optionals.py +6 -2
- qiskit/utils/parallel.py +24 -15
- qiskit/visualization/array.py +1 -1
- qiskit/visualization/bloch.py +2 -3
- qiskit/visualization/circuit/matplotlib.py +44 -14
- qiskit/visualization/circuit/text.py +38 -18
- qiskit/visualization/counts_visualization.py +3 -6
- qiskit/visualization/dag_visualization.py +6 -7
- qiskit/visualization/gate_map.py +9 -1
- qiskit/visualization/pulse_v2/interface.py +8 -3
- qiskit/visualization/state_visualization.py +3 -2
- qiskit/visualization/timeline/interface.py +18 -8
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/METADATA +12 -8
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/RECORD +261 -251
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/WHEEL +1 -1
- qiskit/_qasm2.pyd +0 -0
- qiskit/_qasm3.pyd +0 -0
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/entry_points.txt +0 -0
- {qiskit-1.0.2.dist-info → qiskit-1.1.0.dist-info}/top_level.txt +0 -0
@@ -23,6 +23,7 @@ Output:
|
|
23
23
|
"""
|
24
24
|
|
25
25
|
from __future__ import annotations
|
26
|
+
import cmath
|
26
27
|
from functools import reduce
|
27
28
|
import math
|
28
29
|
from operator import itemgetter
|
@@ -55,8 +56,8 @@ def decompose_xxyy_into_xxyy_xx(a_target, b_target, a_source, b_source, interact
|
|
55
56
|
Returns the 6-tuple (r, s, u, v, x, y).
|
56
57
|
"""
|
57
58
|
|
58
|
-
cplus, cminus =
|
59
|
-
splus, sminus =
|
59
|
+
cplus, cminus = math.cos(a_source + b_source), math.cos(a_source - b_source)
|
60
|
+
splus, sminus = math.sin(a_source + b_source), math.sin(a_source - b_source)
|
60
61
|
ca, sa = np.cos(interaction), np.sin(interaction)
|
61
62
|
|
62
63
|
uplusv = (
|
@@ -117,10 +118,10 @@ def decompose_xxyy_into_xxyy_xx(a_target, b_target, a_source, b_source, interact
|
|
117
118
|
]
|
118
119
|
)
|
119
120
|
inner_phases = [
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
121
|
+
cmath.phase(middle_matrix[0, 0]),
|
122
|
+
cmath.phase(middle_matrix[1, 1]),
|
123
|
+
cmath.phase(middle_matrix[1, 2]) + np.pi / 2,
|
124
|
+
cmath.phase(middle_matrix[0, 3]) + np.pi / 2,
|
124
125
|
]
|
125
126
|
r, s, x, y = np.dot(phase_solver, inner_phases)
|
126
127
|
|
@@ -133,8 +134,8 @@ def decompose_xxyy_into_xxyy_xx(a_target, b_target, a_source, b_source, interact
|
|
133
134
|
np.kron(RZGate(2 * x).to_matrix(), RZGate(2 * y).to_matrix()),
|
134
135
|
],
|
135
136
|
)
|
136
|
-
if (abs(
|
137
|
-
abs(
|
137
|
+
if (abs(cmath.phase(generated_matrix[3, 0]) - np.pi / 2) < 0.01 and a_target > b_target) or (
|
138
|
+
abs(cmath.phase(generated_matrix[3, 0]) + np.pi / 2) < 0.01 and a_target < b_target
|
138
139
|
):
|
139
140
|
x += np.pi / 4
|
140
141
|
y += np.pi / 4
|
@@ -231,8 +232,8 @@ def xx_circuit_step(source, strength, target, embodiment):
|
|
231
232
|
# finally conjugated by p_s_f_o.
|
232
233
|
prefix_circuit.compose(permute_source_for_overlap, inplace=True)
|
233
234
|
prefix_circuit.compose(source_reflection, inplace=True)
|
234
|
-
prefix_circuit.global_phase
|
235
|
-
prefix_circuit.global_phase
|
235
|
+
prefix_circuit.global_phase -= cmath.phase(reflection_phase_shift)
|
236
|
+
prefix_circuit.global_phase -= cmath.phase(shift_phase_shift)
|
236
237
|
|
237
238
|
# the affix circuit is constructed in reverse.
|
238
239
|
# first (i.e., innermost), we install the other half of the source transformations and p_s_f_o.
|
@@ -291,8 +292,8 @@ def canonical_xx_circuit(target, strength_sequence, basis_embodiments):
|
|
291
292
|
circuit.compose(basis_embodiments[strength_sequence[0]], inplace=True)
|
292
293
|
circuit.compose(source_reflection.inverse(), inplace=True)
|
293
294
|
circuit.compose(source_shift, inplace=True)
|
294
|
-
circuit.global_phase
|
295
|
-
circuit.global_phase
|
295
|
+
circuit.global_phase -= cmath.phase(shift_phase_shift)
|
296
|
+
circuit.global_phase -= cmath.phase(reflection_phase_shift)
|
296
297
|
|
297
298
|
circuit.compose(affix_circuit, inplace=True)
|
298
299
|
|
@@ -230,6 +230,7 @@ class XXDecomposer:
|
|
230
230
|
unitary: Operator | np.ndarray,
|
231
231
|
basis_fidelity: dict | float | None = None,
|
232
232
|
approximate: bool = True,
|
233
|
+
use_dag: bool = False,
|
233
234
|
) -> QuantumCircuit:
|
234
235
|
r"""
|
235
236
|
Fashions a circuit which (perhaps approximately) models the special unitary operation
|
@@ -246,6 +247,8 @@ class XXDecomposer:
|
|
246
247
|
interpreted as ``{pi: f, pi/2: f/2, pi/3: f/3}``.
|
247
248
|
If given, overrides the basis_fidelity given at init.
|
248
249
|
approximate (bool): Approximates if basis fidelities are less than 1.0 .
|
250
|
+
use_dag (bool): If true a :class:`.DAGCircuit` is returned instead of a
|
251
|
+
:class:`QuantumCircuit` when this class is called.
|
249
252
|
|
250
253
|
Returns:
|
251
254
|
QuantumCircuit: Synthesized circuit.
|
@@ -279,7 +282,7 @@ class XXDecomposer:
|
|
279
282
|
and self.backup_optimizer is not None
|
280
283
|
):
|
281
284
|
pi2_fidelity = 1 - strength_to_infidelity[np.pi / 2]
|
282
|
-
return self.backup_optimizer(unitary, basis_fidelity=pi2_fidelity)
|
285
|
+
return self.backup_optimizer(unitary, basis_fidelity=pi2_fidelity, use_dag=use_dag)
|
283
286
|
|
284
287
|
# change to positive canonical coordinates
|
285
288
|
if weyl_decomposition.c >= -EPSILON:
|
@@ -314,5 +317,8 @@ class XXDecomposer:
|
|
314
317
|
circ.append(UnitaryGate(weyl_decomposition.K1l), [1])
|
315
318
|
|
316
319
|
circ = self._decomposer1q(circ)
|
320
|
+
if use_dag:
|
321
|
+
from qiskit.converters import circuit_to_dag
|
317
322
|
|
323
|
+
return circuit_to_dag(circ, copy_operations=False)
|
318
324
|
return circ
|
@@ -108,7 +108,7 @@ A basic usage of the AQC algorithm should consist of the following steps::
|
|
108
108
|
unitary = ...
|
109
109
|
|
110
110
|
# Define a number of qubits for the algorithm, at least 3 qubits
|
111
|
-
num_qubits =
|
111
|
+
num_qubits = round(math.log2(unitary.shape[0]))
|
112
112
|
|
113
113
|
# Choose a layout of the CNOT structure for the approximate circuit, e.g. ``spin`` for
|
114
114
|
# a linear layout.
|
@@ -13,6 +13,7 @@
|
|
13
13
|
These are the CNOT structure methods: anything that you need for creating CNOT structures.
|
14
14
|
"""
|
15
15
|
import logging
|
16
|
+
import math
|
16
17
|
|
17
18
|
import numpy as np
|
18
19
|
|
@@ -34,7 +35,7 @@ def _lower_limit(num_qubits: int) -> int:
|
|
34
35
|
Returns:
|
35
36
|
lower limit on the number of CNOT units.
|
36
37
|
"""
|
37
|
-
num_cnots =
|
38
|
+
num_cnots = math.ceil((4**num_qubits - 3 * num_qubits - 1) / 4.0)
|
38
39
|
return num_cnots
|
39
40
|
|
40
41
|
|
@@ -14,6 +14,7 @@
|
|
14
14
|
Implementation of the fast objective function class.
|
15
15
|
"""
|
16
16
|
|
17
|
+
import math
|
17
18
|
import warnings
|
18
19
|
import numpy as np
|
19
20
|
|
@@ -110,7 +111,7 @@ class FastCNOTUnitObjective(CNOTUnitObjective):
|
|
110
111
|
# If thetas are the same as used for objective value calculation
|
111
112
|
# before calling this function, then we re-use the computations,
|
112
113
|
# otherwise we have to re-compute the objective.
|
113
|
-
tol =
|
114
|
+
tol = math.sqrt(np.finfo(float).eps)
|
114
115
|
if not np.allclose(param_values, self._circ_thetas, atol=tol, rtol=tol):
|
115
116
|
self.objective(param_values)
|
116
117
|
warnings.warn("gradient is computed before the objective")
|
qiskit/synthesis/unitary/qsd.py
CHANGED
@@ -15,6 +15,7 @@ Quantum Shannon Decomposition.
|
|
15
15
|
Method is described in arXiv:quant-ph/0406176.
|
16
16
|
"""
|
17
17
|
from __future__ import annotations
|
18
|
+
import math
|
18
19
|
from typing import Callable
|
19
20
|
import scipy
|
20
21
|
import numpy as np
|
@@ -93,7 +94,7 @@ def qs_decomposition(
|
|
93
94
|
"""
|
94
95
|
# _depth (int): Internal use parameter to track recursion depth.
|
95
96
|
dim = mat.shape[0]
|
96
|
-
nqubits = int(
|
97
|
+
nqubits = int(math.log2(dim))
|
97
98
|
if np.allclose(np.identity(dim), mat):
|
98
99
|
return QuantumCircuit(nqubits)
|
99
100
|
if dim == 2:
|
@@ -185,7 +186,7 @@ def _demultiplex(um0, um1, opt_a1=False, opt_a2=False, *, _depth=0):
|
|
185
186
|
QuantumCircuit: decomposed circuit
|
186
187
|
"""
|
187
188
|
dim = um0.shape[0] + um1.shape[0] # these should be same dimension
|
188
|
-
nqubits = int(
|
189
|
+
nqubits = int(math.log2(dim))
|
189
190
|
um0um1 = um0 @ um1.T.conjugate()
|
190
191
|
if is_hermitian_matrix(um0um1):
|
191
192
|
eigvals, vmat = scipy.linalg.eigh(um0um1)
|
qiskit/transpiler/__init__.py
CHANGED
@@ -799,7 +799,7 @@ circuit repeatedly will in general result in a distribution of circuit depths an
|
|
799
799
|
at the output.
|
800
800
|
|
801
801
|
In order to highlight this, we run a GHZ circuit 100 times, using a "bad" (disconnected)
|
802
|
-
|
802
|
+
``initial_layout`` in a heavy hex coupling map:
|
803
803
|
|
804
804
|
.. plot::
|
805
805
|
|
@@ -816,18 +816,22 @@ In order to highlight this, we run a GHZ circuit 100 times, using a "bad" (disco
|
|
816
816
|
import matplotlib.pyplot as plt
|
817
817
|
from qiskit import QuantumCircuit, transpile
|
818
818
|
from qiskit.providers.fake_provider import GenericBackendV2
|
819
|
-
|
819
|
+
from qiskit.transpiler import CouplingMap
|
820
|
+
|
821
|
+
coupling_map = CouplingMap.from_heavy_hex(3)
|
822
|
+
backend = GenericBackendV2(coupling_map.size(), coupling_map=coupling_map)
|
820
823
|
|
821
824
|
ghz = QuantumCircuit(15)
|
822
825
|
ghz.h(0)
|
823
826
|
ghz.cx(0, range(1, 15))
|
824
827
|
|
825
828
|
depths = []
|
826
|
-
for
|
829
|
+
for i in range(100):
|
827
830
|
depths.append(
|
828
831
|
transpile(
|
829
832
|
ghz,
|
830
833
|
backend,
|
834
|
+
seed_transpiler=i,
|
831
835
|
layout_method='trivial' # Fixed layout mapped in circuit order
|
832
836
|
).depth()
|
833
837
|
)
|
qiskit/transpiler/layout.py
CHANGED
@@ -368,22 +368,91 @@ class Layout:
|
|
368
368
|
out.add_register(qreg)
|
369
369
|
return out
|
370
370
|
|
371
|
+
def compose(self, other: Layout, qubits: List[Qubit]) -> Layout:
|
372
|
+
"""Compose this layout with another layout.
|
373
|
+
|
374
|
+
If this layout represents a mapping from the P-qubits to the positions of the Q-qubits,
|
375
|
+
and the other layout represents a mapping from the Q-qubits to the positions of
|
376
|
+
the R-qubits, then the composed layout represents a mapping from the P-qubits to the
|
377
|
+
positions of the R-qubits.
|
378
|
+
|
379
|
+
Args:
|
380
|
+
other: The existing :class:`.Layout` to compose this :class:`.Layout` with.
|
381
|
+
qubits: A list of :class:`.Qubit` objects over which ``other`` is defined,
|
382
|
+
used to establish the correspondence between the positions of the ``other``
|
383
|
+
qubits and the actual qubits.
|
384
|
+
|
385
|
+
Returns:
|
386
|
+
A new layout object the represents this layout composed with the ``other`` layout.
|
387
|
+
"""
|
388
|
+
other_v2p = other.get_virtual_bits()
|
389
|
+
return Layout({virt: other_v2p[qubits[phys]] for virt, phys in self._v2p.items()})
|
390
|
+
|
391
|
+
def inverse(self, source_qubits: List[Qubit], target_qubits: List[Qubit]):
|
392
|
+
"""Finds the inverse of this layout.
|
393
|
+
|
394
|
+
This is possible when the layout is a bijective mapping, however the input
|
395
|
+
and the output qubits may be different (in particular, this layout may be
|
396
|
+
the mapping from the extended-with-ancillas virtual qubits to physical qubits).
|
397
|
+
Thus, if this layout represents a mapping from the P-qubits to the positions
|
398
|
+
of the Q-qubits, the inverse layout represents a mapping from the Q-qubits
|
399
|
+
to the positions of the P-qubits.
|
400
|
+
|
401
|
+
Args:
|
402
|
+
source_qubits: A list of :class:`.Qubit` objects representing the domain
|
403
|
+
of the layout.
|
404
|
+
target_qubits: A list of :class:`.Qubit` objects representing the image
|
405
|
+
of the layout.
|
406
|
+
|
407
|
+
Returns:
|
408
|
+
A new layout object the represents the inverse of this layout.
|
409
|
+
"""
|
410
|
+
source_qubit_to_position = {q: p for p, q in enumerate(source_qubits)}
|
411
|
+
return Layout(
|
412
|
+
{
|
413
|
+
target_qubits[pos_phys]: source_qubit_to_position[virt]
|
414
|
+
for virt, pos_phys in self._v2p.items()
|
415
|
+
}
|
416
|
+
)
|
417
|
+
|
418
|
+
def to_permutation(self, qubits: List[Qubit]):
|
419
|
+
"""Creates a permutation corresponding to this layout.
|
420
|
+
|
421
|
+
This is possible when the layout is a bijective mapping with the same
|
422
|
+
source and target qubits (for instance, a "final_layout" corresponds
|
423
|
+
to a permutation of the physical circuit qubits). If this layout is
|
424
|
+
a mapping from qubits to their new positions, the resulting permutation
|
425
|
+
describes which qubits occupy the positions 0, 1, 2, etc. after
|
426
|
+
applying the permutation.
|
427
|
+
|
428
|
+
For example, suppose that the list of qubits is ``[qr_0, qr_1, qr_2]``,
|
429
|
+
and the layout maps ``qr_0`` to ``2``, ``qr_1`` to ``0``, and
|
430
|
+
``qr_2`` to ``1``. In terms of positions in ``qubits``, this maps ``0``
|
431
|
+
to ``2``, ``1`` to ``0`` and ``2`` to ``1``, with the corresponding
|
432
|
+
permutation being ``[1, 2, 0]``.
|
433
|
+
"""
|
434
|
+
|
435
|
+
perm = [None] * len(qubits)
|
436
|
+
for i, q in enumerate(qubits):
|
437
|
+
pos = self._v2p[q]
|
438
|
+
perm[pos] = i
|
439
|
+
return perm
|
440
|
+
|
371
441
|
|
372
442
|
@dataclass
|
373
443
|
class TranspileLayout:
|
374
|
-
r"""Layout attributes
|
444
|
+
r"""Layout attributes for the output circuit from transpiler.
|
375
445
|
|
376
|
-
The transpiler
|
377
|
-
|
378
|
-
and
|
379
|
-
|
380
|
-
the :
|
381
|
-
|
382
|
-
use the helper methods defined on this class.
|
446
|
+
The :mod:`~qiskit.transpiler` is unitary-preserving up to the "initial layout"
|
447
|
+
and "final layout" permutations. The initial layout permutation is caused by
|
448
|
+
setting and applying the initial layout during the :ref:`layout_stage`.
|
449
|
+
The final layout permutation is caused by :class:`~.SwapGate` insertion during
|
450
|
+
the :ref:`routing_stage`. This class provides an interface to reason about these
|
451
|
+
permutations using a variety of helper methods.
|
383
452
|
|
384
|
-
|
385
|
-
|
386
|
-
|
453
|
+
During the layout stage, the transpiler can potentially remap the order of the
|
454
|
+
qubits in the circuit as it fits the circuit to the target backend. For example,
|
455
|
+
let the input circuit be:
|
387
456
|
|
388
457
|
.. plot:
|
389
458
|
:include-source:
|
@@ -397,7 +466,8 @@ class TranspileLayout:
|
|
397
466
|
qc.cx(0, 2)
|
398
467
|
qc.draw("mpl")
|
399
468
|
|
400
|
-
|
469
|
+
|
470
|
+
Suppose that during the layout stage the transpiler reorders the qubits to be:
|
401
471
|
|
402
472
|
.. plot:
|
403
473
|
:include-source:
|
@@ -410,7 +480,7 @@ class TranspileLayout:
|
|
410
480
|
qc.cx(2, 0)
|
411
481
|
qc.draw("mpl")
|
412
482
|
|
413
|
-
|
483
|
+
Then the output of the :meth:`.initial_virtual_layout` method is
|
414
484
|
equivalent to::
|
415
485
|
|
416
486
|
Layout({
|
@@ -421,10 +491,11 @@ class TranspileLayout:
|
|
421
491
|
|
422
492
|
(it is also this attribute in the :meth:`.QuantumCircuit.draw` and
|
423
493
|
:func:`.circuit_drawer` which is used to display the mapping of qubits to
|
424
|
-
positions in circuit visualizations post-transpilation)
|
494
|
+
positions in circuit visualizations post-transpilation).
|
425
495
|
|
426
|
-
Building on
|
427
|
-
insert swap gates
|
496
|
+
Building on the above example, suppose that during the routing stage
|
497
|
+
the transpiler needs to insert swap gates, and the output circuit
|
498
|
+
becomes:
|
428
499
|
|
429
500
|
.. plot:
|
430
501
|
:include-source:
|
@@ -438,19 +509,19 @@ class TranspileLayout:
|
|
438
509
|
qc.cx(2, 1)
|
439
510
|
qc.draw("mpl")
|
440
511
|
|
441
|
-
|
512
|
+
Then the output of the :meth:`routing_permutation` method is::
|
442
513
|
|
443
514
|
[1, 0, 2]
|
444
515
|
|
445
|
-
which maps
|
446
|
-
|
516
|
+
which maps positions of qubits before routing to their final positions
|
517
|
+
after routing.
|
447
518
|
|
448
519
|
There are three public attributes associated with the class, however these
|
449
520
|
are mostly provided for backwards compatibility and represent the internal
|
450
521
|
state from the transpiler. They are defined as:
|
451
522
|
|
452
523
|
* :attr:`initial_layout` - This attribute is used to model the
|
453
|
-
permutation caused by the :ref:`layout_stage
|
524
|
+
permutation caused by the :ref:`layout_stage`. It is a
|
454
525
|
:class:`~.Layout` object that maps the input :class:`~.QuantumCircuit`\s
|
455
526
|
:class:`~.circuit.Qubit` objects to the position in the output
|
456
527
|
:class:`.QuantumCircuit.qubits` list.
|
@@ -461,18 +532,19 @@ class TranspileLayout:
|
|
461
532
|
:attr:`.QuantumCircuit.qubits` in the original circuit. This
|
462
533
|
is needed when computing the permutation of the :class:`Operator` of
|
463
534
|
the circuit (and used by :meth:`.Operator.from_circuit`).
|
464
|
-
* :attr:`final_layout` - This is
|
465
|
-
|
466
|
-
|
467
|
-
:
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
535
|
+
* :attr:`final_layout` - This attribute is used to model the
|
536
|
+
permutation caused by the :ref:`routing_stage`. It is a
|
537
|
+
:class:`~.Layout` object that maps the output circuit's qubits from
|
538
|
+
:class:`.QuantumCircuit.qubits` in the output circuit to their final
|
539
|
+
positions after routing. Importantly, this only represents the
|
540
|
+
permutation caused by inserting :class:`~.SwapGate`\s into
|
541
|
+
the :class:`~.QuantumCircuit` during the :ref:`routing_stage`.
|
542
|
+
It is **not** a mapping from the original input circuit's position
|
543
|
+
to the final position at the end of the transpiled circuit.
|
544
|
+
If you need this, you can use the :meth:`.final_index_layout` to generate this.
|
545
|
+
If :attr:`final_layout` is set to ``None``, this indicates that routing was not
|
546
|
+
run, and can be considered equivalent to a trivial layout with the qubits from
|
547
|
+
the output circuit's :attr:`~.QuantumCircuit.qubits` list.
|
476
548
|
"""
|
477
549
|
|
478
550
|
initial_layout: Layout
|
@@ -485,8 +557,8 @@ class TranspileLayout:
|
|
485
557
|
"""Return a :class:`.Layout` object for the initial layout.
|
486
558
|
|
487
559
|
This returns a mapping of virtual :class:`~.circuit.Qubit` objects in the input
|
488
|
-
circuit to the physical
|
489
|
-
to the :attr:`.initial_layout` attribute.
|
560
|
+
circuit to the positions of the physical qubits selected during layout.
|
561
|
+
This is analogous to the :attr:`.initial_layout` attribute.
|
490
562
|
|
491
563
|
Args:
|
492
564
|
filter_ancillas: If set to ``True`` only qubits in the input circuit
|
@@ -494,7 +566,7 @@ class TranspileLayout:
|
|
494
566
|
output circuit will be filtered from the returned object.
|
495
567
|
Returns:
|
496
568
|
A layout object mapping the input circuit's :class:`~.circuit.Qubit`
|
497
|
-
objects to the selected physical qubits.
|
569
|
+
objects to the positions of the selected physical qubits.
|
498
570
|
"""
|
499
571
|
if not filter_ancillas:
|
500
572
|
return self.initial_layout
|
@@ -507,7 +579,7 @@ class TranspileLayout:
|
|
507
579
|
)
|
508
580
|
|
509
581
|
def initial_index_layout(self, filter_ancillas: bool = False) -> List[int]:
|
510
|
-
"""Generate an initial layout as an array of integers
|
582
|
+
"""Generate an initial layout as an array of integers.
|
511
583
|
|
512
584
|
Args:
|
513
585
|
filter_ancillas: If set to ``True`` any ancilla qubits added
|
@@ -531,16 +603,15 @@ class TranspileLayout:
|
|
531
603
|
return output
|
532
604
|
|
533
605
|
def routing_permutation(self) -> List[int]:
|
534
|
-
"""Generate a final layout as an array of integers
|
606
|
+
"""Generate a final layout as an array of integers.
|
535
607
|
|
536
608
|
If there is no :attr:`.final_layout` attribute present then that indicates
|
537
609
|
there was no output permutation caused by routing or other transpiler
|
538
|
-
transforms. In this case the function will return a list of ``[0, 1, 2, .., n]
|
539
|
-
to indicate this
|
610
|
+
transforms. In this case the function will return a list of ``[0, 1, 2, .., n]``.
|
540
611
|
|
541
612
|
Returns:
|
542
613
|
A layout array that maps a position in the array to its new position in the output
|
543
|
-
circuit
|
614
|
+
circuit.
|
544
615
|
"""
|
545
616
|
if self.final_layout is None:
|
546
617
|
return list(range(len(self._output_qubit_list)))
|
@@ -548,9 +619,9 @@ class TranspileLayout:
|
|
548
619
|
return [virtual_map[virt] for virt in self._output_qubit_list]
|
549
620
|
|
550
621
|
def final_index_layout(self, filter_ancillas: bool = True) -> List[int]:
|
551
|
-
"""Generate the final layout as an array of integers
|
622
|
+
"""Generate the final layout as an array of integers.
|
552
623
|
|
553
|
-
This method will generate an array of final positions for each qubit in the
|
624
|
+
This method will generate an array of final positions for each qubit in the input circuit.
|
554
625
|
For example, if you had an input circuit like::
|
555
626
|
|
556
627
|
qc = QuantumCircuit(3)
|
@@ -561,18 +632,22 @@ class TranspileLayout:
|
|
561
632
|
and the output from the transpiler was::
|
562
633
|
|
563
634
|
tqc = QuantumCircuit(3)
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
635
|
+
tqc.h(2)
|
636
|
+
tqc.cx(2, 1)
|
637
|
+
tqc.swap(0, 1)
|
638
|
+
tqc.cx(2, 1)
|
568
639
|
|
569
|
-
then the
|
640
|
+
then the :meth:`.final_index_layout` method returns::
|
570
641
|
|
571
642
|
[2, 0, 1]
|
572
643
|
|
573
|
-
|
574
|
-
|
575
|
-
|
644
|
+
This can be seen as follows. Qubit 0 in the original circuit is mapped to qubit 2
|
645
|
+
in the output circuit during the layout stage, which is mapped to qubit 2 during the
|
646
|
+
routing stage. Qubit 1 in the original circuit is mapped to qubit 1 in the output
|
647
|
+
circuit during the layout stage, which is mapped to qubit 0 during the routing
|
648
|
+
stage. Qubit 2 in the original circuit is mapped to qubit 0 in the output circuit
|
649
|
+
during the layout stage, which is mapped to qubit 1 during the routing stage.
|
650
|
+
The output list length will be as wide as the input circuit's number of qubits,
|
576
651
|
as the output list from this method is for tracking the permutation of qubits in the
|
577
652
|
original circuit caused by the transpiler.
|
578
653
|
|
@@ -581,7 +656,7 @@ class TranspileLayout:
|
|
581
656
|
included in the layout.
|
582
657
|
|
583
658
|
Returns:
|
584
|
-
A list of final positions for each input circuit qubit
|
659
|
+
A list of final positions for each input circuit qubit.
|
585
660
|
"""
|
586
661
|
if self._input_qubit_count is None:
|
587
662
|
# TODO: After there is a way to differentiate the ancilla qubits added by the transpiler
|
@@ -614,9 +689,9 @@ class TranspileLayout:
|
|
614
689
|
return qubit_indices
|
615
690
|
|
616
691
|
def final_virtual_layout(self, filter_ancillas: bool = True) -> Layout:
|
617
|
-
"""Generate the final layout as a :class:`.Layout` object
|
692
|
+
"""Generate the final layout as a :class:`.Layout` object.
|
618
693
|
|
619
|
-
This method will generate an array of final positions for each qubit in the
|
694
|
+
This method will generate an array of final positions for each qubit in the input circuit.
|
620
695
|
For example, if you had an input circuit like::
|
621
696
|
|
622
697
|
qc = QuantumCircuit(3)
|
@@ -627,10 +702,10 @@ class TranspileLayout:
|
|
627
702
|
and the output from the transpiler was::
|
628
703
|
|
629
704
|
tqc = QuantumCircuit(3)
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
705
|
+
tqc.h(2)
|
706
|
+
tqc.cx(2, 1)
|
707
|
+
tqc.swap(0, 1)
|
708
|
+
tqc.cx(2, 1)
|
634
709
|
|
635
710
|
then the return from this function would be a layout object::
|
636
711
|
|
@@ -640,9 +715,13 @@ class TranspileLayout:
|
|
640
715
|
qc.qubits[2]: 1,
|
641
716
|
})
|
642
717
|
|
643
|
-
|
644
|
-
|
645
|
-
|
718
|
+
This can be seen as follows. Qubit 0 in the original circuit is mapped to qubit 2
|
719
|
+
in the output circuit during the layout stage, which is mapped to qubit 2 during the
|
720
|
+
routing stage. Qubit 1 in the original circuit is mapped to qubit 1 in the output
|
721
|
+
circuit during the layout stage, which is mapped to qubit 0 during the routing
|
722
|
+
stage. Qubit 2 in the original circuit is mapped to qubit 0 in the output circuit
|
723
|
+
during the layout stage, which is mapped to qubit 1 during the routing stage.
|
724
|
+
The output list length will be as wide as the input circuit's number of qubits,
|
646
725
|
as the output list from this method is for tracking the permutation of qubits in the
|
647
726
|
original circuit caused by the transpiler.
|
648
727
|
|
@@ -651,7 +730,7 @@ class TranspileLayout:
|
|
651
730
|
included in the layout.
|
652
731
|
|
653
732
|
Returns:
|
654
|
-
A layout object mapping to the final positions for each qubit
|
733
|
+
A layout object mapping to the final positions for each qubit.
|
655
734
|
"""
|
656
735
|
res = self.final_index_layout(filter_ancillas=filter_ancillas)
|
657
736
|
pos_to_virt = {v: k for k, v in self.input_qubit_mapping.items()}
|
@@ -46,6 +46,7 @@ Routing
|
|
46
46
|
StochasticSwap
|
47
47
|
SabreSwap
|
48
48
|
Commuting2qGateRouter
|
49
|
+
StarPreRouting
|
49
50
|
|
50
51
|
Basis Change
|
51
52
|
============
|
@@ -81,11 +82,13 @@ Optimizations
|
|
81
82
|
Optimize1qGatesSimpleCommutation
|
82
83
|
RemoveDiagonalGatesBeforeMeasure
|
83
84
|
RemoveResetInZeroState
|
85
|
+
RemoveFinalReset
|
84
86
|
HoareOptimizer
|
85
87
|
TemplateOptimization
|
86
88
|
EchoRZXWeylDecomposition
|
87
89
|
ResetAfterMeasureSimplification
|
88
90
|
OptimizeCliffords
|
91
|
+
ElidePermutations
|
89
92
|
NormalizeRXAngle
|
90
93
|
OptimizeAnnotated
|
91
94
|
|
@@ -151,8 +154,10 @@ The synthesis transpiler plugin documentation can be found in the
|
|
151
154
|
HLSConfig
|
152
155
|
SolovayKitaev
|
153
156
|
|
154
|
-
Post Layout
|
155
|
-
|
157
|
+
Post Layout
|
158
|
+
===========
|
159
|
+
|
160
|
+
These are post qubit selection.
|
156
161
|
|
157
162
|
.. autosummary::
|
158
163
|
:toctree: ../stubs/
|
@@ -203,6 +208,7 @@ from .routing import LookaheadSwap
|
|
203
208
|
from .routing import StochasticSwap
|
204
209
|
from .routing import SabreSwap
|
205
210
|
from .routing import Commuting2qGateRouter
|
211
|
+
from .routing import StarPreRouting
|
206
212
|
|
207
213
|
# basis change
|
208
214
|
from .basis import Decompose
|
@@ -225,6 +231,7 @@ from .optimization import CXCancellation
|
|
225
231
|
from .optimization import Optimize1qGatesSimpleCommutation
|
226
232
|
from .optimization import OptimizeSwapBeforeMeasure
|
227
233
|
from .optimization import RemoveResetInZeroState
|
234
|
+
from .optimization import RemoveFinalReset
|
228
235
|
from .optimization import RemoveDiagonalGatesBeforeMeasure
|
229
236
|
from .optimization import HoareOptimizer
|
230
237
|
from .optimization import TemplateOptimization
|
@@ -234,6 +241,7 @@ from .optimization import CollectLinearFunctions
|
|
234
241
|
from .optimization import CollectCliffords
|
235
242
|
from .optimization import ResetAfterMeasureSimplification
|
236
243
|
from .optimization import OptimizeCliffords
|
244
|
+
from .optimization import ElidePermutations
|
237
245
|
from .optimization import NormalizeRXAngle
|
238
246
|
from .optimization import OptimizeAnnotated
|
239
247
|
|
@@ -97,8 +97,8 @@ class BasisTranslator(TransformationPass):
|
|
97
97
|
|
98
98
|
When this error occurs it typically means that either the target basis
|
99
99
|
is not universal or there are additional equivalence rules needed in the
|
100
|
-
:
|
101
|
-
:class
|
100
|
+
:class:`~.EquivalenceLibrary` instance being used by the
|
101
|
+
:class:`~.BasisTranslator` pass. You can refer to
|
102
102
|
:ref:`custom_basis_gates` for details on adding custom equivalence rules.
|
103
103
|
"""
|
104
104
|
|
@@ -148,16 +148,21 @@ class BasisTranslator(TransformationPass):
|
|
148
148
|
|
149
149
|
# Names of instructions assumed to supported by any backend.
|
150
150
|
if self._target is None:
|
151
|
-
basic_instrs = ["measure", "reset", "barrier", "snapshot", "delay"]
|
151
|
+
basic_instrs = ["measure", "reset", "barrier", "snapshot", "delay", "store"]
|
152
152
|
target_basis = set(self._target_basis)
|
153
153
|
source_basis = set(self._extract_basis(dag))
|
154
154
|
qargs_local_source_basis = {}
|
155
155
|
else:
|
156
|
-
basic_instrs = ["barrier", "snapshot"]
|
156
|
+
basic_instrs = ["barrier", "snapshot", "store"]
|
157
157
|
target_basis = self._target.keys() - set(self._non_global_operations)
|
158
158
|
source_basis, qargs_local_source_basis = self._extract_basis_target(dag, qarg_indices)
|
159
159
|
|
160
160
|
target_basis = set(target_basis).union(basic_instrs)
|
161
|
+
# If the source basis is a subset of the target basis and we have no circuit
|
162
|
+
# instructions on qargs that have non-global operations there is nothing to
|
163
|
+
# translate and we can exit early.
|
164
|
+
if source_basis.issubset(target_basis) and not qargs_local_source_basis:
|
165
|
+
return dag
|
161
166
|
|
162
167
|
logger.info(
|
163
168
|
"Begin BasisTranslator from source basis %s to target basis %s.",
|
@@ -63,7 +63,7 @@ class Unroll3qOrMore(TransformationPass):
|
|
63
63
|
|
64
64
|
if self.target is not None:
|
65
65
|
# Treat target instructions as global since this pass can be run
|
66
|
-
# prior to layout and routing we don't have
|
66
|
+
# prior to layout and routing we don't have physical qubits from
|
67
67
|
# the circuit yet
|
68
68
|
if node.name in self.target:
|
69
69
|
continue
|