Skip to main contentIBM Quantum Documentation Preview
This is a preview build of IBM Quantum® documentation. Refer to quantum.cloud.ibm.com/docs for the official documentation.

Estimator examples

Package versions

The code on this page was developed using the following requirements. We recommend using these versions or newer.

qiskit[all]~=2.3.0
qiskit-ibm-runtime~=0.43.1

The examples in this section illustrate some common ways to use Estimator. Before running these examples, follow the instructions in Install Qiskit.

Note

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

Efficiently calculate and interpret expectation values of the quantum operators required for many algorithms with Estimator. Explore uses in molecular modeling, machine learning, and complex optimization problems.


Run a single experiment

Use Estimator to determine the expectation value of a single circuit-observable pair.

import numpy as np
from qiskit.circuit.library import iqp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.quantum_info import SparsePauliOp, random_hermitian
from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator
 
n_qubits = 50
 
service = QiskitRuntimeService()
backend = service.least_busy(
    operational=True, simulator=False, min_num_qubits=n_qubits
)
 
mat = np.real(random_hermitian(n_qubits, seed=1234))
circuit = iqp(mat)
observable = SparsePauliOp("Z" * 50)
 
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)
 
estimator = Estimator(mode=backend)
job = estimator.run([(isa_circuit, isa_observable)])
result = job.result()
 
print(f" > Expectation value: {result[0].data.evs}")
print(f" > Metadata: {result[0].metadata}")

Output:

 > Expectation value: -0.13582342954159593
 > Metadata: {'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}

Run multiple experiments in a single job

Use Estimator to determine the expectation values of multiple circuit-observable pairs.

import numpy as np
from qiskit.circuit.library import iqp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.quantum_info import SparsePauliOp, random_hermitian
from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator
 
n_qubits = 50
 
service = QiskitRuntimeService()
backend = service.least_busy(
    operational=True, simulator=False, min_num_qubits=n_qubits
)
 
rng = np.random.default_rng()
mats = [np.real(random_hermitian(n_qubits, seed=rng)) for _ in range(3)]
 
pubs = []
circuits = [iqp(mat) for mat in mats]
observables = [
    SparsePauliOp("X" * 50),
    SparsePauliOp("Y" * 50),
    SparsePauliOp("Z" * 50),
]
 
# Get ISA circuits
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
 
for qc, obs in zip(circuits, observables):
    isa_circuit = pm.run(qc)
    isa_obs = obs.apply_layout(isa_circuit.layout)
    pubs.append((isa_circuit, isa_obs))
 
estimator = Estimator(backend)
job = estimator.run(pubs)
job_result = job.result()
 
for idx in range(len(pubs)):
    pub_result = job_result[idx]
    print(f">>> Expectation values for PUB {idx}: {pub_result.data.evs}")
    print(f">>> Standard errors for PUB {idx}: {pub_result.data.stds}")

Output:

>>> Expectation values for PUB 0: 0.4873096446700508
>>> Standard errors for PUB 0: 1.3528950031716114
>>> Expectation values for PUB 1: -0.00390625
>>> Standard errors for PUB 1: 0.015347884419435263
>>> Expectation values for PUB 2: -0.02001953125
>>> Standard errors for PUB 2: 0.013797455737635134

Run parameterized circuits

Use Estimator to run three experiments in a single job, leveraging parameter values to increase circuit reusability.

import numpy as np
 
from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, EstimatorV2 as Estimator
 
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)
 
# Step 1: Map classical inputs to a quantum problem
theta = Parameter("θ")
 
chsh_circuit = QuantumCircuit(2)
chsh_circuit.h(0)
chsh_circuit.cx(0, 1)
chsh_circuit.ry(theta, 0)
 
number_of_phases = 21
phases = np.linspace(0, 2 * np.pi, number_of_phases)
individual_phases = [[ph] for ph in phases]
 
ZZ = SparsePauliOp.from_list([("ZZ", 1)])
ZX = SparsePauliOp.from_list([("ZX", 1)])
XZ = SparsePauliOp.from_list([("XZ", 1)])
XX = SparsePauliOp.from_list([("XX", 1)])
ops = [ZZ, ZX, XZ, XX]
 
# Step 2: Optimize problem for quantum execution.
 
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
chsh_isa_circuit = pm.run(chsh_circuit)
isa_observables = [
    operator.apply_layout(chsh_isa_circuit.layout) for operator in ops
]
 
# Step 3: Execute using Qiskit primitives.
 
# Reshape observable array for broadcasting
reshaped_ops = np.fromiter(isa_observables, dtype=object)
reshaped_ops = reshaped_ops.reshape((4, 1))
 
estimator = Estimator(backend, options={"default_shots": int(1e4)})
job = estimator.run([(chsh_isa_circuit, reshaped_ops, individual_phases)])
# Get results for the first (and only) PUB
pub_result = job.result()[0]
print(f">>> Expectation values: {pub_result.data.evs}")
print(f">>> Standard errors: {pub_result.data.stds}")
print(f">>> Metadata: {pub_result.metadata}")

Output:

