Skip to main contentIBM Quantum Documentation

Get started with primitives

The steps in this topic describes how to set up primitives, explore the options you can use to configure them, and invoke them in a program.

Important

To ensure faster and more efficient results, as of 1 March 2024, circuits and observables need to be transformed to only use instructions supported by the system (referred to as instruction set architecture (ISA) circuits and observables) before being submitted to the Qiskit Runtime primitives. See the transpilation documentation for instructions to transform circuits. Due to this change, the primitives will no longer perform layout or routing operations. Consequently, transpilation options referring to those tasks will no longer have any effect. By default, all primitives except Sampler V2 still optimize the input circuits. To bypass all optimization, set optimization_level=0.

Exception: When you initialize the Qiskit Runtime Service with the Q-CTRL channel strategy (example below), abstract circuits are still supported.

service = QiskitRuntimeService(channel="ibm_cloud", channel_strategy="q-ctrl")
Note

These examples all use the primitives from Qiskit Runtime, but you could use the base primitives instead.


Get started with Estimator

1. Initialize the account

Because Qiskit Runtime Estimator is a managed service, you first need to initialize your account. You can then select the simulator or real system you want to use to calculate the expectation value.

Follow the steps in the Install and set up topic if you don't already have an account.

from qiskit_ibm_runtime import QiskitRuntimeService
 
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)

2. Create a circuit and an observable

You need at least one circuit and one observable as inputs to the Estimator primitive.

import numpy as np
from qiskit.circuit.library import IQP
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.quantum_info import SparsePauliOp, random_hermitian
 
n_qubits = 127
 
mat = np.real(random_hermitian(n_qubits, seed=1234))
circuit = IQP(mat)
observable = SparsePauliOp("Z" * n_qubits)
print(f">>> Observable: {observable.paulis}")

The circuit and observable need to be transformed to only use instructions supported by the system (referred to as instruction set architecture (ISA) circuits). We'll use the transpiler to do this.

pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)

3. Initialize Qiskit Runtime Estimator

When you initialize the Estimator, pass in the system or simulator you previously selected as the target.

To use the Estimator V2, import the EstimatorV2 class. The Estimator class still refers to the version 1 Estimator, for backwards compatibility.

from qiskit_ibm_runtime import EstimatorV2 as Estimator
 
estimator = Estimator(backend=backend)

4. Invoke the Estimator and get results

Next, invoke the run() method to calculate expectation values for the input circuits and observables.

For Estimator V2, the circuit, observable, and optional parameter value sets are input as primitive unified bloc (PUB) tuples.

job = estimator.run([(isa_circuit, isa_observable)])
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job Status: {job.status()}")
result = job.result()
print(f">>> {result}")
print(f"  > Expectation value: {result[0].data.evs}")
print(f"  > Metadata: {result[0].metadata}")

Get started with Sampler

1. Initialize the account

Because Qiskit Runtime Sampler is a managed service, you first need to initialize your account. You can then select the simulator or real system you want to use to calculate the expectation value.

Follow the steps in the Install and set up topic if you don't already have an account set up.

from qiskit_ibm_runtime import QiskitRuntimeService
 
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)

2. Create a circuit

You need at least one circuit as the input to the Sampler primitive.

import numpy as np
from qiskit.circuit.library import IQP
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.quantum_info import random_hermitian
 
n_qubits = 127
 
mat = np.real(random_hermitian(n_qubits, seed=1234))
circuit = IQP(mat)
circuit.measure_all()

Again, we use the transpiler to get an ISA circuit.

pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)

3. Initialize the Qiskit Runtime Sampler

When you initialize the Sampler, pass in the simulator or system you previously selected as the target.

To use the Sampler V2, import the SamplerV2 class. The Sampler class still refers to the version 1 Sampler, for backwards compatibility.

from qiskit_ibm_runtime import SamplerV2 as Sampler
 
sampler = Sampler(backend=backend)

4. Invoke the Sampler and get results

Next, invoke the run() method to generate the output.

For Sampler V2, the circuit and optional parameter value sets are input as primitive unified bloc (PUB) tuples.

job = sampler.run([(isa_circuit)])
print(f">>> Job ID: {job.job_id()}")
print(f">>> Job Status: {job.status()}")
result = job.result()
 
# Get results for the first (and only) PUB
pub_result = result[0]
print(f"Counts for the meas output register: {pub_result.data.meas.get_counts()}")

Next steps

Recommendations
Was this page helpful?