Quantum approximate optimization algorithm
דף זה טרם תורגם. התוכן מוצג באנגלית.
Usage estimate: 22 minutes on a Heron r3 processor (NOTE: This is an estimate only. Your runtime might vary.)
Background
This tutorial demonstrates how to implement the Quantum Approximate Optimization Algorithm (QAOA) – a hybrid (quantum-classical) iterative method – within the context of Qiskit patterns. You will first solve the Maximum-Cut (or Max-Cut) problem for a small graph and then learn how to execute it at utility scale. All the hardware executions in the tutorial should run within the time limit for the freely-accessible Open Plan.
The Max-Cut problem is an optimization problem that is hard to solve (more specifically, it is an NP-hard problem) with a number of different applications in clustering, network science, and statistical physics. This tutorial considers a graph of nodes connected by edges, and aims to partition the nodes into two sets such that the number of edges traversed by this cut is maximized.

Requirements
Before starting this tutorial, be sure you have the following installed:
- Qiskit SDK v1.0 or later, with visualization support
- Qiskit Runtime v0.22 or later (
pip install qiskit-ibm-runtime)
In addition, you will need access to an instance on IBM Quantum Platform. Note that this tutorial cannot be executed on the Open Plan, because it runs workloads using sessions, which are only available with Premium Plan access.
Setup
import matplotlib
import matplotlib.pyplot as plt
import rustworkx as rx
from rustworkx.visualization import mpl_draw as draw_graph
import numpy as np
from scipy.optimize import minimize
from collections import defaultdict
from typing import Sequence
from qiskit.quantum_info import SparsePauliOp
from qiskit.circuit.library import QAOAAnsatz
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit_ibm_runtime import Session, EstimatorV2 as Estimator
from qiskit_ibm_runtime import SamplerV2 as Sampler
Part I. Small-scale QAOA
The first part of this tutorial uses a small-scale Max-Cut problem to illustrate the steps to solve an optimization problem using a quantum computer.
To give some context before mapping this problem to a quantum algorithm, you can better understand how the Max-Cut problem becomes a classical combinatorial optimization problem by first considering the minimization of a function
where the input is a vector whose components correspond to each node of a graph. Then, constrain each of these components to be either or (which represent being included or not included in the cut). This small-scale example case uses a graph with nodes.
You could write a function of a pair of nodes which indicates whether the corresponding edge is in the cut. For example, the function is 1 only if one of either or are 1 (which means that the edge is in the cut) and zero otherwise. The problem of maximizing the edges in the cut can be formulated as
which can be rewritten as a minimization of the form
The minimum of in this case is when the number of edges traversed by the cut is maximal. As you can see, there is nothing relating to quantum computing yet. You need to reformulate this problem into something that a quantum computer can understand. Initialize your problem by creating a graph with nodes.
n = 5
graph = rx.PyGraph()
graph.add_nodes_from(np.arange(0, n, 1))
edge_list = [
(0, 1, 1.0),
(0, 2, 1.0),
(0, 4, 1.0),
(1, 2, 1.0),
(2, 3, 1.0),
(3, 4, 1.0),
]
graph.add_edges_from(edge_list)
draw_graph(graph, node_size=600, with_labels=True)

