0% found this document useful (0 votes)
40 views33 pages

Cost Functions - IBM Quantum Learning

This document provides an overview of cost functions in quantum computing using Qiskit, focusing on the evaluation of cost functions and measurement strategies. It introduces Qiskit Runtime primitives, specifically the Sampler and Estimator, which are used to calculate probabilities and expectation values of quantum states and observables. The document also includes a guided example illustrating how to compute expectation values using these primitives.

Uploaded by

vitalrogatch4
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
40 views33 pages

Cost Functions - IBM Quantum Learning

This document provides an overview of cost functions in quantum computing using Qiskit, focusing on the evaluation of cost functions and measurement strategies. It introduces Qiskit Runtime primitives, specifically the Sampler and Estimator, which are used to calculate probabilities and expectation values of quantum states and observables. The document also includes a guided example illustrating how to compute expectation values using these primitives.

Uploaded by

vitalrogatch4
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

Cost functions
During this lesson, we'll learn how to evaluate a cost function:

First, we'll learn about Qiskit Runtime primitives

Define a cost function C(θ ). This is a problem-specific function that


defines the problem's goal for the optimizer to minimize (or
maximize)

Defining a measurement strategy with the Qiskit Runtime primitives


to optimize speed versus accuracy

Primitives

All physical systems, whether classical or quantum, can exist in different


states. For example, a car on a road can have a certain mass, position,
speed, or acceleration that characterize its state. Similarly, quantum
systems can also have different configurations or states, but they differ from
classical systems in how we deal with measurements and state evolution.
https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 1/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

This leads to unique properties such as superposition and entanglement


that are exclusive to quantum mechanics. Just like we can describe a car's
state using physical properties like speed or acceleration, we can also
describe the state of a quantum system using observables, which are
mathematical objects.

In quantum mechanics, states are represented by normalized complex


column vectors, or kets (∣ψ⟩), and observables are hermitian linear
^
operators (H ^ † ) that act on the kets. An eigenvector (∣λ⟩) of an
=H
observable is known as an eigenstate. Measuring an observable for one of its
eigenstates (∣λ⟩) will give us the corresponding eigenvalue (λ) as readout.

If you're wondering how to measure a quantum system and what you can
measure, Qiskit offers two primitives that can help:

Sampler : Given a quantum state ∣ψ⟩, this primitive obtains the


probability of each possible computational basis state.

^ and a state ∣ψ⟩, this


Estimator : Given a quantum observable H
^.
primitive computes the expected value of H

The Sampler primitive

The Sampler primitive calculates the probability of obtaining each possible


state ∣k⟩ from the computational basis, given a quantum circuit that
prepares the state ∣ψ⟩. It calculates

pk = ∣⟨k∣ψ⟩∣2
​ ∀k ∈ Zn2 ≡ {0, 1, ⋯ , 2n − 1},

Where n is the number of qubits, and k the integer representation of any


possible output binary string {0, 1}n (i.e. integers base 2).

The Qiskit Runtime Sampler runs the circuit multiple times on a quantum
device, performing measurements on each run, and reconstructing the
probability distribution from the recovered bitstrings. The more runs (or
shots) it performs, the more accurate the results will be, but this requires
more time and quantum resources.

However, since the number of possible outputs grows exponentially with the
number of qubits n (i.e. 2n ), the number of shots will need to grow
exponentially as well in order to capture a dense probability distribution.
Therefore, Sampler is only efficient for sparse probability distributions;
where the target state ∣ψ⟩ must be expressible as a linear combination of
https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 2/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

the computational basis states, with the number of terms growing at most
polynomially with the number of qubits:

Poly(n)
∣ψ⟩ = ∑ wk ∣k⟩. ​ ​

The Sampler can also be configured to retrieve probabilities from a


subsection of the circuit, representing a subset of the total possible states.

The Estimator primitive

The Estimator primitive calculates the expectation value of an observable


H^ for a quantum state ∣ψ⟩; where the observable probabilities can be
^
expressed as pλ = ∣⟨λ∣ψ⟩∣2 , being ∣λ⟩ the eigenstates of the observable H

. The expectation value is then defined as the average of all possible


outcomes λ (i.e. the eigenvalues of the observable) of a measurement of the
state ∣ψ⟩, weighted by the corresponding probabilities:

^ ⟩ψ := ∑ pλ λ = ⟨ψ∣H
⟨H ​
^ ∣ψ⟩
​ ​

However, calculating the expectation value of an observable is not always


possible, as we often don't know its eigenbasis. The Qiskit Runtime
Estimator uses a complex algebraic process to estimate the expectation
value on a real quantum device by breaking down the observable into a
combination of other observables whose eigenbasis we do know.

In simpler terms, Estimator breaks down any observable that it doesn't


know how to measure into simpler, measurable observables called Pauli
operators.

Any operator can be expressed as a combination of 4n Pauli operators.

P^k := σkn−1 ⊗ ⋯ ⊗ σk0




​ ∀k ∈ Zn4 ≡ {0, 1, ⋯ , 4n − 1}, ​

such that

4n −1
^ = ∑ wk P^k
H ​ ​ ​

k=0

where n is the number of qubits, k ≡ kn−1 ⋯ k0 for kl ∈ Z4 ≡ ​ ​ ​ ​

{0, 1, 2, 3} (i.e. integers base 4), and (σ0 , σ1 , σ2 , σ3 ) := (I, X, Y , Z). ​ ​ ​ ​

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 3/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

