Skip to content

Commit

Permalink
Improving documentation for transpilation
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillermoAbadLopez committed Dec 30, 2024
1 parent c22ac09 commit 7d0f697
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 55 deletions.
41 changes: 39 additions & 2 deletions docs/fundamentals/transpilation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,44 @@ The process involves the following steps:

**Examples:**

If we instantiate some ``Circuit``, ``Platform`` and ``CircuitTranspiler`` objects like:
For example, the most basic use, would be to automatically transpile during an execute, like:

.. code-block:: python
from qibo import gates, Circuit
from qibo.transpiler import ReverseTraversal, Sabre
import qililab as ql
# Create circuit:
c = Circuit(5)
c.add(gates.CNOT(1, 0))
# Create transpilation config:
transpilation = {routing: True, optimize: False, router: Sabre, placer: ReverseTraversal}
# Create transpiler:
result = ql.execute(c, runcard="<path_to_runcard>", transpile_config=transpilation)
Or from a ``platform.execute()`` instead, like:

.. code-block:: python
from qibo import gates, Circuit
from qibo.transpiler import ReverseTraversal, Sabre
from qililab import build_platform
# Create circuit:
c = Circuit(5)
c.add(gates.CNOT(1, 0))
# Create platform:
platform = build_platform(runcard="<path_to_runcard>")
transpilation = {routing: True, optimize: False, router: Sabre, placer: ReverseTraversal}
# Create transpiler:
result = platform.execute(c, num_avg=1000, repetition_duration=200_000, transpile_config=transpilation)
Now, if we want more manual control instead, we can instantiate the ``CircuitTranspiler`` object like:

.. code-block:: python
Expand All @@ -50,7 +87,7 @@ If we instantiate some ``Circuit``, ``Platform`` and ``CircuitTranspiler`` objec
# Create transpiler:
transpiler = CircuitTranspiler(platform.digital_compilation_settings)
Now we can transpile like, in the following examples:
And now, transpile manually, like in the following examples:

