English
Languages
English
Japanese
German
Korean
Shortcuts

Note

This page was generated from tutorials/circuits_advanced/04_transpiler_passes_and_passmanager.ipynb.

Run interactively in the IBM Quantum lab.

Transpiler Passes and Pass Manager

Introduction

A central component of Qiskit Terra is the transpiler, which is designed for modularity and extensibility. The goal is to be able to easily write new circuit transformations (known as transpiler passes), and combine them with other existing passes. Which passes are chained together and in which order has a major effect on the final outcome. This pipeline is determined by a pass manager, which schedules the passes and also allows passes to communicate with each other by providing a shared space. In this way, the transpiler opens up the door for research into aggressive optimization of quantum circuits.

In this notebook, we look at the built-in passes, how to use the pass manager, and develop a simple custom transpiler pass. In order to do the latter, we first need to introduce the internal representation of quantum circuits in Qiskit, in the form of a Directed Acyclic Graph, or DAG. Then, we illustrate a simple swap mapper pass, which transforms an input circuit to be compatible with a limited-connectivity quantum device.

Before you start: You may need to install the pydot library and the graphviz library for the DAG plotting routines. If you are using Anaconda Python, you can install both with the conda command. If you use your system’s native Python interpreter, install pydot using the pip command, and install graphviz using your system’s native package manager (e.g. yum, apt, dnf, brew, etc.).

[1]:
%matplotlib inline
from qiskit import QuantumCircuit
from qiskit.compiler import transpile
from qiskit.transpiler import PassManager

PassManager object

Lets you specify the set of passes you want.

[2]:
circ = QuantumCircuit(3)
circ.ccx(0, 1, 2)
circ.draw(output='mpl')
[2]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_5_0.png
[3]:
from qiskit.transpiler.passes import Unroller
pass_ = Unroller(['u1', 'u2', 'u3', 'cx'])
pm = PassManager(pass_)
new_circ = pm.run(circ)
new_circ.draw(output='mpl')
[3]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_6_0.png

All of Qiskit’s transpiler passes are accessible from qiskit.transpiler.passes.

[4]:
from qiskit.transpiler import passes
[pass_ for pass_ in dir(passes) if pass_[0].isupper()]
[4]:
['ALAPSchedule',
 'ASAPSchedule',
 'ApplyLayout',
 'BarrierBeforeFinalMeasurements',
 'BasicSwap',
 'BasisTranslator',
 'CSPLayout',
 'CXCancellation',
 'CXDirection',
 'CheckCXDirection',
 'CheckMap',
 'Collect2qBlocks',
 'CommutationAnalysis',
 'CommutativeCancellation',
 'ConsolidateBlocks',
 'CountOps',
 'CountOpsLongestPath',
 'CrosstalkAdaptiveSchedule',
 'DAGFixedPoint',
 'DAGLongestPath',
 'Decompose',
 'DenseLayout',
 'Depth',
 'EnlargeWithAncilla',
 'FixedPoint',
 'FullAncillaAllocation',
 'HoareOptimizer',
 'Layout2qDistance',
 'LayoutTransformation',
 'LookaheadSwap',
 'MergeAdjacentBarriers',
 'NoiseAdaptiveLayout',
 'NumTensorFactors',
 'Optimize1qGates',
 'Optimize1qGatesDecomposition',
 'OptimizeSwapBeforeMeasure',
 'RemoveDiagonalGatesBeforeMeasure',
 'RemoveFinalMeasurements',
 'RemoveResetInZeroState',
 'ResourceEstimation',
 'SabreLayout',
 'SabreSwap',
 'SetLayout',
 'Size',
 'StochasticSwap',
 'TemplateOptimization',
 'TimeUnitAnalysis',
 'TrivialLayout',
 'UnitarySynthesis',
 'Unroll3qOrMore',
 'UnrollCustomDefinitions',
 'Unroller',
 'Width']

Different Variants of the Same Pass

There can be passes that do the same job, but in different ways. For example, the TrivialLayout, DenseLayout and NoiseAdaptiveLayout all choose a layout (binding of virtual qubits to physical qubits), but use different algorithms and objectives. Similarly, the BasicSwap, LookaheadSwap and StochasticSwap all insert swaps to make the circuit compatible with the coupling map. The modularity of the transpiler allows plug-and-play replacements for each pass.

Below, we show the swapper passes all applied to the same circuit, to transform it to match a linear chain topology. You can see differences in performance, where the StochasticSwap is clearly the best. However, this can vary depending on the input circuit.

[5]:
from qiskit.transpiler import CouplingMap, Layout
from qiskit.transpiler.passes import BasicSwap, LookaheadSwap, StochasticSwap

coupling = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]

circuit = QuantumCircuit(7)
circuit.h(3)
circuit.cx(0, 6)
circuit.cx(6, 0)
circuit.cx(0, 1)
circuit.cx(3, 1)
circuit.cx(3, 0)

coupling_map = CouplingMap(couplinglist=coupling)

bs = BasicSwap(coupling_map=coupling_map)
pass_manager = PassManager(bs)
basic_circ = pass_manager.run(circuit)

ls = LookaheadSwap(coupling_map=coupling_map)
pass_manager = PassManager(ls)
lookahead_circ = pass_manager.run(circuit)

