from qat.interop.qiskit import qlm_to_qiskit
from qat.lang.AQASM import Program
from qat.lang.AQASM.gates import H, CNOT
nbqubits = 2
prog = Program()
qreg = prog.qalloc(nbqubits)
creg = prog.calloc(nbqubits)
prog.apply(H, qreg[0])
prog.apply(CNOT, qreg[0], qreg[1])
prog.measure(qreg, creg)
qlm_circuit = prog.to_circ()
# Conversion
qiskit_circuit = qlm_to_qiskit(qlm_circuit)
print(qiskit_circuit)
This conversion is going to be similar with every other language, the function qiskit_to_qlm
is going to be the same for
the other languages with two parameters: the circuit, and a boolean sep_measure
if set to True
it will return the qubits
to measure separately for the user to measure them manually.
A tuple of 2 elements is then returned, the first element is the circuit with no measures, the second one is a list containing the qubits to be measured.
If set to False
(which is the default value) only the QLM circuit will be returned (with measures included inside the circuit).
from qat.interop.qiskit import qiskit_to_qlm
from qiskit import QuantumRegister, QuantumCircuit, ClassicalRegister
from qat.core.util import get_syntax
nbqubits = 2
qreg = QuantumRegister(nbqubits)
creg = ClassicalRegister(nbqubits)
qiskit_circuit = QuantumCircuit(qreg, creg)
qiskit_circuit.h(qreg[0])
qiskit_circuit.cx(qreg[0], qreg[1])
qiskit_circuit.measure(qreg, creg)
# get result with included measures
qlm_circuit = qiskit_to_qlm(qiskit_circuit)
for index, op in enumerate(qlm_circuit.ops):
print("Gate {} with params {} on qubits {} and cbits {}".format(*get_syntax(qlm_circuit, index), op.cbits))
# get result with separated measures
print("---------------------------------------------------------")
qlm_circuit, to_measure = qiskit_to_qlm(qiskit_circuit, sep_measures=True)
for index, op in enumerate(qlm_circuit.ops):
print("Gate {} with params {} on qubits {}".format(*get_syntax(qlm_circuit, index)))
print("qubits to measure {}".format(to_measure))
A wrapper implementing QPUHandler
in order to run synchronous QLM circuits in qiskit backends seamlessly and without any hassle
from qat.interop.qiskit import BackendToQPU
from qiskit import Aer
from qat.lang.AQASM import Program
from qat.lang.AQASM.gates import *
nbqubits = 2
prog = Program()
qreg = prog.qalloc(nbqubits)
creg = prog.calloc(nbqubits)
prog.apply(H, qreg[0])
prog.apply(CNOT, qreg[0], qreg[1])
prog.measure(qreg, creg)
qlm_circuit = prog.to_circ()
qlm_job = qlm_circuit.to_job(nbshots=1024)
# Building a default BackendToQPU that's going to use qiskit's "qasm_simulator" if it couldn't connect
# to IBMQ using a token
qpu = BackendToQPU()
result = qpu.submit(qlm_job)
for entry in result.raw_data:
print("State: {}\t probability: {}".format(entry.state, entry.probability))
We can also have the same thing but this time with an asynchronous qiskit qpu, this won't have the same interface as Qiskit,
but it will have the same interface as our QLM Asyncjob
from qat.interop.qiskit import AsyncBackendToQPU
from qiskit import Aer
from qat.lang.AQASM import Program
from qat.lang.AQASM.gates import *
import time
nbqubits = 2
prog = Program()
qreg = prog.qalloc(nbqubits)
creg = prog.calloc(nbqubits)
prog.apply(H, qreg[0])
prog.apply(CNOT, qreg[0], qreg[1])
prog.measure(qreg, creg)
qlm_circuit = prog.to_circ()
qlm_job = qlm_circuit.to_job(nbshots=1024)
# Building a default AsyncBackendToQPU that's going to use qiskit's "qasm_simulator" if it couldn't connect
# to IBMQ using a token
qpu = AsyncBackendToQPU()
async_job = qpu.submit(qlm_job)
print("ID: {}\t status : {}".format(async_job.job_id(), async_job.status()))
time.sleep(0.01)
print("ID: {}\t status : {}".format(async_job.job_id(), async_job.status()))
time.sleep(0.2)
print("ID: {}\t status : {}".format(async_job.job_id(), async_job.status()))
while async_job.result() is None:
time.sleep(5)
result = async_job.result()
for entry in result.raw_data:
print("State: {}\t probability: {}".format(entry.state, entry.probability))
We have implemented a qiskit style backend, that can be plugged seamlessly into qiskit's ecosystem. With this you can simulate qiskit circuits with any simulator you want that's available in the QLM (this of course includes other simulators like pyquil).
from qat.interop.qiskit import QPUToBackend
from qat.qpus import PyLinalg
from qiskit import QuantumRegister, QuantumCircuit, ClassicalRegister, execute, Aer
from qat.comm.shared.ttypes import Batch
nbqubits = 2
qreg = QuantumRegister(nbqubits)
creg = ClassicalRegister(nbqubits)
qiskit_circuit = QuantumCircuit(qreg, creg)
qiskit_circuit.h(qreg[0])
qiskit_circuit.cx(qreg[0], qreg[1])
qiskit_circuit.measure(qreg, creg)
qpu = PyLinalg()
backend = QPUToBackend(qpu)
result = execute(qiskit_circuit, backend, shots=15).result()
print(result.results)
!export QVM_PATH=/my/path/forest-sdk_2.7.0-linux-barebones/; LD_LIBRARY_PATH=$QVM_PATH $QVM_PATH/qvm -S --skip-version-check -p 17701
Let us put what we hypothesized earlier to the test, this time instead of using a native QLM simulator, we will use PyquilQPU
the qpu wrapper around pyquil's qvm. QiskitConnector
is an object that is used in the same way as a QLM plugin, and yields a QPUToBackend object when given a QPU.
Warning: While the example below is relevent to see how QiskitConnector
works, it will only yield an error in this specific case if the command above was not used to run a qvm server.
Warning: The below cell will not work for python 3.6, the pyquil binder is deprecated for this version.
import sys
if sys.version_info >= (3, 7):
import os
from qat.interop.qiskit import QiskitConnector
from qat.interop.pyquil.providers import PyquilQPU
from qiskit import QuantumRegister, QuantumCircuit, ClassicalRegister, execute
from pyquil import get_qc
nbqubits = 2
qreg = QuantumRegister(nbqubits)
creg = ClassicalRegister(nbqubits)
qiskit_circuit = QuantumCircuit(qreg, creg)
qiskit_circuit.h(qreg[0])
qiskit_circuit.cx(qreg[0], qreg[1])
qiskit_circuit.measure(qreg, creg)
# Connection to the qvm running as server
os.environ["QCS_SETTINGS_APPLICATIONS_PYQUIL_QVM_URL"] = "http://127.0.0.1:17701"
os.environ["QCS_SETTINGS_APPLICATIONS_PYQUIL_QUILC_URL"] = "tcp://127.0.0.1:17702"
qvm = get_qc('9q-qvm')
# Building the backend while using qiskit backend as a plugin
backend = QiskitConnector() | PyquilQPU(qvm)
# This result is in qiskit form since it was executed on qiskit
result = execute(qiskit_circuit, backend, shots=1024).result()
print(result.results)
Conversion of circuits containing abstract variables is supported between Qiskit and QLM. It is done in the same way as other circuits.
# QLM to Qiskit
prog = Program()
qbits = prog.qalloc(2)
theta = prog.new_var(float, "theta")
gamma = 3.14 - 2 * theta
prog.apply(RX(theta), qbits[0])
prog.apply(RX(gamma), qbits[1])
qlm_circuit = prog.to_circ()
qiskit_circuit = qlm_to_qiskit(qlm_circuit)
print(qiskit_circuit)
from qiskit.circuit import Parameter
# Qiskit to QLM
qiskit_circuit = QuantumCircuit(2)
theta = Parameter("theta")
gamma = 3.14 - 2 * theta
qiskit_circuit.rx(theta, 0)
qiskit_circuit.rx(gamma, 1)
qlm_circuit = qiskit_to_qlm(qiskit_circuit)
qlm_circuit.display()