.. code-block:: python
Expand Down
4 changes: 2 additions & 2 deletions src/qililab/digital/circuit_transpiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,9 @@ def transpile_circuit(
.. note::
\\*) If ``routing=False`` in ``transpile_config`` (default behavior), step 1. is skipped.
\\*) If ``routing=False`` (default behavior), step 1. is skipped.
\\**) If ``optimize=False`` in ``transpile_config`` (default behavior), steps 2. and 5. are skipped.
\\**) If ``optimize=False`` (default behavior), steps 2. and 5. are skipped.
The rest of steps are always done.
Expand Down
38 changes: 17 additions & 21 deletions src/qililab/execute_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,47 +31,39 @@ def execute(
configuration. Then the pulse will be compiled into the runcard machines assembly programs, and executed.
The transpilation is performed using the :meth:`.CircuitTranspiler.transpile_circuit()` method. Refer to the method's documentation for more detailed information. The main stages of this process are:
1. \\*)Routes and places the circuit's logical qubits onto the chip's physical qubits. The final qubit layout is returned and logged.
2. \\**)Canceling adjacent pairs of Hermitian gates (H, X, Y, Z, CNOT, CZ, and SWAPs).
3. Translates the circuit into the chip's native gate set (CZ, RZ, Drag, Wait, and M).
4. Commuting virtual RZ gates and adding phase corrections from CZ.
5. \\**)Optimizing the resulting Drag gates, by combining multiple pulses into a single one.
6. Converts the native gates into a pulse schedule using calibrated settings from the runcard.
1. \\*)Routing, 2. \\**)Canceling Hermitian pairs, 3. Translate to native gates, 4. Commute virtual RZ & adding CZ phase corrections, 5. \\**)Optimize Drag gates, 6. Convert to pulse schedule.
.. note ::
\\*) Step `1.` is done only if ``routing=True`` is passed in ``transpile_config``. Otherwise its skipped.
\\*) `1.` is done only if ``routing=True`` is passed in ``transpile_config``. Otherwise its skipped.
\\**) Steps 2. and 5 are done only if ``optimize=True`` is passed in ``transpile_config``. Otherwise its skipped.
\\**) `2.` and `5.` are done only if ``optimize=True`` is passed in ``transpile_config``. Otherwise its skipped.
Args:
circuit (Circuit | list[Circuit]): Qibo Circuit.
runcard (str | dict): If a string, path to the YAML file containing the serialization of the Platform to be
used. If a dictionary, the serialized platform to be used.
nshots (int, optional): Number of shots to execute. Defaults to 1.
transpile_config (dict, optional): Configuration dictionary for the transpilation process. Defaults to ``{}``. It can contain the following keys and values:
- routing (bool, optional): whether to route the circuits. Defaults to False.
- placer (Placer | type[Placer] | tuple[type[Placer], dict], optional): ``Placer`` instance, or subclass ``type[Placer]`` to use, with optionally, its kwargs dict (other than connectivity), both in a tuple. Defaults to ``ReverseTraversal``.
- router (Router | type[Router] | tuple[type[Router], dict], optional): ``Router`` instance, or subclass ``type[Router]`` to use, with optionally, its kwargs dict (other than connectivity), both in a tuple. Defaults to ``Sabre``.
- routing_iterations (int, optional): Number of times to repeat the routing pipeline, to keep the best stochastic result. Defaults to 10.
- optimize (bool, optional): whether to optimize the circuit and/or transpilation. Defaults to True.
transpile_config (dict, optional): Kwargs (``!circuit``) passed to the :meth:`.CircuitTranspiler.transpile_circuit()`
method. Contains the configuration used during transpilation. Defaults to ``{}`` (not changing any default value).
Check the ``transpile_circuit()`` method documentation for the keys and values it can contain.
Returns:
Result | list[Result]: :class:`Result` class (or list of :class:`Result` classes) containing the results of the
execution.
|
Example Usage:
.. code-block:: python
from qibo.models import Circuit
from qibo import gates
from pathlib import Path
import qililab as ql
import os
import numpy as np
from qibo import Circuit, gates
from qibo.transpiler import Sabre, ReverseTraversal
import qililab as ql
# Create circuit:
nqubits = 5
c = Circuit(nqubits)
for qubit in range(nqubits):
Expand All @@ -83,7 +75,11 @@ def execute(
c.add(gates.SWAP(4, 2))
c.add(gates.RX(1, 3 * np.pi / 2))
probabilities = ql.execute(c, runcard="./runcards/galadriel.yml")
# Create transpilation config:
transpilation = {routing: True, optimize: False, router: Sabre, placer: ReverseTraversal}
# Execute with automatic transpilation:
probabilities = ql.execute(c, runcard="./runcards/galadriel.yml", transpile_config=transpilation)
"""
if isinstance(program, Circuit):
program = [program]
Expand Down
63 changes: 33 additions & 30 deletions src/qililab/platform/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -994,32 +994,23 @@ def execute(
To compile to assembly programs, the ``platform.compile()`` method is called; check its documentation for more information.
The transpilation is performed using the :meth:`.CircuitTranspiler.transpile_circuit()` method. Refer to the method's documentation for more detailed information. The main stages of this process are:
1. \\*)Routes and places the circuit's logical qubits onto the chip's physical qubits. The final qubit layout is returned and logged.
2. \\**)Canceling adjacent pairs of Hermitian gates (H, X, Y, Z, CNOT, CZ, and SWAPs).
3. Translates the circuit into the chip's native gate set (CZ, RZ, Drag, Wait, and M).
4. Commuting virtual RZ gates and adding phase corrections from CZ.
5. \\**)Optimizing the resulting Drag gates, by combining multiple pulses into a single one.
6. Converts the native gates into a pulse schedule using calibrated settings from the runcard.
1. \\*)Routing, 2. \\**)Canceling Hermitian pairs, 3. Translate to native gates, 4. Commute virtual RZ & adding CZ phase corrections, 5. \\**)Optimize Drag gates, 6. Convert to pulse schedule.
.. note ::
\\*) Step `1.` is done only if ``routing=True`` is passed in ``transpile_config``. Otherwise its skipped.
\\*) `1.` is done only if ``routing=True`` is passed in ``transpile_config``. Otherwise its skipped.
\\**) Steps 2. and 5 are done only if ``optimize=True`` is passed in ``transpile_config``. Otherwise its skipped.
\\**) `2.` and `5.` are done only if ``optimize=True`` is passed in ``transpile_config``. Otherwise its skipped.
Args:
program (``PulseSchedule`` | ``Circuit``): Circuit or pulse schedule to execute.
num_avg (int): Number of hardware averages used.
repetition_duration (int): Minimum duration of a single execution.
num_bins (int, optional): Number of bins used. Defaults to 1.
queue (Queue, optional): External queue used for asynchronous data handling. Defaults to None.
transpile_config (dict, optional): Configuration dictionary for the transpilation process. Defaults to ``{}``. It can contain the following keys and values:
- routing (bool, optional): whether to route the circuits. Defaults to False.
- placer (Placer | type[Placer] | tuple[type[Placer], dict], optional): ``Placer`` instance, or subclass ``type[Placer]`` to use, with optionally, its kwargs dict (other than connectivity), both in a tuple. Defaults to ``ReverseTraversal``.
- router (Router | type[Router] | tuple[type[Router], dict], optional): ``Router`` instance, or subclass ``type[Router]`` to use, with optionally, its kwargs dict (other than connectivity), both in a tuple. Defaults to ``Sabre``.
- routing_iterations (int, optional): Number of times to repeat the routing pipeline, to keep the best stochastic result. Defaults to 10.
- optimize (bool, optional): whether to optimize the circuit and/or transpilation. Defaults to True.
transpile_config (dict, optional): Kwargs (``!circuit``) passed to the :meth:`.CircuitTranspiler.transpile_circuit()`
method. Contains the configuration used during transpilation. Defaults to ``{}`` (not changing any default value).
Check the ``transpile_circuit()`` method documentation for the keys and values it can contain.
Returns:
Result: Result obtained from the execution. This corresponds to a numpy array that depending on the
Expand All @@ -1029,6 +1020,27 @@ def execute(
path0 (I) and path1 (Q). N corresponds to the length of the scope measured.
- Scope acquisition disabled: An array with dimension `(#sequencers, 2, #bins)`.
|
Example Usage:
.. code-block:: python
from qibo import gates, Circuit
from qibo.transpiler import ReverseTraversal, Sabre
from qililab import build_platform
# Create circuit:
c = Circuit(5)
c.add(gates.CNOT(1, 0))
# Create platform and transpilation config:
platform = build_platform(runcard="<path_to_runcard>")
transpilation = {routing: True, optimize: False, router: Sabre, placer: ReverseTraversal}
# Execute with automatic transpilation:
result = platform.execute(c, num_avg=1000, repetition_duration=200_000, transpile_config=transpilation)
"""
# Compile pulse schedule
programs, final_layout = self.compile(program, num_avg, repetition_duration, num_bins, transpile_config)
Expand Down Expand Up @@ -1130,19 +1142,13 @@ def compile(
settings of the platform and passed transpile configuration. Then the pulse schedules will be compiled into the assembly programs.
The transpilation is performed using the :meth:`.CircuitTranspiler.transpile_circuit()` method. Refer to the method's documentation for more detailed information. The main stages of this process are:
1. \\*)Routes and places the circuit's logical qubits onto the chip's physical qubits. The final qubit layout is returned and logged.
2. \\**)Canceling adjacent pairs of Hermitian gates (H, X, Y, Z, CNOT, CZ, and SWAPs).
3. Translates the circuit into the chip's native gate set (CZ, RZ, Drag, Wait, and M).
4. Commuting virtual RZ gates and adding phase corrections from CZ.
5. \\**)Optimizing the resulting Drag gates, by combining multiple pulses into a single one.
6. Converts the native gates into a pulse schedule using calibrated settings from the runcard.
1. \\*)Routing, 2. \\**)Canceling Hermitian pairs, 3. Translate to native gates, 4. Commute virtual RZ & adding CZ phase corrections, 5. \\**)Optimize Drag gates, 6. Convert to pulse schedule.
.. note ::
\\*) Step `1.` is done only if ``routing=True`` is passed in ``transpile_config``. Otherwise its skipped.
\\*) `1.` is done only if ``routing=True`` is passed in ``transpile_config``. Otherwise its skipped.
\\**) Steps 2. and 5 are done only if ``optimize=True`` is passed in ``transpile_config``. Otherwise its skipped.
\\**) `2.` and `5.` are done only if ``optimize=True`` is passed in ``transpile_config``. Otherwise its skipped.
.. note::
This method is called during the ``platform.execute()`` method, check its documentation for more information.
Expand All @@ -1152,12 +1158,9 @@ def compile(
num_avg (int): Number of hardware averages used.
repetition_duration (int): Minimum duration of a single execution.
num_bins (int): Number of bins used.
transpile_config (dict, optional): Configuration dictionary for the transpilation process. Defaults to ``{}``. It can contain the following keys and values:
- routing (bool, optional): whether to route the circuits. Defaults to False.
- placer (Placer | type[Placer] | tuple[type[Placer], dict], optional): ``Placer`` instance, or subclass ``type[Placer]`` to use, with optionally, its kwargs dict (other than connectivity), both in a tuple. Defaults to ``ReverseTraversal``.
- router (Router | type[Router] | tuple[type[Router], dict], optional): ``Router`` instance, or subclass ``type[Router]`` to use, with optionally, its kwargs dict (other than connectivity), both in a tuple. Defaults to ``Sabre``.
- routing_iterations (int, optional): Number of times to repeat the routing pipeline, to keep the best stochastic result. Defaults to 10.
- optimize (bool, optional): whether to optimize the circuit and/or transpilation. Defaults to True.
transpile_config (dict, optional): Kwargs (``!circuit``) passed to the :meth:`.CircuitTranspiler.transpile_circuit()`
method. Contains the configuration used during transpilation. Defaults to ``{}`` (not changing any default value).
Check the ``transpile_circuit()`` method documentation for the keys and values it can contain.
Returns:
tuple[dict, dict[str, int]]: Tuple containing the dictionary of compiled assembly programs (The key is the bus alias (``str``), and the value is the assembly compilation (``list``)) and the final layout of the qubits in the circuit {"qX":Y}.
Expand Down

0 comments on commit 7d0f697

Please sign in to comment.