mirror of https://github.com/Qiskit/qiskit.git
Move `generate_preset_pass_manager` to a standalone file (#12762)
* Move generate_preset_pass_manager to generate_preset_pass_manager.py * Add top-level import and reno * Apply suggestions from Matt's code review Co-authored-by: Matthew Treinish <mtreinish@kortar.org> * Add import path from qiskit.transpiler too * Fix cyclic import issue * Fix cyclic import issue in tools/pgo_scripts * Address cyclic import issues. Reorder imports alphabetically when relevant. * Fix docstring issue * Update releasenotes/notes/add-generate-preset-pm-global-import-efb12f185f3f738b.yaml Co-authored-by: Matthew Treinish <mtreinish@kortar.org> --------- Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
This commit is contained in:
parent
e362da5c0c
commit
e09d345514
|
@ -101,7 +101,7 @@ import qiskit.circuit.reset
|
|||
_config = _user_config.get_config()
|
||||
|
||||
from qiskit.compiler import transpile, assemble, schedule, sequence
|
||||
|
||||
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
|
||||
from .version import __version__
|
||||
|
||||
__all__ = [
|
||||
|
@ -115,4 +115,5 @@ __all__ = [
|
|||
"schedule",
|
||||
"sequence",
|
||||
"transpile",
|
||||
"generate_preset_pass_manager",
|
||||
]
|
||||
|
|
|
@ -23,7 +23,7 @@ from qiskit.circuit.quantumcircuit import QuantumCircuit
|
|||
from qiskit.exceptions import QiskitError
|
||||
from qiskit.pulse import InstructionScheduleMap, Schedule
|
||||
from qiskit.providers.backend import Backend
|
||||
from qiskit.scheduler import ScheduleConfig
|
||||
from qiskit.scheduler.config import ScheduleConfig
|
||||
from qiskit.scheduler.schedule_circuit import schedule_circuit
|
||||
from qiskit.utils.parallel import parallel_map
|
||||
|
||||
|
|
|
@ -1277,6 +1277,7 @@ from .basepasses import AnalysisPass, TransformationPass
|
|||
from .coupling import CouplingMap
|
||||
from .layout import Layout, TranspileLayout
|
||||
from .instruction_durations import InstructionDurations
|
||||
from .preset_passmanagers import generate_preset_pass_manager
|
||||
from .target import Target
|
||||
from .target import InstructionProperties
|
||||
from .target import QubitProperties
|
||||
|
|
|
@ -15,8 +15,7 @@ from __future__ import annotations
|
|||
from typing import Optional, List, Tuple, Union, Iterable
|
||||
|
||||
import qiskit.circuit
|
||||
from qiskit.circuit import Barrier, Delay
|
||||
from qiskit.circuit import Instruction, ParameterExpression
|
||||
from qiskit.circuit import Barrier, Delay, Instruction, ParameterExpression
|
||||
from qiskit.circuit.duration import duration_in_dt
|
||||
from qiskit.providers import Backend
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
|
|
|
@ -15,15 +15,13 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from qiskit.circuit import Instruction, ParameterExpression, Qubit, Clbit
|
||||
from qiskit.circuit.equivalence_library import EquivalenceLibrary
|
||||
from qiskit.converters import circuit_to_dag
|
||||
from qiskit.dagcircuit import DAGCircuit, DAGOpNode
|
||||
from qiskit.circuit.equivalence_library import EquivalenceLibrary
|
||||
from qiskit.exceptions import QiskitError
|
||||
from qiskit.transpiler import Target
|
||||
|
||||
from qiskit.transpiler.basepasses import TransformationPass
|
||||
|
||||
from .basis_translator import BasisTranslator
|
||||
from qiskit.transpiler.passes.basis.basis_translator import BasisTranslator
|
||||
from qiskit.transpiler.target import Target
|
||||
|
||||
|
||||
class TranslateParameterizedGates(TransformationPass):
|
||||
|
|
|
@ -17,13 +17,13 @@ from functools import lru_cache
|
|||
import numpy as np
|
||||
|
||||
from qiskit.circuit import Instruction
|
||||
from qiskit.circuit.library.standard_gates import RXGate
|
||||
from qiskit.exceptions import QiskitError
|
||||
from qiskit.pulse import Schedule, ScheduleBlock, builder, ScalableSymbolicPulse
|
||||
from qiskit.pulse.channels import Channel
|
||||
from qiskit.pulse.library.symbolic_pulses import Drag
|
||||
from qiskit.transpiler.passes.calibration.base_builder import CalibrationBuilder
|
||||
from qiskit.transpiler import Target
|
||||
from qiskit.circuit.library.standard_gates import RXGate
|
||||
from qiskit.exceptions import QiskitError
|
||||
from qiskit.transpiler.target import Target
|
||||
|
||||
|
||||
class RXCalibrationBuilder(CalibrationBuilder):
|
||||
|
|
|
@ -14,8 +14,11 @@
|
|||
|
||||
import itertools
|
||||
|
||||
from qiskit.transpiler import CouplingMap, Target, AnalysisPass, TranspilerError
|
||||
from qiskit.transpiler.basepasses import AnalysisPass
|
||||
from qiskit.transpiler.coupling import CouplingMap
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler.passes.layout.vf2_layout import VF2Layout
|
||||
from qiskit.transpiler.target import Target
|
||||
from qiskit._accelerate.error_map import ErrorMap
|
||||
|
||||
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
# that they have been altered from the originals.
|
||||
|
||||
"""Set the ``layout`` property to the given layout."""
|
||||
from qiskit.transpiler import Layout
|
||||
from qiskit.transpiler.exceptions import InvalidLayoutError
|
||||
from qiskit.transpiler.basepasses import AnalysisPass
|
||||
from qiskit.transpiler.exceptions import InvalidLayoutError
|
||||
from qiskit.transpiler.layout import Layout
|
||||
|
||||
|
||||
class SetLayout(AnalysisPass):
|
||||
|
|
|
@ -17,8 +17,9 @@ from collections import defaultdict
|
|||
from qiskit.circuit import Gate, QuantumCircuit, Qubit
|
||||
from qiskit.converters import circuit_to_dag
|
||||
from qiskit.dagcircuit import DAGCircuit, DAGOpNode
|
||||
from qiskit.transpiler import TransformationPass, Layout, TranspilerError
|
||||
|
||||
from qiskit.transpiler.basepasses import TransformationPass
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler.layout import Layout
|
||||
from qiskit.transpiler.passes.routing.commuting_2q_gate_routing.swap_strategy import SwapStrategy
|
||||
from qiskit.transpiler.passes.routing.commuting_2q_gate_routing.commuting_2q_block import (
|
||||
Commuting2qBlock,
|
||||
|
|
|
@ -17,7 +17,7 @@ import copy
|
|||
import numpy as np
|
||||
|
||||
from qiskit.exceptions import QiskitError
|
||||
from qiskit.transpiler import CouplingMap
|
||||
from qiskit.transpiler.coupling import CouplingMap
|
||||
|
||||
|
||||
class SwapStrategy:
|
||||
|
|
|
@ -15,9 +15,10 @@ from __future__ import annotations
|
|||
|
||||
import numpy as np
|
||||
|
||||
from qiskit.transpiler import Layout, CouplingMap
|
||||
from qiskit.transpiler.basepasses import TransformationPass
|
||||
from qiskit.transpiler.coupling import CouplingMap
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler.layout import Layout
|
||||
from qiskit.transpiler.passes.routing.algorithms import ApproximateTokenSwapper
|
||||
from qiskit.transpiler.target import Target
|
||||
|
||||
|
|
|
@ -15,10 +15,10 @@ from typing import Iterable, Union, Optional, List, Tuple
|
|||
from math import floor, log10
|
||||
|
||||
from qiskit.circuit import Barrier
|
||||
from qiskit.dagcircuit import DAGOpNode, DAGDepNode, DAGDependency, DAGCircuit
|
||||
from qiskit.transpiler import Layout
|
||||
from qiskit.transpiler.basepasses import TransformationPass
|
||||
from qiskit.circuit.library import SwapGate
|
||||
from qiskit.dagcircuit import DAGOpNode, DAGDepNode, DAGDependency, DAGCircuit
|
||||
from qiskit.transpiler.basepasses import TransformationPass
|
||||
from qiskit.transpiler.layout import Layout
|
||||
|
||||
|
||||
class StarBlock:
|
||||
|
|
|
@ -15,10 +15,9 @@
|
|||
from qiskit.circuit import Delay, Qubit, Measure
|
||||
from qiskit.dagcircuit import DAGCircuit
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler.passes.scheduling.base_scheduler import BaseSchedulerTransform
|
||||
from qiskit.utils.deprecation import deprecate_func
|
||||
|
||||
from .base_scheduler import BaseSchedulerTransform
|
||||
|
||||
|
||||
class ALAPSchedule(BaseSchedulerTransform):
|
||||
"""ALAP Scheduling pass, which schedules the **stop** time of instructions as late as possible.
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
from qiskit.circuit.delay import Delay
|
||||
from qiskit.dagcircuit import DAGCircuit
|
||||
from qiskit.transpiler.basepasses import AnalysisPass
|
||||
from qiskit.transpiler import Target
|
||||
from qiskit.transpiler.target import Target
|
||||
|
||||
|
||||
class InstructionDurationCheck(AnalysisPass):
|
||||
|
|
|
@ -16,7 +16,7 @@ from qiskit.dagcircuit import DAGCircuit
|
|||
from qiskit.pulse import Play
|
||||
from qiskit.transpiler.basepasses import AnalysisPass
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler import Target
|
||||
from qiskit.transpiler.target import Target
|
||||
|
||||
|
||||
class ValidatePulseGates(AnalysisPass):
|
||||
|
|
|
@ -21,7 +21,7 @@ from qiskit.circuit.reset import Reset
|
|||
from qiskit.dagcircuit import DAGCircuit, DAGOpNode, DAGOutNode
|
||||
from qiskit.transpiler.basepasses import AnalysisPass
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler import Target
|
||||
from qiskit.transpiler.target import Target
|
||||
|
||||
|
||||
class ConstrainedReschedule(AnalysisPass):
|
||||
|
|
|
@ -15,10 +15,9 @@
|
|||
from qiskit.circuit import Delay, Qubit, Measure
|
||||
from qiskit.dagcircuit import DAGCircuit
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler.passes.scheduling.base_scheduler import BaseSchedulerTransform
|
||||
from qiskit.utils.deprecation import deprecate_func
|
||||
|
||||
from .base_scheduler import BaseSchedulerTransform
|
||||
|
||||
|
||||
class ASAPSchedule(BaseSchedulerTransform):
|
||||
"""ASAP Scheduling pass, which schedules the start time of instructions as early as possible..
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
"""Base circuit scheduling pass."""
|
||||
import warnings
|
||||
|
||||
from qiskit.transpiler import InstructionDurations
|
||||
from qiskit.transpiler.basepasses import TransformationPass
|
||||
from qiskit.transpiler.passes.scheduling.time_unit_conversion import TimeUnitConversion
|
||||
from qiskit.dagcircuit import DAGOpNode, DAGCircuit, DAGOutNode
|
||||
from qiskit.circuit import Delay, Gate, Measure, Reset
|
||||
from qiskit.circuit.parameterexpression import ParameterExpression
|
||||
from qiskit.dagcircuit import DAGOpNode, DAGCircuit, DAGOutNode
|
||||
from qiskit.transpiler.basepasses import TransformationPass
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler.instruction_durations import InstructionDurations
|
||||
from qiskit.transpiler.passes.scheduling.time_unit_conversion import TimeUnitConversion
|
||||
from qiskit.transpiler.target import Target
|
||||
|
||||
|
||||
|
|
|
@ -20,10 +20,10 @@ from qiskit.circuit.library.standard_gates import IGate, UGate, U3Gate
|
|||
from qiskit.dagcircuit import DAGOpNode, DAGInNode
|
||||
from qiskit.quantum_info.operators.predicates import matrix_equal
|
||||
from qiskit.synthesis.one_qubit import OneQubitEulerDecomposer
|
||||
from qiskit.transpiler import InstructionDurations
|
||||
from qiskit.transpiler.passes.optimization import Optimize1qGates
|
||||
from qiskit.transpiler.basepasses import TransformationPass
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler.instruction_durations import InstructionDurations
|
||||
from qiskit.transpiler.passes.optimization import Optimize1qGates
|
||||
from qiskit.utils.deprecation import deprecate_func
|
||||
|
||||
|
||||
|
|
|
@ -26,9 +26,9 @@ from qiskit.synthesis.one_qubit import OneQubitEulerDecomposer
|
|||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler.instruction_durations import InstructionDurations
|
||||
from qiskit.transpiler.passes.optimization import Optimize1qGates
|
||||
from qiskit.transpiler.passes.scheduling.padding.base_padding import BasePadding
|
||||
from qiskit.transpiler.target import Target
|
||||
|
||||
from .base_padding import BasePadding
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -14,13 +14,13 @@
|
|||
|
||||
import warnings
|
||||
|
||||
from qiskit.transpiler import InstructionDurations
|
||||
from qiskit.transpiler.basepasses import AnalysisPass
|
||||
from qiskit.transpiler.passes.scheduling.time_unit_conversion import TimeUnitConversion
|
||||
from qiskit.dagcircuit import DAGOpNode, DAGCircuit
|
||||
from qiskit.circuit import Delay, Gate
|
||||
from qiskit.circuit.parameterexpression import ParameterExpression
|
||||
from qiskit.dagcircuit import DAGOpNode, DAGCircuit
|
||||
from qiskit.transpiler.basepasses import AnalysisPass
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler.instruction_durations import InstructionDurations
|
||||
from qiskit.transpiler.passes.scheduling.time_unit_conversion import TimeUnitConversion
|
||||
from qiskit.transpiler.target import Target
|
||||
|
||||
|
||||
|
|
|
@ -28,21 +28,9 @@ from itertools import product
|
|||
from functools import partial
|
||||
import numpy as np
|
||||
|
||||
from qiskit.converters import circuit_to_dag, dag_to_circuit
|
||||
from qiskit.transpiler import CouplingMap, Target
|
||||
from qiskit.transpiler.basepasses import TransformationPass
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.dagcircuit.dagcircuit import DAGCircuit, DAGOpNode
|
||||
from qiskit.synthesis.one_qubit import one_qubit_decompose
|
||||
from qiskit.transpiler.passes.optimization.optimize_1q_decomposition import _possible_decomposers
|
||||
from qiskit.synthesis.two_qubit.xx_decompose import XXDecomposer, XXEmbodiments
|
||||
from qiskit.synthesis.two_qubit.two_qubit_decompose import (
|
||||
TwoQubitBasisDecomposer,
|
||||
TwoQubitWeylDecomposition,
|
||||
)
|
||||
from qiskit.quantum_info import Operator
|
||||
from qiskit.circuit.controlflow import CONTROL_FLOW_OP_NAMES
|
||||
from qiskit.circuit import Gate, Parameter, CircuitInstruction
|
||||
from qiskit.circuit.library.standard_gates import get_standard_gate_name_mapping
|
||||
from qiskit.circuit.library.standard_gates import (
|
||||
iSwapGate,
|
||||
CXGate,
|
||||
|
@ -62,13 +50,26 @@ from qiskit.circuit.library.standard_gates import (
|
|||
RYGate,
|
||||
RGate,
|
||||
)
|
||||
from qiskit.transpiler.passes.synthesis import plugin
|
||||
from qiskit.converters import circuit_to_dag, dag_to_circuit
|
||||
from qiskit.dagcircuit.dagcircuit import DAGCircuit, DAGOpNode
|
||||
from qiskit.exceptions import QiskitError
|
||||
from qiskit.providers.models import BackendProperties
|
||||
from qiskit.quantum_info import Operator
|
||||
from qiskit.synthesis.one_qubit import one_qubit_decompose
|
||||
from qiskit.synthesis.two_qubit.xx_decompose import XXDecomposer, XXEmbodiments
|
||||
from qiskit.synthesis.two_qubit.two_qubit_decompose import (
|
||||
TwoQubitBasisDecomposer,
|
||||
TwoQubitWeylDecomposition,
|
||||
)
|
||||
from qiskit.transpiler.basepasses import TransformationPass
|
||||
from qiskit.transpiler.coupling import CouplingMap
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler.passes.optimization.optimize_1q_decomposition import (
|
||||
Optimize1qGatesDecomposition,
|
||||
_possible_decomposers,
|
||||
)
|
||||
from qiskit.providers.models import BackendProperties
|
||||
from qiskit.circuit.library.standard_gates import get_standard_gate_name_mapping
|
||||
from qiskit.exceptions import QiskitError
|
||||
from qiskit.transpiler.passes.synthesis import plugin
|
||||
from qiskit.transpiler.target import Target
|
||||
|
||||
|
||||
GATE_NAME_MAP = {
|
||||
|
|
|
@ -22,7 +22,7 @@ from qiskit.circuit import (
|
|||
QuantumCircuit,
|
||||
)
|
||||
from qiskit.dagcircuit import DAGCircuit
|
||||
from qiskit.transpiler import TransformationPass
|
||||
from qiskit.transpiler.basepasses import TransformationPass
|
||||
|
||||
|
||||
class ConvertConditionsToIfOps(TransformationPass):
|
||||
|
|
|
@ -57,466 +57,12 @@ Stage Generator Functions
|
|||
.. autofunction:: generate_scheduling
|
||||
.. currentmodule:: qiskit.transpiler.preset_passmanagers
|
||||
"""
|
||||
import copy
|
||||
|
||||
from qiskit.circuit.controlflow import CONTROL_FLOW_OP_NAMES
|
||||
from qiskit.circuit.library.standard_gates import get_standard_gate_name_mapping
|
||||
from qiskit.providers.backend_compat import BackendV2Converter
|
||||
|
||||
from qiskit.transpiler.instruction_durations import InstructionDurations
|
||||
from qiskit.transpiler.timing_constraints import TimingConstraints
|
||||
|
||||
from qiskit.transpiler.passmanager_config import PassManagerConfig
|
||||
from qiskit.transpiler.target import Target, target_to_backend_properties
|
||||
from qiskit.transpiler import CouplingMap
|
||||
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
|
||||
from .level0 import level_0_pass_manager
|
||||
from .level1 import level_1_pass_manager
|
||||
from .level2 import level_2_pass_manager
|
||||
from .level3 import level_3_pass_manager
|
||||
|
||||
|
||||
def generate_preset_pass_manager(
|
||||
optimization_level,
|
||||
backend=None,
|
||||
target=None,
|
||||
basis_gates=None,
|
||||
inst_map=None,
|
||||
coupling_map=None,
|
||||
instruction_durations=None,
|
||||
backend_properties=None,
|
||||
timing_constraints=None,
|
||||
initial_layout=None,
|
||||
layout_method=None,
|
||||
routing_method=None,
|
||||
translation_method=None,
|
||||
scheduling_method=None,
|
||||
approximation_degree=1.0,
|
||||
seed_transpiler=None,
|
||||
unitary_synthesis_method="default",
|
||||
unitary_synthesis_plugin_config=None,
|
||||
hls_config=None,
|
||||
init_method=None,
|
||||
optimization_method=None,
|
||||
dt=None,
|
||||
*,
|
||||
_skip_target=False,
|
||||
):
|
||||
"""Generate a preset :class:`~.PassManager`
|
||||
|
||||
This function is used to quickly generate a preset pass manager. Preset pass
|
||||
managers are the default pass managers used by the :func:`~.transpile`
|
||||
function. This function provides a convenient and simple method to construct
|
||||
a standalone :class:`~.PassManager` object that mirrors what the :func:`~.transpile`
|
||||
function internally builds and uses.
|
||||
|
||||
The target constraints for the pass manager construction can be specified through a :class:`.Target`
|
||||
instance, a :class:`.BackendV1` or :class:`.BackendV2` instance, or via loose constraints
|
||||
(``basis_gates``, ``inst_map``, ``coupling_map``, ``backend_properties``, ``instruction_durations``,
|
||||
``dt`` or ``timing_constraints``).
|
||||
The order of priorities for target constraints works as follows: if a ``target``
|
||||
input is provided, it will take priority over any ``backend`` input or loose constraints.
|
||||
If a ``backend`` is provided together with any loose constraint
|
||||
from the list above, the loose constraint will take priority over the corresponding backend
|
||||
constraint. This behavior is independent of whether the ``backend`` instance is of type
|
||||
:class:`.BackendV1` or :class:`.BackendV2`, as summarized in the table below. The first column
|
||||
in the table summarizes the potential user-provided constraints, and each cell shows whether
|
||||
the priority is assigned to that specific constraint input or another input
|
||||
(`target`/`backend(V1)`/`backend(V2)`).
|
||||
|
||||
============================ ========= ======================== =======================
|
||||
User Provided target backend(V1) backend(V2)
|
||||
============================ ========= ======================== =======================
|
||||
**basis_gates** target basis_gates basis_gates
|
||||
**coupling_map** target coupling_map coupling_map
|
||||
**instruction_durations** target instruction_durations instruction_durations
|
||||
**inst_map** target inst_map inst_map
|
||||
**dt** target dt dt
|
||||
**timing_constraints** target timing_constraints timing_constraints
|
||||
**backend_properties** target backend_properties backend_properties
|
||||
============================ ========= ======================== =======================
|
||||
|
||||
Args:
|
||||
optimization_level (int): The optimization level to generate a
|
||||
:class:`~.PassManager` for. This can be 0, 1, 2, or 3. Higher
|
||||
levels generate more optimized circuits, at the expense of
|
||||
longer transpilation time:
|
||||
|
||||
* 0: no optimization
|
||||
* 1: light optimization
|
||||
* 2: heavy optimization
|
||||
* 3: even heavier optimization
|
||||
|
||||
backend (Backend): An optional backend object which can be used as the
|
||||
source of the default values for the ``basis_gates``, ``inst_map``,
|
||||
``coupling_map``, ``backend_properties``, ``instruction_durations``,
|
||||
``timing_constraints``, and ``target``. If any of those other arguments
|
||||
are specified in addition to ``backend`` they will take precedence
|
||||
over the value contained in the backend.
|
||||
target (Target): The :class:`~.Target` representing a backend compilation
|
||||
target. The following attributes will be inferred from this
|
||||
argument if they are not set: ``coupling_map``, ``basis_gates``,
|
||||
``instruction_durations``, ``inst_map``, ``timing_constraints``
|
||||
and ``backend_properties``.
|
||||
basis_gates (list): List of basis gate names to unroll to
|
||||
(e.g: ``['u1', 'u2', 'u3', 'cx']``).
|
||||
inst_map (InstructionScheduleMap): Mapping object that maps gates to schedules.
|
||||
If any user defined calibration is found in the map and this is used in a
|
||||
circuit, transpiler attaches the custom gate definition to the circuit.
|
||||
This enables one to flexibly override the low-level instruction
|
||||
implementation.
|
||||
coupling_map (CouplingMap or list): Directed graph represented a coupling
|
||||
map. Multiple formats are supported:
|
||||
|
||||
#. ``CouplingMap`` instance
|
||||
#. List, must be given as an adjacency matrix, where each entry
|
||||
specifies all directed two-qubit interactions supported by backend,
|
||||
e.g: ``[[0, 1], [0, 3], [1, 2], [1, 5], [2, 5], [4, 1], [5, 3]]``
|
||||
|
||||
instruction_durations (InstructionDurations or list): Dictionary of duration
|
||||
(in dt) for each instruction. If specified, these durations overwrite the
|
||||
gate lengths in ``backend.properties``. Applicable only if ``scheduling_method``
|
||||
is specified.
|
||||
The format of ``instruction_durations`` must be as follows:
|
||||
They must be given as an :class:`.InstructionDurations` instance or a list of tuples
|
||||
|
||||
```
|
||||
[(instruction_name, qubits, duration, unit), ...].
|
||||
| [('cx', [0, 1], 12.3, 'ns'), ('u3', [0], 4.56, 'ns')]
|
||||
| [('cx', [0, 1], 1000), ('u3', [0], 300)]
|
||||
```
|
||||
|
||||
If ``unit`` is omitted, the default is ``'dt'``, which is a sample time depending on backend.
|
||||
If the time unit is ``'dt'``, the duration must be an integer.
|
||||
dt (float): Backend sample time (resolution) in seconds.
|
||||
If provided, this value will overwrite the ``dt`` value in ``instruction_durations``.
|
||||
If ``None`` (default) and a backend is provided, ``backend.dt`` is used.
|
||||
timing_constraints (TimingConstraints): Hardware time alignment restrictions.
|
||||
A quantum computer backend may report a set of restrictions, namely:
|
||||
|
||||
- granularity: An integer value representing minimum pulse gate
|
||||
resolution in units of ``dt``. A user-defined pulse gate should have
|
||||
duration of a multiple of this granularity value.
|
||||
- min_length: An integer value representing minimum pulse gate
|
||||
length in units of ``dt``. A user-defined pulse gate should be longer
|
||||
than this length.
|
||||
- pulse_alignment: An integer value representing a time resolution of gate
|
||||
instruction starting time. Gate instruction should start at time which
|
||||
is a multiple of the alignment value.
|
||||
- acquire_alignment: An integer value representing a time resolution of measure
|
||||
instruction starting time. Measure instruction should start at time which
|
||||
is a multiple of the alignment value.
|
||||
|
||||
This information will be provided by the backend configuration.
|
||||
If the backend doesn't have any restriction on the instruction time allocation,
|
||||
then ``timing_constraints`` is None and no adjustment will be performed.
|
||||
|
||||
initial_layout (Layout | List[int]): Initial position of virtual qubits on
|
||||
physical qubits.
|
||||
layout_method (str): The :class:`~.Pass` to use for choosing initial qubit
|
||||
placement. Valid choices are ``'trivial'``, ``'dense'``,
|
||||
and ``'sabre'``, representing :class:`~.TrivialLayout`, :class:`~.DenseLayout` and
|
||||
:class:`~.SabreLayout` respectively. This can also
|
||||
be the external plugin name to use for the ``layout`` stage of the output
|
||||
:class:`~.StagedPassManager`. You can see a list of installed plugins by using
|
||||
:func:`~.list_stage_plugins` with ``"layout"`` for the ``stage_name`` argument.
|
||||
routing_method (str): The pass to use for routing qubits on the
|
||||
architecture. Valid choices are ``'basic'``, ``'lookahead'``, ``'stochastic'``,
|
||||
``'sabre'``, and ``'none'`` representing :class:`~.BasicSwap`,
|
||||
:class:`~.LookaheadSwap`, :class:`~.StochasticSwap`, :class:`~.SabreSwap`, and
|
||||
erroring if routing is required respectively. This can also be the external plugin
|
||||
name to use for the ``routing`` stage of the output :class:`~.StagedPassManager`.
|
||||
You can see a list of installed plugins by using :func:`~.list_stage_plugins` with
|
||||
``"routing"`` for the ``stage_name`` argument.
|
||||
translation_method (str): The method to use for translating gates to
|
||||
basis gates. Valid choices ``'translator'``, ``'synthesis'`` representing
|
||||
:class:`~.BasisTranslator`, and :class:`~.UnitarySynthesis` respectively. This can
|
||||
also be the external plugin name to use for the ``translation`` stage of the output
|
||||
:class:`~.StagedPassManager`. You can see a list of installed plugins by using
|
||||
:func:`~.list_stage_plugins` with ``"translation"`` for the ``stage_name`` argument.
|
||||
scheduling_method (str): The pass to use for scheduling instructions. Valid choices
|
||||
are ``'alap'`` and ``'asap'``. This can also be the external plugin name to use
|
||||
for the ``scheduling`` stage of the output :class:`~.StagedPassManager`. You can
|
||||
see a list of installed plugins by using :func:`~.list_stage_plugins` with
|
||||
``"scheduling"`` for the ``stage_name`` argument.
|
||||
backend_properties (BackendProperties): Properties returned by a
|
||||
backend, including information on gate errors, readout errors,
|
||||
qubit coherence times, etc.
|
||||
approximation_degree (float): Heuristic dial used for circuit approximation
|
||||
(1.0=no approximation, 0.0=maximal approximation).
|
||||
seed_transpiler (int): Sets random seed for the stochastic parts of
|
||||
the transpiler.
|
||||
unitary_synthesis_method (str): The name of the unitary synthesis
|
||||
method to use. By default ``'default'`` is used. You can see a list of
|
||||
installed plugins with :func:`.unitary_synthesis_plugin_names`.
|
||||
unitary_synthesis_plugin_config (dict): An optional configuration dictionary
|
||||
that will be passed directly to the unitary synthesis plugin. By
|
||||
default this setting will have no effect as the default unitary
|
||||
synthesis method does not take custom configuration. This should
|
||||
only be necessary when a unitary synthesis plugin is specified with
|
||||
the ``unitary_synthesis_method`` argument. As this is custom for each
|
||||
unitary synthesis plugin refer to the plugin documentation for how
|
||||
to use this option.
|
||||
hls_config (HLSConfig): An optional configuration class :class:`~.HLSConfig`
|
||||
that will be passed directly to :class:`~.HighLevelSynthesis` transformation pass.
|
||||
This configuration class allows to specify for various high-level objects
|
||||
the lists of synthesis algorithms and their parameters.
|
||||
init_method (str): The plugin name to use for the ``init`` stage of
|
||||
the output :class:`~.StagedPassManager`. By default an external
|
||||
plugin is not used. You can see a list of installed plugins by
|
||||
using :func:`~.list_stage_plugins` with ``"init"`` for the stage
|
||||
name argument.
|
||||
optimization_method (str): The plugin name to use for the
|
||||
``optimization`` stage of the output
|
||||
:class:`~.StagedPassManager`. By default an external
|
||||
plugin is not used. You can see a list of installed plugins by
|
||||
using :func:`~.list_stage_plugins` with ``"optimization"`` for the
|
||||
``stage_name`` argument.
|
||||
|
||||
Returns:
|
||||
StagedPassManager: The preset pass manager for the given options
|
||||
|
||||
Raises:
|
||||
ValueError: if an invalid value for ``optimization_level`` is passed in.
|
||||
"""
|
||||
|
||||
if backend is not None and getattr(backend, "version", 0) <= 1:
|
||||
# This is a temporary conversion step to allow for a smoother transition
|
||||
# to a fully target-based transpiler pipeline while maintaining the behavior
|
||||
# of `transpile` with BackendV1 inputs.
|
||||
backend = BackendV2Converter(backend)
|
||||
|
||||
# Check if a custom inst_map was specified before overwriting inst_map
|
||||
_given_inst_map = bool(inst_map)
|
||||
# If there are no loose constraints => use backend target if available
|
||||
_no_loose_constraints = (
|
||||
basis_gates is None
|
||||
and coupling_map is None
|
||||
and dt is None
|
||||
and instruction_durations is None
|
||||
and backend_properties is None
|
||||
and timing_constraints is None
|
||||
)
|
||||
# If it's an edge case => do not build target
|
||||
_skip_target = (
|
||||
target is None
|
||||
and backend is None
|
||||
and (basis_gates is None or coupling_map is None or instruction_durations is not None)
|
||||
)
|
||||
|
||||
# Resolve loose constraints case-by-case against backend constraints.
|
||||
# The order of priority is loose constraints > backend.
|
||||
dt = _parse_dt(dt, backend)
|
||||
instruction_durations = _parse_instruction_durations(backend, instruction_durations, dt)
|
||||
timing_constraints = _parse_timing_constraints(backend, timing_constraints)
|
||||
inst_map = _parse_inst_map(inst_map, backend)
|
||||
# The basis gates parser will set _skip_target to True if a custom basis gate is found
|
||||
# (known edge case).
|
||||
basis_gates, name_mapping, _skip_target = _parse_basis_gates(
|
||||
basis_gates, backend, inst_map, _skip_target
|
||||
)
|
||||
coupling_map = _parse_coupling_map(coupling_map, backend)
|
||||
|
||||
if target is None:
|
||||
if backend is not None and _no_loose_constraints:
|
||||
# If a backend is specified without loose constraints, use its target directly.
|
||||
target = backend.target
|
||||
elif not _skip_target:
|
||||
# Only parse backend properties when the target isn't skipped to
|
||||
# preserve the former behavior of transpile.
|
||||
backend_properties = _parse_backend_properties(backend_properties, backend)
|
||||
# Build target from constraints.
|
||||
target = Target.from_configuration(
|
||||
basis_gates=basis_gates,
|
||||
num_qubits=backend.num_qubits if backend is not None else None,
|
||||
coupling_map=coupling_map,
|
||||
# If the instruction map has custom gates, do not give as config, the information
|
||||
# will be added to the target with update_from_instruction_schedule_map
|
||||
inst_map=inst_map if inst_map and not inst_map.has_custom_gate() else None,
|
||||
backend_properties=backend_properties,
|
||||
instruction_durations=instruction_durations,
|
||||
concurrent_measurements=(
|
||||
backend.target.concurrent_measurements if backend is not None else None
|
||||
),
|
||||
dt=dt,
|
||||
timing_constraints=timing_constraints,
|
||||
custom_name_mapping=name_mapping,
|
||||
)
|
||||
|
||||
# Update target with custom gate information. Note that this is an exception to the priority
|
||||
# order (target > loose constraints), added to handle custom gates for scheduling passes.
|
||||
if target is not None and _given_inst_map and inst_map.has_custom_gate():
|
||||
target = copy.deepcopy(target)
|
||||
target.update_from_instruction_schedule_map(inst_map)
|
||||
|
||||
if target is not None:
|
||||
if coupling_map is None:
|
||||
coupling_map = target.build_coupling_map()
|
||||
if basis_gates is None:
|
||||
basis_gates = target.operation_names
|
||||
if instruction_durations is None:
|
||||
instruction_durations = target.durations()
|
||||
if inst_map is None:
|
||||
inst_map = target.instruction_schedule_map()
|
||||
if timing_constraints is None:
|
||||
timing_constraints = target.timing_constraints()
|
||||
if backend_properties is None:
|
||||
backend_properties = target_to_backend_properties(target)
|
||||
|
||||
pm_options = {
|
||||
"target": target,
|
||||
"basis_gates": basis_gates,
|
||||
"inst_map": inst_map,
|
||||
"coupling_map": coupling_map,
|
||||
"instruction_durations": instruction_durations,
|
||||
"backend_properties": backend_properties,
|
||||
"timing_constraints": timing_constraints,
|
||||
"layout_method": layout_method,
|
||||
"routing_method": routing_method,
|
||||
"translation_method": translation_method,
|
||||
"scheduling_method": scheduling_method,
|
||||
"approximation_degree": approximation_degree,
|
||||
"seed_transpiler": seed_transpiler,
|
||||
"unitary_synthesis_method": unitary_synthesis_method,
|
||||
"unitary_synthesis_plugin_config": unitary_synthesis_plugin_config,
|
||||
"initial_layout": initial_layout,
|
||||
"hls_config": hls_config,
|
||||
"init_method": init_method,
|
||||
"optimization_method": optimization_method,
|
||||
}
|
||||
|
||||
if backend is not None:
|
||||
pm_options["_skip_target"] = _skip_target
|
||||
pm_config = PassManagerConfig.from_backend(backend, **pm_options)
|
||||
else:
|
||||
pm_config = PassManagerConfig(**pm_options)
|
||||
if optimization_level == 0:
|
||||
pm = level_0_pass_manager(pm_config)
|
||||
elif optimization_level == 1:
|
||||
pm = level_1_pass_manager(pm_config)
|
||||
elif optimization_level == 2:
|
||||
pm = level_2_pass_manager(pm_config)
|
||||
elif optimization_level == 3:
|
||||
pm = level_3_pass_manager(pm_config)
|
||||
else:
|
||||
raise ValueError(f"Invalid optimization level {optimization_level}")
|
||||
return pm
|
||||
|
||||
|
||||
def _parse_basis_gates(basis_gates, backend, inst_map, skip_target):
|
||||
name_mapping = {}
|
||||
standard_gates = get_standard_gate_name_mapping()
|
||||
# Add control flow gates by default to basis set
|
||||
default_gates = {"measure", "delay", "reset"}.union(CONTROL_FLOW_OP_NAMES)
|
||||
|
||||
try:
|
||||
instructions = set(basis_gates)
|
||||
for name in default_gates:
|
||||
if name not in instructions:
|
||||
instructions.add(name)
|
||||
except TypeError:
|
||||
instructions = None
|
||||
|
||||
if backend is None:
|
||||
# Check for custom instructions
|
||||
if instructions is None:
|
||||
return None, name_mapping, skip_target
|
||||
|
||||
for inst in instructions:
|
||||
if inst not in standard_gates or inst not in default_gates:
|
||||
skip_target = True
|
||||
break
|
||||
|
||||
return list(instructions), name_mapping, skip_target
|
||||
|
||||
instructions = instructions or backend.operation_names
|
||||
name_mapping.update(
|
||||
{name: backend.target.operation_from_name(name) for name in backend.operation_names}
|
||||
)
|
||||
|
||||
# Check for custom instructions before removing calibrations
|
||||
for inst in instructions:
|
||||
if inst not in standard_gates or inst not in default_gates:
|
||||
skip_target = True
|
||||
break
|
||||
|
||||
# Remove calibrated instructions, as they will be added later from the instruction schedule map
|
||||
if inst_map is not None and not skip_target:
|
||||
for inst in inst_map.instructions:
|
||||
for qubit in inst_map.qubits_with_instruction(inst):
|
||||
entry = inst_map._get_calibration_entry(inst, qubit)
|
||||
if entry.user_provided and inst in instructions:
|
||||
instructions.remove(inst)
|
||||
|
||||
return list(instructions) if instructions else None, name_mapping, skip_target
|
||||
|
||||
|
||||
def _parse_inst_map(inst_map, backend):
|
||||
# try getting inst_map from user, else backend
|
||||
if inst_map is None and backend is not None:
|
||||
inst_map = backend.target.instruction_schedule_map()
|
||||
return inst_map
|
||||
|
||||
|
||||
def _parse_backend_properties(backend_properties, backend):
|
||||
# try getting backend_props from user, else backend
|
||||
if backend_properties is None and backend is not None:
|
||||
backend_properties = target_to_backend_properties(backend.target)
|
||||
return backend_properties
|
||||
|
||||
|
||||
def _parse_dt(dt, backend):
|
||||
# try getting dt from user, else backend
|
||||
if dt is None and backend is not None:
|
||||
dt = backend.target.dt
|
||||
return dt
|
||||
|
||||
|
||||
def _parse_coupling_map(coupling_map, backend):
|
||||
# try getting coupling_map from user, else backend
|
||||
if coupling_map is None and backend is not None:
|
||||
coupling_map = backend.coupling_map
|
||||
|
||||
# coupling_map could be None, or a list of lists, e.g. [[0, 1], [2, 1]]
|
||||
if coupling_map is None or isinstance(coupling_map, CouplingMap):
|
||||
return coupling_map
|
||||
if isinstance(coupling_map, list) and all(
|
||||
isinstance(i, list) and len(i) == 2 for i in coupling_map
|
||||
):
|
||||
return CouplingMap(coupling_map)
|
||||
else:
|
||||
raise TranspilerError(
|
||||
"Only a single input coupling map can be used with generate_preset_pass_manager()."
|
||||
)
|
||||
|
||||
|
||||
def _parse_instruction_durations(backend, inst_durations, dt):
|
||||
"""Create a list of ``InstructionDuration``s. If ``inst_durations`` is provided,
|
||||
the backend will be ignored, otherwise, the durations will be populated from the
|
||||
backend.
|
||||
"""
|
||||
final_durations = InstructionDurations()
|
||||
if not inst_durations:
|
||||
backend_durations = InstructionDurations()
|
||||
if backend is not None:
|
||||
backend_durations = backend.instruction_durations
|
||||
final_durations.update(backend_durations, dt or backend_durations.dt)
|
||||
else:
|
||||
final_durations.update(inst_durations, dt or getattr(inst_durations, "dt", None))
|
||||
return final_durations
|
||||
|
||||
|
||||
def _parse_timing_constraints(backend, timing_constraints):
|
||||
if isinstance(timing_constraints, TimingConstraints):
|
||||
return timing_constraints
|
||||
if backend is None and timing_constraints is None:
|
||||
timing_constraints = TimingConstraints()
|
||||
elif backend is not None:
|
||||
timing_constraints = backend.target.timing_constraints()
|
||||
return timing_constraints
|
||||
|
||||
from .generate_preset_pass_manager import generate_preset_pass_manager
|
||||
|
||||
__all__ = [
|
||||
"level_0_pass_manager",
|
||||
|
|
|
@ -0,0 +1,472 @@
|
|||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2024.
|
||||
#
|
||||
# This code is licensed under the Apache License, Version 2.0. You may
|
||||
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
||||
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
#
|
||||
# Any modifications or derivative works of this code must retain this
|
||||
# copyright notice, and modified files need to carry a notice indicating
|
||||
# that they have been altered from the originals.
|
||||
|
||||
"""
|
||||
Preset pass manager generation function
|
||||
"""
|
||||
|
||||
import copy
|
||||
|
||||
from qiskit.circuit.controlflow import CONTROL_FLOW_OP_NAMES
|
||||
from qiskit.circuit.library.standard_gates import get_standard_gate_name_mapping
|
||||
from qiskit.providers.backend_compat import BackendV2Converter
|
||||
from qiskit.transpiler.coupling import CouplingMap
|
||||
from qiskit.transpiler.exceptions import TranspilerError
|
||||
from qiskit.transpiler.instruction_durations import InstructionDurations
|
||||
from qiskit.transpiler.passmanager_config import PassManagerConfig
|
||||
from qiskit.transpiler.target import Target, target_to_backend_properties
|
||||
from qiskit.transpiler.timing_constraints import TimingConstraints
|
||||
|
||||
from .level0 import level_0_pass_manager
|
||||
from .level1 import level_1_pass_manager
|
||||
from .level2 import level_2_pass_manager
|
||||
from .level3 import level_3_pass_manager
|
||||
|
||||
|
||||
def generate_preset_pass_manager(
|
||||
optimization_level,
|
||||
backend=None,
|
||||
target=None,
|
||||
basis_gates=None,
|
||||
inst_map=None,
|
||||
coupling_map=None,
|
||||
instruction_durations=None,
|
||||
backend_properties=None,
|
||||
timing_constraints=None,
|
||||
initial_layout=None,
|
||||
layout_method=None,
|
||||
routing_method=None,
|
||||
translation_method=None,
|
||||
scheduling_method=None,
|
||||
approximation_degree=1.0,
|
||||
seed_transpiler=None,
|
||||
unitary_synthesis_method="default",
|
||||
unitary_synthesis_plugin_config=None,
|
||||
hls_config=None,
|
||||
init_method=None,
|
||||
optimization_method=None,
|
||||
dt=None,
|
||||
*,
|
||||
_skip_target=False,
|
||||
):
|
||||
"""Generate a preset :class:`~.PassManager`
|
||||
|
||||
This function is used to quickly generate a preset pass manager. Preset pass
|
||||
managers are the default pass managers used by the :func:`~.transpile`
|
||||
function. This function provides a convenient and simple method to construct
|
||||
a standalone :class:`~.PassManager` object that mirrors what the :func:`~.transpile`
|
||||
function internally builds and uses.
|
||||
|
||||
The target constraints for the pass manager construction can be specified through a :class:`.Target`
|
||||
instance, a :class:`.BackendV1` or :class:`.BackendV2` instance, or via loose constraints
|
||||
(``basis_gates``, ``inst_map``, ``coupling_map``, ``backend_properties``, ``instruction_durations``,
|
||||
``dt`` or ``timing_constraints``).
|
||||
The order of priorities for target constraints works as follows: if a ``target``
|
||||
input is provided, it will take priority over any ``backend`` input or loose constraints.
|
||||
If a ``backend`` is provided together with any loose constraint
|
||||
from the list above, the loose constraint will take priority over the corresponding backend
|
||||
constraint. This behavior is independent of whether the ``backend`` instance is of type
|
||||
:class:`.BackendV1` or :class:`.BackendV2`, as summarized in the table below. The first column
|
||||
in the table summarizes the potential user-provided constraints, and each cell shows whether
|
||||
the priority is assigned to that specific constraint input or another input
|
||||
(`target`/`backend(V1)`/`backend(V2)`).
|
||||
|
||||
============================ ========= ======================== =======================
|
||||
User Provided target backend(V1) backend(V2)
|
||||
============================ ========= ======================== =======================
|
||||
**basis_gates** target basis_gates basis_gates
|
||||
**coupling_map** target coupling_map coupling_map
|
||||
**instruction_durations** target instruction_durations instruction_durations
|
||||
**inst_map** target inst_map inst_map
|
||||
**dt** target dt dt
|
||||
**timing_constraints** target timing_constraints timing_constraints
|
||||
**backend_properties** target backend_properties backend_properties
|
||||
============================ ========= ======================== =======================
|
||||
|
||||
Args:
|
||||
optimization_level (int): The optimization level to generate a
|
||||
:class:`~.PassManager` for. This can be 0, 1, 2, or 3. Higher
|
||||
levels generate more optimized circuits, at the expense of
|
||||
longer transpilation time:
|
||||
|
||||
* 0: no optimization
|
||||
* 1: light optimization
|
||||
* 2: heavy optimization
|
||||
* 3: even heavier optimization
|
||||
|
||||
backend (Backend): An optional backend object which can be used as the
|
||||
source of the default values for the ``basis_gates``, ``inst_map``,
|
||||
``coupling_map``, ``backend_properties``, ``instruction_durations``,
|
||||
``timing_constraints``, and ``target``. If any of those other arguments
|
||||
are specified in addition to ``backend`` they will take precedence
|
||||
over the value contained in the backend.
|
||||
target (Target): The :class:`~.Target` representing a backend compilation
|
||||
target. The following attributes will be inferred from this
|
||||
argument if they are not set: ``coupling_map``, ``basis_gates``,
|
||||
``instruction_durations``, ``inst_map``, ``timing_constraints``
|
||||
and ``backend_properties``.
|
||||
basis_gates (list): List of basis gate names to unroll to
|
||||
(e.g: ``['u1', 'u2', 'u3', 'cx']``).
|
||||
inst_map (InstructionScheduleMap): Mapping object that maps gates to schedules.
|
||||
If any user defined calibration is found in the map and this is used in a
|
||||
circuit, transpiler attaches the custom gate definition to the circuit.
|
||||
This enables one to flexibly override the low-level instruction
|
||||
implementation.
|
||||
coupling_map (CouplingMap or list): Directed graph represented a coupling
|
||||
map. Multiple formats are supported:
|
||||
|
||||
#. ``CouplingMap`` instance
|
||||
#. List, must be given as an adjacency matrix, where each entry
|
||||
specifies all directed two-qubit interactions supported by backend,
|
||||
e.g: ``[[0, 1], [0, 3], [1, 2], [1, 5], [2, 5], [4, 1], [5, 3]]``
|
||||
|
||||
instruction_durations (InstructionDurations or list): Dictionary of duration
|
||||
(in dt) for each instruction. If specified, these durations overwrite the
|
||||
gate lengths in ``backend.properties``. Applicable only if ``scheduling_method``
|
||||
is specified.
|
||||
The format of ``instruction_durations`` must be as follows:
|
||||
They must be given as an :class:`.InstructionDurations` instance or a list of tuples
|
||||
|
||||
```
|
||||
[(instruction_name, qubits, duration, unit), ...].
|
||||
| [('cx', [0, 1], 12.3, 'ns'), ('u3', [0], 4.56, 'ns')]
|
||||
| [('cx', [0, 1], 1000), ('u3', [0], 300)]
|
||||
```
|
||||
|
||||
If ``unit`` is omitted, the default is ``'dt'``, which is a sample time depending on backend.
|
||||
If the time unit is ``'dt'``, the duration must be an integer.
|
||||
dt (float): Backend sample time (resolution) in seconds.
|
||||
If provided, this value will overwrite the ``dt`` value in ``instruction_durations``.
|
||||
If ``None`` (default) and a backend is provided, ``backend.dt`` is used.
|
||||
timing_constraints (TimingConstraints): Hardware time alignment restrictions.
|
||||
A quantum computer backend may report a set of restrictions, namely:
|
||||
|
||||
- granularity: An integer value representing minimum pulse gate
|
||||
resolution in units of ``dt``. A user-defined pulse gate should have
|
||||
duration of a multiple of this granularity value.
|
||||
- min_length: An integer value representing minimum pulse gate
|
||||
length in units of ``dt``. A user-defined pulse gate should be longer
|
||||
than this length.
|
||||
- pulse_alignment: An integer value representing a time resolution of gate
|
||||
instruction starting time. Gate instruction should start at time which
|
||||
is a multiple of the alignment value.
|
||||
- acquire_alignment: An integer value representing a time resolution of measure
|
||||
instruction starting time. Measure instruction should start at time which
|
||||
is a multiple of the alignment value.
|
||||
|
||||
This information will be provided by the backend configuration.
|
||||
If the backend doesn't have any restriction on the instruction time allocation,
|
||||
then ``timing_constraints`` is None and no adjustment will be performed.
|
||||
|
||||
initial_layout (Layout | List[int]): Initial position of virtual qubits on
|
||||
physical qubits.
|
||||
layout_method (str): The :class:`~.Pass` to use for choosing initial qubit
|
||||
placement. Valid choices are ``'trivial'``, ``'dense'``,
|
||||
and ``'sabre'``, representing :class:`~.TrivialLayout`, :class:`~.DenseLayout` and
|
||||
:class:`~.SabreLayout` respectively. This can also
|
||||
be the external plugin name to use for the ``layout`` stage of the output
|
||||
:class:`~.StagedPassManager`. You can see a list of installed plugins by using
|
||||
:func:`~.list_stage_plugins` with ``"layout"`` for the ``stage_name`` argument.
|
||||
routing_method (str): The pass to use for routing qubits on the
|
||||
architecture. Valid choices are ``'basic'``, ``'lookahead'``, ``'stochastic'``,
|
||||
``'sabre'``, and ``'none'`` representing :class:`~.BasicSwap`,
|
||||
:class:`~.LookaheadSwap`, :class:`~.StochasticSwap`, :class:`~.SabreSwap`, and
|
||||
erroring if routing is required respectively. This can also be the external plugin
|
||||
name to use for the ``routing`` stage of the output :class:`~.StagedPassManager`.
|
||||
You can see a list of installed plugins by using :func:`~.list_stage_plugins` with
|
||||
``"routing"`` for the ``stage_name`` argument.
|
||||
translation_method (str): The method to use for translating gates to
|
||||
basis gates. Valid choices ``'translator'``, ``'synthesis'`` representing
|
||||
:class:`~.BasisTranslator`, and :class:`~.UnitarySynthesis` respectively. This can
|
||||
also be the external plugin name to use for the ``translation`` stage of the output
|
||||
:class:`~.StagedPassManager`. You can see a list of installed plugins by using
|
||||
:func:`~.list_stage_plugins` with ``"translation"`` for the ``stage_name`` argument.
|
||||
scheduling_method (str): The pass to use for scheduling instructions. Valid choices
|
||||
are ``'alap'`` and ``'asap'``. This can also be the external plugin name to use
|
||||
for the ``scheduling`` stage of the output :class:`~.StagedPassManager`. You can
|
||||
see a list of installed plugins by using :func:`~.list_stage_plugins` with
|
||||
``"scheduling"`` for the ``stage_name`` argument.
|
||||
backend_properties (BackendProperties): Properties returned by a
|
||||
backend, including information on gate errors, readout errors,
|
||||
qubit coherence times, etc.
|
||||
approximation_degree (float): Heuristic dial used for circuit approximation
|
||||
(1.0=no approximation, 0.0=maximal approximation).
|
||||
seed_transpiler (int): Sets random seed for the stochastic parts of
|
||||
the transpiler.
|
||||
unitary_synthesis_method (str): The name of the unitary synthesis
|
||||
method to use. By default ``'default'`` is used. You can see a list of
|
||||
installed plugins with :func:`.unitary_synthesis_plugin_names`.
|
||||
unitary_synthesis_plugin_config (dict): An optional configuration dictionary
|
||||
that will be passed directly to the unitary synthesis plugin. By
|
||||
default this setting will have no effect as the default unitary
|
||||
synthesis method does not take custom configuration. This should
|
||||
only be necessary when a unitary synthesis plugin is specified with
|
||||
the ``unitary_synthesis_method`` argument. As this is custom for each
|
||||
unitary synthesis plugin refer to the plugin documentation for how
|
||||
to use this option.
|
||||
hls_config (HLSConfig): An optional configuration class :class:`~.HLSConfig`
|
||||
that will be passed directly to :class:`~.HighLevelSynthesis` transformation pass.
|
||||
This configuration class allows to specify for various high-level objects
|
||||
the lists of synthesis algorithms and their parameters.
|
||||
init_method (str): The plugin name to use for the ``init`` stage of
|
||||
the output :class:`~.StagedPassManager`. By default an external
|
||||
plugin is not used. You can see a list of installed plugins by
|
||||
using :func:`~.list_stage_plugins` with ``"init"`` for the stage
|
||||
name argument.
|
||||
optimization_method (str): The plugin name to use for the
|
||||
``optimization`` stage of the output
|
||||
:class:`~.StagedPassManager`. By default an external
|
||||
plugin is not used. You can see a list of installed plugins by
|
||||
using :func:`~.list_stage_plugins` with ``"optimization"`` for the
|
||||
``stage_name`` argument.
|
||||
|
||||
Returns:
|
||||
StagedPassManager: The preset pass manager for the given options
|
||||
|
||||
Raises:
|
||||
ValueError: if an invalid value for ``optimization_level`` is passed in.
|
||||
"""
|
||||
|
||||
if backend is not None and getattr(backend, "version", 0) <= 1:
|
||||
# This is a temporary conversion step to allow for a smoother transition
|
||||
# to a fully target-based transpiler pipeline while maintaining the behavior
|
||||
# of `transpile` with BackendV1 inputs.
|
||||
backend = BackendV2Converter(backend)
|
||||
|
||||
# Check if a custom inst_map was specified before overwriting inst_map
|
||||
_given_inst_map = bool(inst_map)
|
||||
# If there are no loose constraints => use backend target if available
|
||||
_no_loose_constraints = (
|
||||
basis_gates is None
|
||||
and coupling_map is None
|
||||
and dt is None
|
||||
and instruction_durations is None
|
||||
and backend_properties is None
|
||||
and timing_constraints is None
|
||||
)
|
||||
# If it's an edge case => do not build target
|
||||
_skip_target = (
|
||||
target is None
|
||||
and backend is None
|
||||
and (basis_gates is None or coupling_map is None or instruction_durations is not None)
|
||||
)
|
||||
|
||||
# Resolve loose constraints case-by-case against backend constraints.
|
||||
# The order of priority is loose constraints > backend.
|
||||
dt = _parse_dt(dt, backend)
|
||||
instruction_durations = _parse_instruction_durations(backend, instruction_durations, dt)
|
||||
timing_constraints = _parse_timing_constraints(backend, timing_constraints)
|
||||
inst_map = _parse_inst_map(inst_map, backend)
|
||||
# The basis gates parser will set _skip_target to True if a custom basis gate is found
|
||||
# (known edge case).
|
||||
basis_gates, name_mapping, _skip_target = _parse_basis_gates(
|
||||
basis_gates, backend, inst_map, _skip_target
|
||||
)
|
||||
coupling_map = _parse_coupling_map(coupling_map, backend)
|
||||
|
||||
if target is None:
|
||||
if backend is not None and _no_loose_constraints:
|
||||
# If a backend is specified without loose constraints, use its target directly.
|
||||
target = backend.target
|
||||
elif not _skip_target:
|
||||
# Only parse backend properties when the target isn't skipped to
|
||||
# preserve the former behavior of transpile.
|
||||
backend_properties = _parse_backend_properties(backend_properties, backend)
|
||||
# Build target from constraints.
|
||||
target = Target.from_configuration(
|
||||
basis_gates=basis_gates,
|
||||
num_qubits=backend.num_qubits if backend is not None else None,
|
||||
coupling_map=coupling_map,
|
||||
# If the instruction map has custom gates, do not give as config, the information
|
||||
# will be added to the target with update_from_instruction_schedule_map
|
||||
inst_map=inst_map if inst_map and not inst_map.has_custom_gate() else None,
|
||||
backend_properties=backend_properties,
|
||||
instruction_durations=instruction_durations,
|
||||
concurrent_measurements=(
|
||||
backend.target.concurrent_measurements if backend is not None else None
|
||||
),
|
||||
dt=dt,
|
||||
timing_constraints=timing_constraints,
|
||||
custom_name_mapping=name_mapping,
|
||||
)
|
||||
|
||||
# Update target with custom gate information. Note that this is an exception to the priority
|
||||
# order (target > loose constraints), added to handle custom gates for scheduling passes.
|
||||
if target is not None and _given_inst_map and inst_map.has_custom_gate():
|
||||
target = copy.deepcopy(target)
|
||||
target.update_from_instruction_schedule_map(inst_map)
|
||||
|
||||
if target is not None:
|
||||
if coupling_map is None:
|
||||
coupling_map = target.build_coupling_map()
|
||||
if basis_gates is None:
|
||||
basis_gates = target.operation_names
|
||||
if instruction_durations is None:
|
||||
instruction_durations = target.durations()
|
||||
if inst_map is None:
|
||||
inst_map = target.instruction_schedule_map()
|
||||
if timing_constraints is None:
|
||||
timing_constraints = target.timing_constraints()
|
||||
if backend_properties is None:
|
||||
backend_properties = target_to_backend_properties(target)
|
||||
|
||||
pm_options = {
|
||||
"target": target,
|
||||
"basis_gates": basis_gates,
|
||||
"inst_map": inst_map,
|
||||
"coupling_map": coupling_map,
|
||||
"instruction_durations": instruction_durations,
|
||||
"backend_properties": backend_properties,
|
||||
"timing_constraints": timing_constraints,
|
||||
"layout_method": layout_method,
|
||||
"routing_method": routing_method,
|
||||
"translation_method": translation_method,
|
||||
"scheduling_method": scheduling_method,
|
||||
"approximation_degree": approximation_degree,
|
||||
"seed_transpiler": seed_transpiler,
|
||||
"unitary_synthesis_method": unitary_synthesis_method,
|
||||
"unitary_synthesis_plugin_config": unitary_synthesis_plugin_config,
|
||||
"initial_layout": initial_layout,
|
||||
"hls_config": hls_config,
|
||||
"init_method": init_method,
|
||||
"optimization_method": optimization_method,
|
||||
}
|
||||
|
||||
if backend is not None:
|
||||
pm_options["_skip_target"] = _skip_target
|
||||
pm_config = PassManagerConfig.from_backend(backend, **pm_options)
|
||||
else:
|
||||
pm_config = PassManagerConfig(**pm_options)
|
||||
if optimization_level == 0:
|
||||
pm = level_0_pass_manager(pm_config)
|
||||
elif optimization_level == 1:
|
||||
pm = level_1_pass_manager(pm_config)
|
||||
elif optimization_level == 2:
|
||||
pm = level_2_pass_manager(pm_config)
|
||||
elif optimization_level == 3:
|
||||
pm = level_3_pass_manager(pm_config)
|
||||
else:
|
||||
raise ValueError(f"Invalid optimization level {optimization_level}")
|
||||
return pm
|
||||
|
||||
|
||||
def _parse_basis_gates(basis_gates, backend, inst_map, skip_target):
|
||||
name_mapping = {}
|
||||
standard_gates = get_standard_gate_name_mapping()
|
||||
# Add control flow gates by default to basis set
|
||||
default_gates = {"measure", "delay", "reset"}.union(CONTROL_FLOW_OP_NAMES)
|
||||
|
||||
try:
|
||||
instructions = set(basis_gates)
|
||||
for name in default_gates:
|
||||
if name not in instructions:
|
||||
instructions.add(name)
|
||||
except TypeError:
|
||||
instructions = None
|
||||
|
||||
if backend is None:
|
||||
# Check for custom instructions
|
||||
if instructions is None:
|
||||
return None, name_mapping, skip_target
|
||||
|
||||
for inst in instructions:
|
||||
if inst not in standard_gates or inst not in default_gates:
|
||||
skip_target = True
|
||||
break
|
||||
|
||||
return list(instructions), name_mapping, skip_target
|
||||
|
||||
instructions = instructions or backend.operation_names
|
||||
name_mapping.update(
|
||||
{name: backend.target.operation_from_name(name) for name in backend.operation_names}
|
||||
)
|
||||
|
||||
# Check for custom instructions before removing calibrations
|
||||
for inst in instructions:
|
||||
if inst not in standard_gates or inst not in default_gates:
|
||||
skip_target = True
|
||||
break
|
||||
|
||||
# Remove calibrated instructions, as they will be added later from the instruction schedule map
|
||||
if inst_map is not None and not skip_target:
|
||||
for inst in inst_map.instructions:
|
||||
for qubit in inst_map.qubits_with_instruction(inst):
|
||||
entry = inst_map._get_calibration_entry(inst, qubit)
|
||||
if entry.user_provided and inst in instructions:
|
||||
instructions.remove(inst)
|
||||
|
||||
return list(instructions) if instructions else None, name_mapping, skip_target
|
||||
|
||||
|
||||
def _parse_inst_map(inst_map, backend):
|
||||
# try getting inst_map from user, else backend
|
||||
if inst_map is None and backend is not None:
|
||||
inst_map = backend.target.instruction_schedule_map()
|
||||
return inst_map
|
||||
|
||||
|
||||
def _parse_backend_properties(backend_properties, backend):
|
||||
# try getting backend_props from user, else backend
|
||||
if backend_properties is None and backend is not None:
|
||||
backend_properties = target_to_backend_properties(backend.target)
|
||||
return backend_properties
|
||||
|
||||
|
||||
def _parse_dt(dt, backend):
|
||||
# try getting dt from user, else backend
|
||||
if dt is None and backend is not None:
|
||||
dt = backend.target.dt
|
||||
return dt
|
||||
|
||||
|
||||
def _parse_coupling_map(coupling_map, backend):
|
||||
# try getting coupling_map from user, else backend
|
||||
if coupling_map is None and backend is not None:
|
||||
coupling_map = backend.coupling_map
|
||||
|
||||
# coupling_map could be None, or a list of lists, e.g. [[0, 1], [2, 1]]
|
||||
if coupling_map is None or isinstance(coupling_map, CouplingMap):
|
||||
return coupling_map
|
||||
if isinstance(coupling_map, list) and all(
|
||||
isinstance(i, list) and len(i) == 2 for i in coupling_map
|
||||
):
|
||||
return CouplingMap(coupling_map)
|
||||
else:
|
||||
raise TranspilerError(
|
||||
"Only a single input coupling map can be used with generate_preset_pass_manager()."
|
||||
)
|
||||
|
||||
|
||||
def _parse_instruction_durations(backend, inst_durations, dt):
|
||||
"""Create a list of ``InstructionDuration``s. If ``inst_durations`` is provided,
|
||||
the backend will be ignored, otherwise, the durations will be populated from the
|
||||
backend.
|
||||
"""
|
||||
final_durations = InstructionDurations()
|
||||
if not inst_durations:
|
||||
backend_durations = InstructionDurations()
|
||||
if backend is not None:
|
||||
backend_durations = backend.instruction_durations
|
||||
final_durations.update(backend_durations, dt or backend_durations.dt)
|
||||
else:
|
||||
final_durations.update(inst_durations, dt or getattr(inst_durations, "dt", None))
|
||||
return final_durations
|
||||
|
||||
|
||||
def _parse_timing_constraints(backend, timing_constraints):
|
||||
if isinstance(timing_constraints, TimingConstraints):
|
||||
return timing_constraints
|
||||
if backend is None and timing_constraints is None:
|
||||
timing_constraints = TimingConstraints()
|
||||
elif backend is not None:
|
||||
timing_constraints = backend.target.timing_constraints()
|
||||
return timing_constraints
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
features_transpiler:
|
||||
- |
|
||||
Added a new import path option for :func:`.generate_preset_pass_manager`, so that it can now be imported as::
|
||||
|
||||
from qiskit import generate_preset_pass_manager
|
||||
|
||||
instead of having to type the full path::
|
||||
|
||||
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
|
||||
|
||||
The function is also importable from the :mod:`qiskit.transpiler` module as::
|
||||
|
||||
from qiskit.transpiler import generate_preset_pass_manager
|
|
@ -15,11 +15,10 @@
|
|||
"""Script to generate 'utility scale' load for profiling in a PGO context"""
|
||||
|
||||
import os
|
||||
|
||||
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
|
||||
from qiskit import qasm2
|
||||
from qiskit.providers.fake_provider import GenericBackendV2
|
||||
from qiskit.transpiler import CouplingMap
|
||||
from qiskit import qasm2
|
||||
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
|
||||
|
||||
QASM_DIR = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
|
||||
|
|
Loading…
Reference in New Issue