Transforms
Adapt quantum programs to specific hardware requirements.
In the qBraid-SDK, a “transpile” action refers to converting a quantum program from one type to another, such as from Qiskit to Amazon Braket. In contrast, a “transform” action involves modifying a quantum program to meet specific requirements dictated by the target device or API through which the program will be executed.
Let’s delve into the various “transforms” employed to prepare a quantum program for execution on an IonQ backend.
We begin by constructing a simple Qiskit circuit that executes a controlled Y rotation:
import numpy as np
from qiskit import QuantumCircuit
circuit = QuantumCircuit(2, 2)
circuit.cry(np.pi/4, 0, 1)
circuit.measure_all()
We then connect to the IonQProvider
and retrieve the specifications for the IonQ Harmony device:
from qbraid.runtime.ionq import IonQProvider
provider = IonQProvider()
device = provider.get_device("qpu.harmony")
device.profile.get("program_spec")
# <ProgramSpec('openqasm3', openqasm3.ast.Program)>
device.profile.get("basis_gates")
# { "x","y","z","rx","ry","rz","h","cx","s","sdg","t","tdg","sx","sxdg","swap" }
By reviewing the device’s TargetProfile
, we understand that in order to run a program on IonQ Harmony,
qBraid runtime requires that it be expressed as an openqasm3.ast.Program
and utilize only the gates from
its defined basis gate set. Consequently, our first step is to transpile our qiskit
program to the openqasm3
program type:
from qbraid.transpiler import transpile
qasm3_program = transpile(circuit, 'openqasm3')
type(qasm3_program)
# openqasm3.ast.Program
Next, we load the program into a qBraid QuantumProgram
object and examine its string representation:
>>> from qbraid.programs import load_program
>>> qprogram = load_program(qasm3_program)
>>> print(qprogram.program)
OPENQASM 3.0;
include "stdgates.inc";
bit[2] c;
bit[2] meas;
qubit[2] q;
cry(pi / 4) q[0], q[1];
barrier q[0], q[1];
meas[0] = measure q[0];
meas[1] = measure q[1];
We can now apply a “transform” to this program, using our device object as argument, ensuring it is represented exclusively in terms of gates supported by IonQ Harmony:
>>> program.transform(device)
>>> print(program.program)
OPENQASM 3.0;
bit[2] b;
qubit[2] q;
ry(0.39269908169872414) q[1];
cx q[0], q[1];
ry(-0.39269908169872414) q[1];
cx q[0], q[1];
b[0] = measure q[0];
b[1] = measure q[1];
Device-specific transforms are a crucial component of the qBraid runtime framework, applied as the final step before a program is executed on a quantum backend.
We’ve just demonstrated how one can utilize these transforms independently, outside of a runtime protocol, which
may be beneficial for testing or local simulations. However, for qBraid runtime end-users, these steps are automatically
performed behind the scenes whenever the QuantumDevice.run
method is invoked.