qiskit 1.1.2__cp38-abi3-win32.whl → 1.2.0rc1__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 +1 -1
- 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 +392 -384
- 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 +41 -127
- 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 +32 -24
- qiskit/providers/fake_provider/fake_backend.py +10 -3
- qiskit/providers/fake_provider/fake_openpulse_2q.py +154 -146
- qiskit/providers/fake_provider/fake_openpulse_3q.py +226 -217
- qiskit/providers/fake_provider/fake_qasm_backend.py +5 -1
- qiskit/providers/fake_provider/generic_backend_v2.py +80 -50
- qiskit/providers/models/__init__.py +11 -0
- 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 +578 -481
- 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/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 +14 -16
- 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 +82 -63
- 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 +11 -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 +1 -1
- 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 +11 -11
- 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 +117 -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 +19 -67
- 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 +5 -12
- 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.0rc1.dist-info}/METADATA +26 -26
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/RECORD +340 -338
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/WHEEL +1 -1
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.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.0rc1.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.1.2.dist-info → qiskit-1.2.0rc1.dist-info}/top_level.txt +0 -0
@@ -33,6 +33,7 @@ from qiskit.circuit.library.standard_gates import (
|
|
33
33
|
XGate,
|
34
34
|
)
|
35
35
|
from qiskit.circuit import Qubit
|
36
|
+
from qiskit.circuit.quantumcircuitdata import CircuitInstruction
|
36
37
|
from qiskit.dagcircuit.dagcircuit import DAGCircuit
|
37
38
|
from qiskit.dagcircuit.dagnode import DAGOpNode
|
38
39
|
|
@@ -110,16 +111,7 @@ class Optimize1qGatesDecomposition(TransformationPass):
|
|
110
111
|
else:
|
111
112
|
return None
|
112
113
|
|
113
|
-
def
|
114
|
-
"""
|
115
|
-
Re-synthesizes one 2x2 `matrix`, typically extracted via `dag.collect_1q_runs`.
|
116
|
-
|
117
|
-
Returns the newly synthesized circuit in the indicated basis, or None
|
118
|
-
if no synthesis routine applied.
|
119
|
-
|
120
|
-
When multiple synthesis options are available, it prefers the one with the lowest
|
121
|
-
error when the circuit is applied to `qubit`.
|
122
|
-
"""
|
114
|
+
def _get_decomposer(self, qubit=None):
|
123
115
|
# include path for when target exists but target.num_qubits is None (BasicSimulator)
|
124
116
|
if self._target is not None and self._target.num_qubits is not None:
|
125
117
|
if qubit is not None:
|
@@ -133,6 +125,19 @@ class Optimize1qGatesDecomposition(TransformationPass):
|
|
133
125
|
decomposers = _possible_decomposers(available_1q_basis)
|
134
126
|
else:
|
135
127
|
decomposers = self._global_decomposers
|
128
|
+
return decomposers
|
129
|
+
|
130
|
+
def _resynthesize_run(self, matrix, qubit=None):
|
131
|
+
"""
|
132
|
+
Re-synthesizes one 2x2 `matrix`, typically extracted via `dag.collect_1q_runs`.
|
133
|
+
|
134
|
+
Returns the newly synthesized circuit in the indicated basis, or None
|
135
|
+
if no synthesis routine applied.
|
136
|
+
|
137
|
+
When multiple synthesis options are available, it prefers the one with the lowest
|
138
|
+
error when the circuit is applied to `qubit`.
|
139
|
+
"""
|
140
|
+
decomposers = self._get_decomposer(qubit)
|
136
141
|
|
137
142
|
best_synth_circuit = euler_one_qubit_decomposer.unitary_to_gate_sequence(
|
138
143
|
matrix,
|
@@ -149,10 +154,13 @@ class Optimize1qGatesDecomposition(TransformationPass):
|
|
149
154
|
out_dag.global_phase = best_synth_circuit.global_phase
|
150
155
|
|
151
156
|
for gate_name, angles in best_synth_circuit:
|
152
|
-
|
157
|
+
op = CircuitInstruction.from_standard(gate_name, qubits, angles)
|
158
|
+
out_dag.apply_operation_back(op.operation, qubits, check=False)
|
153
159
|
return out_dag
|
154
160
|
|
155
|
-
def _substitution_checks(
|
161
|
+
def _substitution_checks(
|
162
|
+
self, dag, old_run, new_circ, basis, qubit, old_error=None, new_error=None
|
163
|
+
):
|
156
164
|
"""
|
157
165
|
Returns `True` when it is recommended to replace `old_run` with `new_circ` over `basis`.
|
158
166
|
"""
|
@@ -176,11 +184,14 @@ class Optimize1qGatesDecomposition(TransformationPass):
|
|
176
184
|
# if we're outside of the basis set, we're obligated to logically decompose.
|
177
185
|
# if we're outside of the set of gates for which we have physical definitions,
|
178
186
|
# then we _try_ to decompose, using the results if we see improvement.
|
179
|
-
new_error = 0.0
|
180
|
-
old_error = 0.0
|
181
187
|
if not uncalibrated_and_not_basis_p:
|
182
|
-
new_error
|
183
|
-
|
188
|
+
if new_error is None:
|
189
|
+
new_error = self._error(new_circ, qubit)
|
190
|
+
if old_error is None:
|
191
|
+
old_error = self._error(old_run, qubit)
|
192
|
+
else:
|
193
|
+
new_error = 0.0
|
194
|
+
old_error = 0.0
|
184
195
|
|
185
196
|
return (
|
186
197
|
uncalibrated_and_not_basis_p
|
@@ -198,32 +209,47 @@ class Optimize1qGatesDecomposition(TransformationPass):
|
|
198
209
|
Returns:
|
199
210
|
DAGCircuit: the optimized DAG.
|
200
211
|
"""
|
201
|
-
runs =
|
202
|
-
|
212
|
+
runs = []
|
213
|
+
qubits = []
|
214
|
+
bases = []
|
215
|
+
for run in dag.collect_1q_runs():
|
203
216
|
qubit = dag.find_bit(run[0].qargs[0]).index
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
217
|
+
runs.append(run)
|
218
|
+
qubits.append(qubit)
|
219
|
+
bases.append(self._get_decomposer(qubit))
|
220
|
+
best_sequences = euler_one_qubit_decomposer.optimize_1q_gates_decomposition(
|
221
|
+
runs, qubits, bases, simplify=True, error_map=self.error_map
|
222
|
+
)
|
223
|
+
for index, best_circuit_sequence in enumerate(best_sequences):
|
224
|
+
run = runs[index]
|
225
|
+
qubit = qubits[index]
|
209
226
|
if self._target is None:
|
210
227
|
basis = self._basis_gates
|
211
228
|
else:
|
212
229
|
basis = self._target.operation_names_for_qargs((qubit,))
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
230
|
+
if best_circuit_sequence is not None:
|
231
|
+
(old_error, new_error, best_circuit_sequence) = best_circuit_sequence
|
232
|
+
if self._substitution_checks(
|
233
|
+
dag,
|
234
|
+
run,
|
235
|
+
best_circuit_sequence,
|
236
|
+
basis,
|
237
|
+
qubit,
|
238
|
+
old_error=old_error,
|
239
|
+
new_error=new_error,
|
240
|
+
):
|
241
|
+
first_node_id = run[0]._node_id
|
242
|
+
qubit = run[0].qargs
|
243
|
+
for gate, angles in best_circuit_sequence:
|
244
|
+
op = CircuitInstruction.from_standard(gate, qubit, angles)
|
245
|
+
node = DAGOpNode.from_instruction(op, dag=dag)
|
246
|
+
node._node_id = dag._multi_graph.add_node(node)
|
247
|
+
dag._increment_op(gate.name)
|
248
|
+
dag._multi_graph.insert_node_on_in_edges(node._node_id, first_node_id)
|
249
|
+
dag.global_phase += best_circuit_sequence.global_phase
|
250
|
+
# Delete the other nodes in the run
|
251
|
+
for current_node in run:
|
252
|
+
dag.remove_op_node(current_node)
|
227
253
|
|
228
254
|
return dag
|
229
255
|
|
@@ -241,10 +267,7 @@ class Optimize1qGatesDecomposition(TransformationPass):
|
|
241
267
|
circuit, qubit, self.error_map
|
242
268
|
)
|
243
269
|
else:
|
244
|
-
|
245
|
-
return euler_one_qubit_decomposer.compute_error_list(
|
246
|
-
circuit_list, qubit, self.error_map
|
247
|
-
)
|
270
|
+
return euler_one_qubit_decomposer.compute_error_list(circuit, qubit, self.error_map)
|
248
271
|
|
249
272
|
|
250
273
|
def _possible_decomposers(basis_set):
|
@@ -308,7 +308,7 @@ class Optimize1qGates(TransformationPass):
|
|
308
308
|
if "u3" in self.basis:
|
309
309
|
new_op = U3Gate(*right_parameters)
|
310
310
|
else:
|
311
|
-
raise TranspilerError("It was not possible to use the basis
|
311
|
+
raise TranspilerError(f"It was not possible to use the basis {self.basis}")
|
312
312
|
|
313
313
|
dag.global_phase += right_global_phase
|
314
314
|
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# This code is part of Qiskit.
|
2
|
+
#
|
3
|
+
# (C) Copyright IBM 2017, 2024.
|
4
|
+
#
|
5
|
+
# This code is licensed under the Apache License, Version 2.0. You may
|
6
|
+
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
7
|
+
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
8
|
+
#
|
9
|
+
# Any modifications or derivative works of this code must retain this
|
10
|
+
# copyright notice, and modified files need to carry a notice indicating
|
11
|
+
# that they have been altered from the originals.
|
12
|
+
"""Splits each two-qubit gate in the `dag` into two single-qubit gates, if possible without error."""
|
13
|
+
from typing import Optional
|
14
|
+
|
15
|
+
from qiskit.transpiler.basepasses import TransformationPass
|
16
|
+
from qiskit.circuit.quantumcircuitdata import CircuitInstruction
|
17
|
+
from qiskit.dagcircuit.dagcircuit import DAGCircuit, DAGOpNode
|
18
|
+
from qiskit.circuit.library.generalized_gates import UnitaryGate
|
19
|
+
from qiskit.synthesis.two_qubit.two_qubit_decompose import TwoQubitWeylDecomposition
|
20
|
+
|
21
|
+
|
22
|
+
class Split2QUnitaries(TransformationPass):
|
23
|
+
"""Attempt to splits two-qubit gates in a :class:`.DAGCircuit` into two single-qubit gates
|
24
|
+
|
25
|
+
This pass will analyze all the two qubit gates in the circuit and analyze the gate's unitary
|
26
|
+
matrix to determine if the gate is actually a product of 2 single qubit gates. In these
|
27
|
+
cases the 2q gate can be simplified into two single qubit gates and this pass will
|
28
|
+
perform this optimization and will replace the two qubit gate with two single qubit
|
29
|
+
:class:`.UnitaryGate`.
|
30
|
+
"""
|
31
|
+
|
32
|
+
def __init__(self, fidelity: Optional[float] = 1.0 - 1e-16):
|
33
|
+
"""Split2QUnitaries initializer.
|
34
|
+
|
35
|
+
Args:
|
36
|
+
fidelity (float): Allowed tolerance for splitting two-qubit unitaries and gate decompositions
|
37
|
+
"""
|
38
|
+
super().__init__()
|
39
|
+
self.requested_fidelity = fidelity
|
40
|
+
|
41
|
+
def run(self, dag: DAGCircuit):
|
42
|
+
"""Run the Split2QUnitaries pass on `dag`."""
|
43
|
+
for node in dag.topological_op_nodes():
|
44
|
+
# skip operations without two-qubits and for which we can not determine a potential 1q split
|
45
|
+
if (
|
46
|
+
len(node.cargs) > 0
|
47
|
+
or len(node.qargs) != 2
|
48
|
+
or node.matrix is None
|
49
|
+
or node.is_parameterized()
|
50
|
+
):
|
51
|
+
continue
|
52
|
+
|
53
|
+
decomp = TwoQubitWeylDecomposition(node.op, fidelity=self.requested_fidelity)
|
54
|
+
if (
|
55
|
+
decomp._inner_decomposition.specialization
|
56
|
+
== TwoQubitWeylDecomposition._specializations.IdEquiv
|
57
|
+
):
|
58
|
+
new_dag = DAGCircuit()
|
59
|
+
new_dag.add_qubits(node.qargs)
|
60
|
+
|
61
|
+
ur = decomp.K1r
|
62
|
+
ur_node = DAGOpNode.from_instruction(
|
63
|
+
CircuitInstruction(UnitaryGate(ur), qubits=(node.qargs[0],)), dag=new_dag
|
64
|
+
)
|
65
|
+
|
66
|
+
ul = decomp.K1l
|
67
|
+
ul_node = DAGOpNode.from_instruction(
|
68
|
+
CircuitInstruction(UnitaryGate(ul), qubits=(node.qargs[1],)), dag=new_dag
|
69
|
+
)
|
70
|
+
new_dag._apply_op_node_back(ur_node)
|
71
|
+
new_dag._apply_op_node_back(ul_node)
|
72
|
+
new_dag.global_phase = decomp.global_phase
|
73
|
+
dag.substitute_node_with_dag(node, new_dag)
|
74
|
+
elif (
|
75
|
+
decomp._inner_decomposition.specialization
|
76
|
+
== TwoQubitWeylDecomposition._specializations.SWAPEquiv
|
77
|
+
):
|
78
|
+
# TODO maybe also look into swap-gate-like gates? Things to consider:
|
79
|
+
# * As the qubit mapping may change, we'll always need to build a new dag in this pass
|
80
|
+
# * There may not be many swap-gate-like gates in an arbitrary input circuit
|
81
|
+
# * Removing swap gates from a user-routed input circuit here is unexpected
|
82
|
+
pass
|
83
|
+
return dag
|
@@ -622,7 +622,7 @@ class BackwardMatch:
|
|
622
622
|
)
|
623
623
|
self.matching_list.append_scenario(new_matching_scenario)
|
624
624
|
|
625
|
-
# Third option: if blocking the
|
625
|
+
# Third option: if blocking the successors breaks a match, we consider
|
626
626
|
# also the possibility to block all predecessors (push the gate to the left).
|
627
627
|
if broken_matches and all(global_broken):
|
628
628
|
|
@@ -507,7 +507,7 @@ class TemplateSubstitution:
|
|
507
507
|
to_native_symbolic = lambda x: x
|
508
508
|
|
509
509
|
circuit_params, template_params = [], []
|
510
|
-
# Set of all parameter names that are present in the circuits to be
|
510
|
+
# Set of all parameter names that are present in the circuits to be optimized.
|
511
511
|
circuit_params_set = set()
|
512
512
|
|
513
513
|
template_dag_dep = copy.deepcopy(self.template_dag_dep)
|
@@ -17,8 +17,9 @@ from collections import defaultdict
|
|
17
17
|
from qiskit.circuit import Gate, QuantumCircuit, Qubit
|
18
18
|
from qiskit.converters import circuit_to_dag
|
19
19
|
from qiskit.dagcircuit import DAGCircuit, DAGOpNode
|
20
|
-
from qiskit.transpiler import TransformationPass
|
21
|
-
|
20
|
+
from qiskit.transpiler.basepasses import TransformationPass
|
21
|
+
from qiskit.transpiler.exceptions import TranspilerError
|
22
|
+
from qiskit.transpiler.layout import Layout
|
22
23
|
from qiskit.transpiler.passes.routing.commuting_2q_gate_routing.swap_strategy import SwapStrategy
|
23
24
|
from qiskit.transpiler.passes.routing.commuting_2q_gate_routing.commuting_2q_block import (
|
24
25
|
Commuting2qBlock,
|
@@ -15,9 +15,10 @@ from __future__ import annotations
|
|
15
15
|
|
16
16
|
import numpy as np
|
17
17
|
|
18
|
-
from qiskit.transpiler import Layout, CouplingMap
|
19
18
|
from qiskit.transpiler.basepasses import TransformationPass
|
19
|
+
from qiskit.transpiler.coupling import CouplingMap
|
20
20
|
from qiskit.transpiler.exceptions import TranspilerError
|
21
|
+
from qiskit.transpiler.layout import Layout
|
21
22
|
from qiskit.transpiler.passes.routing.algorithms import ApproximateTokenSwapper
|
22
23
|
from qiskit.transpiler.target import Target
|
23
24
|
|
@@ -18,7 +18,7 @@ import time
|
|
18
18
|
|
19
19
|
import rustworkx
|
20
20
|
|
21
|
-
from qiskit.circuit import SwitchCaseOp,
|
21
|
+
from qiskit.circuit import SwitchCaseOp, Clbit, ClassicalRegister
|
22
22
|
from qiskit.circuit.library.standard_gates import SwapGate
|
23
23
|
from qiskit.circuit.controlflow import condition_resources, node_resources
|
24
24
|
from qiskit.converters import dag_to_circuit
|
@@ -28,15 +28,10 @@ from qiskit.transpiler.exceptions import TranspilerError
|
|
28
28
|
from qiskit.transpiler.layout import Layout
|
29
29
|
from qiskit.transpiler.target import Target
|
30
30
|
from qiskit.transpiler.passes.layout import disjoint_utils
|
31
|
-
from qiskit.dagcircuit import DAGCircuit
|
31
|
+
from qiskit.dagcircuit import DAGCircuit, DAGOpNode
|
32
32
|
from qiskit.utils.parallel import CPU_COUNT
|
33
33
|
|
34
|
-
from qiskit._accelerate.sabre import
|
35
|
-
sabre_routing,
|
36
|
-
Heuristic,
|
37
|
-
NeighborTable,
|
38
|
-
SabreDAG,
|
39
|
-
)
|
34
|
+
from qiskit._accelerate.sabre import sabre_routing, Heuristic, SetScaling, NeighborTable, SabreDAG
|
40
35
|
from qiskit._accelerate.nlayout import NLayout
|
41
36
|
|
42
37
|
logger = logging.getLogger(__name__)
|
@@ -211,14 +206,27 @@ class SabreSwap(TransformationPass):
|
|
211
206
|
" This circuit cannot be routed to this device."
|
212
207
|
)
|
213
208
|
|
214
|
-
if self.heuristic
|
215
|
-
heuristic =
|
209
|
+
if isinstance(self.heuristic, Heuristic):
|
210
|
+
heuristic = self.heuristic
|
211
|
+
elif self.heuristic == "basic":
|
212
|
+
heuristic = Heuristic(attempt_limit=10 * num_dag_qubits).with_basic(
|
213
|
+
1.0, SetScaling.Size
|
214
|
+
)
|
216
215
|
elif self.heuristic == "lookahead":
|
217
|
-
heuristic =
|
216
|
+
heuristic = (
|
217
|
+
Heuristic(attempt_limit=10 * num_dag_qubits)
|
218
|
+
.with_basic(1.0, SetScaling.Size)
|
219
|
+
.with_lookahead(0.5, 20, SetScaling.Size)
|
220
|
+
)
|
218
221
|
elif self.heuristic == "decay":
|
219
|
-
heuristic =
|
222
|
+
heuristic = (
|
223
|
+
Heuristic(attempt_limit=10 * num_dag_qubits)
|
224
|
+
.with_basic(1.0, SetScaling.Size)
|
225
|
+
.with_lookahead(0.5, 20, SetScaling.Size)
|
226
|
+
.with_decay(0.001, 5)
|
227
|
+
)
|
220
228
|
else:
|
221
|
-
raise TranspilerError("Heuristic
|
229
|
+
raise TranspilerError(f"Heuristic {self.heuristic} not recognized.")
|
222
230
|
disjoint_utils.require_layout_isolated_to_component(
|
223
231
|
dag, self.coupling_map if self.target is None else self.target
|
224
232
|
)
|
@@ -289,9 +297,9 @@ def _build_sabre_dag(dag, num_physical_qubits, qubit_indices):
|
|
289
297
|
node_blocks = {}
|
290
298
|
for node in block_dag.topological_op_nodes():
|
291
299
|
cargs_bits = set(node.cargs)
|
292
|
-
if node.
|
293
|
-
cargs_bits.update(condition_resources(node.
|
294
|
-
if isinstance(node.op, SwitchCaseOp):
|
300
|
+
if node.condition is not None:
|
301
|
+
cargs_bits.update(condition_resources(node.condition).clbits)
|
302
|
+
if node.is_control_flow() and isinstance(node.op, SwitchCaseOp):
|
295
303
|
target = node.op.target
|
296
304
|
if isinstance(target, Clbit):
|
297
305
|
cargs_bits.add(target)
|
@@ -300,7 +308,7 @@ def _build_sabre_dag(dag, num_physical_qubits, qubit_indices):
|
|
300
308
|
else: # Expr
|
301
309
|
cargs_bits.update(node_resources(target).clbits)
|
302
310
|
cargs = {block_dag.find_bit(x).index for x in cargs_bits}
|
303
|
-
if
|
311
|
+
if node.is_control_flow():
|
304
312
|
node_blocks[node._node_id] = [
|
305
313
|
recurse(
|
306
314
|
block,
|
@@ -313,7 +321,7 @@ def _build_sabre_dag(dag, num_physical_qubits, qubit_indices):
|
|
313
321
|
node._node_id,
|
314
322
|
[wire_map[x] for x in node.qargs],
|
315
323
|
cargs,
|
316
|
-
|
324
|
+
node.is_directive(),
|
317
325
|
)
|
318
326
|
)
|
319
327
|
return SabreDAG(num_physical_qubits, block_dag.num_clbits(), dag_list, node_blocks)
|
@@ -383,14 +391,15 @@ def _apply_sabre_result(
|
|
383
391
|
node = source_dag._multi_graph[node_id]
|
384
392
|
if node_id in swap_map:
|
385
393
|
apply_swaps(dest_dag, swap_map[node_id], layout)
|
386
|
-
if not
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
+
if not node.is_control_flow():
|
395
|
+
qubits = [
|
396
|
+
physical_qubits[layout.virtual_to_physical(root_logical_map[q])]
|
397
|
+
for q in node.qargs
|
398
|
+
]
|
399
|
+
dest_dag._apply_op_node_back(
|
400
|
+
DAGOpNode.from_instruction(
|
401
|
+
node._to_circuit_instruction().replace(qubits=qubits)
|
402
|
+
),
|
394
403
|
check=False,
|
395
404
|
)
|
396
405
|
continue
|
@@ -14,11 +14,15 @@
|
|
14
14
|
from typing import Iterable, Union, Optional, List, Tuple
|
15
15
|
from math import floor, log10
|
16
16
|
|
17
|
-
from qiskit.circuit import Barrier
|
17
|
+
from qiskit.circuit import SwitchCaseOp, Clbit, ClassicalRegister, Barrier
|
18
|
+
from qiskit.circuit.controlflow import condition_resources, node_resources
|
18
19
|
from qiskit.dagcircuit import DAGOpNode, DAGDepNode, DAGDependency, DAGCircuit
|
19
|
-
from qiskit.transpiler import Layout
|
20
20
|
from qiskit.transpiler.basepasses import TransformationPass
|
21
|
-
from qiskit.
|
21
|
+
from qiskit.transpiler.layout import Layout
|
22
|
+
from qiskit.transpiler.passes.routing.sabre_swap import _build_sabre_dag, _apply_sabre_result
|
23
|
+
|
24
|
+
from qiskit._accelerate import star_prerouting
|
25
|
+
from qiskit._accelerate.nlayout import NLayout
|
22
26
|
|
23
27
|
|
24
28
|
class StarBlock:
|
@@ -260,7 +264,7 @@ class StarPreRouting(TransformationPass):
|
|
260
264
|
# star block by a linear sequence of gates
|
261
265
|
new_dag, qubit_mapping = self.star_preroute(dag, star_blocks, processing_order)
|
262
266
|
|
263
|
-
# Fix output
|
267
|
+
# Fix output permutation -- copied from ElidePermutations
|
264
268
|
input_qubit_mapping = {qubit: index for index, qubit in enumerate(dag.qubits)}
|
265
269
|
self.property_set["original_layout"] = Layout(input_qubit_mapping)
|
266
270
|
if self.property_set["original_qubit_indices"] is None:
|
@@ -305,113 +309,84 @@ class StarPreRouting(TransformationPass):
|
|
305
309
|
new_dag: a dag specifying the pre-routed circuit
|
306
310
|
qubit_mapping: the final qubit mapping after pre-routing
|
307
311
|
"""
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
is_first_star = True
|
321
|
-
last_2q_gate = [
|
322
|
-
op
|
323
|
-
for op in reversed(processing_order)
|
324
|
-
if ((len(op.qargs) > 1) and (op.name != "barrier"))
|
312
|
+
# Convert the DAG to a SabreDAG
|
313
|
+
num_qubits = len(dag.qubits)
|
314
|
+
canonical_register = dag.qregs["q"]
|
315
|
+
current_layout = Layout.generate_trivial_layout(canonical_register)
|
316
|
+
qubit_indices = {bit: idx for idx, bit in enumerate(canonical_register)}
|
317
|
+
layout_mapping = {qubit_indices[k]: v for k, v in current_layout.get_virtual_bits().items()}
|
318
|
+
initial_layout = NLayout(layout_mapping, num_qubits, num_qubits)
|
319
|
+
sabre_dag, circuit_to_dag_dict = _build_sabre_dag(dag, num_qubits, qubit_indices)
|
320
|
+
|
321
|
+
# Extract the nodes from the blocks for the Rust representation
|
322
|
+
rust_blocks = [
|
323
|
+
(block.center is not None, _extract_nodes(block.get_nodes(), dag)) for block in blocks
|
325
324
|
]
|
326
|
-
if len(last_2q_gate) > 0:
|
327
|
-
last_2q_gate = last_2q_gate[0]
|
328
|
-
else:
|
329
|
-
last_2q_gate = None
|
330
325
|
|
326
|
+
# Determine the processing order of the nodes in the DAG for the Rust representation
|
331
327
|
int_digits = floor(log10(len(processing_order))) + 1
|
332
328
|
processing_order_index_map = {
|
333
|
-
node: f"a{
|
334
|
-
for index, node in enumerate(processing_order)
|
329
|
+
node: f"a{index:0{int_digits}}" for index, node in enumerate(processing_order)
|
335
330
|
}
|
336
331
|
|
337
332
|
def tie_breaker_key(node):
|
338
333
|
return processing_order_index_map.get(node, node.sort_key)
|
339
334
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
)
|
399
|
-
# Swap mapping
|
400
|
-
index_0 = dag.find_bit(inner_node.qargs[0]).index
|
401
|
-
index_1 = dag.find_bit(inner_node.qargs[1]).index
|
402
|
-
qubit_mapping[index_1], qubit_mapping[index_0] = (
|
403
|
-
qubit_mapping[index_0],
|
404
|
-
qubit_mapping[index_1],
|
405
|
-
)
|
406
|
-
|
407
|
-
prev = inner_node.qargs
|
408
|
-
is_first_star = False
|
409
|
-
else:
|
410
|
-
# the node is not part of a block
|
411
|
-
new_dag.apply_operation_back(
|
412
|
-
node.op,
|
413
|
-
_apply_mapping(node.qargs, qubit_mapping, dag.qubits),
|
414
|
-
node.cargs,
|
415
|
-
check=False,
|
416
|
-
)
|
417
|
-
return new_dag, qubit_mapping
|
335
|
+
rust_processing_order = _extract_nodes(dag.topological_op_nodes(key=tie_breaker_key), dag)
|
336
|
+
|
337
|
+
# Run the star prerouting algorithm to obtain the new DAG and qubit mapping
|
338
|
+
*sabre_result, qubit_mapping = star_prerouting.star_preroute(
|
339
|
+
sabre_dag, rust_blocks, rust_processing_order
|
340
|
+
)
|
341
|
+
|
342
|
+
res_dag = _apply_sabre_result(
|
343
|
+
dag.copy_empty_like(),
|
344
|
+
dag,
|
345
|
+
sabre_result,
|
346
|
+
initial_layout,
|
347
|
+
dag.qubits,
|
348
|
+
circuit_to_dag_dict,
|
349
|
+
)
|
350
|
+
|
351
|
+
return res_dag, qubit_mapping
|
352
|
+
|
353
|
+
|
354
|
+
def _extract_nodes(nodes, dag):
|
355
|
+
"""Extract and format node information for Rust representation used in SabreDAG.
|
356
|
+
|
357
|
+
Each node is represented as a tuple containing:
|
358
|
+
- Node ID (int): The unique identifier of the node in the DAG.
|
359
|
+
- Qubit indices (list of int): Indices of qubits involved in the node's operation.
|
360
|
+
- Classical bit indices (set of int): Indices of classical bits involved in the node's operation.
|
361
|
+
- Directive flag (bool): Indicates whether the operation is a directive (True) or not (False).
|
362
|
+
|
363
|
+
Args:
|
364
|
+
nodes (list[DAGOpNode]): List of DAGOpNode objects to extract information from.
|
365
|
+
dag (DAGCircuit): DAGCircuit object containing the circuit structure.
|
366
|
+
|
367
|
+
Returns:
|
368
|
+
list of tuples: Each tuple contains information about a node in the format described above.
|
369
|
+
"""
|
370
|
+
extracted_node_info = []
|
371
|
+
for node in nodes:
|
372
|
+
qubit_indices = [dag.find_bit(qubit).index for qubit in node.qargs]
|
373
|
+
classical_bit_indices = set()
|
374
|
+
|
375
|
+
if node.op.condition is not None:
|
376
|
+
classical_bit_indices.update(condition_resources(node.op.condition).clbits)
|
377
|
+
|
378
|
+
if isinstance(node.op, SwitchCaseOp):
|
379
|
+
switch_case_target = node.op.target
|
380
|
+
if isinstance(switch_case_target, Clbit):
|
381
|
+
classical_bit_indices.add(switch_case_target)
|
382
|
+
elif isinstance(switch_case_target, ClassicalRegister):
|
383
|
+
classical_bit_indices.update(switch_case_target)
|
384
|
+
else: # Assume target is an expression involving classical bits
|
385
|
+
classical_bit_indices.update(node_resources(switch_case_target).clbits)
|
386
|
+
|
387
|
+
is_directive = getattr(node.op, "_directive", False)
|
388
|
+
extracted_node_info.append(
|
389
|
+
(node._node_id, qubit_indices, classical_bit_indices, is_directive)
|
390
|
+
)
|
391
|
+
|
392
|
+
return extracted_node_info
|