Skip to content

Latest commit

 

History

History
276 lines (203 loc) · 8.06 KB

File metadata and controls

276 lines (203 loc) · 8.06 KB
title description
Common use cases
Common use cases when migrating from backend.run to Qiskit Runtime primitives

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.

This guide is no longer maintained. It is archived in GitHub for historical reference only.

Basic circuits

The only changes when running basic circuits are how you run the job and retrieve results.

```python 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]

  </TabItem>

  <TabItem value="Legacy" label="backend.run">
```python
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
```python from qiskit_ibm_provider import IBMProvider

provider = IBMProvider() backend = provider.get_backend("backend_name")

backend.run(isa_circuit, shots=1024)

  </TabItem>
</Tabs>


## Dynamic circuits

To migrate programs that run dynamic circuits, change the run call.

<Tabs>
  <TabItem value="primitives" label="Sampler">
    ```python
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()}")
```python job = backend.run(dynamic_circ, dynamic=True) job.job_id()

hardware_counts = job.result().get_counts() hardware_counts

  </TabItem>
</Tabs>

For more information about dynamic circuits, see the [Classical feedforward and control flow](/docs/guides/classical-feedforward-and-control-flow) topic.

<span id="parm-circ"></span>
## 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:

```python
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 `.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)

```python 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}")

  </TabItem>

  <TabItem value="legacy" label="backend.run">
```python
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.