Routing on a device
In many quantum computing architectures, not all qubits are directly connected, meaning that operations between distant qubits must be routed through intermediate qubits. This is accomplished by inserting SWAP operations between qubits in a circuit.
The SingleOperationSwapRouter
Converter
pyqonvert
provides the SingleOperationSwapRouter
Converter that inserts SWAP operations into a quantum circuit or QuantumProgram to enable operations on devices with limited connectivity.
Initalizing the SingleOperationSwapRouter
Class.
The SingleOperationSwapRouter
class is imported from the pyqonvert.routing
module.
Parameters
swap_back
- if set toTrue
, additional SWAP operations are inserted to retrieve the original layout.only_before_decomposition
- if set toTrue
, SWAPS are only inserted outside of decomposition blocks. This option comes in handy during noise mapping which extensively makes use of decomposition blocks. Naively routing together with noise mapping requires a large number of SWAPs contributing to additional complexity. To minimize the number of SWAPs and allow for remapping without disrupting noise mapping, SWAPs are strategically inserted only before decomposition blocks that involve one or two qubits. To learn more about noise mapping, refer to this research article.
Note that when using setting only_before_decomposition=True
, not all operations in the circuit (especially decomposition blocks involving more qubits in the first place) are routed. For full routing, a second pass with swap_back=True
is necessary.
from pyqonvert.routing import SingleOperationSwapRouter
# initialize converter
noise_inserter = SingleOperationSwapRouter(
swap_back=True,
only_before_decomposition=False,
)
# Ready to use for routing.
Examples
Here is a simple example showing the functionality of the routing converter.
from pyqonvert.routing import SingleOperationSwapRouter
from qoqo import devices, Circuit
from qoqo import operations as ops
router = SingleOperationSwapRouter(True, False)
# Initialize device
number_qubits = 3
device = devices.GenericDevice(number_qubits)
device.set_two_qubit_gate_time("CNOT", 0, 1, 1.0)
device.set_two_qubit_gate_time("CNOT", 1, 0, 1.0)
device.set_two_qubit_gate_time("CNOT", 1, 2, 1.0)
device.set_two_qubit_gate_time("CNOT", 2, 1, 1.0)
# initialize circuit
circuit = Circuit()
circuit += ops.CNOT(0,2)
circuit += ops.PragmaRepeatedMeasurement("ro", 10)
# Routing
circuit = router.convert(circuit, device, [])
Figure 1: SWAP gates insertions in a circuit for routing over a device of linear topology.
The following example shows how only_before_decomposition
flag functions.
from pyqonvert.routing import SingleOperationSwapRouter
from qoqo import devices, Circuit
from qoqo import operations as ops
router = SingleOperationSwapRouter(False, True)
# Initialize device
number_qubits = 3
device = devices.GenericDevice(number_qubits)
device.set_two_qubit_gate_time("CNOT", 0, 1, 1.0)
device.set_two_qubit_gate_time("CNOT", 1, 0, 1.0)
device.set_two_qubit_gate_time("CNOT", 1, 2, 1.0)
device.set_two_qubit_gate_time("CNOT", 2, 1, 1.0)
# Initialize circuit
circuit = Circuit()
map = {0: 2, 2:0}
circuit += ops.PragmaStartDecompositionBlock([0, 2], map)
circuit += ops.CNOT(0, 2)
circuit += ops.CNOT(2, 0)
circuit += ops.PragmaStopDecompositionBlock([0, 2])
circuit += ops.PragmaStartDecompositionBlock([0, 1, 2], {})
circuit += ops.CNOT(1, 2)
circuit += ops.PragmaStopDecompositionBlock([0, 1, 2])
# Routing
circuit = router.convert(circuit, device, [])
Figure 2: SWAP gates are added outside of the original decomposition blocks when only_before_decomposition = True
.