ss = StochasticSwap(coupling_map=coupling_map)
pass_manager = PassManager(ss)
stochastic_circ = pass_manager.run(circuit)
[6]:
circuit.draw(output='mpl')
[6]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_11_0.png
[7]:
basic_circ.draw(output='mpl')
[7]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_12_0.png
[8]:
lookahead_circ.draw(output='mpl')
[8]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_13_0.png
[9]:
stochastic_circ.draw(output='mpl')
[9]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_14_0.png

Preset Pass Managers

Qiskit comes with several pre-defined pass managers, corresponding to various levels of optimization achieved through different pipelines of passes. Currently optimization_level 0 through 3 are supported; the higher the number, the more optimized it is, at the expense of more time. Choosing a good pass manager may take trial and error, as it depends heavily on the circuit being transpiled and the backend being targeted.

Here we illustrate the different levels by looking at a state synthesis circuit. We initialize four qubits to an arbitrary state, and then try to optimize the circuit that achieves this.

  • optimization_level=0: just maps the circuit to the backend, with no explicit optimization (except whatever optimizations the mapper does).

  • optimization_level=1: maps the circuit, but also does light-weight optimizations by collapsing adjacent gates.

  • optimization_level=2: medium-weight optimization, including a noise-adaptive layout and a gate-cancellation procedure based on gate commutation relationships.

  • optimization_level=3: heavy-weight optimization, which in addition to previous steps, does resynthesis of two-qubit blocks of gates in the circuit.

[10]:
import math
from qiskit.test.mock import FakeTokyo

backend = FakeTokyo()     # mimics the tokyo device in terms of coupling map and basis gates
[11]:
qc = QuantumCircuit(10)

random_state = [
    1 / math.sqrt(4) * complex(0, 1),
    1 / math.sqrt(8) * complex(1, 0),
    0,
    0,
    0,
    0,
    0,
    0,
    1 / math.sqrt(8) * complex(1, 0),
    1 / math.sqrt(8) * complex(0, 1),
    0,
    0,
    0,
    0,
    1 / math.sqrt(4) * complex(1, 0),
    1 / math.sqrt(8) * complex(1, 0)]

qc.initialize(random_state, range(4))
qc.draw()
[11]:
     »
q_0: »
     »
q_1: »
     »
q_2: »
     »
q_3: »
     »
q_4: »
     »
q_5: »
     »
q_6: »
     »
q_7: »
     »
q_8: »
     »
q_9: »
     »
«     ┌────────────────────────────────────────────────────────────────────────────┐
«q_0: ┤0                                                                           ├
«     │                                                                            │
«q_1: ┤1                                                                           ├
«     │  initialize(0.5j,0.35355,0,0,0,0,0,0,0.35355,0.35355j,0,0,0,0,0.5,0.35355) │
«q_2: ┤2                                                                           ├
«     │                                                                            │
«q_3: ┤3                                                                           ├
«     └────────────────────────────────────────────────────────────────────────────┘
«q_4: ──────────────────────────────────────────────────────────────────────────────
«
«q_5: ──────────────────────────────────────────────────────────────────────────────
«
«q_6: ──────────────────────────────────────────────────────────────────────────────
«
«q_7: ──────────────────────────────────────────────────────────────────────────────
«
«q_8: ──────────────────────────────────────────────────────────────────────────────
«
«q_9: ──────────────────────────────────────────────────────────────────────────────
«                                                                                   

Now map this to the 20-qubit Tokyo device, with different optimization levels:

[12]:
optimized_0 = transpile(qc, backend=backend, seed_transpiler=11, optimization_level=0)
print('gates = ', optimized_0.count_ops())
print('depth = ', optimized_0.depth())
gates =  OrderedDict([('cx', 70), ('u3', 15), ('u1', 15), ('reset', 4)])
depth =  73
[13]:
optimized_1 = transpile(qc, backend=backend, seed_transpiler=11, optimization_level=1)
print('gates = ', optimized_1.count_ops())
print('depth = ', optimized_1.depth())
gates =  OrderedDict([('cx', 70), ('u3', 15), ('u1', 6)])
depth =  64
[14]:
optimized_2 = transpile(qc, backend=backend, seed_transpiler=11, optimization_level=2)
print('gates = ', optimized_2.count_ops())
print('depth = ', optimized_2.depth())
gates =  OrderedDict([('cx', 64), ('u3', 15), ('u1', 6)])
depth =  60
[15]:
optimized_3 = transpile(qc, backend=backend, seed_transpiler=11, optimization_level=3)
print('gates = ', optimized_3.count_ops())
print('depth = ', optimized_3.depth())
gates =  OrderedDict([('cx', 20), ('u3', 15), ('u1', 6)])
depth =  38

Introducing the DAG

In Qiskit, we represent circuits internally using a Directed Acyclic Graph (DAG). The advantage of this representation over a pure list of gates (i.e., netlist) is that the flow of information between operations are explicit, making it easier for passes to make transformation decisions without changing the semantics of the circuit.

Let’s start by building a simple circuit, and examining its DAG.

[16]:
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.dagcircuit import DAGCircuit
q = QuantumRegister(3, 'q')
c = ClassicalRegister(3, 'c')
circ = QuantumCircuit(q, c)
circ.h(q[0])
circ.cx(q[0], q[1])
circ.measure(q[0], c[0])
circ.rz(0.5, q[1]).c_if(c, 2)
circ.draw(output='mpl')
[16]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_25_0.png

In the DAG, there are three kinds of graph nodes: qubit/clbit input nodes (green), operation nodes (blue), and output nodes (red). Each edge indicates data flow (or dependency) between two nodes.