After performing this decomposition, Estimator derives a new circuit


Vk ∣ψ⟩ for each observable P^k (i.e. from the original circuit), to effectively
​ ​

diagonalize the Pauli observable in the computational basis and measure it.
We can easily measure Pauli observables because we know Vk ahead of ​

time, which is not the case generally for other observables.


^k , the Estimator runs the corresponding circuit on a quantum
For each P ​

device multiple times, measures the output state in the computational


basis, and calculates the probability pkj of obtaining each possible output j .

It then looks for the eigenvalue λkj of Pk corresponding to each output j ,


​ ​

multiplies by wk , and adds all the results together to obtain the expected

^ for the given state ∣ψ⟩.


value of the observable H

4n −1 2n −1
^ ⟩ψ = ∑ wk ∑ pkj λkj ,
⟨H ​ ​ ​ ​ ​ ​

k=0 j=0

Since calculating the expectation value of 4n Paulis is impractical (i.e.


exponentially growing), Estimator can only be efficient when a large
amount of wk are zero (i.e. sparse Pauli decomposition instead of dense).

Formally we say that, for this computation to be efficiently solvable, the


number of non-zero terms has to grow at most polynomially with the
^
number of qubits n: H = ∑k
Poly(n)
​ wk P^k .
​ ​

The reader may notice the implicit assumption that probability sampling
also needs to be efficient as explained for Sampler , which means

Poly(n) Poly(n)
^ ⟩ψ = ∑ wk ∑ pkj λkj .
⟨H ​ ​ ​ ​ ​ ​

k j

Guided example to calculate expectation values

1
Let's assume the single-qubit state ∣+⟩ := H∣0⟩ = (∣0⟩ + ∣1⟩), and
2

observable

^ = (−1 2)
H
2 1
​ ​

​ ​

= 2X − Z

^ ⟩+
with the following theoretical expectation value ⟨H ​
^ ∣+⟩ = 2.
= ⟨+∣H

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 4/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

Since we do not know how to measure this observable, we cannot compute


^ ⟩+
its expectation value directly, and we need to re-express it as ⟨H ​ =
2⟨X⟩+ − ⟨Z⟩+ . Which can be shown to evaluate to the same result by
​ ​

virtue of noting that ⟨+∣X∣+⟩ = 1, and ⟨+∣Z∣+⟩ = 0.

Let see how to compute ⟨X⟩+ and ⟨Z⟩+ directly. Since X and Z do not
​ ​

