Transpiler
Graph-based approach to quantum program type conversions.
The qBraid-SDK transpiler allows converting quantum programs from one type to another, for any two program types for which
a “conversion path” exists. Registered program types are interconnected via a directed graph, where each program type is
represented as a node and supported conversions as edges. The breadth, depth, and connectivity of this ConversionGraph
can be customized by the user.
API Reference: qbraid.transpiler
Conversion Graph
To view what conversions are available, you can plot the ConversionGraph
:
from qbraid.transpiler import ConversionGraph
graph = ConversionGraph()
len(graph.nodes()) # 10
len(graph.edges()) # 25
graph.plot(legend=True)
Gray arrows denote conversions implemented and managed by qBraid. Red arrows represent conversions implemented by external packages or extensions. These are automatically incorporated into the conversion graph upon installing the specified ‘extra’.
You can use the native conversions supported by qBraid, or define your own custom nodes and/or edges. For example:
from unittest.mock import Mock
from qbraid.programs import register_program_type
from qbraid.transpiler import Conversion
# replace with any program type
register_program_type(Mock, alias="mock")
# replace with your custom conversion function
example_qasm3_to_mock_func = lambda x: x
conversion = Conversion("qasm3", "mock", example_qasm3_to_mock_func)
graph.add_conversion(conversion)
# using a seed is helpful to ensure reproducibility
graph.plot(seed=20, k=3, legend=True)
Blue arrows indicate conversions added by the user during their current session.
Check if a conversion is supported between two given program types, and if so, what “conversion path(s)” would be used:
>>> graph.has_path("qiskit", "braket")
True
>>> for p in graph.all_paths("qiskit", "braket"): print(p)
qiskit -> braket
qiskit -> qasm3 -> braket
qiskit -> qasm2 -> qasm3 -> braket
qiskit -> qasm2 -> pytket -> braket
qiskit -> qasm2 -> cirq -> braket
>>> graph.shortest_path("qiskit", "braket")
qiskit -> braket
Scope the conversions available to the transpiler by specifying your own conversions
list:
from qbraid.transpiler import ConversionGraph, Conversion
from qbraid.transpiler.conversions.qiskit import qiskit_to_braket
conv = Conversion("qiskit", "braket", qiskit_to_braket)
graph = ConversionGraph(conversions=[conv])
graph.all_paths("qiskit", "braket")
# ["qiskit -> qasm3 -> braket"]
Conversion Scheme
The ConversionScheme
data class details information about conversion configurations, such as numbers of nodes and edges, as well as max depth.
from qbraid.transpiler import ConversionGraph
from qbraid.transpiler.scheme import ConversionScheme
scheme = ConversionScheme(max_path_attempts=3, max_path_depth=None)
custom_graph = ConversionGraph(...)
scheme.update_scheme(conversion_graph=custom_graph)
scheme.to_dict()
Transpile
Using the qbraid.transpiler.transpile
method, simply pass in the name of the target package from one of qbraid.programs.QPROGRAM_ALIASES
. For example, use input "cirq"
to return a cirq.Circuit
:
from qiskit import QuantumCircuit
def bell():
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0,1)
return circuit
qiskit_circuit = bell()
from qbraid.transpiler import transpile
cirq_circuit = transpile(qiskit_circuit, "cirq")
print(cirq_circuit)
# q_0: ───H───@───
# │
# q_1: ───────X───
This time, using the same origin circuit, we’ll input "pyquil"
to return a pyquil.quil.Program
:
pyquil_program = transpile(qiskit_circuit, "pyquil")
print(pyquil_program)
# H 0
# CNOT 0 1