[17]:
from qiskit.converters import circuit_to_dag
from qiskit.tools.visualization import dag_drawer
dag = circuit_to_dag(circ)
dag_drawer(dag)
[17]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_27_0.png

Therefore, writing a transpiler pass means using Qiskit’s DAGCircuit API to analyze or transform the circuit. Let’s see some examples of this.

a. Get all op nodes in the DAG:

[18]:
dag.op_nodes()
[18]:
[<qiskit.dagcircuit.dagnode.DAGNode at 0x7fd5750af900>,
 <qiskit.dagcircuit.dagnode.DAGNode at 0x7fd5750aff90>,
 <qiskit.dagcircuit.dagnode.DAGNode at 0x7fd5750afba0>,
 <qiskit.dagcircuit.dagnode.DAGNode at 0x7fd5750af820>]

Each node is an instance of the DAGNode class. Let’s examine the information stored in the second op node.

[19]:
node = dag.op_nodes()[3]
print("node name: ", node.name)
print("node op: ", node.op)
print("node qargs: ", node.qargs)
print("node cargs: ", node.cargs)
print("node condition: ", node.condition)
node name:  rz
node op:  <qiskit.circuit.library.standard_gates.rz.RZGate object at 0x7fd5750258e0>
node qargs:  [Qubit(QuantumRegister(3, 'q'), 1)]
node cargs:  []
node condition:  (ClassicalRegister(3, 'c'), 2)

b. Add an operation to the back:

[20]:
from qiskit.circuit.library import HGate
dag.apply_operation_back(HGate(), qargs=[q[0]])
dag_drawer(dag)
[20]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_34_0.png

c. Add an operation to the front:

[21]:
from qiskit.circuit.library import CCXGate
dag.apply_operation_front(CCXGate(), qargs=[q[0], q[1], q[2]], cargs=[])
dag_drawer(dag)
[21]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_36_0.png

d. Substitute a node with a subcircuit:

[22]:
from qiskit.circuit.library import CHGate, U2Gate, CXGate
mini_dag = DAGCircuit()
p = QuantumRegister(2, "p")
mini_dag.add_qreg(p)
mini_dag.apply_operation_back(CHGate(), qargs=[p[1], p[0]])
mini_dag.apply_operation_back(U2Gate(0.1, 0.2), qargs=[p[1]])

# substitute the cx node with the above mini-dag
cx_node = dag.op_nodes(op=CXGate).pop()
dag.substitute_node_with_dag(node=cx_node, input_dag=mini_dag, wires=[p[0], p[1]])
dag_drawer(dag)
[22]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_38_0.png

Finally, after all transformations are complete, we can convert back to a regular QuantumCircuit object. This is what the transpiler does! It takes a circuit, operates on it in DAG form, and outputs a transformed circuit.

[23]:
from qiskit.converters import dag_to_circuit
circuit = dag_to_circuit(dag)
circuit.draw(output='mpl')
[23]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_40_0.png

Implementing a BasicMapper Pass

Now that we are familiar with the DAG, let’s use it to write a transpiler pass. Here we will implement a basic pass for mapping an arbitrary circuit to a device with limited qubit connectivity. We call this the BasicMapper. This pass is included in Qiskit Terra as well.

The first thing to do when writing a transpiler pass is to decide whether the pass class derives from a TransformationPass or AnalysisPass. Transformation passes modify the circuit, while analysis passes only collect information about a circuit (to be used by other passes). Then, the run(dag) method is implemented, which does the main task. Finally, the pass is registered inside the qiskit.transpiler.passes module.

This pass functions as follows: it traverses the DAG layer-by-layer (each layer is a group of operations that does not act on independent qubits, so in theory all operations in a layer can be done independently). For each operation, if it does not already meet the coupling map constraints, the pass identifies a swap path and inserts swaps to bring the two qubits close to each other.

Follow the comments in the code for more details.

[24]:
from copy import copy

from qiskit.transpiler.basepasses import TransformationPass
from qiskit.transpiler import Layout
from qiskit.circuit.library import SwapGate


class BasicSwap(TransformationPass):
    """Maps (with minimum effort) a DAGCircuit onto a `coupling_map` adding swap gates."""

    def __init__(self,
                 coupling_map,
                 initial_layout=None):
        """Maps a DAGCircuit onto a `coupling_map` using swap gates.

        Args:
            coupling_map (CouplingMap): Directed graph represented a coupling map.
            initial_layout (Layout): initial layout of qubits in mapping
        """
        super().__init__()
        self.coupling_map = coupling_map
        self.initial_layout = initial_layout

    def run(self, dag):
        """Runs the BasicSwap pass on `dag`.

        Args:
            dag (DAGCircuit): DAG to map.

        Returns:
            DAGCircuit: A mapped DAG.

        Raises:
            TranspilerError: if the coupling map or the layout are not
            compatible with the DAG.
        """
        new_dag = DAGCircuit()
        for qreg in dag.qregs.values():
            new_dag.add_qreg(qreg)
        for creg in dag.cregs.values():
            new_dag.add_creg(creg)


        if self.initial_layout is None:
            if self.property_set["layout"]:
                self.initial_layout = self.property_set["layout"]
            else:
                self.initial_layout = Layout.generate_trivial_layout(*dag.qregs.values())

        if len(dag.qubits) != len(self.initial_layout):
            raise TranspilerError('The layout does not match the amount of qubits in the DAG')

        if len(self.coupling_map.physical_qubits) != len(self.initial_layout):
            raise TranspilerError(
                "Mappers require to have the layout to be the same size as the coupling map")

        canonical_register = dag.qregs['q']
        trivial_layout = Layout.generate_trivial_layout(canonical_register)
        current_layout = trivial_layout.copy()

        for layer in dag.serial_layers():
            subdag = layer['graph']

            for gate in subdag.two_qubit_ops():
                physical_q0 = current_layout[gate.qargs[0]]
                physical_q1 = current_layout[gate.qargs[1]]
                if self.coupling_map.distance(physical_q0, physical_q1) != 1:
                    # Insert a new layer with the SWAP(s).
                    swap_layer = DAGCircuit()
                    swap_layer.add_qreg(canonical_register)

                    path = self.coupling_map.shortest_undirected_path(physical_q0, physical_q1)
                    for swap in range(len(path) - 2):
                        connected_wire_1 = path[swap]
                        connected_wire_2 = path[swap + 1]

                        qubit_1 = current_layout[connected_wire_1]
                        qubit_2 = current_layout[connected_wire_2]

                        # create the swap operation
                        swap_layer.apply_operation_back(SwapGate(),
                                                        qargs=[qubit_1, qubit_2],
                                                        cargs=[])

                    # layer insertion
                    order = current_layout.reorder_bits(new_dag.qubits)
                    new_dag.compose(swap_layer, qubits=order)

                    # update current_layout
                    for swap in range(len(path) - 2):
                        current_layout.swap(path[swap], path[swap + 1])

            order = current_layout.reorder_bits(new_dag.qubits)
            new_dag.compose(subdag, qubits=order)

        return new_dag

