Skip to content

Commit

Permalink
Start making the BasisTranslator Target/BackendV2 aware
Browse files Browse the repository at this point in the history
In Qiskit#5885 we added the next version of the abstract Backend interface
BackendV2 which added the concept of a Target which represents a
compiler target for the transpiler. It contains all the information
about the constraints of a backend for the compiler to use and replaces
the combination of basis_gates, coupling_map, etc and expands the
representation to model more complex devices. However, in Qiskit#5885 we only
introduced the interface and didn't modify the transpiler to use the
Target natively or any of the extra information it contains. This commit
is the start of the process of updated the transpiler to work with a
target natively. To start if a backend has a target that is now passed
through from transpile to the passmanager_config so we can start passing
it directly to passes as we enable it. Then the basis translator is
updated to work natively with a target instead of the basis gates list
it used before. In addition to using a target directly support is added
for heterogeneous gate sets so that target instructions can work on only
a subset of qargs.

Building off this in the future There are additional features in target
that we might want to expand support for in the BasisTranslator in the
future, such as supporting custom variants of the same gate, or handling
fixed angle rotation gate variants, etc.
  • Loading branch information
mtreinish committed Dec 1, 2021
1 parent 3694fff commit 070db99
Show file tree
Hide file tree
Showing 12 changed files with 806 additions and 29 deletions.
22 changes: 21 additions & 1 deletion qiskit/compiler/transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
level_3_pass_manager,
)
from qiskit.transpiler.timing_constraints import TimingConstraints
from qiskit.transpiler.target import Target

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -67,6 +68,7 @@ def transpile(
output_name: Optional[Union[str, List[str]]] = None,
unitary_synthesis_method: str = "default",
unitary_synthesis_plugin_config: dict = None,
target: Target = None,
) -> Union[QuantumCircuit, List[QuantumCircuit]]:
"""Transpile one or more circuits, according to some desired transpilation targets.
Expand Down Expand Up @@ -229,7 +231,10 @@ def callback_func(**kwargs):
the ``unitary_synthesis`` argument. As this is custom for each
unitary synthesis plugin refer to the plugin documentation for how
to use this option.
target: A backend transpiler target. Normally this is specified as part of
the ``backend`` argument, but if you have manually constructed a
:class:`~qiskit.transpiler.Target` object you can specify it manually here.
This will override the target from ``backend``.
Returns:
The transpiled circuit(s).
Expand Down Expand Up @@ -268,6 +273,7 @@ def callback_func(**kwargs):
approximation_degree=approximation_degree,
unitary_synthesis_method=unitary_synthesis_method,
backend=backend,
target=target,
)

warnings.warn(
Expand Down Expand Up @@ -314,6 +320,7 @@ def callback_func(**kwargs):
timing_constraints,
unitary_synthesis_method,
unitary_synthesis_plugin_config,
target,
)

_check_circuits_coupling_map(circuits, transpile_args, backend)
Expand Down Expand Up @@ -505,6 +512,7 @@ def _parse_transpile_args(
timing_constraints,
unitary_synthesis_method,
unitary_synthesis_plugin_config,
target,
) -> List[Dict]:
"""Resolve the various types of args allowed to the transpile() function through
duck typing, overriding args, etc. Refer to the transpile() docstring for details on
Expand Down Expand Up @@ -550,6 +558,7 @@ def _parse_transpile_args(
durations = _parse_instruction_durations(backend, instruction_durations, dt, circuits)
scheduling_method = _parse_scheduling_method(scheduling_method, num_circuits)
timing_constraints = _parse_timing_constraints(backend, timing_constraints, num_circuits)
target = _parse_target(backend, target, num_circuits)
if scheduling_method and any(d is None for d in durations):
raise TranspilerError(
"Transpiling a circuit with a scheduling method"
Expand Down Expand Up @@ -579,6 +588,7 @@ def _parse_transpile_args(
"faulty_qubits_map": faulty_qubits_map,
"unitary_synthesis_method": unitary_synthesis_method,
"unitary_synthesis_plugin_config": unitary_synthesis_plugin_config,
"target": target,
}
):
transpile_args = {
Expand All @@ -598,6 +608,7 @@ def _parse_transpile_args(
seed_transpiler=kwargs["seed_transpiler"],
unitary_synthesis_method=kwargs["unitary_synthesis_method"],
unitary_synthesis_plugin_config=kwargs["unitary_synthesis_plugin_config"],
target=kwargs["target"],
),
"optimization_level": kwargs["optimization_level"],
"output_name": kwargs["output_name"],
Expand Down Expand Up @@ -898,6 +909,15 @@ def _parse_unitary_plugin_config(unitary_synthesis_plugin_config, num_circuits):
return unitary_synthesis_plugin_config


def _parse_target(backend, target, num_circuits):
backend_target = getattr(backend, "target", None)
if target is None:
target = backend_target
if not isinstance(target, list):
target = [target] * num_circuits
return target


def _parse_seed_transpiler(seed_transpiler, num_circuits):
if not isinstance(seed_transpiler, list):
seed_transpiler = [seed_transpiler] * num_circuits
Expand Down
1 change: 1 addition & 0 deletions qiskit/test/mock/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from .fake_provider import FakeProviderFactory
from .fake_backend import FakeBackend, FakeLegacyBackend
from .fake_backend_v2 import FakeBackendV2
from .fake_mumbai_v2 import FakeMumbaiV2
from .fake_job import FakeJob, FakeLegacyJob
from .fake_qobj import FakeQobj

Expand Down
8 changes: 6 additions & 2 deletions qiskit/test/mock/fake_backend_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@

from qiskit.circuit.parameter import Parameter
from qiskit.circuit.measure import Measure
from qiskit.circuit.library.standard_gates import CXGate, UGate, ECRGate, RXGate
from qiskit.circuit.library.standard_gates import (
CXGate,
UGate,
ECRGate,
RXGate,
)
from qiskit.providers.backend import BackendV2, QubitProperties
from qiskit.providers.options import Options
from qiskit.transpiler import Target, InstructionProperties
Expand Down Expand Up @@ -58,7 +63,6 @@ def __init__(self):
self._target.add_instruction(UGate(self._theta, self._phi, self._lam), u_props)
cx_props = {
(0, 1): InstructionProperties(duration=5.23e-7, error=0.00098115),
(1, 0): InstructionProperties(duration=4.52e-7, error=0.00132115),
}
self._target.add_instruction(CXGate(), cx_props)
measure_props = {
Expand Down
Loading

0 comments on commit 070db99

Please sign in to comment.