Experiment with Qiskit Runtime

Learn how Qiskit Runtime works by trying out a prebuilt program.

Overview

Qiskit Runtime speeds up processing time by combining classical and quantum computing in a streamlined architecture.

In this first version you can explore running simple circuits or more complex variational algorithms (based on VQE); in future releases, you will be able to create your own full Qiskit Runtime programs. This version of Qiskit Runtime will be deployed gradually to all our systems. Additionally, you will be able to test it using our quantum simulators on the cloud, so that you can quickly get up to speed with this new way to run Qiskit programs. With Qiskit Runtime, you can keep your quantum program on the cloud and run it any time.

Diagram of Qiskit Runtime's architecture.

Diagram of Qiskit Runtime’s architecture.

View available Qiskit Runtime programs

On the Services page, click the Programs tab to view available programs. Click any program to learn more about it, and optionally choose a backend and provider to generate a custom program template and open it directly in Quantum Lab. You can then modify it as necessary and use it to execute circuits.

Find backends that support Qiskit Runtime

As of Qiskit 0.27.0, you can now query for backends that support Qiskit Runtime. If the input_allowed attribute of backend configuration contains runtime, then the backend supports Qiskit Runtime. Alternatively, you can use input_allowed in backend filtering:

from qiskit import IBMQ

provider = IBMQ.load_account()
# Get a list of all backends that support runtime.
runtime_backends = provider.backends(input_allowed='runtime')

Run a Qiskit Runtime program

Note

Qiskit Runtime uses Qiskit version 0.28.0, Terra version 0.18.0, and IBM Quantum Provider version 0.15.0.

In this example we will use a preloaded Qiskit Runtime program called circuit-runner. We will first build a circuit using Qiskit, then execute it with Qiskit Runtime, taking advantage of its low-latency architecture.

circuit-runner is a program that takes in one or more circuits, compiles them, executes them, and optionally applies measurement error mitigation. The program metadata tells you what the inputs and outputs are.

The following tutorial is also available in a Jupyter notebook. To build the code yourself, copy the following code blocks into empty cells in your notebook.

Note

The current Qiskit Runtime was designed for executing program scripts and is not tailored to large batches of quantum circuits. As such, there is a size limitation that translates into roughly a five circuit maximum per job.

from qiskit import IBMQ

IBMQ.load_account()
provider = IBMQ.get_provider(hub='MY_HUB', group='MY_GROUP', project='MY_PROJECT')  # Change this to your provider.
program = provider.runtime.program('circuit-runner')
print(program)

print(program) prints the program metadata, such as maximum execution time, parameter descriptions, and so on.

Program metadata
circuit-runner:
Name: circuit-runner
Description: A runtime program that takes one or more circuits, compiles them, executes them, and optionally applies measurement error mitigation.
Version: 1
Creation date: 2021-05-07T00:17:07Z
Max execution time: 1800
Input parameters:
 - circuits:
   Description: A circuit or a list of circuits.
   Type: A QuantumCircuit or a list of QuantumCircuits.
   Required: True
 - shots:
   Description: Number of repetitions of each circuit, for sampling. Default: 1024.
   Type: int
   Required: False
 - initial_layout:
   Description: Initial position of virtual qubits on physical qubits.
   Type: dict or list
   Required: False
 - layout_method:
   Description: Name of layout selection pass ('trivial', 'dense', 'noise_adaptive', 'sabre')
   Type: string
   Required: False
 - routing_method:
   Description: Name of routing pass ('basic', 'lookahead', 'stochastic', 'sabre').
   Type: string
   Required: False
 - translation_method:
   Description: Name of translation pass ('unroller', 'translator', 'synthesis').
   Type: string
   Required: False
 - seed_transpiler:
   Description: Sets random seed for the stochastic parts of the transpiler.
   Type: int
   Required: False
 - optimization_level:
   Description: How much optimization to perform on the circuits (0-3). Higher levels generate more optimized circuits. Default is 1.
   Type: int
   Required: False
 - init_qubits:
   Description: Whether to reset the qubits to the ground state for each shot.
   Type: bool
   Required: False
 - rep_delay:
   Description: Delay between programs in seconds.
   Type: float
   Required: False
 - transpiler_options:
   Description: Additional compilation options.
   Type: dict
   Required: False
 - measurement_error_mitigation:
   Description: Whether to apply measurement error mitigation. Default is False.
   Type: bool
   Required: False
Interim results:
 none
Returns:
 - -:
   Description: Circuit execution results.
   Type: RunnerResult object

The following is an example of running a circuit using circuit-runner. First we prepare the initial state:

import numpy as np

k = 5
state = (1/np.sqrt(8))*np.array([np.exp(-1j*2*np.pi*k*(0)/8),np.exp(-1j*2*np.pi*k*(1)/8),
                                 np.exp(-1j*2*np.pi*k*(2)/8),
 np.exp(-1j*2*np.pi*k*3/8),np.exp(-1j*2*np.pi*k*4/8),np.exp(-1j*2*np.pi*k*5/8),
 np.exp(-1j*2*np.pi*k*6/8), np.exp(-1j*2*np.pi*k*7/8)])

We then construct and show the circuit:

from qiskit import QuantumCircuit
from qiskit.circuit.library import QFT
from qiskit.quantum_info import Statevector

qubits = 3

circuit = QuantumCircuit(qubits, qubits)
circuit.initialize(state)
circuit.append(QFT(qubits), range(qubits))
circuit.measure(range(qubits), range(qubits))

circuit.draw(output="mpl")
../../_images/circ-runtime1.png

Now let’s run this circuit using the circuit-runner program. There is an AccountProvider.run_circuits() method to do this easily:

backend = provider.backend.ibmq_qasm_simulator

result = provider.run_circuits(circuit, backend=backend, optimization_level=3).result()

from qiskit.visualization import plot_histogram

counts = result.get_counts()
plot_histogram(counts)
../../_images/qiskit-runtime021.png

run_circuits() is a convenience method for the circuit-runner program. The standard way of invoking a Qiskit Runtime program is to use the run() method, as demonstrated below. Note that circuit-runner has its own result decoder in RunnerResult, so you’ll need to pass that when getting the job result:

from qiskit.providers.ibmq import RunnerResult

program_inputs = {
    'circuits': circuit,
    'optimization_level': 3
}
options = {'backend_name': backend.name()}
job = provider.runtime.run(program_id="circuit-runner",
                           options=options,
                           inputs=program_inputs,
                          )
print(f"job ID: {job.job_id()}")
result = job.result(decoder=RunnerResult)

You can also choose to have measurement error mitigation automatically applied when the circuit execution finishes:

from qiskit.providers.ibmq import RunnerResult

backend = provider.backend.ibmq_qasm_simulator

program_inputs = {
    'circuits': circuit,
    'optimization_level': 3,
    'measurement_error_mitigation': True
}
options = {'backend_name': backend.name()}
job = provider.runtime.run(program_id="circuit-runner",
                           options=options,
                           inputs=program_inputs,
                          )
print(f"job ID: {job.job_id()}")
result = job.result(decoder=RunnerResult)

Applying measurement error mitigation to the circuit execution output will result in a vector that does not correspond to a probability distribution. Because of this we call the mitigated probabilities quasi-probabilities:

noisy = result.get_counts()
mitigated = result.get_quasiprobabilities().nearest_probability_distribution()
plot_histogram([noisy, mitigated], legend=['noisy', 'mitigated'])
../../_images/qiskit-runtime31.png

View your Qiskit program jobs

You can view details about running and completed jobs by opening the Jobs page from the application switcher ( switcher ), then clicking the Program jobs tab.

Upload and manage your own programs (coming soon)

In addition to pre-built programs, you will soon be able to upload and manage your own Qiskit Runtime programs. See this tutorial for more information.

Qiskit Runtime tutorials and other resources

To learn more, visit the Qiskit Runtime program architecture topic and the Qiskit Runtime Github repository. You can also implement Qiskit Runtime by using the public REST API.

Explore these Qiskit Runtime tutorials, which are in Jupyter notebook format:

Limitations

API

Qiskit Runtime is still in beta mode, and heavy modifications to both functionality and API are likely to occur. Some of the changes might not be backward-compatible and would require updating your Qiskit version.

Qiskit Runtime glossary

Qiskit program

Qiskit Python source code that describes the problem to solve, combining classical and quantum computation. It takes inputs from the users, makes the calculation, and returns the results. Each instance of a Qiskit program execution is similar to a computer process and is represented as a runtime job.

Qiskit program metadata

The data that defines your program. Critical components are name, maximum execution time, version, backend requirements, and input/output parameters.

Qiskit Runtime

Qiskit Runtime is a cloud service that runs the Qiskit program remotely as a process, passing the input from the user, and handling the connectivity between the Qiskit program, the user, and the quantum processing unit. You can repeat this multiple times with the same or different Qiskit programs.

Qiskit Runtime manager

The main task of this component of the architecture is to prepare Qiskit Runtime, load the Qiskit programs, and supervise the correct execution.

OpenQASM circuit

Quantum circuit format generated by the Qiskit program. OpenQASM is the low-level language consumed by the Quantum Processing Unit (QPU).

Quantum processing unit (QPU)

Part of the computational unit that performs the quantum computation.