Let’s test this pass on a small example circuit.

[25]:
q = QuantumRegister(7, 'q')
in_circ = QuantumCircuit(q)
in_circ.h(q[0])
in_circ.cx(q[0], q[4])
in_circ.cx(q[2], q[3])
in_circ.cx(q[6], q[1])
in_circ.cx(q[5], q[0])
in_circ.rz(0.1, q[2])
in_circ.cx(q[5], q[0])
[25]:
<qiskit.circuit.instructionset.InstructionSet at 0x7fd5753f3df0>

Now we construct a pass manager that contains our new pass. We pass the example circuit above to this pass manager, and obtain a new, transformed circuit.

[26]:
from qiskit.transpiler import PassManager
from qiskit.transpiler import CouplingMap
from qiskit import BasicAer
pm = PassManager()
coupling = [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]
coupling_map = CouplingMap(couplinglist=coupling)

pm.append([BasicSwap(coupling_map)])

out_circ = pm.run(in_circ)
[27]:
in_circ.draw(output='mpl')
[27]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_48_0.png
[28]:
out_circ.draw(output='mpl')
[28]:
../../_images/tutorials_circuits_advanced_04_transpiler_passes_and_passmanager_49_0.png

Note that this pass only inserts the swaps necessary to make every two-qubit interaction conform to the device coupling map. It does not, for example, care about the direction of interactions, or the native gate set supported by the device. This is a design philosophy of Qiskit’s transpiler: every pass performs a small, well-defined action, and the aggressive circuit optimization is achieved by the pass manager through combining multiple passes.

Transpiler Logging

Due to the complexity of the internal operations that the transpiler is performing it’s likely that you’ll end up in a situation where you’d like to debug an issue or just understand more of what is happening inside the transpiler when you call it. To facilitate this the transpiler emits log messages as part of its normal operation. This logging uses the Python standard library logging module to emit the log messages. Python’s standard logging was used because it allows Qiskit-Terra’s logging to integrate in a standard way with other applications and libraries.

For a more thorough introduction to Python logging refer to the official documentation and the tutorials and cookbook linked off of there.

Note: Most of the logging module functions used in this section adjust global settings. If you run commands in this section it might effect the output from other cells if they are run in a different order.

Configuring Python Standard Library Logging

By default Python Standard Logging only prints log messages at the WARNING, ERROR, or CRITICAL log levels. Since none of the logs emitted by the transpiler use these log levels (they’re all informative) you need to configure logging.

The simplest way to do this is to just run:

[29]:
import logging

logging.basicConfig(level='DEBUG')