Step 1: Map classical inputs to a quantum problem
The first step of the pattern is to map the classical problem (graph) into quantum circuits and operators. To do this, there are three main steps to take:
- Utilize a series of mathematical reformulations, to represent this problem using the Quadratic Unconstrained Binary Optimization (QUBO) problems notation.
- Rewrite the optimization problem as a Hamiltonian for which the ground state corresponds to the solution which minimizes the cost function.
- Create a quantum circuit which will prepare the ground state of this Hamiltonian via a process similar to quantum annealing.
Note: In the QAOA methodology, you ultimately want to have an operator (Hamiltonian) that represents the cost function of our hybrid algorithm, as well as a parametrized circuit (Ansatz) that represents quantum states with candidate solutions to the problem. You can sample from these candidate states and then evaluate them using the cost function.
Graph → optimization problem
The first step of the mapping is a notation change, The following expresses the problem in QUBO notation:
where is a matrix of real numbers, corresponds to the number of nodes in your graph, is the vector of binary variables introduced above, and indicates the transpose of the vector .
Maximize
-2*x_0*x_1 - 2*x_0*x_2 - 2*x_0*x_4 - 2*x_1*x_2 - 2*x_2*x_3 - 2*x_3*x_4 + 3*x_0
+ 2*x_1 + 3*x_2 + 2*x_3 + 2*x_4
Subject to
No constraints
Binary variables (5)
x_0 x_1 x_2 x_3 x_4
Optimization problem → Hamiltonian
You can then reformulate the QUBO problem as a Hamiltonian (here, a matrix that represents the energy of a system):
Reformulation steps from the QAOA problem to the Hamiltonian
To demonstrate how the QAOA problem can be rewritten in this way, first replace the binary variables to a new set of variables via
Here you can see that if is , then must be . When the 's are substituted for the 's in the optimization problem (), an equivalent formulation can be obtained.
Now if we define , remove the prefactor, and the constant term, we arrive at the two equivalent formulations of the same optimization problem.
Here, depends on . Note that to obtain we dropped the factor of 1/4 and a constant offset of which do not play a role in the optimization.
Now, to obtain a quantum formulation of the problem, promote the variables to a Pauli matrix, such as a matrix of the form
When you substitute these matrices in the optimization problem above, you obtain the following Hamiltonian
Also recall that the matrices are embedded in the quantum computer's computational space, that is, a Hilbert space of size . Therefore, you should understand terms such as as the tensor product embedded in the Hilbert space. For example, in a problem with five decision variables the term is understood to mean where is the identity matrix.
This Hamiltonian is called the cost function Hamiltonian. It has the property that its ground state corresponds to the solution that minimizes the cost function . Therefore, to solve your optimization problem you now need to prepare the ground state of (or a state with a high overlap with it) on the quantum computer. Then, sampling from this state will, with a high probability, yield the solution to . Now let us consider the Hamiltonian for the Max-Cut problem. Let each vertex of the graph be associated with a qubit in state or , where the value denotes the set the vertex is in. The goal of the problem is to maximize the number of edges for which and , or vice-versa. If we associate the operator with each qubit, where
then an edge belongs to the cut if the eigenvalue of ; in other words, the qubits associated with and are different. Similarly, does not belong to the cut if the eigenvalue of . Note that, we do not care about the exact qubit state associated with each vertex, rather we care only whether they are same or not across an edge. The Max-Cut problem requires us to find an assignment of the qubits on the vertices such that the eigenvalue of the following Hamiltonian is minimized
In other words, for all in the Max-Cut problem. The value of denotes the weight of the edge. In this tutorial we consider an unweighted graph, that is, for all .
def build_max_cut_paulis(
graph: rx.PyGraph,
) -> list[tuple[str, list[int], float]]:
"""Convert the graph to Pauli list.
This function does the inverse of `build_max_cut_graph`
"""
pauli_list = []
for edge in list(graph.edge_list()):
weight = graph.get_edge_data(edge[0], edge[1])
pauli_list.append(("ZZ", [edge[0], edge[1]], weight))
return pauli_list
max_cut_paulis = build_max_cut_paulis(graph)
cost_hamiltonian = SparsePauliOp.from_sparse_list(max_cut_paulis, n)
print("Cost Function Hamiltonian:", cost_hamiltonian)
Cost Function Hamiltonian: SparsePauliOp(['IIIZZ', 'IIZIZ', 'ZIIIZ', 'IIZZI', 'IZZII', 'ZZIII'],
coeffs=[1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j, 1.+0.j])
Hamiltonian → quantum circuit
The Hamiltonian contains the quantum definition of your problem. Now you can create a quantum circuit that will help sample good solutions from the quantum computer. The QAOA is inspired by quantum annealing and applies alternating layers of operators in the quantum circuit.
The general idea is to start in the ground state of a known system, above, and then steer the system into the ground state of the cost operator that you are interested in. This is done by applying the operators and