commute (i.e. don't share the same eigenbasis), they cannot be measured
simultaneously, therefore we need the auxiliary circuits:

1 from qiskit import QuantumCircuit


2 from qiskit.quantum_info import SparsePauliOp
3
4 # The following code will work for any other initial sin
5 original_circuit = QuantumCircuit(1)
6 original_circuit.h(0)
7
8 H = SparsePauliOp(["X", "Z"], [2, -1])
9
10 aux_circuits = []
11 for pauli in H.paulis:
12 aux_circ = original_circuit.copy()
13 aux_circ.barrier()
14 if str(pauli) == "X":
15 aux_circ.h(0)
16 elif str(pauli) == "Y":
17 aux_circ.sdg(0)
18 aux_circ.h(0)
19 else:
20 aux_circ.id(0)
21 aux_circ.measure_all()
22 aux_circuits.append(aux_circ)
23
24 original_circuit.draw("mpl")

 

Output:

1 # Auxiliary circuit for X


2 aux_circuits[0].draw("mpl")

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 5/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning
Output:

1 # Auxiliary circuit for Z


2 aux_circuits[1].draw("mpl")

Output:

We can now carry out the computation manually using Sampler and check
the results on Estimator :

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 6/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

1 from qiskit.primitives import StatevectorSampler, Statev


2 from qiskit.result import QuasiDistribution
3 from qiskit.circuit.library import IGate, ZGate, XGate
4 import numpy as np
5
6
7 ## SAMPLER
8 shots = 10000
9 sampler = StatevectorSampler()
10 job = sampler.run(aux_circuits, shots=shots)
11 data_pub = job.result()[1].data
12 bitstrings = data_pub.meas.get_bitstrings()
13 counts = data_pub.meas.get_counts()
14 quasi_dist = QuasiDistribution(
15 {outcome: freq / shots for outcome, freq in counts.i
16 )
17
18 expvals = []
19 for pauli in H.paulis:
20 val = 0
21
22 if str(pauli) == "I":
23 Lambda = IGate().to_matrix().real
24
25 if str(pauli) == "X":
26 Lambda = XGate().to_matrix().real
27 val += Lambda[0][1] * quasi_dist.get(1)
28 val += Lambda[1][0] * quasi_dist.get(0)
29
30 if str(pauli) == "Y":
31 Lambda = XGate().to_matrix().real
32 val += Lambda[0][1] * 1.0j * quasi_dist.get(1)
33 val += Lambda[1][0] * -1.0j * quasi_dist.get(0)
34
35 if str(pauli) == "Z":
36 Lambda = ZGate().to_matrix().real
37 val += Lambda[0][0] * quasi_dist.get(0)
38 val += Lambda[1][1] * quasi_dist.get(1)
39
40 expvals.append(val)
41
42 print("Sampler results:")
43 for pauli, expval in zip(H.paulis, expvals):
44 print(f" >> Expected value of {str(pauli)}: {expval
45
46 total_expval = np.sum(H.coeffs * expvals).real
47 print(f" >> Total expected value: {total_expval:.5f}")
48
49 ## ESTIMATOR
https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 7/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning
49 ## ESTIMATOR
50 observables = [
51 *H.paulis,
52 H,
53 ] # Note: run for individual Paulis as well as full obs
54
55 estimator = StatevectorEstimator()
56 job = estimator.run([(original_circuit, observables)])
57 estimator_expvals = job.result()[0].data.evs
58
59 print("Estimator results:")
60 for obs, expval in zip(observables, estimator_expvals):
61 if obs is not H:
62 print(f" >> Expected value of {str(obs)}: {expv
63 else:
64 print(f" >> Total expected value: {expval:.5f}"

 
Output:

Sampler results:
>> Expected value of X: 1.00000
>> Expected value of Z: -0.00300
>> Total expected value: 2.00300
Estimator results:
>> Expected value of X: 1.00000
>> Expected value of Z: 0.00000
>> Total expected value: 2.00000

Mathematical rigor (optional)

^ , ∣ψ⟩
Expressing ∣ψ⟩ with respect to the basis of eigenstates of H =
∑λ aλ ∣λ⟩, it follows:
​ ​

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 8/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

^ ∣ψ⟩ = ( ∑ a∗ ′ ⟨λ′ ∣)H


⟨ψ∣H ^ ( ∑ aλ ∣λ⟩)
λ ​ ​ ​ ​

λ′ λ

= ∑ ∑ a∗λ′ aλ ⟨λ′ ∣H

^ ∣λ⟩ ​ ​ ​

λ λ′

= ∑ ∑ a∗λ′ aλ λ⟨λ′ ∣λ⟩


​ ​ ​ ​

λ λ′

∑ ∑ a∗λ′ aλ λ
​ ​

= ​ ​ ​ ​ ⋅ δλ,λ′ ​

λ λ′

= ∑ ∣aλ ∣2 λ ​ ​

= ∑ pλ λ ​ ​

Since we do not know the eigenvalues or eigenstates of the target


^ , first we need to consider its diagonalization. Given that H
observable H ^ is
^
hermitian, there exists a unitary transformation V such that H = V † ΛV ,
where Λ is the diagonal eigenvalue matrix, so ⟨j∣Λ∣k⟩ = 0 if j =
 k , and
⟨j∣Λ∣j⟩ = λj . ​

This implies that the expected value can be rewritten as:

^ ∣ψ ⟩ = ⟨ψ∣V † ΛV ∣ψ⟩
⟨ψ ∣ H
2n −1 2n −1
= ⟨ψ∣V † ( ∑ ∣j⟩⟨j∣)Λ( ∑ ∣k⟩⟨k∣)V ∣ψ⟩ ​ ​

j=0 k=0
n n
2 −1 2 −1
= ∑ ∑ ⟨ψ∣V † ∣j⟩⟨j∣Λ∣k⟩⟨k∣V ∣ψ⟩
​ ​

j=0 k=0 ​

2n −1
= ∑ ⟨ψ∣V † ∣j⟩⟨j∣Λ∣j⟩⟨j∣V ∣ψ⟩

j=0
2n −1
= ∑ ∣⟨j∣V ∣ψ⟩∣2 λj
​ ​

j=0

Given that if a system is in the state ∣ϕ⟩ = V ∣ψ⟩ the probability of


2
measuring ∣j⟩ is pj ​ = ∣⟨j∣ϕ⟩∣ , the above expected value can be expressed
as:

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 9/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning
2n −1
^ ∣ψ⟩ = ∑ pj λj .
⟨ψ∣H ​ ​ ​

j=0

It is very important to note that the probabilities are taken from the state
V ∣ψ⟩ instead of ∣ψ⟩. This is why the matrix V is absolutely necessary.
You might be wondering how to obtain the matrix V and the eigenvalues Λ.
If you already had the eigenvalues, then there would be no need to use a
quantum computer since the goal of variational algorithms is to find these
^.
eigenvalues of H

Fortunately, there is a way around that: any 2n × 2n matrix can be written


as a linear combination of 4n tensor products of n Pauli matrices and
identities, all of which are both hermitian and unitary with known V and Λ.
This is what Runtime's Estimator does internally by decomposing any
Operator object into a SparsePauliOp .

Here are the Operators that can be used:

Operator σ V
1 0
I σ0 = ( ) V0 = I
0 1
​ ​ ​ ​

0 1 1
X σ1 = ( ) V1 = H = 1
(
1 0 2 1 −
​ ​ ​ ​ ​ ​

​ ​

0 −i 1 1 1 0
Y σ2 = ( ) V2 = HS † = 1
( )⋅(
i 0 2 1 −1 0 −i
​ ​ ​ ​ ​ ​ ​ ​

1 0
Z σ3 = ( ) V3 = I
0 −1
​ ​ ​ ​

 

^ with respect to the Paulis and identities:


So let's rewrite H

3 3 4n −1
^ = ∑ ... ∑ wkn−1 ...k0 σkn−1 ⊗ ... ⊗ σk0 = ∑ wk P^k ,
H ​ ​

​ ​



​ ​ ​ ​

kn−1 =0 ​ k0 = 0
​ k=0

n−1
where k = ∑l=0 4l kl ≡ kn−1 ...k0 for kn−1 , ..., k0 ∈ {0, 1, 2, 3} (i.e.
​ ​ ​ ​ ​ ​

^k := σkn−1 ⊗ ... ⊗ σk0 :


base 4), and P ​



https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 10/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning
n
4 −1 2n −1
^ ∣ψ⟩ = ∑ wk ∑ ∣⟨j∣Vk ∣ψ⟩∣2 ⟨j∣Λk ∣j⟩
⟨ψ∣H ​ ​ ​ ​ ​

k=0 j=0
n
4 −1 2n −1
​ ​

= ∑ wk ∑ pkj λkj ,
​ ​ ​ ​ ​

k=0 j=0

where Vk ​
:= Vkn−1 ​

⊗ ... ⊗ Vk0 and Λk := Λkn−1 ⊗ ... ⊗ Λk0 , such that:

​ ​



P^k =

​ ​
V k Λk V k .
​ ​ ​

Cost functions

In general, cost functions are used to describe the goal of a problem and
how well a trial state is performing with respect to that goal. This definition
can be applied to various examples in chemistry, machine learning, finance,
optimization, and so on.

Let's consider a simple example of finding the ground state of a system. Our
objective is to minimize the expectation value of the observable
^ ):
representing energy (Hamiltonian H

^ ∣ψ(θ)⟩
min⟨ψ(θ)∣H ​

We can use the Estimator to evaluate the expectation value and pass this
value to an optimizer to minimize. If the optimization is successful, it will
return a set of optimal parameter values θ ∗ , from which we will be able to
construct the proposed solution state ∣ψ(θ ∗ )⟩ and compute the observed
expectation value as C(θ ∗ ).

Notice how we will only be able to minimize the cost function for the limited
set of states that we are considering. This leads us to two separate
possibilities:

Our ansatz does not define the solution state across the search
space: If this is the case, our optimizer will never find the solution,
and we need to experiment with other ansatzes that might be able to
represent our search space more accurately.

Our optimizer is unable to find this valid solution: Optimization can


be globally defined and locally defined. We'll explore what this means
https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 11/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

in the later section.

All in all, we will be performing a classical optimization loop but relying on


the evaluation of the cost function to a quantum computer. From this
perspective, one could think of the optimization as a purely classical
endeavor where we call some black-box quantum oracle each time the
optimizer needs to evaluate the cost function.

1 def cost_func_vqe(params, circuit, hamiltonian, estimato


2 """Return estimate of energy from estimator
3
4 Parameters:
5 params (ndarray): Array of ansatz parameters
6 ansatz (QuantumCircuit): Parameterized ansatz ci
7 hamiltonian (SparsePauliOp): Operator representa
8 estimator (Estimator): Estimator primitive insta
9
10 Returns:
11 float: Energy estimate
12 """
13 pub = (circuit, hamiltonian, params)
14 cost = estimator.run([pub]).result()[0].data.evs
15 return cost

 

1 from qiskit.circuit.library import TwoLocal


2
3 observable = SparsePauliOp.from_list([("XX", 1), ("YY",
4
5 reference_circuit = QuantumCircuit(2)
6 reference_circuit.x(0)
7
8 variational_form = TwoLocal(
9 2,
10 rotation_blocks=["rz", "ry"],
11 entanglement_blocks="cx",
12 entanglement="linear",
13 reps=1,
14 )
15 ansatz = reference_circuit.compose(variational_form)
16
17 theta_list = (2 * np.pi * np.random.rand(1, 8)).tolist()
18 ansatz.decompose().draw("mpl")

 

Output:

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 12/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

We will first carry this out using a simulator: the StatevectorEstimator. This
is usually advisable for debugging, but we will immediately follow the
debugging run with a calculation on real quantum hardware. Increasingly,
problems of interest are no longer classically simulable without state-of-
the-art supercomputing facilities.

1 estimator = StatevectorEstimator()
2 cost = cost_func_vqe(theta_list, ansatz, observable, esti
3 print(cost)

 

Output:

[-0.58744589]

We will now proceed with running on a real quantum computer. Note the
syntax changes. The steps involving the pass_manager will be discussed
further in the next example. One step of particular importance in variational
algorithms is the use of a Qiskit Runtime session. Starting a session allows
you to run multiple iterations of a variational algorithm without waiting in a
new queue each time parameters are updated. This is important if queue
times are long and/or many iterations are needed. Only partners in the IBM
Quantum Network can use Runtime sessions. If you do not have access to
sessions, you can reduce the number of iterations you submit at a given
time, and save the most recent parameters for use in future runs. If you
submit too many iterations or encounter queue times that are too long, you
may encounter error code 1217, which refers to long delays between job
submissions.

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 13/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

1 # Estimated usage: < 1 min. Benchmarked at 7 seconds on


2 # Load necessary packages:
3
4 from qiskit_ibm_runtime import (
5 QiskitRuntimeService,
6 Session,
7 EstimatorOptions,
8 EstimatorV2 as Estimator,
9 )
10 from qiskit.transpiler.preset_passmanagers import genera
11
12 # Select the least busy backend:
13
14 service = QiskitRuntimeService()
15 backend = service.least_busy(
16 operational=True, min_num_qubits=ansatz.num_qubits,
17 )
18 # Or get a specific backend:
19 # backend = service.backend("ibm_cusco")
20
21 # Use a pass manager to transpile the circuit and observ
22
23 pm = generate_preset_pass_manager(backend=backend, optim
24 isa_ansatz = pm.run(ansatz)
25 isa_observable = observable.apply_layout(layout=isa_ansa
26
27
28 # Set estimator options
29 estimator_options = EstimatorOptions(resilience_level=1,
30
31 # Open a Runtime session:
32
33 with Session(backend=backend) as session:
34 estimator = Estimator(mode=session, options=estimato
35 cost = cost_func_vqe(theta_list, isa_ansatz, isa_obs
36
37 session.close()
38 print(cost)

 

Note that the values obtained from the two calculations above are very
similar. Techniques for improving results will be discussed further below.

Example mapping to non-physical systems

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 14/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

The maximum cut (Max-Cut) problem is a combinatorial optimization


problem that involves dividing the vertices of a graph into two disjoint sets
such that the number of edges between the two sets is maximized. More
formally, given an undirected graph G = (V , E), where V is the set of
vertices and E is the set of edges, the Max-Cut problem asks to partition the
vertices into two disjoint subsets, S and T , such that the number of edges
with one endpoint in S and the other in T is maximized.

We can apply Max-Cut to solve a various problems including: clustering,


network design, phase transitions, etc. We'll start by creating a problem
graph:

1 import rustworkx as rx
2 from rustworkx.visualization import mpl_draw
3
4 n = 4
5 G = rx.PyGraph()
6 G.add_nodes_from(range(n))
7 # The edge syntax is (start, end, weight)
8 edges = [(0, 1, 1.0), (0, 2, 1.0), (0, 3, 1.0), (1, 2, 1
9 G.add_edges_from(edges)
10
11 mpl_draw(
12 G, pos=rx.shell_layout(G), with_labels=True, edge_la
13 )

 

Output:

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 15/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

This problem can be expressed as a binary optimization problem. For each


node 0 ≤ i < n, where n is the number of nodes of the graph (in this case
n = 4), we will consider the binary variable xi . This variable will have the ​

value 1 if node i is one of the groups that we'll label 1 and 0 if it's in the
other group, that we'll label as 0. We will also denote as wij (element (i, j) ​

of the adjacency matrix w ) the weight of the edge that goes from node i to
node j . Because the graph is undirected, wij = wji . Then we can formulate
​ ​

our problem as maximizing the following cost function:


n
C(x) = ∑ wij xi (1 − xj )
​ ​ ​ ​

i,j=0
n n


= ∑ wij xi − ∑ wij xi xj
​ ​ ​ ​ ​ ​ ​

i,j=0 i,j=0
n n i
= ∑ wij xi − ∑ ∑ 2wij xi xj
​ ​ ​ ​ ​ ​ ​ ​

i,j=0 i=0 j=0

To solve this problem with a quantum computer, we are going to express the
cost function as the expected value of an observable. However, the
observables that Qiskit admits natively consist of Pauli operators, that have

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 16/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

eigenvalues 1 and −1 instead of 0 and 1. That's why we are going to make


the following change of variable:

Where x = (x0 , x1 , ⋯ , xn−1 ). We can use the adjacency matrix w to


​ ​

comfortably access the weights of all the edge. This will be used to obtain
our cost function:

1 − zi
zi = 1 − 2xi → xi =

2
​ ​ ​ ​

This implies that:

xi = 0 → z i = 1
​ ​

xi = 1 → zi = −1.
​ ​ ​

​ ​

So the new cost function we want to maximize is:


n
1 − zi 1 − zj
C(z ) = ∑ wij ( )(1 − )
​ ​

2 2
​ ​ ​ ​

i,j=0
n n
wij wij
=∑ −∑
​ ​

zi zj
4 4
​ ​ ​ ​ ​ ​

​ ​

i,j=0 i,j=0
n i n i
wij wij
= ∑∑ − ∑∑
​ ​

zi zj
2 2
​ ​ ​ ​ ​ ​ ​ ​

i=0 j=0 i=0 j=0

Moreover, the natural tendency of a quantum computer is to find minima


(usually the lowest energy) instead of maxima so instead of maximizing
C(z ) we are going to minimize:
n i n i
wij wij
−C(z ) = ∑ ∑ zi zj − ∑ ∑
​ ​

2 2
​ ​ ​ ​ ​ ​ ​ ​

i=0 j=0 i=0 j=0

Now that we have a cost function to minimize whose variables can have the
values −1 and 1, we can make the following analogy with the Pauli Z :
n−1 i 0

zi ≡ Zi = I ⊗ ... ⊗ Z ⊗ ... ⊗ I
​ ​

In other words, the variable zi will be equivalent to a Z gate acting on qubit


i. Moreover:

Zi ∣xn−1 ⋯ x0 ⟩ = zi ∣xn−1 ⋯ x0 ⟩ → ⟨xn−1 ⋯ x0 ∣Zi ∣xn−1 ⋯ x0 ⟩ = zi


​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 17/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

Then the observable we are going to consider is:

n i
^ = ∑ ∑ wij Zi Zj
H

2
​ ​ ​ ​ ​

i=0 j=0

to which we will have to add the independent term afterwards:

n i
wij
offset = − ∑ ∑

2
​ ​ ​

i=0 j=0

The operator is a linear combination of terms with Z operators on nodes


connected by an edge (recall that the 0th qubit is farthest right): IIZZ +
IZIZ + IZZI + ZIIZ + ZZII . Once the operator is constructed, the
ansatz for the QAOA algorithm can easily be built by using the QAOAAnsatz
circuit from the Qiskit circuit library.

1 from qiskit.circuit.library import QAOAAnsatz


2 from qiskit.quantum_info import SparsePauliOp
3
4 hamiltonian = SparsePauliOp.from_list(
5 [("IIZZ", 1), ("IZIZ", 1), ("IZZI", 1), ("ZIIZ", 1),
6 )
7
8
9 ansatz = QAOAAnsatz(hamiltonian, reps=2)
10 # Draw
11 ansatz.decompose(reps=3).draw("mpl")

 

Output:

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 18/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

1 # Sum the weights, and divide by 2


2
3 offset = -sum(edge[2] for edge in edges) / 2
4 print(f"""Offset: {offset}""")

Output:

Offset: -2.5

With the Runtime Estimator directly taking a Hamiltonian and parameterized


ansatz, and returning the necessary energy, The cost function for a QAOA
instance is quite simple:

1 def cost_func(params, ansatz, hamiltonian, estimator):


2 """Return estimate of energy from estimator
3
4 Parameters:
5 params (ndarray): Array of ansatz parameters
6 ansatz (QuantumCircuit): Parameterized ansatz ci
7 hamiltonian (SparsePauliOp): Operator representa
8 estimator (Estimator): Estimator primitive insta
9
10 Returns:
11 float: Energy estimate
12 """
13 pub = (ansatz, hamiltonian, params)
14 cost = estimator.run([pub]).result()[0].data.evs
15 # cost = estimator.run(ansatz, hamiltonian, param
16 return cost

 

1 import numpy as np
2
3 x0 = 2 * np.pi * np.random.rand(ansatz.num_parameters)
4
5 estimator = StatevectorEstimator()
6 cost = cost_func_vqe(x0, ansatz, hamiltonian, estimator)
7 print(cost)

 

Output:

1.473098768180865

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 19/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

1 # Estimated usage: < 1 min, benchmarked at 6 seconds on


2 # Load some necessary packages:
3
4 from qiskit_ibm_runtime import QiskitRuntimeService
5 from qiskit_ibm_runtime import Session, EstimatorV2 as E
6
7 # Select the least busy backend:
8
9 backend = service.least_busy(
10 operational=True, min_num_qubits=ansatz.num_qubits,
11 )
12
13 # Or get a specific backend:
14 # backend = service.backend("ibm_cusco")
15
16 # Use a pass manager to transpile the circuit and observ
17
18 pm = generate_preset_pass_manager(backend=backend, optim
19 isa_ansatz = pm.run(ansatz)
20 isa_hamiltonian = hamiltonian.apply_layout(layout=isa_an
21
22 # Set estimator options
23 estimator_options = EstimatorOptions(resilience_level=1,
24
25 # Open a Runtime session:
26
27 with Session(backend=backend) as session:
28 estimator = Estimator(mode=session, options=estimato
29 cost = cost_func_vqe(x0, isa_ansatz, isa_hamiltonian
30
31 # Close session after done
32 session.close()
33 print(cost)

 

Output:

1.1120776913677988

We will revisit this example in Applications to explore how to leverage an


optimizer to iterate through the search space. Generally speaking, this
includes:

Leveraging an optimizer to find optimal parameters

Binding optimal parameters to the ansatz to find the eigenvalues


https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 20/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

Translating the eigenvalues to our problem definition

Measurement strategy: speed versus


accuracy

As mentioned, we are using a noisy quantum computer as a black-box


oracle, where noise can make the retrieved values non-deterministic,
leading to random fluctuations which, in turn, will harm — or even
completely prevent — convergence of certain optimizers to a proposed
solution. This is a general problem that we must address as we
incrementally explore quantum utility and progress towards quantum
advantage:

We can use Qiskit Runtime Primitive's error suppression and error mitigation
options to address noise and maximize the utility of today's quantum
computers.

Error Suppression

Error suppression refers to techniques used to optimize and transform a


circuit during compilation in order to minimize errors. This is a basic error

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 21/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

handling technique that usually results in some classical pre-processing


overhead to the overall runtime. The overhead includes transpiling circuits
to run on quantum hardware by:

Expressing the circuit using the native gates available on a quantum


system

Mapping the virtual qubits to physical qubits

Adding SWAPs based on connectivity requirements

Optimizing 1Q and 2Q gates

Adding dynamical decoupling to idle qubits to prevent the effects of


decoherence.

Primitives allow for the use of error suppression techniques by setting the
optimization_level option and selecting advanced transpilation options.
In a later course, we will delve into different circuit construction methods to
improve results, but for most cases, we recommend setting
optimization_level=3 .

We will visualize the value of increasing optimization in the transpilation


process by looking at an example circuit with a simple ideal behavior.

1 from qiskit.circuit import Parameter, QuantumCircuit


2 from qiskit.quantum_info import SparsePauliOp
3
4 theta = Parameter("theta")
5
6 qc = QuantumCircuit(2)
7 qc.x(1)
8 qc.h(0)
9 qc.cp(theta, 0, 1)
10 qc.h(0)
11 observables = SparsePauliOp.from_list([("ZZ", 1)])
12
13 qc.draw("mpl")

 

Output:

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 22/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

The circuit above can yield sinusoidal expectation values of the observable
given, provided we insert phases spanning an appropriate interval, such as
[0, 2π].

1 ## Setup phases
2 import numpy as np
3
4 phases = np.linspace(0, 2 * np.pi, 50)
5
6 # phases need to be expressed as a list of lists in order
7 individual_phases = [[phase] for phase in phases]

 

We can use a simulator to show the usefulness of an optimized transpilation.


We will return below to using real hardware to demonstrate the usefulness
of error mitigation. We will use QiskitRuntimeService to get a real backend
(in this case, ibm_sherbrooke), and use AerSimulator to simulate that
backend, including its noise behavior.

1 from qiskit_ibm_runtime import QiskitRuntimeService


2 from qiskit_aer import AerSimulator
3
4 # get a real backend from the runtime service
5 service = QiskitRuntimeService()
6 backend = service.backend("ibm_sherbrooke")
7
8 # generate a simulator that mimics the real quantum syste
9 backend_sim = AerSimulator.from_backend(backend)

 

We can now use a pass manager to transpile the circuit into the "instruction
set architecture" or ISA of the backend. This is a new requirement in Qiskit
Runtime: all circuits submitted to a backend must conform to the
constraints of the backend’s target, meaning they must be written in terms

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 23/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

of the backend's ISA — i.e., the set of instructions the device can understand
and execute. These target constraints are defined by factors like the device’s
native basis gates, its qubit connectivity, and - when relevant - its pulse and
other instruction timing specifications.

Note that in the present case, we will do this twice: once with
optimization_level = 0, and once with it set to 3. Each time we will use the
Estimator primitive to estimate the expectation values of the observable at
different values of phase.

1 # Import estimator and specify that we are using the simu


2
3 from qiskit_ibm_runtime import EstimatorV2 as Estimator
4
5 estimator = Estimator(mode=backend_sim)
6
7 circuit = qc

 

1 # Use a pass manager to transpile the circuit and observ


2 # Start with no optimization:
3
4 from qiskit.transpiler.preset_passmanagers import genera
5
6 pm = generate_preset_pass_manager(backend=backend_sim, o
7 isa_circuit = pm.run(circuit)
8 isa_observables = observables.apply_layout(layout=isa_ci
9
10 noisy_exp_values = []
11 pub = (isa_circuit, isa_observables, [individual_phases]
12 cost = estimator.run([pub]).result()[0].data.evs
13 noisy_exp_values = cost[0]
14
15 # Repeat above steps, but now with optimization = 3:
16
17 exp_values_with_opt_es = []
18 pm = generate_preset_pass_manager(backend=backend_sim, o
19 isa_circuit = pm.run(circuit)
20 isa_observables = observables.apply_layout(layout=isa_ci
21
22 pub = (isa_circuit, isa_observables, [individual_phases]
23 cost = estimator.run([pub]).result()[0].data.evs
24 exp_values_with_opt_es = cost[0]

 

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 24/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

Finally, we can plot the results, and we see that the precision of the
calculation was fairly good even without optimization, but it definitely
improved by increasing optimization to level 3. Note that in deeper, more
complicated circuits, the difference between optimization levels of 0 and 3
are likely to be more significant. This is a very simple circuit used as a toy
model.

1 import matplotlib.pyplot as plt


2
3 plt.plot(phases, noisy_exp_values, "o", label="opt=0")
4 plt.plot(phases, exp_values_with_opt_es, "o", label="opt=
5 plt.plot(phases, 2 * np.sin(phases / 2) ** 2 - 1, label="
6 plt.ylabel("Expectation")
7 plt.legend()
8 plt.show()

 

Output:

Error Mitigation

Error mitigation refers to techniques that allow users to reduce circuit errors
by modeling the device noise at the time of execution. Typically, this results
in quantum pre-processing overhead related to model training and classical

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 25/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

post-processing overhead to mitigate errors in the raw results by using the


generated model.

The Qiskit Runtime primitive's resilience_level option specifies the


amount of resilience to build against errors. Higher levels generate more
accurate results at the expense of longer processing times due to quantum
sampling overhead. Resilience levels can be used to configure the trade-off
between cost and accuracy when applying error mitigation to your primitive
query.

When implementing any error mitigation technique, we expect the bias in


our results to be reduced with respect to the previous, unmitigated bias. In
some cases, the bias may even disappear. However, this comes at a cost. As
we reduce the bias in our estimated quantities, the statistical variability will
increase (that is, variance), which we can account for by further increasing
the number of shots per circuit in our sampling process. This will introduce
overhead beyond that needed to reduce the bias, so it is not done by default.
We can easily opt-in to this behavior by adjusting the number of shots per
circuit in options.executions.shots, as shown in the example below.

For this course, we will explore these error mitigation models at a high level
to illustrate the error mitigation that Qiskit Runtime primitives can perform
without requiring full implementation details.

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 26/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

Twirled readout error extinction (T-REx)

Twirled readout error extinction (T-REx) uses a technique known as Pauli


twirling to reduce the noise introduced during the process of quantum
measurement. This technique assumes no specific form of noise, which
makes it very general and effective.

Overall workflow:

1. Acquire data for the zero state with randomized bit flips (Pauli X before
measurement)

2. Acquire data for the desired (noisy) state with randomized bit flips
(Pauli X before measurement)

3. Compute the special function for each data set, and divide.

We can set this with options.resilience_level = 1 , demonstrated in


the example below.

Zero noise extrapolation

Zero noise extrapolation (ZNE) works by first amplifying the noise in the
circuit that is preparing the desired quantum state, obtaining measurements
for several different levels of noise, and using those measurements to infer
the noiseless result.

Overall workflow:

1. Amplify circuit noise for several noise factors

2. Run every noise amplified circuit

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 27/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

3. Extrapolate back to the zero noise limit

We can set this with options.resilience_level = 2 . We can optimize


this further by exploring a variety of noise_factors , noise_amplifiers ,
and extrapolators , but this is outside the scope of this course. We
encourage you to experiment with these options as described here.

Each method comes with its own associated overhead: a trade-off between
the number of quantum computations needed (time) and the accuracy of
our results:

Methods R = 1, T-REx R = 2, ZNE


Assumptions None Ability to scale noise
Qubit overhead ​
1 ​
1 ​ ​

Sampling overhead 2 Nnoise-factors


Bias 0 O(λNnoise-factors )

Using Qiskit Runtime's mitigation and suppression options

Here's how to calculate an expectation value while using error mitigation


and suppression in Qiskit Runtime. We can make use of precisely the same
circuit and observable as before, but this time keeping the optimization level
fixed at level 2, and now tuning the resilience or the error mitigation
technique(s) being used. This error mitigation process occurs multiple times
throughout an optimization loop.

We perform this part on real hardware, since error mitigation is not available
on simulators.

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 28/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

1 # Estimated usage: 8 minutes, benchmarked on ibm_sherbro


2
3 from qiskit_ibm_runtime import QiskitRuntimeService
4 from qiskit_ibm_runtime import (
5 Session,
6 EstimatorOptions,
7 EstimatorV2 as Estimator,
8 )
9
10 # We select the least busy backend
11
12 # Select the least busy backend
13 # backend = service.least_busy(
14 # operational=True, min_num_qubits=ansatz.num_qubits,
15 # )
16
17 # Or use a specific backend
18 backend = service.backend("ibm_cusco")
19
20 # Initialize some variables to save the results from dif
21
22 exp_values_with_em0_es = []
23 exp_values_with_em1_es = []
24 exp_values_with_em2_es = []
25
26 # Use a pass manager to optimize the circuit and observa
27
28 pm = generate_preset_pass_manager(backend=backend, optim
29 isa_circuit = pm.run(circuit)
30 isa_observables = observables.apply_layout(layout=isa_ci
31
32 # Open a session and run with no error mitigation:
33
34 estimator_options = EstimatorOptions(resilience_level=0,
35
36 with Session(backend=backend) as session:
37 estimator = Estimator(mode=session, options=estimato
38
39 pub = (isa_circuit, isa_observables, [individual_pha
40 cost = estimator.run([pub]).result()[0].data.evs
41
42 session.close()
43
44 exp_values_with_em0_es = cost[0]
45
46 # Open a session and run with resilience = 1:
47
48 estimator_options = EstimatorOptions(resilience_level=1,
49
https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 29/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning
49
50 with Session(backend=backend) as session:
51 estimator = Estimator(mode=session, options=estimato
52
53 pub = (isa_circuit, isa_observables, [individual_pha
54 cost = estimator.run([pub]).result()[0].data.evs
55
56 session.close()
57
58 exp_values_with_em1_es = cost[0]
59
60 # Open a session and run with resilience = 2:
61
62 estimator_options = EstimatorOptions(resilience_level=2,
63
64 with Session(backend=backend) as session:
65 estimator = Estimator(mode=session, options=estimato
66
67 pub = (isa_circuit, isa_observables, [individual_pha
68 cost = estimator.run([pub]).result()[0].data.evs
69
70 session.close()
71
72 exp_values_with_em2_es = cost[0]

 
As before, we can plot the resulting expectation values as a function of
phase angle for the three levels of error mitigation used. With great
difficulty, one can see that error mitigation improves the results slightly.
Again, this effect is much more pronounced in deeper, more complicated
circuits.

1 import matplotlib.pyplot as plt


2
3 plt.plot(phases, exp_values_with_em0_es, "o", label="unmi
4 plt.plot(phases, exp_values_with_em1_es, "o", label="resi
5 plt.plot(phases, exp_values_with_em2_es, "o", label="resi
6 plt.plot(phases, 2 * np.sin(phases / 2) ** 2 - 1, label="
7 plt.ylabel("Expectation")
8 plt.legend()
9 plt.show()

 

Output:

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 30/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

Summary

With this lesson, you learned how to create a cost function:

Create a cost function

How to leverage Qiskit Runtime primitives to mitigate and


suppression noise

How to define a measurement strategy to optimize speed vs accuracy

Here's our high-level variational workload:

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 31/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning

Our cost function runs during every iteration of the optimization loop. The
next lesson will explore how the classical optimizer uses our cost function
evaluation to select new parameters.

1 import qiskit
2 import qiskit_ibm_runtime
3
4 print(qiskit.version.get_version_info())
5 print(qiskit_ibm_runtime.version.get_version_info())

 

Output:

1.1.0
0.23.0

Was this page helpful?

Yes No

Report a bug or request content on GitHub .

Previous page Start the next lesson

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 32/33
7/24/25, 10:56 AM Cost functions | IBM Quantum Learning
© IBM Corp., 2017-2025

https://quantum.cloud.ibm.com/learning/en/courses/variational-algorithm-design/cost-functions 33/33

You might also like