The basicConfig() function (see the docs here: https://docs.python.org/3/library/logging.html#logging.basicConfig) configures a root handler and formatter. We also specify the log level to display with the level kwarg. Setting it to a level will also include and higher levels. For example, if you set it to 'INFO' in addition to the INFO level this will also include the WARNING, ERROR, and CRITICAL log levels.

Now the python environment in this notebook is configured to emit log messages to stderr when you run the transpiler. For example:

Note: basicConfig() will only work when called the first time it’s called. It detects if a root handler and formatter have already been setup (either by using an earlier basicConfig() call or otherwise) and does nothing if they have. Further adjustments will have to by interacting with the handler directly.

[30]:
from qiskit.test.mock import FakeTenerife


log_circ = QuantumCircuit(2, 2)
log_circ.h(0)
log_circ.h(1)
log_circ.h(1)
log_circ.x(1)
log_circ.cx(0, 1)
log_circ.measure([0,1], [0,1])

backend = FakeTenerife()

transpile(log_circ, backend);
INFO:qiskit.transpiler.runningpassmanager:Pass: SetLayout - 0.00882 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: TrivialLayout - 0.05507 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Layout2qDistance - 0.76580 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FullAncillaAllocation - 0.06032 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: EnlargeWithAncilla - 0.06795 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: ApplyLayout - 0.40174 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Unroll3qOrMore - 0.01454 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CheckMap - 0.04339 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: UnrollCustomDefinitions - 0.07415 (ms)
INFO:qiskit.transpiler.passes.basis.basis_translator:Begin BasisTranslator from source basis {('x', 1), ('h', 1), ('cx', 2), ('measure', 1)} to target basis {'u2', 'u3', 'snapshot', 'delay', 'u1', 'id', 'reset', 'measure', 'barrier', 'cx'}.
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Begining basis search from frozenset({('x', 1), ('h', 1), ('cx', 2), ('measure', 1)}) to frozenset({'u2', 'u3', 'snapshot', 'delay', 'reset', 'u1', 'id', 'measure', 'barrier', 'cx'}).
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Inspecting basis frozenset({('x', 1), ('h', 1), ('cx', 2), ('measure', 1)}).
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Inspecting basis frozenset({('h', 1), ('cx', 2), ('measure', 1), ('u3', 1)}).
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Transformation path:
DEBUG:qiskit.transpiler.passes.basis.basis_translator:x/1 => []
     ┌───────────┐
q_0: ┤ U3(π,0,π) ├
     └───────────┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:h/1 => []
     ┌─────────┐
q_0: ┤ U2(0,π) ├
     └─────────┘
INFO:qiskit.transpiler.passes.basis.basis_translator:Basis translation path search completed in 0.011s.
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Composing transform step: x/1 [] =>
     ┌───────────┐
q_0: ┤ U3(π,0,π) ├
     └───────────┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Updating transform for mapped instr ('x', 1) x, [] from
        ┌───┐
q301_0: ┤ x ├
        └───┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Updated transform for mapped instr ('x', 1) x, [] to
        ┌───────────┐
q301_0: ┤ U3(π,0,π) ├
        └───────────┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Composing transform step: h/1 [] =>
     ┌─────────┐
q_0: ┤ U2(0,π) ├
     └─────────┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Updating transform for mapped instr ('h', 1) h, [] from
        ┌───┐
q302_0: ┤ h ├
        └───┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Updated transform for mapped instr ('h', 1) h, [] to
        ┌─────────┐
q302_0: ┤ U2(0,π) ├
        └─────────┘
INFO:qiskit.transpiler.passes.basis.basis_translator:Basis translation paths composed in 0.011s.
INFO:qiskit.transpiler.passes.basis.basis_translator:Basis translation instructions replaced in 0.000s.
INFO:qiskit.transpiler.runningpassmanager:Pass: BasisTranslator - 25.18058 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CheckCXDirection - 0.05865 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXDirection - 0.51689 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: RemoveResetInZeroState - 0.01788 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Depth - 0.02980 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FixedPoint - 0.01383 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Optimize1qGates - 1.41168 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXCancellation - 0.05078 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Depth - 0.01884 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FixedPoint - 0.01740 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Optimize1qGates - 0.42987 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXCancellation - 0.05054 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Depth - 0.02217 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FixedPoint - 0.01168 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Optimize1qGates - 0.39315 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXCancellation - 0.04745 (ms)
INFO:qiskit.compiler.transpile:Total Transpile Time - 68.16912 (ms)
[30]:
<qiskit.circuit.quantumcircuit.QuantumCircuit at 0x7fd574e158b0>

As you can clearly see here when calling transpile() it now prints 2 types of log messages. The first is at the INFO log level and come from the pass manager. These indicate each pass that was executed and how long that took. The second are at the DEBUG level and come from the StochasticSwap pass and describes the internal operation of that pass. It’s useful for debugging issues in the pass’s operation.

Adjusting the log level for the transpiler

The qiskit transpiler uses a single namespace qiskit.transpiler, as used by logging.getLogger('qiskit.transpiler')). This makes it very easy to adjust the log level for just the transpiler. For example if you only wish to see log messages at the INFO level or above you can run:

[31]:
logging.getLogger('qiskit.transpiler').setLevel('INFO')
transpile(log_circ, backend);
INFO:qiskit.transpiler.runningpassmanager:Pass: SetLayout - 0.00501 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: TrivialLayout - 0.04840 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Layout2qDistance - 0.43678 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FullAncillaAllocation - 0.05245 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: EnlargeWithAncilla - 0.07367 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: ApplyLayout - 0.58651 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Unroll3qOrMore - 0.01478 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CheckMap - 0.02646 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: UnrollCustomDefinitions - 0.04935 (ms)
INFO:qiskit.transpiler.passes.basis.basis_translator:Begin BasisTranslator from source basis {('x', 1), ('h', 1), ('cx', 2), ('measure', 1)} to target basis {'u2', 'u3', 'snapshot', 'delay', 'u1', 'id', 'reset', 'measure', 'barrier', 'cx'}.
INFO:qiskit.transpiler.passes.basis.basis_translator:Basis translation path search completed in 0.000s.
INFO:qiskit.transpiler.passes.basis.basis_translator:Basis translation paths composed in 0.001s.
INFO:qiskit.transpiler.passes.basis.basis_translator:Basis translation instructions replaced in 0.000s.
INFO:qiskit.transpiler.runningpassmanager:Pass: BasisTranslator - 10.78224 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CheckCXDirection - 0.07415 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXDirection - 0.56124 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: RemoveResetInZeroState - 0.01669 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Depth - 0.02933 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FixedPoint - 0.01597 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Optimize1qGates - 1.37687 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXCancellation - 0.05078 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Depth - 0.01979 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FixedPoint - 0.01216 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Optimize1qGates - 0.37575 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXCancellation - 0.04840 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Depth - 0.01812 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FixedPoint - 0.01264 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Optimize1qGates - 0.42629 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXCancellation - 0.04649 (ms)
INFO:qiskit.compiler.transpile:Total Transpile Time - 41.09144 (ms)
[31]:
<qiskit.circuit.quantumcircuit.QuantumCircuit at 0x7fd575448760>

