Prev Tutorial: Noise
Next Tutorial: Quantum Intermediate Compiler
Transpiler Module Tutorial
This tutorial provides an overview of the functionalities available in the Transpiler module, which includes generating circuit topologies, transpiling quantum programs, and decomposing quantum circuits. These operations are essential for optimizing and adapting quantum algorithms to specific hardware architectures.
1. Overview
The Transpiler
module is designed to facilitate the preparation of quantum programs for execution by generating topologies, transpiling programs to fit specific architectures, and decomposing circuits into simpler components.
2. Functions and Classes
2.1 Transpiler Class
The Transpiler class is responsible for transpiling quantum programs to fit a specific topology and optimization level.
Constructor
Initializes a new instance of the Transpiler class.
Here is an example of how to constructor Transpiler
.
Python
transpiler = Transpiler()
Definition transpilation.py:1
Methods
transpile
transpile is an interface used to compile a quantum program (QProg) onto a specified backend topology through multiple compilation processes (passes). This process usually includes the following steps:
- Optimizing quantum circuits: By using different optimization strategies, the number and complexity of quantum gates can be reduced, thereby improving the execution efficiency of quantum programs.
- Mapping to a specified topology: Based on the topology of the target quantum computer, map qubits to actual physical qubits. This step takes into account the connection limitations of quantum computers, ensuring that quantum gates are physically achievable.
- Transform quantum gates: Convert high-level quantum gates in a quantum subroutine into low-level gates supported by the target hardware. This may involve the decomposition of some gates to adapt to the capabilities of the target hardware
- Note
- Chip Topology edges: If
chip_topology_edges
is empty, the layoutPass
and routingPass
will be skipped during the transpilation process. This can affect the optimization and performance of the resulting circuit, so it is important to provide a valid chip topology when applicable.
- Optimization Levels:
0
: No optimization is performed.
1
: Basic optimizations are applied, including simple two-qubit gate cancellation and single-qubit gate merging.
2
: Advanced optimizations are performed, including matrix optimization, two-qubit gate cancellation, and single-qubit gate merging.
Here is an example of how to use the Transpiler
class to transpile a quantum circuit:
Python
prog_1 = QProg()
prog_1 << H(0) << RX(0, 1.25) << CNOT(0, 1) << U1(1, 0.0001) << CNOT(0, 1) << CNOT(1, 2)
for i in range(3):
prog_1.append(measure(i, i))
print('prog: \n', draw_qprog(prog_1))
topo = generate_topology(20, "square")
transpiler = Transpiler()
prog_level_0 = transpiler.transpile(prog_1, topo, {}, 0)
prog_level_1 = transpiler.transpile(prog_1, topo, {}, 1)
prog_level_2 = transpiler.transpile(prog_1, topo, {}, 2)
print('Transpiler lavel 0: \n', draw_qprog(prog_level_0))
print('Transpiler lavel 1: \n', draw_qprog(prog_level_1))
print('Transpiler lavel 2: \n',draw_qprog(prog_level_2))
Run result:
prog:
┌─┐ ┌──┐ ┌─┐
q_0: |0>─┤H├ ┤RX├ ───*── ──── ───*── ───────┤M├ ───────
└─┘ └──┘ ┌──┴─┐ ┌──┐ ┌──┴─┐ └╥┘ ┌─┐
q_1: |0>──── ──── ┤CNOT├ ┤U1├ ┤CNOT├ ───*────╫─ ─┤M├───
└────┘ └──┘ └────┘ ┌──┴─┐ ║ └╥┘┌─┐
q_2: |0>──── ──── ────── ──── ────── ┤CNOT├──╫─ ──╫─┤M├
└────┘ ║ ║ └╥┘
c : / ═════════════════════════════════════╩════╩══╩═
0 1 2
Transpiler lavel 0:
┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌─┐ >
q_0: |0>─┤RZ├ ┤X1├ ┤RZ├ ┤RZ├ ┤X1├ ┤RZ├ ┤X1├ ┤RZ├ ──*─ ──── ──── ──── ──── ──── ──── ──── ──*─ ─────┤M├ >
├──┤ ├──┤ ├──┤ └──┘ └──┘ └──┘ └──┘ └──┘ ┌─┴┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌─┴┐ ┌──┐ └╥┘ >
q_1: |0>─┤RZ├ ┤X1├ ┤RZ├ ──── ──── ──── ──── ──── ┤CZ├ ┤RZ├ ┤X1├ ┤RZ├ ┤RZ├ ┤RZ├ ┤X1├ ┤RZ├ ┤CZ├ ┤RZ├──╫─ >
├──┤ ├──┤ ├──┤ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ ║ >
q_2: |0>─┤RZ├ ┤X1├ ┤RZ├ ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──────╫─ >
└──┘ └──┘ └──┘ ║ >
c : / ════════════════════════════════════════════════════════════════════════════════════════════╩═
0
q_0: |0>──── ──── ──── ──────── ──── ──── ────
┌──┐ ┌──┐ ┌─┐
q_1: |0>┤X1├ ┤RZ├ ──*─ ─────┤M├ ──── ──── ────
└──┘ └──┘ ┌─┴┐ ┌──┐ └╥┘ ┌──┐ ┌──┐ ┌─┐
q_2: |0>──── ──── ┤CZ├ ┤RZ├──╫─ ┤X1├ ┤RZ├ ─┤M├
└──┘ └──┘ ║ └──┘ └──┘ └╥┘
c : / ═════════════════════╩══════════════╩═
1 2
Transpiler lavel 1:
┌──┐ ┌──┐ ┌──┐ ┌─┐ >
q_0: |0>─┤RZ├ ┤X1├ ┤RZ├ ──*─ ──── ──── ──── ──── ──── ──── ──── ──*─ ─────┤M├ ──── ──── ──── ──────── >
├──┤ ├──┤ ├──┤ ┌─┴┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌─┴┐ ┌──┐ └╥┘ ┌──┐ ┌──┐ ┌─┐ >
q_1: |0>─┤RZ├ ┤X1├ ┤RZ├ ┤CZ├ ┤RZ├ ┤X1├ ┤RZ├ ┤RZ├ ┤RZ├ ┤X1├ ┤RZ├ ┤CZ├ ┤RZ├──╫─ ┤X1├ ┤RZ├ ──*─ ─────┤M├ >
├──┤ ├──┤ ├──┤ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ ║ └──┘ └──┘ ┌─┴┐ ┌──┐ └╥┘ >
q_2: |0>─┤RZ├ ┤X1├ ┤RZ├ ──── ──── ──── ──── ──── ──── ──── ──── ──── ──────╫─ ──── ──── ┤CZ├ ┤RZ├──╫─ >
└──┘ └──┘ └──┘ ║ └──┘ └──┘ ║ >
c : / ═══════════════════════════════════════════════════════════════════╩═══════════════════════╩═
0 1
q_0: |0>──── ──── ────
q_1: |0>──── ──── ────
┌──┐ ┌──┐ ┌─┐
q_2: |0>┤X1├ ┤RZ├ ─┤M├
└──┘ └──┘ └╥┘
c : / ════════════╩═
2
Transpiler lavel 2:
┌──┐ ┌──┐ ┌──┐ ┌─┐
q_0: |0>─┤RZ├ ┤X1├ ┤RZ├ ─────┤M├ ──────── ──── ──── ────
├──┤ └──┘ └──┘ └╥┘ ┌─┐
q_1: |0>─┤RZ├ ──── ──── ──*───╫─ ─────┤M├ ──── ──── ────
├──┤ ┌──┐ ┌──┐ ┌─┴┐ ║ ┌──┐ └╥┘ ┌──┐ ┌──┐ ┌─┐
q_2: |0>─┤RZ├ ┤X1├ ┤RZ├ ┤CZ├──╫─ ┤RZ├──╫─ ┤X1├ ┤RZ├ ─┤M├
└──┘ └──┘ └──┘ └──┘ ║ └──┘ ║ └──┘ └──┘ └╥┘
c : / ══════════════════════╩════════╩══════════════╩═
0 1 2
If the chip_topology_edges
parameters are not passed, routing pass will be skipped.
Python
prog_2 = transpiler.transpile(prog_1, init_mapping ={}, optimization_level = 2)
print('no chip_topology_edges prog: \n',draw_qprog(prog_2))
Run result:
no chip_topology_edges prog:
┌──┐ ┌──┐ ┌──┐ ┌─┐
q_0: |0>─┤RZ├ ┤X1├ ┤RZ├ ─────┤M├ ──────── ──── ──── ────
├──┤ └──┘ └──┘ └╥┘ ┌─┐
q_1: |0>─┤RZ├ ──── ──── ──*───╫─ ─────┤M├ ──── ──── ────
├──┤ ┌──┐ ┌──┐ ┌─┴┐ ║ ┌──┐ └╥┘ ┌──┐ ┌──┐ ┌─┐
q_2: |0>─┤RZ├ ┤X1├ ┤RZ├ ┤CZ├──╫─ ┤RZ├──╫─ ┤X1├ ┤RZ├ ─┤M├
└──┘ └──┘ └──┘ └──┘ ║ └──┘ ║ └──┘ └──┘ └╥┘
c : / ══════════════════════╩════════╩══════════════╩═
0 1 2
If the init_mappings parameter is passed in, then routingPasses will be performed based on init_mappings.
Python
init_mapping = {0:2, 1:1, 2:0}
prog_3 = transpiler.transpile(prog_1, topo, init_mapping=init_mapping, optimization_level = 2)
print('init_mapping prog: \n',draw_qprog(prog_3))
Run result:
init_mapping prog:
┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌─┐
q_0: |0>─┤RZ├ ┤X1├ ┤RZ├ ┤CZ├ ┤RZ├ ┤X1├ ┤RZ├ ─┤M├
├──┤ └──┘ └──┘ └─┬┘ └┬─┤ └──┘ └──┘ └╥┘
q_1: |0>─┤RZ├ ──── ──── ──*─ ─┤M├ ──── ──── ──╫─
├──┤ ┌──┐ ┌──┐ ┌─┐ └╥┘ ║
q_2: |0>─┤RZ├ ┤X1├ ┤RZ├ ─┤M├ ──╫─ ──── ──── ──╫─
└──┘ └──┘ └──┘ └╥┘ ║ ║
c : / ══════════════════╩════╩══════════════╩═
0 1 2
2.2 generate_topology
generate_topology generates the topology for quantum circuits based on specified parameters.
2.3 decompose
The decompose function can be used to break down quantum programs and circuits into their constituent parts.
Here is an example of how to use the decompose
function:
Python
decomposed_prog = decompose(prog_1)
print('decomposed prog: \n',draw_qprog(decomposed_prog))
circuit = QCircuit()
circuit << H(0) << RX(0, 1.25) << CNOT(0, 1) << U1(1, 0.0001) << CNOT(0, 1) << CNOT(1, 2)
decomposed_circuit = decompose(circuit)
Run result:
decomposed prog:
┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌─┐ >
q_0: |0>─┤RZ├ ┤X1├ ┤RZ├ ┤RZ├ ┤X1├ ┤RZ├ ┤X1├ ┤RZ├ ──*─ ──── ──── ──── ──── ──── ──── ──── ──*─ ─────┤M├ >
├──┤ ├──┤ ├──┤ └──┘ └──┘ └──┘ └──┘ └──┘ ┌─┴┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌─┴┐ ┌──┐ └╥┘ >
q_1: |0>─┤RZ├ ┤X1├ ┤RZ├ ──── ──── ──── ──── ──── ┤CZ├ ┤RZ├ ┤X1├ ┤RZ├ ┤RZ├ ┤RZ├ ┤X1├ ┤RZ├ ┤CZ├ ┤RZ├──╫─ >
├──┤ ├──┤ ├──┤ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ └──┘ ║ >
q_2: |0>─┤RZ├ ┤X1├ ┤RZ├ ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──────╫─ >
└──┘ └──┘ └──┘ ║ >
c : / ════════════════════════════════════════════════════════════════════════════════════════════╩═
0
q_0: |0>──── ──── ──── ──────── ──── ──── ────
┌──┐ ┌──┐ ┌─┐
q_1: |0>┤X1├ ┤RZ├ ──*─ ─────┤M├ ──── ──── ────
└──┘ └──┘ ┌─┴┐ ┌──┐ └╥┘ ┌──┐ ┌──┐ ┌─┐
q_2: |0>──── ──── ┤CZ├ ┤RZ├──╫─ ┤X1├ ┤RZ├ ─┤M├
└──┘ └──┘ ║ └──┘ └──┘ └╥┘
c : / ═════════════════════╩══════════════╩═
1 2