>>> Expectation values: [[ 1.0455093   0.98152862  0.82113463  0.60354133  0.29572641  0.01149883
  -0.33110743 -0.60560522 -0.83322315 -0.96531231 -1.0257549  -0.95853095
  -0.81081517 -0.61091237 -0.30221293  0.0035381   0.31371176  0.61061753
   0.83646641  0.97091431  1.03135689]
 [ 0.03390682  0.31194271  0.620937    0.87391133  0.96973494  1.03872794
   0.94260949  0.82378821  0.56344283  0.28688115 -0.04570049 -0.37474403
  -0.64540887 -0.87803912 -0.97887504 -1.03577952 -0.97268336 -0.83970967
  -0.59705481 -0.29867482  0.0380346 ]
 [ 0.00265358 -0.32992806 -0.59646512 -0.80934096 -0.96737621 -1.00128302
  -0.94673728 -0.82703147 -0.59705481 -0.31341692 -0.00117937  0.29985419
   0.59469607  0.78486908  0.93346939  0.97622146  0.94732696  0.81199454
   0.60914332  0.28393273 -0.00678136]
 [ 0.99656555  0.93553328  0.78398456  0.55872536  0.29749546 -0.04511081
  -0.33523522 -0.62889773 -0.82201916 -0.95351864 -1.02634458 -0.96796589
  -0.82054495 -0.57553135 -0.30103356  0.00265358  0.3104685   0.59705481
   0.83322315  0.94437854  0.99214292]]
>>> Standard errors: [[0.014353   0.01441151 0.01620648 0.0195418  0.019762   0.01515649
  0.02102523 0.02112359 0.0148494  0.01119219 0.01576623 0.01245824
  0.01239832 0.01501273 0.01821305 0.01776286 0.01500156 0.01635231
  0.01577367 0.01315371 0.01089558]
 [0.01352805 0.01627835 0.01247646 0.01287866 0.01570182 0.01060924
  0.01590468 0.01620303 0.01530626 0.01619973 0.01918078 0.01379676
  0.01564971 0.01377673 0.01454324 0.01242184 0.01252201 0.01396738
  0.01326188 0.0145736  0.01795044]
 [0.02029376 0.01610892 0.0161542  0.0157785  0.01385665 0.01113743
  0.01375237 0.01380922 0.0145974  0.01759484 0.01594193 0.02111719
  0.01521368 0.01365888 0.01188512 0.01353009 0.01195674 0.01446547
  0.01660987 0.01511225 0.01880871]
 [0.01105161 0.01164476 0.01329858 0.01439545 0.01888747 0.01629201
  0.01405852 0.01406643 0.01088709 0.01275198 0.01281432 0.01333301
  0.01268483 0.01443594 0.01495655 0.01715532 0.01822699 0.01508936
  0.01435528 0.01340555 0.01295649]]
>>> Metadata: {'shots': 10016, 'target_precision': 0.01, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}

Use sessions and advanced options

Explore sessions and advanced options to optimize circuit performance on QPUs.

Caution

The following code block will return an error for Open Plan users because it uses sessions. Open Plan workloads can run only in job mode or batch mode.

import numpy as np
from qiskit.circuit.library import iqp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.quantum_info import SparsePauliOp, random_hermitian
from qiskit_ibm_runtime import (
    QiskitRuntimeService,
    Session,
    EstimatorV2 as Estimator,
)
 
n_qubits = 50
 
service = QiskitRuntimeService()
backend = service.least_busy(
    operational=True, simulator=False, min_num_qubits=n_qubits
)
 
rng = np.random.default_rng(1234)
mat = np.real(random_hermitian(n_qubits, seed=rng))
circuit = iqp(mat)
mat = np.real(random_hermitian(n_qubits, seed=rng))
another_circuit = iqp(mat)
observable = SparsePauliOp("X" * 50)
another_observable = SparsePauliOp("Y" * 50)
 
pm = generate_preset_pass_manager(optimization_level=1, backend=backend)
isa_circuit = pm.run(circuit)
another_isa_circuit = pm.run(another_circuit)
isa_observable = observable.apply_layout(isa_circuit.layout)
another_isa_observable = another_observable.apply_layout(
    another_isa_circuit.layout
)
 
with Session(backend=backend) as session:
    estimator = Estimator(mode=session)
 
    estimator.options.resilience_level = 1
 
    job = estimator.run([(isa_circuit, isa_observable)])
    another_job = estimator.run(
        [(another_isa_circuit, another_isa_observable)]
    )
    result = job.result()
    another_result = another_job.result()
 
    # first job
    print(f" > Expectation value: {result[0].data.evs}")
    print(f" > Metadata: {result[0].metadata}")
 
    # second job
    print(f" > Another Expectation value: {another_result[0].data.evs}")
    print(f" > More Metadata: {another_result[0].metadata}")

Output:

 > Expectation value: 0.08045977011494253
 > Metadata: {'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}
 > Another Expectation value: 0.02127659574468085
 > More Metadata: {'shots': 4096, 'target_precision': 0.015625, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}

Next steps

Recommendations