Setting up logging to deal with parallel execution

When running the transpiler with multiple circuits by default these circuits are transpiled in parallel. If you want to do this with logging enabled and be able to understand the output some additional steps are required.

If you were just to enable logging as above and then pass transpile() multiple circuits you’ll get results that are difficult to decipher. For example:

[32]:
# Change log level back to DEBUG
logging.getLogger('qiskit.transpiler').setLevel('DEBUG')
# Transpile multiple circuits
circuits = [log_circ, log_circ]
transpile(circuits, backend);
INFO:qiskit.transpiler.runningpassmanager:Pass: SetLayout - 0.01502 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: SetLayout - 0.00930 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: TrivialLayout - 0.17929 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Layout2qDistance - 0.82278 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: TrivialLayout - 0.14710 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FullAncillaAllocation - 0.22602 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: EnlargeWithAncilla - 0.10324 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: ApplyLayout - 0.59628 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Layout2qDistance - 0.82469 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Unroll3qOrMore - 0.02289 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FullAncillaAllocation - 0.14639 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: EnlargeWithAncilla - 0.10276 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: ApplyLayout - 0.50688 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CheckMap - 0.02980 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Unroll3qOrMore - 0.02265 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CheckMap - 0.05388 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: UnrollCustomDefinitions - 0.13757 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: UnrollCustomDefinitions - 0.14567 (ms)
INFO:qiskit.transpiler.passes.basis.basis_translator:Begin BasisTranslator from source basis {('x', 1), ('h', 1), ('cx', 2), ('measure', 1)} to target basis {'u2', 'u3', 'snapshot', 'delay', 'u1', 'id', 'reset', 'measure', 'barrier', 'cx'}.
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Begining basis search from frozenset({('x', 1), ('h', 1), ('cx', 2), ('measure', 1)}) to frozenset({'u2', 'u3', 'snapshot', 'delay', 'reset', 'u1', 'id', 'measure', 'barrier', 'cx'}).
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Inspecting basis frozenset({('x', 1), ('h', 1), ('cx', 2), ('measure', 1)}).
INFO:qiskit.transpiler.passes.basis.basis_translator:Begin BasisTranslator from source basis {('x', 1), ('h', 1), ('cx', 2), ('measure', 1)} to target basis {'u2', 'u3', 'snapshot', 'delay', 'u1', 'id', 'reset', 'measure', 'barrier', 'cx'}.
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Inspecting basis frozenset({('h', 1), ('cx', 2), ('measure', 1), ('u3', 1)}).
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Begining basis search from frozenset({('x', 1), ('h', 1), ('cx', 2), ('measure', 1)}) to frozenset({'u2', 'u3', 'snapshot', 'delay', 'reset', 'u1', 'id', 'measure', 'barrier', 'cx'}).
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Inspecting basis frozenset({('x', 1), ('h', 1), ('cx', 2), ('measure', 1)}).
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Inspecting basis frozenset({('h', 1), ('cx', 2), ('measure', 1), ('u3', 1)}).
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Transformation path:
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Transformation path:
DEBUG:qiskit.transpiler.passes.basis.basis_translator:x/1 => []
     ┌───────────┐
q_0: ┤ U3(π,0,π) ├
     └───────────┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:x/1 => []
     ┌───────────┐
q_0: ┤ U3(π,0,π) ├
     └───────────┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:h/1 => []
     ┌─────────┐
q_0: ┤ U2(0,π) ├
     └─────────┘
INFO:qiskit.transpiler.passes.basis.basis_translator:Basis translation path search completed in 0.021s.
DEBUG:qiskit.transpiler.passes.basis.basis_translator:h/1 => []
     ┌─────────┐
q_0: ┤ U2(0,π) ├
     └─────────┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Composing transform step: x/1 [] =>
     ┌───────────┐
q_0: ┤ U3(π,0,π) ├
     └───────────┘
INFO:qiskit.transpiler.passes.basis.basis_translator:Basis translation path search completed in 0.022s.
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Updating transform for mapped instr ('x', 1) x, [] from
        ┌───┐
q311_0: ┤ x ├
        └───┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Composing transform step: x/1 [] =>
     ┌───────────┐
q_0: ┤ U3(π,0,π) ├
     └───────────┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Updated transform for mapped instr ('x', 1) x, [] to
        ┌───────────┐
q311_0: ┤ U3(π,0,π) ├
        └───────────┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Updating transform for mapped instr ('x', 1) x, [] from
        ┌───┐
q311_0: ┤ x ├
        └───┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Composing transform step: h/1 [] =>
     ┌─────────┐
q_0: ┤ U2(0,π) ├
     └─────────┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Updated transform for mapped instr ('x', 1) x, [] to
        ┌───────────┐
q311_0: ┤ U3(π,0,π) ├
        └───────────┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Updating transform for mapped instr ('h', 1) h, [] from
        ┌───┐
q312_0: ┤ h ├
        └───┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Composing transform step: h/1 [] =>
     ┌─────────┐
q_0: ┤ U2(0,π) ├
     └─────────┘
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Updated transform for mapped instr ('h', 1) h, [] to
        ┌─────────┐
