Minimum Eigen Optimizer¶
Introduction¶
An interesting class of optimization problems to be addressed by quantum computing are Quadratic Unconstrained Binary Optimization (QUBO) problems. QUBO is equivalent to finding the ground state of a corresponding Hamiltonian, which is an important problem not only in optimization, but also in quantum chemistry and physics. For this translation, the binary variables taking values in \(\{0, 1\}\) are replaced by spin variables taking values in \(\{-1, +1\}\), which allows to replace the resulting spin variables by Pauli Z matrices, and thus, an Hamiltonian. For more details on this mapping we refere to [1].
Qiskit provides automatic conversion from a suitable QuadraticProgram
to an Ising Hamiltonian, which then allows to leverage all the MinimumEigenSolver
available in Qiskit Aqua, such as - VQE
, - QAOA
, or - NumpyMinimumEigensolver
(classical exact method).
Qiskit wraps the translation to an Ising Hamiltonian (in Qiskit Aqua also called Operator
), the call to an MinimumEigensolver
as well as the translation of the results back to OptimizationResult
in the MinimumEigenOptimizer
.
In the following we first illustrate the conversion from a QuadraticProgram
to an Operator
and then show how to use the MinimumEigenOptimizer
with different MinimumEigensolver
to solve a given QuadraticProgram
. The algorithms in Qiskit automatically try to convert a given problem to the supported problem class if possible, for instance, the MinimumEigenOptimizer
will automatically translate integer variables to binary variables or add a linear equality constraints as a
quadratic penalty term to the objective. It should be mentioned that Aqua will through a QiskitOptimizationError
if conversion of a quadratic program with integer variable is attempted.
The circuit depth of QAOA
potentially has to be increased with the problem size, which might be prohibitive for near-term quantum devices. A possible workaround is Recursive QAOA, as introduced in [2]. Qiskit generalizes this concept to the RecursiveMinimumEigenOptimizer
, which is introduced at the end of this tutorial.
Converting a QUBO to an Operator¶
[1]:
from qiskit import BasicAer
from qiskit.aqua.algorithms import QAOA, NumPyMinimumEigensolver
from qiskit.optimization.algorithms import MinimumEigenOptimizer, RecursiveMinimumEigenOptimizer
from qiskit.optimization import QuadraticProgram
from qiskit.optimization.converters import QuadraticProgramToIsing
[2]:
# create a QUBO
qubo = QuadraticProgram()
qubo.binary_var('x')
qubo.binary_var('y')
qubo.binary_var('z')
qubo.minimize(linear=[1,-2,3], quadratic={('x', 'y'): 1, ('x', 'z'): -1, ('y', 'z'): 2})
print(qubo.export_as_lp_string())
\ This file has been generated by DOcplex
\ ENCODING=ISO-8859-1
\Problem name: CPLEX
Minimize
obj: x - 2 y + 3 z + [ 2 x*y - 2 x*z + 4 y*z ]/2
Subject To
Bounds
0 <= x <= 1
0 <= y <= 1
0 <= z <= 1
Binaries
x y z
End
Next we translate this QUBO into an Ising operator. This results not only in an Operator
but also in a constant offset to be taking into account to shift the resulting value.
[3]:
qp2op = QuadraticProgramToIsing()
op, offset = qp2op.encode(qubo)
print('offset: {}'.format(offset))
print('operator:')
print(op.print_details())
offset: 1.5
operator:
IIZ (-0.5+0j)
IZI (0.25+0j)
ZII (-1.75+0j)
IZZ (0.25+0j)
ZIZ (-0.25+0j)
ZZI (0.5+0j)
Sometimes an QuadraticProgram
might also directly be given in the form of an Operator
. For such cases, Qiskit also provides a converter from an Operator
back to a QuadraticProgram
, which we illustrate in the following.
[4]:
from qiskit.optimization.converters import IsingToQuadraticProgram
[5]:
op2qp = IsingToQuadraticProgram()
print(op2qp.encode(op, offset).export_as_lp_string())
\ This file has been generated by DOcplex
\ ENCODING=ISO-8859-1
\Problem name: CPLEX
Minimize
obj: [ 2 x_0^2 + 2 x_0*x_1 - 2 x_0*x_2 - 4 x_1^2 + 4 x_1*x_2 + 6 x_2^2 ]/2
Subject To
Bounds
0 <= x_0 <= 1
0 <= x_1 <= 1
0 <= x_2 <= 1
Binaries
x_0 x_1 x_2
End
This converter allows, for instance, to translate an Operator
to a QuadraticProgram
and then solve the problem with other algorithms that are not based on the Ising Hamiltonian representation, such as the GroverOptimizer
.
Solving a QUBO with the MinimumEigenOptimizer
¶
We start by initializing the MinimumEigensolver
we want to use.
[6]:
qaoa_mes = QAOA(quantum_instance=BasicAer.get_backend('statevector_simulator'))
exact_mes = NumPyMinimumEigensolver()
Then, we use the MinimumEigensolver
to create MinimumEigenOptimizer
.
[7]:
qaoa = MinimumEigenOptimizer(qaoa_mes) # using QAOA
exact = MinimumEigenOptimizer(exact_mes) # using the exact classical numpy minimum eigen solver
We first use the MinimumEigenOptimizer
based on the classical exact NumPyMinimumEigensolver
to get the optimal benchmark solution for this small example.
[8]:
exact_result = exact.solve(qubo)
print(exact_result)
x=[0.0,1.0,0.0], fval=-2.0
Next we apply the MinimumEigenOptimizer
based on QAOA
to the same problem.
[9]:
qaoa_result = qaoa.solve(qubo)
print(qaoa_result)
x=[0.0,1.0,0.0], fval=-2.0
RecursiveMinimumEigenOptimizer
¶
The RecursiveMinimumEigenOptimizer
takes a MinimumEigenOptimizer
as input and applies the recursive optimization scheme to reduce the size of the problem one variable at a time. Once the size of the generated intermediate problem is below a given threshold (min...
), the RecursiveMinimumEigenOptimizer
uses another solver (...
), e.g., an exact classical solver such as CPLEX or the MinimumEigenOptimizer
based on the NumPyMinimumEigensolver
.
In the following, we show how to use the RecursiveMinimumEigenOptimizer
using the two MinimumEigenOptimizer
introduced before.
First, we construct the RecursiveMinimumEigenOptimizer
such that it reduces the problem size from 3 variables to 1 variable and then uses the exact solver for the last variable. Then we call solve
to optimize the considered problem.
[10]:
rqaoa = RecursiveMinimumEigenOptimizer(min_eigen_optimizer=qaoa, min_num_vars=1, min_num_vars_optimizer=exact)
[11]:
rqaoa_result = rqaoa.solve(qubo)
print(rqaoa_result)
x=[0.0,1.0,0.0], fval=-2.0
[12]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Qiskit Software | Version |
---|---|
Qiskit | 0.19.6 |
Terra | 0.14.2 |
Aer | 0.5.2 |
Ignis | 0.3.3 |
Aqua | 0.7.3 |
IBM Q Provider | 0.7.2 |
System information | |
Python | 3.7.7 (default, May 6 2020, 04:59:01) [Clang 4.0.1 (tags/RELEASE_401/final)] |
OS | Darwin |
CPUs | 4 |
Memory (Gb) | 16.0 |
Fri Jul 10 15:15:58 2020 EDT |
This code is a part of Qiskit
© Copyright IBM 2017, 2020.
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.
[ ]: