Common use cases
This topic describes how to migrate programs with the most commonly used types of circuits. For a full example, see End-to-end examples.
Basic circuits
The only changes when running basic circuits are how you run the job and retrieve results.
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
# Define the service. This allows you to access IBM QPUs (quantum processing units).
service = QiskitRuntimeService()
# Get a backend
backend = service.least_busy(operational=True, simulator=False)
job = sampler.run([isa_circuit])
result = job.result()
# Get results for the first (and only) PUB
pub_result = result[0]
from qiskit_ibm_provider import IBMProvider
# Define provider and backend
provider = IBMProvider()
backend = provider.get_backend("ibmq_qasm_simulator")
job = backend.run(isa_circuit)
result = job.result()
Specifying options
All options that were available with backend.run
are available in the Qiskit Runtime primitives, but they are specified differently. For more information, see Migrate options and Advanced Qiskit Runtime options.
from qiskit_ibm_runtime import SamplerV2 as Sampler
sampler = Sampler(backend)
# You can use auto-complete to see and complete the options.
sampler.options.default_shots = 1024
from qiskit_ibm_provider import IBMProvider
provider = IBMProvider()
backend = provider.get_backend("backend_name")
backend.run(isa_circuit, shots=1024)
Dynamic circuits
To migrate programs that run dynamic circuits, change the run call.
from qiskit_ibm_runtime import SamplerV2 as Sampler
sampler = Sampler(backend)
job = sampler.run([dynamic_circ])
pub_result = job.result()[0]
print(f">>> Hardware counts: {pub_result.data.meas.get_counts()}")
job = backend.run(dynamic_circ, dynamic=True)
job.job_id()
hardware_counts = job.result().get_counts()
hardware_counts
For more information about dynamic circuits, see the Classical feedforward and control flow topic, or try the Repeat until success tutorial.
Parameterized circuits
Parametrized circuits are a commonly used tool for quantum algorithm
design. Because backend.run()
did not accept parametrized
circuits, the parameter binding step had to be integrated in the
algorithm workflow. The primitives can perform the parameter binding
step internally, which results in a simplification of the algorithm-side
logic.
The following example summarizes the new workflow for managing parametrized circuits.
Example
Define a parametrized circuit:
from qiskit.circuit import QuantumCircuit, ParameterVector
n = 3
thetas = ParameterVector('θ',n)
qc = QuantumCircuit(n, 1)
qc.h(0)
for i in range(n-1):
qc.cx(i, i+1)
for i,t in enumerate(thetas):
qc.rz(t, i)
for i in reversed(range(n-1)):
qc.cx(i, i+1)
qc.h(0)
qc.measure(0, 0)
qc.draw()
Assign the following parameter values to the circuit:
import numpy as np
theta_values = [np.pi/2, np.pi/2, np.pi/2]
Only circuits that adhere to the Instruction Set Architecture (ISA) of a specific backend are accepted, so we must transform the circuits.
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)
The primitives take in parametrized circuits directly, together with the parameter values, and the parameter assignment operation can be performed more efficiently on the server side. The input is in the form of primitive unified blocs (PUBs), where each PUB is a tuple that contains a circuit and the data broadcasted to it. For further details, see Primitive inputs and outputs.
If you have multiple sets of parameter values you want to bind to the same circuit, you can specify them in a single PUB, in the format of (circuit, [parameter_value_set1, parameter_value_set2]).
You need the classical register name to get the results. By default, it is named meas
when you use measure_all()
. However, the classical register name for this example is c
. You can find the classical register name by running <circuit_name>.cregs
. For example, qc.cregs
.
from qiskit_ibm_runtime import SamplerV2 as Sampler
sampler = Sampler(backend)
job = sampler.run([(isa_circuit, theta_values)])
result = job.result()
# Get results for the first (and only) PUB
pub_result = result[0]
# Get counts from the classical register "c".
print(f" >> Counts for the c output register: {pub_result.data.c.get_counts()}")
The parameter values had to be bound to their respective
circuit parameters prior to calling backend.run()
.
from qiskit import Aer
bound_circuit = qc.bind_parameters(theta_values)
bound_circuit.draw()
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(bound_circuit)
backend = Aer.get_backend('aer_simulator')
job = backend.run(isa_circuit)
counts = job.result().get_counts()
print(counts)
Get the averaged IQ data (meas_level=1)
from qiskit.circuit import QuantumCircuit
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)
sampler = Sampler(backend)
# Get the averaged IQ data.
# This is equivalent to meas_level=1, meas_return="avg" in backend.run
sampler.options.execution.meas_type = "avg_kerneled"
job = sampler.run([isa_circuit], shots=10)
pub_result = job.result()[0]
print(f">>> Averaged IQ data: {pub_result.data.meas}")
from qiskit import QuantumCircuit
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
# Define provider and simulator backend
from qiskit_ibm_provider import IBMProvider
provider = IBMProvider()
backend = provider.get_backend("ibmq_qasm_simulator")
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)
result = backend.run(isa_circuit, shots=10, meas_level=1, meas_return="avg").result()
>>> print("result: ", result)
Upload, view, or delete custom prototype programs
This function has been replaced with Quantum Serverless patterns. For instructions to migrate, see Converting from Qiskit Runtime Programs.