Note
This page was generated from docs/tutorials/11_using_classical_optimization_solvers_and_models.ipynb.
Using Classical Optimization Solvers and Models with Qiskit Optimization¶
We can use classical optimization solvers (CPLEX and Gurobi) with Qiskit Optimization. Docplex and Gurobipy are the Python APIs for CPLEX and Gurobi, respectively. We can load and save an optimization model by Docplex and Gurobipy and can apply CPLEX and Gurobi to QuadraticProgram
.
If you want to use the CPLEX solver, you need to install pip install 'qiskit-optimization[cplex]'
. Docplex is automatically installed, as a dependent, when you install Qiskit Optimization.
If you want to use Gurobi and Gurobipy, you need to install pip install 'qiskit-optimization[gurobi]'
.
Note: these solvers, that are installed via pip, are free versions and come with some limitations, such as number of variables. The following links provide further details:
CplexSolver and GurobiSolver¶
Qiskit Optimization supports the classical solvers of CPLEX and Gurobi as CplexSolver
and GurobiSolver
, respectively. We can solve QuadraticProgram
with CplexSolver
and GurobiSolver
as follows.
[1]:
from qiskit_optimization.problems import QuadraticProgram
# define a problem
qp = QuadraticProgram()
qp.binary_var("x")
qp.integer_var(name="y", lowerbound=-1, upperbound=4)
qp.maximize(quadratic={("x", "y"): 1})
qp.linear_constraint({"x": 1, "y": -1}, "<=", 0)
print(qp.prettyprint())
Problem name:
Maximize
x*y
Subject to
Linear constraints (1)
x - y <= 0 'c0'
Integer variables (1)
-1 <= y <= 4
Binary variables (1)
x
[2]:
from qiskit_optimization.algorithms import CplexOptimizer, GurobiOptimizer
cplex_result = CplexOptimizer().solve(qp)
gurobi_result = GurobiOptimizer().solve(qp)
print("cplex")
print(cplex_result.prettyprint())
print()
print("gurobi")
print(gurobi_result.prettyprint())
Restricted license - for non-production use only - expires 2024-10-28
cplex
objective function value: 4.0
variable values: x=1.0, y=4.0
status: SUCCESS
gurobi
objective function value: 4.0
variable values: x=1.0, y=4.0
status: SUCCESS
We can set the solver parameter of CPLEX as follows. We can display the solver message of CPLEX by setting disp=True
. See Parameters of CPLEX for details of CPLEX parameters.
[3]:
result = CplexOptimizer(disp=True, cplex_parameters={"threads": 1, "timelimit": 0.1}).solve(qp)
print(result.prettyprint())
Version identifier: 22.1.0.0 | 2022-03-25 | 54982fbec
CPXPARAM_Read_DataCheck 1
CPXPARAM_Threads 1
CPXPARAM_TimeLimit 0.10000000000000001
Found incumbent of value 0.000000 after 0.00 sec. (0.00 ticks)
Found incumbent of value 4.000000 after 0.00 sec. (0.00 ticks)
Root node processing (before b&c):
Real time = 0.00 sec. (0.00 ticks)
Sequential b&c:
Real time = 0.00 sec. (0.00 ticks)
------------
Total (root+branch&cut) = 0.00 sec. (0.00 ticks)
objective function value: 4.0
variable values: x=1.0, y=4.0
status: SUCCESS
We get the same optimal solution by QAOA as follows.
[4]:
from qiskit_optimization.algorithms import MinimumEigenOptimizer
from qiskit_aer import Aer
from qiskit.algorithms.minimum_eigensolvers import QAOA
from qiskit.algorithms.optimizers import COBYLA
from qiskit.primitives import Sampler
meo = MinimumEigenOptimizer(QAOA(sampler=Sampler(), optimizer=COBYLA(maxiter=100)))
result = meo.solve(qp)
print(result.prettyprint())
print("\ndisplay the best 5 solution samples")
for sample in result.samples[:5]:
print(sample)
objective function value: 4.0
variable values: x=1.0, y=4.0
status: SUCCESS
display the best 5 solution samples
SolutionSample(x=array([1., 4.]), fval=4.0, probability=0.0016564197643766, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 3.]), fval=3.0, probability=0.18224989338090608, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 2.]), fval=2.0, probability=0.03242433314463279, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 1.]), fval=1.0, probability=0.24074431445411482, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([0., 0.]), fval=0.0, probability=0.0423276348481163, status=<OptimizationResultStatus.SUCCESS: 0>)
Translators between QuadraticProgram
and Docplex/Gurobipy¶
Qiskit Optimization can load QuadraticProgram
from a Docplex model and a Gurobipy model.
First, we define an optimization problem by Docplex and Gurobipy.
[5]:
# docplex model
from docplex.mp.model import Model
docplex_model = Model("docplex")
x = docplex_model.binary_var("x")
y = docplex_model.integer_var(-1, 4, "y")
docplex_model.maximize(x * y)
docplex_model.add_constraint(x <= y)
docplex_model.prettyprint()
// This file has been generated by DOcplex
// model name is: docplex
// single vars section
dvar bool x;
dvar int y;
maximize
[ x*y ];
subject to {
x <= y;
}
[6]:
# gurobi model
import gurobipy as gp
gurobipy_model = gp.Model("gurobi")
x = gurobipy_model.addVar(vtype=gp.GRB.BINARY, name="x")
y = gurobipy_model.addVar(vtype=gp.GRB.INTEGER, lb=-1, ub=4, name="y")
gurobipy_model.setObjective(x * y, gp.GRB.MAXIMIZE)
gurobipy_model.addConstr(x - y <= 0)
gurobipy_model.update()
gurobipy_model.display()
Maximize
0.0 + [ x * y ]
Subject To
R0: x + -1.0 y <= 0
Bounds
-1 <= y <= 4
Binaries
['x']
General Integers
['y']
We can generate QuadraticProgram
object from both Docplex and Gurobipy models. We see that the two QuadraticProgram
objects generated from Docplex and Gurobipy are identical.
[7]:
from qiskit_optimization.translators import from_docplex_mp, from_gurobipy
qp = from_docplex_mp(docplex_model)
print("QuadraticProgram obtained from docpblex")
print(qp.prettyprint())
print("-------------")
print("QuadraticProgram obtained from gurobipy")
qp2 = from_gurobipy(gurobipy_model)
print(qp2.prettyprint())
QuadraticProgram obtained from docpblex
Problem name: docplex
Maximize
x*y
Subject to
Linear constraints (1)
x - y <= 0 'c0'
Integer variables (1)
-1 <= y <= 4
Binary variables (1)
x
-------------
QuadraticProgram obtained from gurobipy
Problem name: gurobi
Maximize
x*y
Subject to
Linear constraints (1)
x - y <= 0 'R0'
Integer variables (1)
-1 <= y <= 4
Binary variables (1)
x
We can generate a Docplex model and a Gurobipy model from QuadraticProgram
too.
[8]:
from qiskit_optimization.translators import to_gurobipy, to_docplex_mp
gmod = to_gurobipy(from_docplex_mp(docplex_model))
print("convert docplex to gurobipy via QuadraticProgram")
gmod.display()
dmod = to_docplex_mp(from_gurobipy(gurobipy_model))
print("\nconvert gurobipy to docplex via QuadraticProgram")
print(dmod.export_as_lp_string())
convert docplex to gurobipy via QuadraticProgram
Maximize
0.0 + [ x * y ]
Subject To
c0: x + -1.0 y <= 0
Bounds
-1 <= y <= 4
Binaries
['x']
General Integers
['y']
convert gurobipy to docplex via QuadraticProgram
\ This file has been generated by DOcplex
\ ENCODING=ISO-8859-1
\Problem name: gurobi
Maximize
obj: [ 2 x*y ]/2
Subject To
R0: x - y <= 0
Bounds
0 <= x <= 1
-1 <= y <= 4
Binaries
x
Generals
y
End
Indicator constraints of Docplex¶
from_docplex_mp
supports indicator constraints, e.g., u = 0 => x + y <= z
(u: binary variable) when we convert a Docplex model into QuadraticProgram
. It converts indicator constraints into linear constraints using the big-M formulation.
[9]:
ind_mod = Model("docplex")
x = ind_mod.binary_var("x")
y = ind_mod.integer_var(-1, 2, "y")
z = ind_mod.integer_var(-1, 2, "z")
ind_mod.maximize(3 * x + y - z)
ind_mod.add_indicator(x, y >= z, 1)
print(ind_mod.export_as_lp_string())
\ This file has been generated by DOcplex
\ ENCODING=ISO-8859-1
\Problem name: docplex
Maximize
obj: 3 x + y - z
Subject To
lc1: x = 1 -> y - z >= 0
Bounds
0 <= x <= 1
-1 <= y <= 2
-1 <= z <= 2
Binaries
x
Generals
y z
End
Let’s compare the solutions of the model with an indicator constraint by
applying CPLEX directly to the Docplex model (without translating it to
QuadraticProgram
. CPLEX solver natively supports the indicator constraints),applying QAOA to
QuadraticProgram
obtained byfrom_docplex_mp
.
We see the solutions are same.
[10]:
qp = from_docplex_mp(ind_mod)
result = meo.solve(qp) # apply QAOA to QuadraticProgram
print("QAOA")
print(result.prettyprint())
print("-----\nCPLEX")
print(ind_mod.solve()) # apply CPLEX directly to the Docplex model
QAOA
objective function value: 6.0
variable values: x=1.0, y=2.0, z=-1.0
status: SUCCESS
-----
CPLEX
solution for: docplex
objective: 6
status: OPTIMAL_SOLUTION(2)
x=1
y=2
z=-1
[11]:
import qiskit.tools.jupyter
%qiskit_version_table
%qiskit_copyright
Version Information
Software | Version |
---|---|
qiskit | None |
qiskit-terra | 0.25.1 |
qiskit_aer | 0.12.2 |
qiskit_optimization | 0.5.0 |
System information | |
Python version | 3.8.17 |
Python compiler | GCC 11.3.0 |
Python build | default, Jun 7 2023 12:29:56 |
OS | Linux |
CPUs | 2 |
Memory (Gb) | 6.769481658935547 |
Fri Sep 01 13:52:39 2023 UTC |
This code is a part of Qiskit
© Copyright IBM 2017, 2023.
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.