English
Languages
English
Shortcuts

# 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 that these solvers installed via pip are free versions, which have some limitations such as number of variables. Also note that the latest version 20.1 of CPLEX is available only for Python 3.7 and 3.8 as of July 2021. See the following pages for 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.

:

from qiskit_optimization.problems import QuadraticProgram

# define a problem
qp.binary_var('x')
qp.integer_var(name='y', lowerbound=-1, upperbound=4)
qp.linear_constraint({'x': 1, 'y': -1}, '<=', 0)
print(qp.export_as_lp_string())

\ This file has been generated by DOcplex
\ ENCODING=ISO-8859-1
\Problem name: CPLEX

Maximize
obj: [ 2 x*y ]/2
Subject To
c0: x - y <= 0

Bounds
0 <= x <= 1
-1 <= y <= 4

Binaries
x

Generals
y
End


:

from qiskit_optimization.algorithms import CplexOptimizer, GurobiOptimizer
print('cplex')
print(CplexOptimizer().solve(qp))
print()
print('gurobi')
print(GurobiOptimizer().solve(qp))

cplex
optimal function value: 4.0
optimal value: [1. 4.]
status: SUCCESS

gurobi
Restricted license - for non-production use only - expires 2022-01-13
optimal function value: 4.0
optimal value: [1. 4.]
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.

:

CplexOptimizer(disp=True, cplex_parameters={'threads': 1, 'timelimit': 0.1}).solve(qp)

Version identifier: 20.1.0.0 | 2020-11-11 | 9bedb6d68
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)

:

optimal function value: 4.0
optimal value: [1. 4.]
status: SUCCESS


We get the same optimal solution by QAOA as follows.

:

from qiskit_optimization.algorithms import MinimumEigenOptimizer

from qiskit import Aer
from qiskit.utils import QuantumInstance
from qiskit.algorithms import QAOA
from qiskit.algorithms.optimizers import COBYLA

qins = QuantumInstance(backend=Aer.get_backend('aer_simulator'), shots=1000)
meo = MinimumEigenOptimizer(QAOA(COBYLA(maxiter=100), quantum_instance=qins))
result = meo.solve(qp)
print(result)
print('\ndisplay the best 5 solution samples')
for sample in result.samples[:5]:
print(sample)

optimal function value: 4.0
optimal value: [1. 4.]
status: SUCCESS

display the best 5 solution samples
SolutionSample(x=array([1., 4.]), fval=4.0, probability=0.236, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 3.]), fval=3.0, probability=0.092, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 2.]), fval=2.0, probability=0.052000000000000005, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 1.]), fval=1.0, probability=0.030000000000000002, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([0., 0.]), fval=0.0, probability=0.025, 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.

:

# 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.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;

}

:

# gurobi model
import gurobipy as gp
gurobipy_model = gp.Model('gurobi')
y = gurobipy_model.addVar(vtype=gp.GRB.INTEGER, lb=-1, ub=4, name="y")
gurobipy_model.setObjective(x * y, gp.GRB.MAXIMIZE)
gurobipy_model.update()
gurobipy_model.display()

Maximize
<gurobi.QuadExpr: 0.0 + [ x * y ]>
Subject To
R0 : <gurobi.LinExpr: x + -1.0 y> <= 0.0
Bounds
-1.0 <= y <= 4.0
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.

:

from qiskit_optimization.translators import from_docplex_mp, from_gurobipy
qp = from_docplex_mp(docplex_model)
print(qp.export_as_lp_string())
print('-------------')
qp2 = from_gurobipy(gurobipy_model)
print(qp2.export_as_lp_string())

QuadraticProgram obtained from docpblex
\ This file has been generated by DOcplex
\ ENCODING=ISO-8859-1
\Problem name: docplex

Maximize
obj: [ 2 x*y ]/2
Subject To
c0: x - y <= 0

Bounds
0 <= x <= 1
-1 <= y <= 4

Binaries
x

Generals
y
End

-------------
\ 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



We can generate a Docplex model and a Gurobipy model from QuadraticProgram too.

:

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')
dmod.prettyprint()

convert docplex to gurobipy via QuadraticProgram
Maximize
<gurobi.QuadExpr: 0.0 + [ x * y ]>
Subject To
c0 : <gurobi.LinExpr: x + -1.0 y> <= 0.0
Bounds
-1.0 <= y <= 4.0
Binaries
['x']
General Integers
['y']

convert gurobipy to docplex via QuadraticProgram
// This file has been generated by DOcplex
// model name is: gurobi
// single vars section
dvar bool x;
dvar int y;

maximize
[ x*y ];

subject to {
R0:
x - y <= 0;

}


### 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.

:

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)
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

1. applying CPLEX directly to the Docplex model (without translating it to QuadraticProgram. CPLEX solver natively supports the indicator constraints),

2. applying QAOA to QuadraticProgram obtained by from_docplex_mp.

We see the solutions are same.

:

qp = from_docplex_mp(ind_mod)
result = meo.solve(qp)  # apply QAOA to QuadraticProgram
print('QAOA')
print(result)
print('-----\nCPLEX')
print(ind_mod.solve())  # apply CPLEX directly to the Docplex model

QAOA
optimal function value: 6.0
optimal value: [ 1.  2. -1.]
status: SUCCESS
-----
CPLEX
solution for: docplex
objective: 6
x=1
y=2
z=-1


:

import qiskit.tools.jupyter
%qiskit_version_table


### Version Information

Qiskit SoftwareVersion
qiskit-terra0.18.3
qiskit-aer0.9.0
qiskit-optimization0.2.3
System information
Python3.8.12 (default, Sep 13 2021, 08:28:12) [GCC 9.3.0]
OSLinux
CPUs2
Memory (Gb)6.790924072265625
Wed Oct 06 16:50:57 2021 UTC