Executing / Compiling quantum jobs

QPUs & Plugins on Qaptiva

A QPU, or Quantum Processor Unit is the abstraction used on Qaptiva for designating either the workflow of a quantum computer, or an emulator of such a workflow. provides several classical emulators of QPUs.

See Quantum Processing Unit (QPU) for more information on QPUs.

A Plugin is an object from the Qaptiva API that can be used to process quantum circuits (or jobs) on their way to or on their way back from a QPU. A plugin can also be used independently from any QPU, they are in this case used only for compiling a circuit without executing it on a QPU.

See Extending a QPU (by using Plugins) for more information on plugins.

Getting a remote object

QPUs and plugins can respectively be “imported” from Qaptiva as remote QPUs and remote plugins.

A remote QPU can then be instanciated, creating a QLMaaSQPU. Similarly, a remote plugin can be instanciated, creating a QLMaaSPlugin. These instanciated objects can then be used to process jobs.

Getting a remote object

Warning

This sample of code requires a configuration file (to connect automatically to the server)

If a configuration file is set, myQLM is able to automatically connect to the Qaptiva Access server. The modules qlmaas.qpus and qlmaas.plugins allow for easily creating remote QPUs and plugins.

Equivalent code on Qaptiva
from qat.qpus import LinAlg
from qat.plugins import Nnizer

qpu = LinAlg()
plugin = Nnizer()
from qlmaas.qpus import LinAlg
from qlmaas.plugins import Nnizer

qpu = LinAlg()
plugin = Nnizer()

This “import” is done with the QLMaaSConnection get_qpu() and get_plugin() methods. As an example, the following code would create a remote QPU for LinAlg and a remote plugin for Nnizer:

Equivalent code on Qaptiva
from qat.qpus import LinAlg
from qat.plugins import Nnizer

qpu = LinAlg()
plugin = Nnizer()
from qat.qlmaas.connection import QLMaaSConnection

# importing a remote QPU and a remote plugin
connection = QLMaaSConnection()
LinAlg = connection.get_qpu("qat.qpus:LinAlg")
Nnizer = connection.get_plugin("qat.plugins:Nnizer")

# the remote QPU and plugin can then be instanciated in the usual way
qpu = LinAlg()
plugin = Nnizer()

Submitting a job to a remote QPU

A job can be submitted to a remote QPU by using a remote QPU’s submit() method. This method is asynchronous, meaning that its use is different from the submit method used directly on Qaptiva. See next section for retrieving the result of a simulation. Here is an example of job submission to a remote LinAlg QPU:

Equivalent code on Qaptiva
from qat.lang.AQASM import Program, H, CNOT

qprog = Program()
qbits = qprog.qalloc(2)
H(qbits[0])
CNOT(qbits[0], qbits[1])
circuit = qprog.to_circ()

job = circuit.to_job()

from qat.qpus import LinAlg

qpu = LinAlg()

# this is not strictly equivalent, since the Qaptiva's QPU submit method is synchronous
# while the QLMaaSQPU submit method is asynchronous
qpu.submit(job)
# creating a circuit and its corresponding job by using qat.lang
from qat.lang.AQASM import Program, H, CNOT

qprog = Program()
qbits = qprog.qalloc(2)
H(qbits[0])
CNOT(qbits[0], qbits[1])
circuit = qprog.to_circ()

job = circuit.to_job()

# creating a remote QPU - use of module 'qlmaas'
from qlmaas.qpus import LinAlg

# submitting the job
asynchronous_result = qpu.submit(job)

Getting the result of a job

There are a number of ways of obtaining the result of a job previously submited to a remote . Using one method or another depends on your workflow.

Getting the result of a job

As seen above, the submit() method returns a AsyncResult object (and so does the compile() method).

This object can then be used to check the status of the corresponding job with its get_status() method, and get its result when it is available by using either get_result() or join().

# check the status of a job
status = asynchronous_result.get_status()

# returns its result if the job is finished
result = asynchronous_result.get_result()

# for waiting until the job is finished and then get the result
result = asynchronous_result.join()

Warning

This sample of code requires a configuration file (to connect automatically to the server)

If a configuration file is set, myQLM is able to automatically connect to the Qaptiva Access server. The module qlmaas.jobs will contains all the job submitted by a user (except the job having a status DELETED).

from qlmaas.jobs import Job17

# Check the status of the job
status = Job17.get_status()

# Get the result
result = Job17.get_result()

Another way to interact with a submitted job is by using its job_id. This job_id can be obtained in various way; it is printed to the standard output when using the submit method, but it also is a field from AsyncResult.

The job_id can be used to get the result of your job later, as long as you have a QLMaaSConnection object to the same Qaptiva Access server:

from qat.qlmaas.connection import QLMaaSConnection

# recreating a connection to the server
connection = QLMaaSConnection()

# let us say that our job_id was Job17
JOB_ID = "Job17"

# check the status of the job
status = connection.get_status(JOB_ID)

# get the result of the job
result = connection.get_result(JOB_ID)

Building a custom execution stack

The Qaptiva syntax of using plugins and QPUs to build execution stacks is reproduced on Qaptiva Access. Building a remote stack by using Qaptiva Access would therefore look like that:

Equivalent code on Qaptiva
from qat.plugins import Plugin1, Plugin2, ..., PluginN
from qat.qpus import QPU

stack = Plugin1() | Plugin2() | ... | PluginN() | QPU()
# simple syntax using a configuration file
from qlmaas.plugins import Plugin1, Plugin2, ..., PluginN
from qlmaas.qpus import QPU

# the remote qpu and plugins are stacked and instanciated
stack = Plugin1() | Plugin2() | ... | PluginN() | QPU()

Such remote stack can then be used to submit jobs as with a remote qpu. This time, let us retrieve the result by using the job_id.

Equivalent code on the Qaptiva
result = stack.submit(batch)
# submit the stack
asynchronous_result = stack.submit(batch)

# get the result
result = asynchronous_result.get_result()

Compiling a quantum circuit

As on Qaptiva, a quantum circuit can be compiled with a plugin. This can be done with a remote plugin’s compile() method. Let us take the example of an Nnizer.

Equivalent code on Qaptiva
from qat.plugins import Nnizer
nnizer = Nnizer()

from qat.core import HardwareSpecs, Topology, TopologyType
specs = HardwareSpecs(topology=Topology(type=TopologyType.LNN))

new_batch = nnizer.compile(batch, specs)
# get the remote Nnizer (simple syntax using a configuration file)
from qlmaas.plugins import Nnizer
nnizer = Nnizer()

# define a limited LNN connectivity by using the qat.core library
from qat.core import HardwareSpecs, Topology, TopologyType
specs = HardwareSpecs(topology=Topology(type=TopologyType.LNN))

# a batch of jobs can then be compiled remotely
asynchronous_batch = nnizer.compile(batch, specs)
new_batch = asynchronous_batch.join()

# bonus: the QLMaaS syntax allows for compiling Job objects as well as Batch objects
asynchronous_job = nnizer.compile(job, specs)
new_job = asynchronous_job.join()