q312_0: ┤ U2(0,π) ├
        └─────────┘
INFO:qiskit.transpiler.passes.basis.basis_translator:Basis translation paths composed in 0.026s.
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Updating transform for mapped instr ('h', 1) h, [] from
        ┌───┐
q312_0: ┤ h ├
        └───┘
INFO:qiskit.transpiler.passes.basis.basis_translator:Basis translation instructions replaced in 0.000s.
DEBUG:qiskit.transpiler.passes.basis.basis_translator:Updated transform for mapped instr ('h', 1) h, [] to
        ┌─────────┐
q312_0: ┤ U2(0,π) ├
        └─────────┘
INFO:qiskit.transpiler.runningpassmanager:Pass: BasisTranslator - 62.38842 (ms)
INFO:qiskit.transpiler.passes.basis.basis_translator:Basis translation paths composed in 0.031s.
INFO:qiskit.transpiler.runningpassmanager:Pass: CheckCXDirection - 0.12040 (ms)
INFO:qiskit.transpiler.passes.basis.basis_translator:Basis translation instructions replaced in 0.000s.
INFO:qiskit.transpiler.runningpassmanager:Pass: CXDirection - 0.92316 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: BasisTranslator - 67.78598 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: RemoveResetInZeroState - 0.03314 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CheckCXDirection - 0.08392 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Depth - 0.05960 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FixedPoint - 0.04530 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXDirection - 0.66137 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: RemoveResetInZeroState - 0.03242 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Optimize1qGates - 2.46263 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXCancellation - 0.06342 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Depth - 0.04363 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Depth - 0.03791 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FixedPoint - 0.01264 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Optimize1qGates - 0.44870 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FixedPoint - 0.02718 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXCancellation - 0.04864 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Depth - 0.01955 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FixedPoint - 0.01216 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Optimize1qGates - 2.10500 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Optimize1qGates - 0.45228 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXCancellation - 0.06127 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXCancellation - 0.06890 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Depth - 0.02146 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FixedPoint - 0.01383 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Optimize1qGates - 0.49329 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXCancellation - 0.06056 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Depth - 0.02813 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: FixedPoint - 0.01216 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: Optimize1qGates - 0.44131 (ms)
INFO:qiskit.transpiler.runningpassmanager:Pass: CXCancellation - 0.04983 (ms)
INFO:qiskit.compiler.transpile:Total Transpile Time - 196.85435 (ms)
[32]:
[<qiskit.circuit.quantumcircuit.QuantumCircuit at 0x7fd57542b430>,
 <qiskit.circuit.quantumcircuit.QuantumCircuit at 0x7fd57542b6d0>]

As you can see here we get log messages from all 3 circuits being transpiled together. There is no way to know which pass is part of which circuit’s transpilation. Luckily Python logging provides tools to deal with this. The simplest one is to just change the log formatter so that includes additional information so we can associate a log message with the process it came from.

[33]:
formatter = logging.Formatter('%(name)s - %(processName)-10s - %(levelname)s: %(message)s')
handler = logging.getLogger().handlers[0]
handler.setFormatter(formatter)

Then rerun the transpile() call and see the new log formatter.

[34]:
transpile(circuits, backend);
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: SetLayout - 0.01097 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: SetLayout - 0.01001 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: TrivialLayout - 0.13733 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: Layout2qDistance - 0.78940 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: TrivialLayout - 0.11492 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: FullAncillaAllocation - 0.17428 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: Layout2qDistance - 0.82016 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: FullAncillaAllocation - 0.15616 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: EnlargeWithAncilla - 0.12851 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: EnlargeWithAncilla - 0.19670 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: ApplyLayout - 0.49329 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: ApplyLayout - 0.59509 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: Unroll3qOrMore - 0.02670 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: Unroll3qOrMore - 0.02098 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: CheckMap - 0.03052 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: CheckMap - 0.02885 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: UnrollCustomDefinitions - 0.17023 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: UnrollCustomDefinitions - 0.19956 (ms)
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - INFO: Begin BasisTranslator from source basis {('x', 1), ('h', 1), ('cx', 2), ('measure', 1)} to target basis {'u2', 'u3', 'snapshot', 'delay', 'u1', 'id', 'reset', 'measure', 'barrier', 'cx'}.
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - INFO: Begin BasisTranslator from source basis {('x', 1), ('h', 1), ('cx', 2), ('measure', 1)} to target basis {'u2', 'u3', 'snapshot', 'delay', 'u1', 'id', 'reset', 'measure', 'barrier', 'cx'}.
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - DEBUG: Begining basis search from frozenset({('x', 1), ('h', 1), ('cx', 2), ('measure', 1)}) to frozenset({'u2', 'u3', 'snapshot', 'delay', 'reset', 'u1', 'id', 'measure', 'barrier', 'cx'}).
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - DEBUG: Begining basis search from frozenset({('x', 1), ('h', 1), ('cx', 2), ('measure', 1)}) to frozenset({'u2', 'u3', 'snapshot', 'delay', 'reset', 'u1', 'id', 'measure', 'barrier', 'cx'}).
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - DEBUG: Inspecting basis frozenset({('x', 1), ('h', 1), ('cx', 2), ('measure', 1)}).
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - DEBUG: Inspecting basis frozenset({('x', 1), ('h', 1), ('cx', 2), ('measure', 1)}).
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - DEBUG: Inspecting basis frozenset({('h', 1), ('cx', 2), ('measure', 1), ('u3', 1)}).
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - DEBUG: Inspecting basis frozenset({('h', 1), ('cx', 2), ('measure', 1), ('u3', 1)}).
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - DEBUG: Transformation path:
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - DEBUG: Transformation path:
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - DEBUG: x/1 => []
     ┌───────────┐
