Note
This page was generated from docs/tutorials/04_grover_optimizer.ipynb.
Grover Optimizer#
Introduction#
Grover Adaptive Search (GAS) has been explored as a possible solution for combinatorial optimization problems, alongside variational algorithms such as Variational Quantum Eigensolver (VQE) and Quantum Approximate Optimization Algorithm (QAOA). The algorithm iteratively applies Grover Search to find the optimum value of an objective function, by using the best-known value from the previous run as a threshold. The adaptive oracle used in GAS recognizes all values above or below the current threshold (for max and min respectively), decreasing the size of the search space every iteration the threshold is updated, until an optimum is found.
In this notebook we will explore each component of the GroverOptimizer
, which utilizes the techniques described in GAS, by minimizing a Quadratic Unconstrained Binary Optimization (QUBO) problem, as described in [1]
References#
Grover Adaptive Search#
Grover Search, the core element of GAS, needs three ingredients:
A state preparation operator
to construct a superposition of all states in the search space.An oracle operator
, that recognizes the states of interest and multiplies their amplitudes by -1.The Grover diffusion operator
, that multiplies the amplitude of the state by -1.
While implementations of GAS vary around the specific use case, the general framework still loosely follows the steps described below.
GroverOptimizer
uses QuadraticProgramToNegativeValueOracle
to construct
Put formally, QuadraticProgramToNegativeValueOracle
constructs an
where
At each iteration in which the threshold
Find the Minimum of a QUBO Problem using GroverOptimizer#
The following is a toy example of a minimization problem.
For our initial steps, we create a docplex model that defines the problem above, and then use the from_docplex_mp()
function to convert the model to a QuadraticProgram
, which can be used to represent a QUBO in Qiskit Optimization.
[1]:
from qiskit_algorithms import NumPyMinimumEigensolver
from qiskit.primitives import Sampler
from qiskit_optimization.algorithms import GroverOptimizer, MinimumEigenOptimizer
from qiskit_optimization.translators import from_docplex_mp
from docplex.mp.model import Model
[2]:
model = Model()
x0 = model.binary_var(name="x0")
x1 = model.binary_var(name="x1")
x2 = model.binary_var(name="x2")
model.minimize(-x0 + 2 * x1 - 3 * x2 - 2 * x0 * x2 - 1 * x1 * x2)
qp = from_docplex_mp(model)
print(qp.prettyprint())
Problem name: docplex_model1
Minimize
-2*x0*x2 - x1*x2 - x0 + 2*x1 - 3*x2
Subject to
No constraints
Binary variables (3)
x0 x1 x2
Next, we create a GroverOptimizer
that uses 6 qubits to encode the value, and will terminate after there have been 10 iterations of GAS without progress (i.e. the value of solve()
function takes the QuadraticProgram
we created earlier, and returns a results object that contains information about the run.
[3]:
grover_optimizer = GroverOptimizer(6, num_iterations=10, sampler=Sampler())
results = grover_optimizer.solve(qp)
print(results.prettyprint())
objective function value: -6.0
variable values: x0=1.0, x1=0.0, x2=1.0
status: SUCCESS
This results in the optimal solution GroverOptimizer
applied to this QUBO.
Each graph shows a single iteration of GAS, with the current values of
Check that GroverOptimizer finds the correct value#
We can verify that the algorithm is working correctly using the MinimumEigenOptimizer
in Qiskit optimization.
[4]:
exact_solver = MinimumEigenOptimizer(NumPyMinimumEigensolver())
exact_result = exact_solver.solve(qp)
print(exact_result.prettyprint())
objective function value: -6.0
variable values: x0=1.0, x1=0.0, x2=1.0
status: SUCCESS
[5]:
import tutorial_magics
%qiskit_version_table
%qiskit_copyright
Version Information
Software | Version |
---|---|
qiskit | 1.0.1 |
qiskit_algorithms | 0.3.0 |
qiskit_optimization | 0.6.1 |
System information | |
Python version | 3.8.18 |
OS | Linux |
Wed Feb 28 02:58:05 2024 UTC |
This code is a part of a Qiskit project
© Copyright IBM 2017, 2024.
This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.
[ ]: