Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate lists for argument input on transpile() #8835

Merged
merged 7 commits into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 48 additions & 11 deletions qiskit/compiler/transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,22 +88,22 @@ def transpile(
) -> Union[QuantumCircuit, List[QuantumCircuit]]:
"""Transpile one or more circuits, according to some desired transpilation targets.

All arguments may be given as either a singleton or list. In case of a list,
the length must be equal to the number of circuits being transpiled.
.. deprecated:: 0.23.0

All arguments (except for ``circuits``) may be given as either a singleton or list. In
case of a list, the length must be equal to the number of circuits being transpiled. The
kevinhartman marked this conversation as resolved.
Show resolved Hide resolved
support for using a list for an argument is deprecated and will be removed in the 0.25.0
release. If you need to use multiple values for an argument you can
use multiple :func:`~.transpile` calls (and potentially use :func:`~.parallel_map`
to leverage multiprocessing if needed).
mtreinish marked this conversation as resolved.
Show resolved Hide resolved

Transpilation is done in parallel using multiprocessing.

Args:
circuits: Circuit(s) to transpile
backend: If set, transpiler options are automatically grabbed from
``backend.configuration()`` and ``backend.properties()``.
If any other option is explicitly set (e.g., ``coupling_map``), it
backend: If set, the transpiler will compile the input circuit to this target
device. If any other option is explicitly set (e.g., ``coupling_map``), it
will override the backend's.

.. note::

The backend arg is purely for convenience. The resulting
circuit may be run on any backend as long as it is compatible.
basis_gates: List of basis gate names to unroll to
(e.g: ``['u1', 'u2', 'u3', 'cx']``). If ``None``, do not unroll.
inst_map: Mapping of unrolled gates to pulse schedules. If this is not provided,
Expand Down Expand Up @@ -626,7 +626,9 @@ def _parse_transpile_args(
# Each arg could be single or a list. If list, it must be the same size as
# number of circuits. If single, duplicate to create a list of that size.
num_circuits = len(circuits)

user_input_durations = instruction_durations
user_input_timing_constraints = timing_constraints
user_input_initial_layout = initial_layout
# If a target is specified have it override any implicit selections from a backend
# but if an argument is explicitly passed use that instead of the target version
if target is not None:
Expand Down Expand Up @@ -702,6 +704,41 @@ def _parse_transpile_args(
"hls_config": hls_config,
}.items():
if isinstance(value, list):
# This giant if-statement detects deprecated use of argument
# broadcasting. For arguments that previously supported broadcast
# but were not themselves of type list (the majority), we simply warn
# when the user provides a list. For the others, special handling is
# required to disambiguate an expected value of type list from
# an attempt to provide multiple values for broadcast. This path is
# super buggy in general (outside of the warning) and since we're
# deprecating this it's better to just remove it than try to clean it up.
# pylint: disable=too-many-boolean-expressions
if (
key not in {"instruction_durations", "timing_constraints", "initial_layout"}
or (
key == "initial_layout"
and user_input_initial_layout
and isinstance(user_input_initial_layout, list)
and isinstance(user_input_initial_layout[0], (Layout, dict, list))
)
or (
key == "instruction_durations"
and user_input_durations
and isinstance(user_input_durations, list)
and isinstance(user_input_durations[0], (list, InstructionDurations))
)
or (
key == "timing_constraints"
and user_input_timing_constraints
and isinstance(user_input_timing_constraints, list)
)
):
warnings.warn(
f"Passing in a list of arguments for {key} is deprecated and will no longer work "
"starting in the 0.25.0 release.",
DeprecationWarning,
stacklevel=3,
)
unique_dict[key] = value
else:
shared_dict[key] = value
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
deprecations:
- |
Support for passing in lists of argument values to the :func:`~.transpile`
function is deprecated and will be removed in the 0.25.0 release. This
is being done to facilitate greatly reducing the overhead for parallel
execution for transpiling multiple circuits at once. If you're using
this functionality currently you can call :func:`~.transpile` multiple
times instead. For example if you were previously doing something like::

from qiskit.transpiler import CouplingMap
from qiskit import QuantumCircuit
from qiskit import transpile

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()
cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)]
results = transpile([qc] * 6, coupling_map=cmaps)

instead you should run something like:

from itertools import cycle
from qiskit.transpiler import CouplingMap
from qiskit import QuantumCircuit
from qiskit import transpile

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()
cmaps = [CouplingMap.from_heavy_hex(d) for d in range(3, 15, 2)]

results = []
for qc, cmap in zip(cycle([qc]), cmaps):
results.append(transpile(qc, coupling_map=cmap))

You can also leverage :func:`~.parallel_map` or ``multiprocessing`` from
the Python standard library if you want to run this in parallel.