qiskit 1.1.2__cp38-abi3-win32.whl → 1.2.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 -24
- qiskit/_accelerate.pyd +0 -0
- qiskit/_numpy_compat.py +1 -1
- qiskit/assembler/assemble_circuits.py +107 -64
- qiskit/assembler/assemble_schedules.py +5 -12
- qiskit/assembler/disassemble.py +10 -1
- qiskit/circuit/__init__.py +6 -3
- qiskit/circuit/_classical_resource_map.py +5 -5
- qiskit/circuit/_utils.py +0 -13
- qiskit/circuit/add_control.py +1 -1
- qiskit/circuit/annotated_operation.py +23 -1
- qiskit/circuit/classical/expr/expr.py +4 -4
- qiskit/circuit/classical/expr/visitors.py +1 -1
- qiskit/circuit/classical/types/__init__.py +1 -1
- qiskit/circuit/classical/types/types.py +2 -2
- qiskit/circuit/classicalfunction/boolean_expression.py +1 -1
- qiskit/circuit/classicalfunction/classical_function_visitor.py +5 -5
- qiskit/circuit/classicalfunction/utils.py +1 -1
- qiskit/circuit/classicalregister.py +1 -1
- qiskit/circuit/commutation_checker.py +83 -35
- qiskit/circuit/controlflow/_builder_utils.py +1 -1
- qiskit/circuit/controlflow/builder.py +10 -6
- qiskit/circuit/controlflow/if_else.py +2 -2
- qiskit/circuit/controlflow/switch_case.py +1 -1
- qiskit/circuit/delay.py +1 -1
- qiskit/circuit/duration.py +2 -2
- qiskit/circuit/equivalence.py +5 -7
- qiskit/circuit/gate.py +11 -8
- qiskit/circuit/instruction.py +31 -13
- qiskit/circuit/instructionset.py +2 -5
- qiskit/circuit/library/__init__.py +2 -1
- qiskit/circuit/library/arithmetic/linear_amplitude_function.py +1 -1
- qiskit/circuit/library/arithmetic/linear_pauli_rotations.py +1 -1
- qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +1 -1
- qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +1 -1
- qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +3 -3
- qiskit/circuit/library/arithmetic/polynomial_pauli_rotations.py +1 -1
- qiskit/circuit/library/basis_change/__init__.py +1 -1
- qiskit/circuit/library/basis_change/qft.py +40 -6
- qiskit/circuit/library/blueprintcircuit.py +3 -5
- qiskit/circuit/library/data_preparation/__init__.py +9 -2
- qiskit/circuit/library/data_preparation/initializer.py +8 -0
- qiskit/circuit/library/data_preparation/state_preparation.py +98 -178
- qiskit/circuit/library/generalized_gates/isometry.py +8 -8
- qiskit/circuit/library/generalized_gates/linear_function.py +3 -2
- qiskit/circuit/library/generalized_gates/mcg_up_to_diagonal.py +4 -4
- qiskit/circuit/library/generalized_gates/permutation.py +8 -9
- qiskit/circuit/library/generalized_gates/uc.py +3 -3
- qiskit/circuit/library/generalized_gates/uc_pauli_rot.py +2 -2
- qiskit/circuit/library/generalized_gates/unitary.py +13 -11
- qiskit/circuit/library/graph_state.py +1 -1
- qiskit/circuit/library/hamiltonian_gate.py +1 -2
- qiskit/circuit/library/hidden_linear_function.py +1 -1
- qiskit/circuit/library/n_local/evolved_operator_ansatz.py +3 -2
- qiskit/circuit/library/n_local/n_local.py +4 -5
- qiskit/circuit/library/n_local/pauli_two_design.py +1 -1
- qiskit/circuit/library/n_local/qaoa_ansatz.py +6 -8
- qiskit/circuit/library/n_local/two_local.py +1 -1
- qiskit/circuit/library/overlap.py +11 -5
- qiskit/circuit/library/pauli_evolution.py +7 -3
- qiskit/circuit/library/standard_gates/dcx.py +3 -0
- qiskit/circuit/library/standard_gates/ecr.py +3 -0
- qiskit/circuit/library/standard_gates/global_phase.py +3 -0
- qiskit/circuit/library/standard_gates/h.py +13 -5
- qiskit/circuit/library/standard_gates/i.py +3 -0
- qiskit/circuit/library/standard_gates/iswap.py +3 -0
- qiskit/circuit/library/standard_gates/multi_control_rotation_gates.py +19 -10
- qiskit/circuit/library/standard_gates/p.py +14 -9
- qiskit/circuit/library/standard_gates/r.py +3 -0
- qiskit/circuit/library/standard_gates/rx.py +21 -6
- qiskit/circuit/library/standard_gates/rxx.py +40 -1
- qiskit/circuit/library/standard_gates/ry.py +21 -6
- qiskit/circuit/library/standard_gates/ryy.py +40 -1
- qiskit/circuit/library/standard_gates/rz.py +22 -6
- qiskit/circuit/library/standard_gates/rzx.py +40 -1
- qiskit/circuit/library/standard_gates/rzz.py +41 -2
- qiskit/circuit/library/standard_gates/s.py +77 -0
- qiskit/circuit/library/standard_gates/swap.py +12 -5
- qiskit/circuit/library/standard_gates/sx.py +14 -5
- qiskit/circuit/library/standard_gates/t.py +5 -0
- qiskit/circuit/library/standard_gates/u.py +22 -7
- qiskit/circuit/library/standard_gates/u1.py +8 -3
- qiskit/circuit/library/standard_gates/u2.py +3 -0
- qiskit/circuit/library/standard_gates/u3.py +22 -7
- qiskit/circuit/library/standard_gates/x.py +156 -92
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +40 -1
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +52 -11
- qiskit/circuit/library/standard_gates/y.py +6 -1
- qiskit/circuit/library/standard_gates/z.py +8 -1
- qiskit/circuit/operation.py +1 -1
- qiskit/circuit/parameter.py +9 -10
- qiskit/circuit/parameterexpression.py +16 -13
- qiskit/circuit/parametertable.py +1 -190
- qiskit/circuit/parametervector.py +1 -1
- qiskit/circuit/quantumcircuit.py +395 -387
- qiskit/circuit/quantumcircuitdata.py +3 -5
- qiskit/circuit/quantumregister.py +1 -1
- qiskit/circuit/random/__init__.py +1 -1
- qiskit/circuit/random/utils.py +175 -26
- qiskit/circuit/register.py +5 -7
- qiskit/circuit/singleton.py +3 -3
- qiskit/circuit/tools/pi_check.py +4 -4
- qiskit/compiler/assembler.py +95 -24
- qiskit/compiler/scheduler.py +2 -2
- qiskit/compiler/transpiler.py +42 -128
- qiskit/converters/circuit_to_dag.py +4 -6
- qiskit/converters/circuit_to_gate.py +4 -8
- qiskit/converters/circuit_to_instruction.py +5 -17
- qiskit/converters/dag_to_circuit.py +2 -6
- qiskit/dagcircuit/collect_blocks.py +2 -2
- qiskit/dagcircuit/dagcircuit.py +190 -187
- qiskit/dagcircuit/dagdependency.py +4 -4
- qiskit/dagcircuit/dagdependency_v2.py +4 -4
- qiskit/dagcircuit/dagdepnode.py +1 -1
- qiskit/dagcircuit/dagnode.py +66 -157
- qiskit/passmanager/flow_controllers.py +1 -1
- qiskit/passmanager/passmanager.py +3 -3
- qiskit/primitives/__init__.py +1 -5
- qiskit/primitives/backend_estimator.py +25 -15
- qiskit/primitives/backend_estimator_v2.py +31 -7
- qiskit/primitives/backend_sampler.py +21 -12
- qiskit/primitives/backend_sampler_v2.py +12 -3
- qiskit/primitives/base/base_estimator.py +31 -4
- qiskit/primitives/base/base_primitive.py +2 -2
- qiskit/primitives/base/base_result.py +2 -2
- qiskit/primitives/base/base_sampler.py +26 -2
- qiskit/primitives/base/estimator_result.py +2 -2
- qiskit/primitives/base/sampler_result.py +2 -2
- qiskit/primitives/containers/__init__.py +0 -1
- qiskit/primitives/containers/bindings_array.py +2 -2
- qiskit/primitives/containers/bit_array.py +108 -10
- qiskit/primitives/containers/shape.py +3 -3
- qiskit/primitives/estimator.py +9 -2
- qiskit/primitives/primitive_job.py +1 -1
- qiskit/primitives/sampler.py +10 -3
- qiskit/primitives/statevector_estimator.py +5 -3
- qiskit/primitives/statevector_sampler.py +11 -5
- qiskit/primitives/utils.py +16 -0
- qiskit/providers/backend.py +15 -6
- qiskit/providers/backend_compat.py +7 -4
- qiskit/providers/basic_provider/basic_provider_tools.py +1 -1
- qiskit/providers/basic_provider/basic_simulator.py +33 -25
- qiskit/providers/fake_provider/fake_backend.py +10 -3
- qiskit/providers/fake_provider/fake_openpulse_2q.py +157 -149
- qiskit/providers/fake_provider/fake_openpulse_3q.py +228 -220
- qiskit/providers/fake_provider/fake_pulse_backend.py +2 -1
- qiskit/providers/fake_provider/fake_qasm_backend.py +7 -2
- qiskit/providers/fake_provider/generic_backend_v2.py +514 -68
- qiskit/providers/models/__init__.py +48 -11
- qiskit/providers/models/backendconfiguration.py +50 -4
- qiskit/providers/models/backendproperties.py +13 -2
- qiskit/providers/models/pulsedefaults.py +10 -11
- qiskit/providers/options.py +13 -13
- qiskit/providers/providerutils.py +3 -1
- qiskit/pulse/configuration.py +8 -12
- qiskit/pulse/instruction_schedule_map.py +3 -5
- qiskit/pulse/instructions/acquire.py +7 -8
- qiskit/pulse/instructions/instruction.py +2 -3
- qiskit/pulse/library/samplers/decorators.py +5 -9
- qiskit/pulse/library/symbolic_pulses.py +4 -7
- qiskit/pulse/library/waveform.py +2 -5
- qiskit/pulse/macros.py +11 -6
- qiskit/pulse/parser.py +8 -10
- qiskit/pulse/schedule.py +9 -17
- qiskit/pulse/transforms/alignments.py +1 -3
- qiskit/pulse/utils.py +1 -2
- qiskit/qasm/libs/stdgates.inc +35 -28
- qiskit/qasm2/__init__.py +7 -7
- qiskit/qasm2/export.py +5 -9
- qiskit/qasm2/parse.py +1 -1
- qiskit/qasm3/ast.py +9 -25
- qiskit/qasm3/exporter.py +582 -479
- qiskit/qasm3/printer.py +7 -16
- qiskit/qobj/common.py +10 -0
- qiskit/qobj/converters/lo_config.py +9 -0
- qiskit/qobj/converters/pulse_instruction.py +13 -6
- qiskit/qobj/pulse_qobj.py +69 -15
- qiskit/qobj/qasm_qobj.py +72 -20
- qiskit/qobj/utils.py +9 -0
- qiskit/qpy/__init__.py +1 -1
- qiskit/qpy/binary_io/circuits.py +8 -5
- qiskit/qpy/binary_io/schedules.py +1 -1
- qiskit/qpy/binary_io/value.py +3 -3
- qiskit/qpy/interface.py +3 -2
- qiskit/qpy/type_keys.py +2 -2
- qiskit/quantum_info/operators/channel/quantum_channel.py +3 -6
- qiskit/quantum_info/operators/channel/superop.py +2 -2
- qiskit/quantum_info/operators/channel/transformations.py +1 -1
- qiskit/quantum_info/operators/dihedral/dihedral.py +3 -4
- qiskit/quantum_info/operators/dihedral/dihedral_circuits.py +1 -3
- qiskit/quantum_info/operators/dihedral/random.py +6 -3
- qiskit/quantum_info/operators/measures.py +2 -2
- qiskit/quantum_info/operators/op_shape.py +12 -20
- qiskit/quantum_info/operators/operator.py +14 -21
- qiskit/quantum_info/operators/predicates.py +1 -0
- qiskit/quantum_info/operators/symplectic/base_pauli.py +7 -11
- qiskit/quantum_info/operators/symplectic/clifford.py +1 -1
- qiskit/quantum_info/operators/symplectic/pauli.py +3 -3
- qiskit/quantum_info/operators/symplectic/pauli_list.py +9 -10
- qiskit/quantum_info/operators/symplectic/random.py +1 -1
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +15 -17
- qiskit/quantum_info/quaternion.py +1 -1
- qiskit/quantum_info/states/densitymatrix.py +5 -8
- qiskit/quantum_info/states/stabilizerstate.py +128 -37
- qiskit/quantum_info/states/statevector.py +4 -8
- qiskit/result/counts.py +2 -2
- qiskit/result/mitigation/correlated_readout_mitigator.py +2 -2
- qiskit/result/mitigation/local_readout_mitigator.py +2 -2
- qiskit/result/mitigation/utils.py +1 -3
- qiskit/result/models.py +17 -16
- qiskit/result/result.py +15 -20
- qiskit/scheduler/lowering.py +2 -2
- qiskit/synthesis/__init__.py +2 -1
- qiskit/synthesis/clifford/__init__.py +1 -1
- qiskit/synthesis/clifford/clifford_decompose_ag.py +2 -2
- qiskit/synthesis/clifford/clifford_decompose_bm.py +10 -240
- qiskit/synthesis/clifford/clifford_decompose_greedy.py +9 -303
- qiskit/synthesis/clifford/clifford_decompose_layers.py +25 -23
- qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_full.py +1 -1
- qiskit/synthesis/cnotdihedral/cnotdihedral_decompose_general.py +1 -1
- qiskit/synthesis/discrete_basis/generate_basis_approximations.py +1 -1
- qiskit/synthesis/discrete_basis/solovay_kitaev.py +2 -2
- qiskit/synthesis/evolution/evolution_synthesis.py +4 -2
- qiskit/synthesis/evolution/lie_trotter.py +46 -19
- qiskit/synthesis/evolution/product_formula.py +111 -55
- qiskit/synthesis/evolution/qdrift.py +40 -10
- qiskit/synthesis/evolution/suzuki_trotter.py +43 -33
- qiskit/synthesis/linear/__init__.py +1 -0
- qiskit/synthesis/linear/cnot_synth.py +22 -96
- qiskit/synthesis/linear/linear_depth_lnn.py +8 -8
- qiskit/synthesis/linear/linear_matrix_utils.py +13 -161
- qiskit/synthesis/linear_phase/cnot_phase_synth.py +1 -1
- qiskit/synthesis/linear_phase/cx_cz_depth_lnn.py +3 -3
- qiskit/synthesis/linear_phase/cz_depth_lnn.py +1 -1
- qiskit/synthesis/one_qubit/one_qubit_decompose.py +29 -29
- qiskit/synthesis/permutation/permutation_full.py +5 -29
- qiskit/synthesis/permutation/permutation_lnn.py +2 -24
- qiskit/synthesis/permutation/permutation_utils.py +2 -59
- qiskit/synthesis/qft/__init__.py +1 -0
- qiskit/synthesis/qft/qft_decompose_full.py +79 -0
- qiskit/synthesis/qft/qft_decompose_lnn.py +17 -9
- qiskit/synthesis/stabilizer/stabilizer_circuit.py +6 -6
- qiskit/synthesis/stabilizer/stabilizer_decompose.py +2 -2
- qiskit/synthesis/two_qubit/local_invariance.py +8 -38
- qiskit/synthesis/two_qubit/two_qubit_decompose.py +48 -129
- qiskit/synthesis/unitary/aqc/cnot_structures.py +1 -1
- qiskit/synthesis/unitary/qsd.py +5 -3
- qiskit/transpiler/__init__.py +1 -0
- qiskit/transpiler/basepasses.py +1 -1
- qiskit/transpiler/coupling.py +3 -3
- qiskit/transpiler/instruction_durations.py +1 -2
- qiskit/transpiler/layout.py +3 -3
- qiskit/transpiler/passes/__init__.py +2 -0
- qiskit/transpiler/passes/basis/basis_translator.py +84 -64
- qiskit/transpiler/passes/basis/translate_parameterized.py +3 -5
- qiskit/transpiler/passes/basis/unroll_3q_or_more.py +1 -1
- qiskit/transpiler/passes/basis/unroll_custom_definitions.py +10 -10
- qiskit/transpiler/passes/calibration/rx_builder.py +3 -3
- qiskit/transpiler/passes/calibration/rzx_builder.py +3 -3
- qiskit/transpiler/passes/layout/apply_layout.py +13 -3
- qiskit/transpiler/passes/layout/sabre_layout.py +10 -8
- qiskit/transpiler/passes/layout/sabre_pre_layout.py +4 -1
- qiskit/transpiler/passes/layout/set_layout.py +2 -2
- qiskit/transpiler/passes/layout/vf2_layout.py +1 -1
- qiskit/transpiler/passes/layout/vf2_utils.py +3 -3
- qiskit/transpiler/passes/optimization/__init__.py +1 -0
- qiskit/transpiler/passes/optimization/collect_multiqubit_blocks.py +2 -2
- qiskit/transpiler/passes/optimization/commutation_analysis.py +7 -10
- qiskit/transpiler/passes/optimization/commutative_cancellation.py +35 -19
- qiskit/transpiler/passes/optimization/consolidate_blocks.py +17 -8
- qiskit/transpiler/passes/optimization/inverse_cancellation.py +6 -6
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +64 -41
- qiskit/transpiler/passes/optimization/optimize_1q_gates.py +1 -1
- qiskit/transpiler/passes/optimization/split_2q_unitaries.py +83 -0
- qiskit/transpiler/passes/optimization/template_matching/backward_match.py +1 -1
- qiskit/transpiler/passes/optimization/template_matching/forward_match.py +2 -2
- qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +1 -1
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/commuting_2q_gate_router.py +3 -2
- qiskit/transpiler/passes/routing/commuting_2q_gate_routing/swap_strategy.py +1 -1
- qiskit/transpiler/passes/routing/layout_transformation.py +2 -1
- qiskit/transpiler/passes/routing/sabre_swap.py +35 -26
- qiskit/transpiler/passes/routing/star_prerouting.py +80 -105
- qiskit/transpiler/passes/routing/stochastic_swap.py +1 -3
- qiskit/transpiler/passes/scheduling/alap.py +1 -2
- qiskit/transpiler/passes/scheduling/alignments/__init__.py +2 -2
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/pulse_gate_validation.py +2 -2
- qiskit/transpiler/passes/scheduling/alignments/reschedule.py +1 -1
- qiskit/transpiler/passes/scheduling/asap.py +1 -2
- qiskit/transpiler/passes/scheduling/base_scheduler.py +5 -5
- qiskit/transpiler/passes/scheduling/dynamical_decoupling.py +3 -3
- qiskit/transpiler/passes/scheduling/padding/base_padding.py +1 -1
- qiskit/transpiler/passes/scheduling/padding/dynamical_decoupling.py +20 -14
- qiskit/transpiler/passes/scheduling/scheduling/base_scheduler.py +7 -6
- qiskit/transpiler/passes/scheduling/time_unit_conversion.py +4 -3
- qiskit/transpiler/passes/synthesis/high_level_synthesis.py +211 -36
- qiskit/transpiler/passes/synthesis/plugin.py +2 -2
- qiskit/transpiler/passes/synthesis/unitary_synthesis.py +80 -40
- qiskit/transpiler/passes/utils/__init__.py +0 -1
- qiskit/transpiler/passes/utils/check_gate_direction.py +4 -4
- qiskit/transpiler/passes/utils/check_map.py +3 -6
- qiskit/transpiler/passes/utils/convert_conditions_to_if_ops.py +3 -4
- qiskit/transpiler/passes/utils/error.py +2 -2
- qiskit/transpiler/passes/utils/fixed_point.py +3 -3
- qiskit/transpiler/passes/utils/gate_direction.py +1 -1
- qiskit/transpiler/passes/utils/gates_basis.py +1 -2
- qiskit/transpiler/passmanager.py +7 -6
- qiskit/transpiler/preset_passmanagers/__init__.py +4 -228
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +73 -18
- qiskit/transpiler/preset_passmanagers/common.py +3 -6
- qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +518 -0
- qiskit/transpiler/preset_passmanagers/level0.py +1 -1
- qiskit/transpiler/target.py +27 -8
- qiskit/user_config.py +29 -6
- qiskit/utils/classtools.py +3 -3
- qiskit/utils/deprecation.py +3 -2
- qiskit/utils/lazy_tester.py +2 -2
- qiskit/utils/optionals.py +8 -8
- qiskit/visualization/bloch.py +18 -23
- qiskit/visualization/circuit/_utils.py +34 -10
- qiskit/visualization/circuit/circuit_visualization.py +23 -16
- qiskit/visualization/circuit/latex.py +29 -27
- qiskit/visualization/circuit/matplotlib.py +4 -2
- qiskit/visualization/circuit/qcstyle.py +2 -2
- qiskit/visualization/circuit/text.py +9 -15
- qiskit/visualization/dag_visualization.py +2 -2
- qiskit/visualization/pulse_v2/core.py +1 -1
- qiskit/visualization/pulse_v2/events.py +1 -1
- qiskit/visualization/pulse_v2/generators/frame.py +3 -4
- qiskit/visualization/pulse_v2/generators/waveform.py +5 -9
- qiskit/visualization/pulse_v2/layouts.py +1 -5
- qiskit/visualization/pulse_v2/plotters/matplotlib.py +1 -2
- qiskit/visualization/state_visualization.py +5 -6
- qiskit/visualization/timeline/plotters/matplotlib.py +1 -2
- qiskit/visualization/transition_visualization.py +7 -2
- {qiskit-1.1.2.dist-info → qiskit-1.2.0.dist-info}/METADATA +12 -12
- {qiskit-1.1.2.dist-info → qiskit-1.2.0.dist-info}/RECORD +342 -340
- {qiskit-1.1.2.dist-info → qiskit-1.2.0.dist-info}/entry_points.txt +3 -0
- qiskit/transpiler/passes/utils/block_to_matrix.py +0 -47
- {qiskit-1.1.2.dist-info → qiskit-1.2.0.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.1.2.dist-info → qiskit-1.2.0.dist-info}/WHEEL +0 -0
- {qiskit-1.1.2.dist-info → qiskit-1.2.0.dist-info}/top_level.txt +0 -0
@@ -30,11 +30,12 @@ from qiskit.circuit import (
|
|
30
30
|
QuantumCircuit,
|
31
31
|
ParameterExpression,
|
32
32
|
)
|
33
|
-
from qiskit.dagcircuit import DAGCircuit
|
33
|
+
from qiskit.dagcircuit import DAGCircuit, DAGOpNode
|
34
34
|
from qiskit.converters import circuit_to_dag, dag_to_circuit
|
35
35
|
from qiskit.circuit.equivalence import Key, NodeData
|
36
36
|
from qiskit.transpiler.basepasses import TransformationPass
|
37
37
|
from qiskit.transpiler.exceptions import TranspilerError
|
38
|
+
from qiskit.circuit.controlflow import CONTROL_FLOW_OP_NAMES
|
38
39
|
|
39
40
|
logger = logging.getLogger(__name__)
|
40
41
|
|
@@ -161,7 +162,8 @@ class BasisTranslator(TransformationPass):
|
|
161
162
|
# If the source basis is a subset of the target basis and we have no circuit
|
162
163
|
# instructions on qargs that have non-global operations there is nothing to
|
163
164
|
# translate and we can exit early.
|
164
|
-
|
165
|
+
source_basis_names = {x[0] for x in source_basis}
|
166
|
+
if source_basis_names.issubset(target_basis) and not qargs_local_source_basis:
|
165
167
|
return dag
|
166
168
|
|
167
169
|
logger.info(
|
@@ -207,7 +209,7 @@ class BasisTranslator(TransformationPass):
|
|
207
209
|
"target basis is not universal or there are additional equivalence rules "
|
208
210
|
"needed in the EquivalenceLibrary being used. For more details on this "
|
209
211
|
"error see: "
|
210
|
-
"https://docs.quantum.ibm.com/api/qiskit/
|
212
|
+
"https://docs.quantum.ibm.com/api/qiskit/qiskit.transpiler.passes."
|
211
213
|
"BasisTranslator#translation-errors"
|
212
214
|
)
|
213
215
|
|
@@ -225,7 +227,7 @@ class BasisTranslator(TransformationPass):
|
|
225
227
|
f"basis: {list(target_basis)}. This likely means the target basis is not universal "
|
226
228
|
"or there are additional equivalence rules needed in the EquivalenceLibrary being "
|
227
229
|
"used. For more details on this error see: "
|
228
|
-
"https://docs.quantum.ibm.com/api/qiskit/
|
230
|
+
"https://docs.quantum.ibm.com/api/qiskit/qiskit.transpiler.passes."
|
229
231
|
"BasisTranslator#translation-errors"
|
230
232
|
)
|
231
233
|
|
@@ -248,72 +250,85 @@ class BasisTranslator(TransformationPass):
|
|
248
250
|
replace_start_time = time.time()
|
249
251
|
|
250
252
|
def apply_translation(dag, wire_map):
|
251
|
-
|
252
|
-
|
253
|
+
is_updated = False
|
254
|
+
out_dag = dag.copy_empty_like()
|
255
|
+
for node in dag.topological_op_nodes():
|
253
256
|
node_qargs = tuple(wire_map[bit] for bit in node.qargs)
|
254
257
|
qubit_set = frozenset(node_qargs)
|
255
258
|
if node.name in target_basis or len(node.qargs) < self._min_qubits:
|
256
|
-
if
|
259
|
+
if node.name in CONTROL_FLOW_OP_NAMES:
|
257
260
|
flow_blocks = []
|
258
261
|
for block in node.op.blocks:
|
259
262
|
dag_block = circuit_to_dag(block)
|
260
|
-
|
263
|
+
updated_dag, is_updated = apply_translation(
|
261
264
|
dag_block,
|
262
265
|
{
|
263
266
|
inner: wire_map[outer]
|
264
267
|
for inner, outer in zip(block.qubits, node.qargs)
|
265
268
|
},
|
266
269
|
)
|
267
|
-
if
|
268
|
-
flow_circ_block = dag_to_circuit(
|
270
|
+
if is_updated:
|
271
|
+
flow_circ_block = dag_to_circuit(updated_dag)
|
269
272
|
else:
|
270
273
|
flow_circ_block = block
|
271
274
|
flow_blocks.append(flow_circ_block)
|
272
275
|
node.op = node.op.replace_blocks(flow_blocks)
|
276
|
+
out_dag.apply_operation_back(node.op, node.qargs, node.cargs, check=False)
|
273
277
|
continue
|
274
278
|
if (
|
275
279
|
node_qargs in self._qargs_with_non_global_operation
|
276
280
|
and node.name in self._qargs_with_non_global_operation[node_qargs]
|
277
281
|
):
|
282
|
+
out_dag.apply_operation_back(node.op, node.qargs, node.cargs, check=False)
|
278
283
|
continue
|
279
284
|
|
280
285
|
if dag.has_calibration_for(node):
|
286
|
+
out_dag.apply_operation_back(node.op, node.qargs, node.cargs, check=False)
|
281
287
|
continue
|
282
288
|
if qubit_set in extra_instr_map:
|
283
|
-
self._replace_node(
|
284
|
-
elif (node.
|
285
|
-
self._replace_node(
|
289
|
+
self._replace_node(out_dag, node, extra_instr_map[qubit_set])
|
290
|
+
elif (node.name, node.num_qubits) in instr_map:
|
291
|
+
self._replace_node(out_dag, node, instr_map)
|
286
292
|
else:
|
287
293
|
raise TranspilerError(f"BasisTranslator did not map {node.name}.")
|
288
|
-
|
289
|
-
return
|
294
|
+
is_updated = True
|
295
|
+
return out_dag, is_updated
|
290
296
|
|
291
|
-
apply_translation(dag, qarg_indices)
|
297
|
+
out_dag, _ = apply_translation(dag, qarg_indices)
|
292
298
|
replace_end_time = time.time()
|
293
299
|
logger.info(
|
294
300
|
"Basis translation instructions replaced in %.3fs.",
|
295
301
|
replace_end_time - replace_start_time,
|
296
302
|
)
|
297
303
|
|
298
|
-
return
|
304
|
+
return out_dag
|
299
305
|
|
300
306
|
def _replace_node(self, dag, node, instr_map):
|
301
|
-
target_params, target_dag = instr_map[node.
|
302
|
-
if len(node.
|
307
|
+
target_params, target_dag = instr_map[node.name, node.num_qubits]
|
308
|
+
if len(node.params) != len(target_params):
|
303
309
|
raise TranspilerError(
|
304
310
|
"Translation num_params not equal to op num_params."
|
305
|
-
"Op: {} {} Translation: {}\n{}"
|
306
|
-
node.op.params, node.op.name, target_params, target_dag
|
307
|
-
)
|
311
|
+
f"Op: {node.params} {node.name} Translation: {target_params}\n{target_dag}"
|
308
312
|
)
|
309
|
-
if node.
|
310
|
-
parameter_map = dict(zip(target_params, node.
|
311
|
-
bound_target_dag = target_dag.copy_empty_like()
|
313
|
+
if node.params:
|
314
|
+
parameter_map = dict(zip(target_params, node.params))
|
312
315
|
for inner_node in target_dag.topological_op_nodes():
|
313
|
-
|
314
|
-
|
316
|
+
new_node = DAGOpNode.from_instruction(
|
317
|
+
inner_node._to_circuit_instruction(),
|
318
|
+
dag=target_dag,
|
319
|
+
)
|
320
|
+
new_node.qargs = tuple(
|
321
|
+
node.qargs[target_dag.find_bit(x).index] for x in inner_node.qargs
|
322
|
+
)
|
323
|
+
new_node.cargs = tuple(
|
324
|
+
node.cargs[target_dag.find_bit(x).index] for x in inner_node.cargs
|
325
|
+
)
|
326
|
+
|
327
|
+
if not new_node.is_standard_gate():
|
328
|
+
new_node.op = new_node.op.copy()
|
329
|
+
if any(isinstance(x, ParameterExpression) for x in inner_node.params):
|
315
330
|
new_params = []
|
316
|
-
for param in
|
331
|
+
for param in new_node.params:
|
317
332
|
if not isinstance(param, ParameterExpression):
|
318
333
|
new_params.append(param)
|
319
334
|
else:
|
@@ -327,10 +342,11 @@ class BasisTranslator(TransformationPass):
|
|
327
342
|
if not new_value.parameters:
|
328
343
|
new_value = new_value.numeric()
|
329
344
|
new_params.append(new_value)
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
345
|
+
new_node.params = new_params
|
346
|
+
if not new_node.is_standard_gate():
|
347
|
+
new_node.op.params = new_params
|
348
|
+
dag._apply_op_node_back(new_node)
|
349
|
+
|
334
350
|
if isinstance(target_dag.global_phase, ParameterExpression):
|
335
351
|
old_phase = target_dag.global_phase
|
336
352
|
bind_dict = {x: parameter_map[x] for x in old_phase.parameters}
|
@@ -338,31 +354,37 @@ class BasisTranslator(TransformationPass):
|
|
338
354
|
new_phase = old_phase
|
339
355
|
for x in bind_dict.items():
|
340
356
|
new_phase = new_phase.assign(*x)
|
341
|
-
|
342
357
|
else:
|
343
358
|
new_phase = old_phase.bind(bind_dict)
|
344
359
|
if not new_phase.parameters:
|
345
360
|
new_phase = new_phase.numeric()
|
346
361
|
if isinstance(new_phase, complex):
|
347
362
|
raise TranspilerError(f"Global phase must be real, but got '{new_phase}'")
|
348
|
-
|
349
|
-
|
350
|
-
bound_target_dag = target_dag
|
351
|
-
|
352
|
-
if len(bound_target_dag.op_nodes()) == 1 and len(
|
353
|
-
bound_target_dag.op_nodes()[0].qargs
|
354
|
-
) == len(node.qargs):
|
355
|
-
dag_op = bound_target_dag.op_nodes()[0].op
|
356
|
-
# dag_op may be the same instance as other ops in the dag,
|
357
|
-
# so if there is a condition, need to copy
|
358
|
-
if getattr(node.op, "condition", None):
|
359
|
-
dag_op = dag_op.copy()
|
360
|
-
dag.substitute_node(node, dag_op, inplace=True)
|
361
|
-
|
362
|
-
if bound_target_dag.global_phase:
|
363
|
-
dag.global_phase += bound_target_dag.global_phase
|
363
|
+
dag.global_phase += new_phase
|
364
|
+
|
364
365
|
else:
|
365
|
-
|
366
|
+
for inner_node in target_dag.topological_op_nodes():
|
367
|
+
new_node = DAGOpNode.from_instruction(
|
368
|
+
inner_node._to_circuit_instruction(),
|
369
|
+
dag=target_dag,
|
370
|
+
)
|
371
|
+
new_node.qargs = tuple(
|
372
|
+
node.qargs[target_dag.find_bit(x).index] for x in inner_node.qargs
|
373
|
+
)
|
374
|
+
new_node.cargs = tuple(
|
375
|
+
node.cargs[target_dag.find_bit(x).index] for x in inner_node.cargs
|
376
|
+
)
|
377
|
+
if not new_node.is_standard_gate:
|
378
|
+
new_node.op = new_node.op.copy()
|
379
|
+
# dag_op may be the same instance as other ops in the dag,
|
380
|
+
# so if there is a condition, need to copy
|
381
|
+
if getattr(node.op, "condition", None):
|
382
|
+
new_node_op = new_node.op.to_mutable()
|
383
|
+
new_node_op.condition = node.op.condition
|
384
|
+
new_node.op = new_node_op
|
385
|
+
dag._apply_op_node_back(new_node)
|
386
|
+
if target_dag.global_phase:
|
387
|
+
dag.global_phase += target_dag.global_phase
|
366
388
|
|
367
389
|
@singledispatchmethod
|
368
390
|
def _extract_basis(self, circuit):
|
@@ -372,8 +394,8 @@ class BasisTranslator(TransformationPass):
|
|
372
394
|
def _(self, dag: DAGCircuit):
|
373
395
|
for node in dag.op_nodes():
|
374
396
|
if not dag.has_calibration_for(node) and len(node.qargs) >= self._min_qubits:
|
375
|
-
yield (node.name, node.
|
376
|
-
if
|
397
|
+
yield (node.name, node.num_qubits)
|
398
|
+
if node.name in CONTROL_FLOW_OP_NAMES:
|
377
399
|
for block in node.op.blocks:
|
378
400
|
yield from self._extract_basis(block)
|
379
401
|
|
@@ -414,10 +436,10 @@ class BasisTranslator(TransformationPass):
|
|
414
436
|
frozenset(qargs).issuperset(incomplete_qargs)
|
415
437
|
for incomplete_qargs in self._qargs_with_non_global_operation
|
416
438
|
):
|
417
|
-
qargs_local_source_basis[frozenset(qargs)].add((node.name, node.
|
439
|
+
qargs_local_source_basis[frozenset(qargs)].add((node.name, node.num_qubits))
|
418
440
|
else:
|
419
|
-
source_basis.add((node.name, node.
|
420
|
-
if
|
441
|
+
source_basis.add((node.name, node.num_qubits))
|
442
|
+
if node.name in CONTROL_FLOW_OP_NAMES:
|
421
443
|
for block in node.op.blocks:
|
422
444
|
block_dag = circuit_to_dag(block)
|
423
445
|
source_basis, qargs_local_source_basis = self._extract_basis_target(
|
@@ -468,7 +490,7 @@ class BasisSearchVisitor(rustworkx.visit.DijkstraVisitor):
|
|
468
490
|
score,
|
469
491
|
)
|
470
492
|
self._basis_transforms.append((gate.name, gate.num_qubits, rule.params, rule.circuit))
|
471
|
-
# we can stop the search if we have found all gates in the original
|
493
|
+
# we can stop the search if we have found all gates in the original circuit.
|
472
494
|
if not self._source_gates_remain:
|
473
495
|
# if we start from source gates and apply `basis_transforms` in reverse order, we'll end
|
474
496
|
# up with gates in the target basis. Note though that `basis_transforms` may include
|
@@ -512,7 +534,7 @@ class BasisSearchVisitor(rustworkx.visit.DijkstraVisitor):
|
|
512
534
|
|
513
535
|
cost_tot = 0
|
514
536
|
for instruction in edge_data.rule.circuit:
|
515
|
-
key = Key(name=instruction.
|
537
|
+
key = Key(name=instruction.name, num_qubits=len(instruction.qubits))
|
516
538
|
cost_tot += self._opt_cost_map[key]
|
517
539
|
|
518
540
|
return cost_tot - self._opt_cost_map[edge_data.source]
|
@@ -550,7 +572,7 @@ def _basis_search(equiv_lib, source_basis, target_basis):
|
|
550
572
|
if not source_basis:
|
551
573
|
return []
|
552
574
|
|
553
|
-
# This is only
|
575
|
+
# This is only necessary since gates in target basis are currently reported by
|
554
576
|
# their names and we need to have in addition the number of qubits they act on.
|
555
577
|
target_basis_keys = [key for key in equiv_lib.keys() if key.name in target_basis]
|
556
578
|
|
@@ -630,7 +652,7 @@ def _compose_transforms(basis_transforms, source_basis, source_dag):
|
|
630
652
|
doomed_nodes = [
|
631
653
|
node
|
632
654
|
for node in dag.op_nodes()
|
633
|
-
if (node.
|
655
|
+
if (node.name, node.num_qubits) == (gate_name, gate_num_qubits)
|
634
656
|
]
|
635
657
|
|
636
658
|
if doomed_nodes and logger.isEnabledFor(logging.DEBUG):
|
@@ -644,9 +666,7 @@ def _compose_transforms(basis_transforms, source_basis, source_dag):
|
|
644
666
|
|
645
667
|
for node in doomed_nodes:
|
646
668
|
|
647
|
-
replacement = equiv.assign_parameters(
|
648
|
-
dict(zip_longest(equiv_params, node.op.params))
|
649
|
-
)
|
669
|
+
replacement = equiv.assign_parameters(dict(zip_longest(equiv_params, node.params)))
|
650
670
|
|
651
671
|
replacement_dag = circuit_to_dag(replacement)
|
652
672
|
|
@@ -668,8 +688,8 @@ def _get_example_gates(source_dag):
|
|
668
688
|
def recurse(dag, example_gates=None):
|
669
689
|
example_gates = example_gates or {}
|
670
690
|
for node in dag.op_nodes():
|
671
|
-
example_gates[(node.
|
672
|
-
if
|
691
|
+
example_gates[(node.name, node.num_qubits)] = node
|
692
|
+
if node.name in CONTROL_FLOW_OP_NAMES:
|
673
693
|
for block in node.op.blocks:
|
674
694
|
example_gates = recurse(circuit_to_dag(block), example_gates)
|
675
695
|
return example_gates
|
@@ -15,15 +15,13 @@
|
|
15
15
|
from __future__ import annotations
|
16
16
|
|
17
17
|
from qiskit.circuit import Instruction, ParameterExpression, Qubit, Clbit
|
18
|
+
from qiskit.circuit.equivalence_library import EquivalenceLibrary
|
18
19
|
from qiskit.converters import circuit_to_dag
|
19
20
|
from qiskit.dagcircuit import DAGCircuit, DAGOpNode
|
20
|
-
from qiskit.circuit.equivalence_library import EquivalenceLibrary
|
21
21
|
from qiskit.exceptions import QiskitError
|
22
|
-
from qiskit.transpiler import Target
|
23
|
-
|
24
22
|
from qiskit.transpiler.basepasses import TransformationPass
|
25
|
-
|
26
|
-
from .
|
23
|
+
from qiskit.transpiler.passes.basis.basis_translator import BasisTranslator
|
24
|
+
from qiskit.transpiler.target import Target
|
27
25
|
|
28
26
|
|
29
27
|
class TranslateParameterizedGates(TransformationPass):
|
@@ -78,7 +78,7 @@ class Unroll3qOrMore(TransformationPass):
|
|
78
78
|
continue
|
79
79
|
raise QiskitError(
|
80
80
|
"Cannot unroll all 3q or more gates. "
|
81
|
-
"No rule to expand instruction
|
81
|
+
f"No rule to expand instruction {node.op.name}."
|
82
82
|
)
|
83
83
|
decomposition = circuit_to_dag(node.op.definition, copy_operations=False)
|
84
84
|
decomposition = self.run(decomposition) # recursively unroll
|
@@ -60,9 +60,9 @@ class UnrollCustomDefinitions(TransformationPass):
|
|
60
60
|
if self._basis_gates is None and self._target is None:
|
61
61
|
return dag
|
62
62
|
|
63
|
+
device_insts = {"measure", "reset", "barrier", "snapshot", "delay", "store"}
|
63
64
|
if self._target is None:
|
64
|
-
|
65
|
-
device_insts = basic_insts | set(self._basis_gates)
|
65
|
+
device_insts |= set(self._basis_gates)
|
66
66
|
|
67
67
|
for node in dag.op_nodes():
|
68
68
|
if isinstance(node.op, ControlFlowOp):
|
@@ -77,14 +77,14 @@ class UnrollCustomDefinitions(TransformationPass):
|
|
77
77
|
|
78
78
|
controlled_gate_open_ctrl = isinstance(node.op, ControlledGate) and node.op._open_ctrl
|
79
79
|
if not controlled_gate_open_ctrl:
|
80
|
-
|
81
|
-
self._target.instruction_supported(
|
80
|
+
if self._target is not None:
|
81
|
+
inst_supported = self._target.instruction_supported(
|
82
82
|
operation_name=node.op.name,
|
83
83
|
qargs=tuple(dag.find_bit(x).index for x in node.qargs),
|
84
84
|
)
|
85
|
-
|
86
|
-
|
87
|
-
|
85
|
+
else:
|
86
|
+
inst_supported = node.name in device_insts
|
87
|
+
|
88
88
|
if inst_supported or self._equiv_lib.has_entry(node.op):
|
89
89
|
continue
|
90
90
|
try:
|
@@ -95,9 +95,9 @@ class UnrollCustomDefinitions(TransformationPass):
|
|
95
95
|
if unrolled is None:
|
96
96
|
# opaque node
|
97
97
|
raise QiskitError(
|
98
|
-
"Cannot unroll the circuit to the given basis,
|
99
|
-
"Instruction
|
100
|
-
"and no rule found to expand."
|
98
|
+
f"Cannot unroll the circuit to the given basis, {str(self._basis_gates)}. "
|
99
|
+
f"Instruction {node.op.name} not found in equivalence library "
|
100
|
+
"and no rule found to expand."
|
101
101
|
)
|
102
102
|
|
103
103
|
decomposition = circuit_to_dag(unrolled, copy_operations=False)
|
@@ -17,13 +17,13 @@ from functools import lru_cache
|
|
17
17
|
import numpy as np
|
18
18
|
|
19
19
|
from qiskit.circuit import Instruction
|
20
|
+
from qiskit.circuit.library.standard_gates import RXGate
|
21
|
+
from qiskit.exceptions import QiskitError
|
20
22
|
from qiskit.pulse import Schedule, ScheduleBlock, builder, ScalableSymbolicPulse
|
21
23
|
from qiskit.pulse.channels import Channel
|
22
24
|
from qiskit.pulse.library.symbolic_pulses import Drag
|
23
25
|
from qiskit.transpiler.passes.calibration.base_builder import CalibrationBuilder
|
24
|
-
from qiskit.transpiler import Target
|
25
|
-
from qiskit.circuit.library.standard_gates import RXGate
|
26
|
-
from qiskit.exceptions import QiskitError
|
26
|
+
from qiskit.transpiler.target import Target
|
27
27
|
|
28
28
|
|
29
29
|
class RXCalibrationBuilder(CalibrationBuilder):
|
@@ -204,7 +204,7 @@ class RZXCalibrationBuilder(CalibrationBuilder):
|
|
204
204
|
if cal_type in [CRCalType.ECR_CX_FORWARD, CRCalType.ECR_FORWARD]:
|
205
205
|
xgate = self._inst_map.get("x", qubits[0])
|
206
206
|
with builder.build(
|
207
|
-
default_alignment="sequential", name="rzx(
|
207
|
+
default_alignment="sequential", name=f"rzx({theta:.3f})"
|
208
208
|
) as rzx_theta_native:
|
209
209
|
for cr_tone, comp_tone in zip(cr_tones, comp_tones):
|
210
210
|
with builder.align_left():
|
@@ -230,7 +230,7 @@ class RZXCalibrationBuilder(CalibrationBuilder):
|
|
230
230
|
builder.call(szt, name="szt")
|
231
231
|
|
232
232
|
with builder.build(
|
233
|
-
default_alignment="sequential", name="rzx(
|
233
|
+
default_alignment="sequential", name=f"rzx({theta:.3f})"
|
234
234
|
) as rzx_theta_flip:
|
235
235
|
builder.call(hadamard, name="hadamard")
|
236
236
|
for cr_tone, comp_tone in zip(cr_tones, comp_tones):
|
@@ -297,7 +297,7 @@ class RZXCalibrationBuilderNoEcho(RZXCalibrationBuilder):
|
|
297
297
|
|
298
298
|
# RZXCalibrationNoEcho only good for forward CR direction
|
299
299
|
if cal_type in [CRCalType.ECR_CX_FORWARD, CRCalType.ECR_FORWARD]:
|
300
|
-
with builder.build(default_alignment="left", name="rzx(
|
300
|
+
with builder.build(default_alignment="left", name=f"rzx({theta:.3f})") as rzx_theta:
|
301
301
|
stretched_dur = self.rescale_cr_inst(cr_tones[0], 2 * theta)
|
302
302
|
self.rescale_cr_inst(comp_tones[0], 2 * theta)
|
303
303
|
# Placeholder to make pulse gate work
|
@@ -13,7 +13,7 @@
|
|
13
13
|
"""Transform a circuit with virtual qubits into a circuit with physical qubits."""
|
14
14
|
|
15
15
|
from qiskit.circuit import QuantumRegister
|
16
|
-
from qiskit.dagcircuit import DAGCircuit
|
16
|
+
from qiskit.dagcircuit import DAGCircuit, DAGOpNode
|
17
17
|
from qiskit.transpiler.basepasses import TransformationPass
|
18
18
|
from qiskit.transpiler.exceptions import TranspilerError
|
19
19
|
from qiskit.transpiler.layout import Layout
|
@@ -79,7 +79,12 @@ class ApplyLayout(TransformationPass):
|
|
79
79
|
virtual_physical_map = layout.get_virtual_bits()
|
80
80
|
for node in dag.topological_op_nodes():
|
81
81
|
qargs = [q[virtual_physical_map[qarg]] for qarg in node.qargs]
|
82
|
-
new_dag.
|
82
|
+
new_dag._apply_op_node_back(
|
83
|
+
DAGOpNode.from_instruction(
|
84
|
+
node._to_circuit_instruction().replace(qubits=qargs)
|
85
|
+
),
|
86
|
+
check=False,
|
87
|
+
)
|
83
88
|
else:
|
84
89
|
# First build a new layout object going from:
|
85
90
|
# old virtual -> old physical -> new virtual -> new physical
|
@@ -99,7 +104,12 @@ class ApplyLayout(TransformationPass):
|
|
99
104
|
# Apply new layout to the circuit
|
100
105
|
for node in dag.topological_op_nodes():
|
101
106
|
qargs = [q[new_virtual_to_physical[qarg]] for qarg in node.qargs]
|
102
|
-
new_dag.
|
107
|
+
new_dag._apply_op_node_back(
|
108
|
+
DAGOpNode.from_instruction(
|
109
|
+
node._to_circuit_instruction().replace(qubits=qargs)
|
110
|
+
),
|
111
|
+
check=False,
|
112
|
+
)
|
103
113
|
self.property_set["layout"] = full_layout
|
104
114
|
if (final_layout := self.property_set["final_layout"]) is not None:
|
105
115
|
final_layout_mapping = {
|
@@ -35,11 +35,7 @@ from qiskit.transpiler.layout import Layout
|
|
35
35
|
from qiskit.transpiler.basepasses import TransformationPass
|
36
36
|
from qiskit.transpiler.exceptions import TranspilerError
|
37
37
|
from qiskit._accelerate.nlayout import NLayout
|
38
|
-
from qiskit._accelerate.sabre import
|
39
|
-
sabre_layout_and_routing,
|
40
|
-
Heuristic,
|
41
|
-
NeighborTable,
|
42
|
-
)
|
38
|
+
from qiskit._accelerate.sabre import sabre_layout_and_routing, Heuristic, NeighborTable, SetScaling
|
43
39
|
from qiskit.transpiler.passes.routing.sabre_swap import _build_sabre_dag, _apply_sabre_result
|
44
40
|
from qiskit.transpiler.target import Target
|
45
41
|
from qiskit.transpiler.coupling import CouplingMap
|
@@ -144,7 +140,7 @@ class SabreLayout(TransformationPass):
|
|
144
140
|
with the ``routing_pass`` argument and an error will be raised
|
145
141
|
if both are used.
|
146
142
|
layout_trials (int): The number of random seed trials to run
|
147
|
-
layout with. When > 1 the trial that
|
143
|
+
layout with. When > 1 the trial that results in the output with
|
148
144
|
the fewest swap gates will be selected. If this is not specified
|
149
145
|
(and ``routing_pass`` is not set) then the number of local
|
150
146
|
physical CPUs will be used as the default value. This option is
|
@@ -393,12 +389,18 @@ class SabreLayout(TransformationPass):
|
|
393
389
|
coupling_map.size(),
|
394
390
|
original_qubit_indices,
|
395
391
|
)
|
392
|
+
heuristic = (
|
393
|
+
Heuristic(attempt_limit=10 * coupling_map.size())
|
394
|
+
.with_basic(1.0, SetScaling.Size)
|
395
|
+
.with_lookahead(0.5, 20, SetScaling.Size)
|
396
|
+
.with_decay(0.001, 5)
|
397
|
+
)
|
396
398
|
sabre_start = time.perf_counter()
|
397
399
|
(initial_layout, final_permutation, sabre_result) = sabre_layout_and_routing(
|
398
400
|
sabre_dag,
|
399
401
|
neighbor_table,
|
400
402
|
dist_matrix,
|
401
|
-
|
403
|
+
heuristic,
|
402
404
|
self.max_iterations,
|
403
405
|
self.swap_trials,
|
404
406
|
self.layout_trials,
|
@@ -420,7 +422,7 @@ class SabreLayout(TransformationPass):
|
|
420
422
|
)
|
421
423
|
|
422
424
|
def _ancilla_allocation_no_pass_manager(self, dag):
|
423
|
-
"""Run the ancilla-allocation and -
|
425
|
+
"""Run the ancilla-allocation and -enlargement passes on the DAG chained onto our
|
424
426
|
``property_set``, skipping the DAG-to-circuit conversion cost of using a ``PassManager``."""
|
425
427
|
ancilla_pass = FullAncillaAllocation(self.coupling_map)
|
426
428
|
ancilla_pass.property_set = self.property_set
|
@@ -14,8 +14,11 @@
|
|
14
14
|
|
15
15
|
import itertools
|
16
16
|
|
17
|
-
from qiskit.transpiler import
|
17
|
+
from qiskit.transpiler.basepasses import AnalysisPass
|
18
|
+
from qiskit.transpiler.coupling import CouplingMap
|
19
|
+
from qiskit.transpiler.exceptions import TranspilerError
|
18
20
|
from qiskit.transpiler.passes.layout.vf2_layout import VF2Layout
|
21
|
+
from qiskit.transpiler.target import Target
|
19
22
|
from qiskit._accelerate.error_map import ErrorMap
|
20
23
|
|
21
24
|
|
@@ -11,9 +11,9 @@
|
|
11
11
|
# that they have been altered from the originals.
|
12
12
|
|
13
13
|
"""Set the ``layout`` property to the given layout."""
|
14
|
-
from qiskit.transpiler import Layout
|
15
|
-
from qiskit.transpiler.exceptions import InvalidLayoutError
|
16
14
|
from qiskit.transpiler.basepasses import AnalysisPass
|
15
|
+
from qiskit.transpiler.exceptions import InvalidLayoutError
|
16
|
+
from qiskit.transpiler.layout import Layout
|
17
17
|
|
18
18
|
|
19
19
|
class SetLayout(AnalysisPass):
|
@@ -195,7 +195,7 @@ class VF2Layout(AnalysisPass):
|
|
195
195
|
if len(cm_graph) == len(im_graph):
|
196
196
|
chosen_layout = mapping_to_layout(layout_mapping)
|
197
197
|
break
|
198
|
-
# If there is no error map
|
198
|
+
# If there is no error map available we can just skip the scoring stage as there
|
199
199
|
# is nothing to score with, so any match is the best we can find.
|
200
200
|
if self.avg_error_map is None:
|
201
201
|
chosen_layout = mapping_to_layout(layout_mapping)
|
@@ -19,7 +19,7 @@ import random
|
|
19
19
|
import numpy as np
|
20
20
|
from rustworkx import PyDiGraph, PyGraph, connected_components
|
21
21
|
|
22
|
-
from qiskit.circuit import
|
22
|
+
from qiskit.circuit import ForLoopOp
|
23
23
|
from qiskit.converters import circuit_to_dag
|
24
24
|
from qiskit._accelerate import vf2_layout
|
25
25
|
from qiskit._accelerate.nlayout import NLayout
|
@@ -37,7 +37,7 @@ def build_interaction_graph(dag, strict_direction=True):
|
|
37
37
|
|
38
38
|
def _visit(dag, weight, wire_map):
|
39
39
|
for node in dag.op_nodes(include_directives=False):
|
40
|
-
if
|
40
|
+
if node.is_control_flow():
|
41
41
|
if isinstance(node.op, ForLoopOp):
|
42
42
|
inner_weight = len(node.op.params[0]) * weight
|
43
43
|
else:
|
@@ -57,7 +57,7 @@ def build_interaction_graph(dag, strict_direction=True):
|
|
57
57
|
im_graph_node_map[qargs[0]] = im_graph.add_node(weights)
|
58
58
|
reverse_im_graph_node_map[im_graph_node_map[qargs[0]]] = qargs[0]
|
59
59
|
else:
|
60
|
-
im_graph[im_graph_node_map[qargs[0]]][node.
|
60
|
+
im_graph[im_graph_node_map[qargs[0]]][node.name] += weight
|
61
61
|
if len_args == 2:
|
62
62
|
if qargs[0] not in im_graph_node_map:
|
63
63
|
im_graph_node_map[qargs[0]] = im_graph.add_node(defaultdict(int))
|
@@ -218,8 +218,8 @@ class CollectMultiQBlocks(AnalysisPass):
|
|
218
218
|
prev = bit
|
219
219
|
self.gate_groups[self.find_set(prev)].append(nd)
|
220
220
|
# need to turn all groups that still exist into their own blocks
|
221
|
-
for index in self.parent:
|
222
|
-
if
|
221
|
+
for index, item in self.parent.items():
|
222
|
+
if item == index and len(self.gate_groups[index]) != 0:
|
223
223
|
block_list.append(self.gate_groups[index][:])
|
224
224
|
|
225
225
|
self.property_set["block_list"] = block_list
|
@@ -27,9 +27,13 @@ class CommutationAnalysis(AnalysisPass):
|
|
27
27
|
are grouped into a set of gates that commute.
|
28
28
|
"""
|
29
29
|
|
30
|
-
def __init__(self):
|
30
|
+
def __init__(self, *, _commutation_checker=None):
|
31
31
|
super().__init__()
|
32
|
-
|
32
|
+
# allow setting a private commutation checker, this allows better performance if we
|
33
|
+
# do not care about commutations of all gates, but just a subset
|
34
|
+
if _commutation_checker is None:
|
35
|
+
_commutation_checker = scc
|
36
|
+
self.comm_checker = _commutation_checker
|
33
37
|
|
34
38
|
def run(self, dag):
|
35
39
|
"""Run the CommutationAnalysis pass on `dag`.
|
@@ -72,14 +76,7 @@ class CommutationAnalysis(AnalysisPass):
|
|
72
76
|
does_commute = (
|
73
77
|
isinstance(current_gate, DAGOpNode)
|
74
78
|
and isinstance(prev_gate, DAGOpNode)
|
75
|
-
and self.comm_checker.
|
76
|
-
current_gate.op,
|
77
|
-
current_gate.qargs,
|
78
|
-
current_gate.cargs,
|
79
|
-
prev_gate.op,
|
80
|
-
prev_gate.qargs,
|
81
|
-
prev_gate.cargs,
|
82
|
-
)
|
79
|
+
and self.comm_checker.commute_nodes(current_gate, prev_gate)
|
83
80
|
)
|
84
81
|
if not does_commute:
|
85
82
|
break
|