Source code for qibocal.auto.transpile

from typing import Optional

from qibo import Circuit
from qibo.backends.abstract import Backend
from qibo.transpiler.pipeline import Passes
from qibo.transpiler.unroller import NativeGates, Unroller
from qibolab.qubits import QubitId


[docs]def transpile_circuits( circuits: list[Circuit], qubit_maps: list[list[QubitId]], backend: Backend, transpiler: Optional[Passes], ): """Transpile and pad `circuits` according to the platform. Apply the `transpiler` to `circuits` and pad them in circuits with the same number of qubits in the platform. Before manipulating the circuits, this function check that the `qubit_maps` contain string ids and in the positive case it remap them in integers, following the ids order provided by the platform. .. note:: In this function we are implicitly assume that the qubit ids are all string or all integers. """ transpiled_circuits = [] qubits = list(backend.platform.qubits) if isinstance(qubit_maps[0][0], str): for i, qubit_map in enumerate(qubit_maps): qubit_map = map(lambda x: qubits.index(x), qubit_map) qubit_maps[i] = list(qubit_map) if backend.name == "qibolab": platform_nqubits = backend.platform.nqubits for circuit, qubit_map in zip(circuits, qubit_maps): new_circuit = pad_circuit(platform_nqubits, circuit, qubit_map) transpiled_circ, _ = transpiler(new_circuit) transpiled_circuits.append(transpiled_circ) else: transpiled_circuits = circuits return transpiled_circuits
[docs]def execute_transpiled_circuits( circuits: list[Circuit], qubit_maps: list[list[QubitId]], backend: Backend, transpiler: Optional[Passes], initial_states=None, nshots=1000, ): """Transpile `circuits`. If the `qibolab` backend is used, this function pads the `circuits` in new ones with a number of qubits equal to the one provided by the platform. At the end, the circuits are transpiled, executed and the results returned. The input `transpiler` is optional, but it should be provided if the backend is `qibolab`. For the qubit map look :func:`dummy_transpiler`. This function returns the list of transpiled circuits and the execution results. """ transpiled_circuits = transpile_circuits( circuits, qubit_maps, backend, transpiler, ) return transpiled_circuits, backend.execute_circuits( transpiled_circuits, initial_states=initial_states, nshots=nshots )
[docs]def execute_transpiled_circuit( circuit: Circuit, qubit_map: list[QubitId], backend: Backend, transpiler: Optional[Passes], initial_state=None, nshots=1000, ): """Transpile `circuit`. If the `qibolab` backend is used, this function pads the `circuit` in new a one with a number of qubits equal to the one provided by the platform. At the end, the circuit is transpiled, executed and the results returned. The input `transpiler` is optional, but it should be provided if the backend is `qibolab`. For the qubit map look :func:`dummy_transpiler`. This function returns the transpiled circuit and the execution results. """ transpiled_circ = transpile_circuits( [circuit], [qubit_map], backend, transpiler, )[0] return transpiled_circ, backend.execute_circuit( transpiled_circ, initial_state=initial_state, nshots=nshots )
[docs]def dummy_transpiler(backend) -> Optional[Passes]: """ If the backend is `qibolab`, a transpiler with just an unroller is returned, otherwise None. """ if backend.name == "qibolab": unroller = Unroller(NativeGates.default()) return Passes(connectivity=backend.platform.topology, passes=[unroller]) return None
[docs]def pad_circuit(nqubits, circuit: Circuit, qubit_map: list[int]) -> Circuit: """ Pad `circuit` in a new one with `nqubits` qubits, according to `qubit_map`. `qubit_map` is a list `[i, j, k, ...]`, where the i-th physical qubit is mapped into the 0th logical qubit and so on. """ new_circuit = Circuit(nqubits) new_circuit.add(circuit.on_qubits(*qubit_map)) return new_circuit