q_0: ┤ U3(π,0,π) ├
     └───────────┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - DEBUG: x/1 => []
     ┌───────────┐
q_0: ┤ U3(π,0,π) ├
     └───────────┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - DEBUG: h/1 => []
     ┌─────────┐
q_0: ┤ U2(0,π) ├
     └─────────┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - INFO: Basis translation path search completed in 0.018s.
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - DEBUG: h/1 => []
     ┌─────────┐
q_0: ┤ U2(0,π) ├
     └─────────┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - DEBUG: Composing transform step: x/1 [] =>
     ┌───────────┐
q_0: ┤ U3(π,0,π) ├
     └───────────┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - INFO: Basis translation path search completed in 0.024s.
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - DEBUG: Updating transform for mapped instr ('x', 1) x, [] from
        ┌───┐
q311_0: ┤ x ├
        └───┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - DEBUG: Composing transform step: x/1 [] =>
     ┌───────────┐
q_0: ┤ U3(π,0,π) ├
     └───────────┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - DEBUG: Updated transform for mapped instr ('x', 1) x, [] to
        ┌───────────┐
q311_0: ┤ U3(π,0,π) ├
        └───────────┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - DEBUG: Updating transform for mapped instr ('x', 1) x, [] from
        ┌───┐
q311_0: ┤ x ├
        └───┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - DEBUG: Composing transform step: h/1 [] =>
     ┌─────────┐
q_0: ┤ U2(0,π) ├
     └─────────┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - DEBUG: Updated transform for mapped instr ('x', 1) x, [] to
        ┌───────────┐
q311_0: ┤ U3(π,0,π) ├
        └───────────┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - DEBUG: Composing transform step: h/1 [] =>
     ┌─────────┐
q_0: ┤ U2(0,π) ├
     └─────────┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - DEBUG: Updating transform for mapped instr ('h', 1) h, [] from
        ┌───┐
q312_0: ┤ h ├
        └───┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - DEBUG: Updated transform for mapped instr ('h', 1) h, [] to
        ┌─────────┐
q312_0: ┤ U2(0,π) ├
        └─────────┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - DEBUG: Updating transform for mapped instr ('h', 1) h, [] from
        ┌───┐
q312_0: ┤ h ├
        └───┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - INFO: Basis translation paths composed in 0.022s.
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-4 - INFO: Basis translation instructions replaced in 0.000s.
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - DEBUG: Updated transform for mapped instr ('h', 1) h, [] to
        ┌─────────┐
q312_0: ┤ U2(0,π) ├
        └─────────┘
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - INFO: Basis translation paths composed in 0.037s.
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: BasisTranslator - 59.69834 (ms)
qiskit.transpiler.passes.basis.basis_translator - ForkProcess-3 - INFO: Basis translation instructions replaced in 0.000s.
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: BasisTranslator - 63.03811 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: CheckCXDirection - 0.09751 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: CheckCXDirection - 0.08988 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: CXDirection - 0.74840 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: CXDirection - 0.73314 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: RemoveResetInZeroState - 0.05031 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: RemoveResetInZeroState - 0.03576 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: Depth - 0.07415 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: FixedPoint - 0.02694 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: Depth - 0.04077 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: FixedPoint - 0.02575 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: Optimize1qGates - 2.33030 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: Optimize1qGates - 2.13647 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: CXCancellation - 0.06938 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: CXCancellation - 0.07558 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: Depth - 0.02122 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: Depth - 0.06437 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: FixedPoint - 0.01550 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: FixedPoint - 0.01669 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: Optimize1qGates - 0.61536 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: Optimize1qGates - 0.52786 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: CXCancellation - 0.07105 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: CXCancellation - 0.07057 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: Depth - 0.02432 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: Depth - 0.02813 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: FixedPoint - 0.01383 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: Optimize1qGates - 0.49996 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: FixedPoint - 0.01478 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: Optimize1qGates - 0.48018 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-3 - INFO: Pass: CXCancellation - 0.08702 (ms)
qiskit.transpiler.runningpassmanager - ForkProcess-4 - INFO: Pass: CXCancellation - 0.04840 (ms)
qiskit.compiler.transpile - MainProcess - INFO: Total Transpile Time - 192.25025 (ms)
[34]:
[<qiskit.circuit.quantumcircuit.QuantumCircuit at 0x7fd574ea7610>,
 <qiskit.circuit.quantumcircuit.QuantumCircuit at 0x7fd574ea7e50>]

Now the format for the log messages has been changed and it includes a process name for each of the transpilation processes so it’s at least clear which log messages go together.

There are many different options for how you can configure, this example is pretty limited. Refer to the documentation for more examples and options to build more sophisticated use cases that suit your specific use case or preferences.

[35]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright

Version Information

Qiskit SoftwareVersion
Qiskit0.23.6
Terra0.16.4
Aer0.7.5
Ignis0.5.2
Aqua0.8.2
IBM Q Provider0.11.1
System information
Python3.8.7 (default, Jan 25 2021, 16:23:06) [GCC 9.3.0]
OSLinux
CPUs2
Memory (Gb)6.791378021240234
Sat Feb 27 17:25:03 2021 UTC

This code is a part of Qiskit

© Copyright IBM 2017, 2021.

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.

[ ]: