Tutorials
qcr:2606.29483.1

Using Classical Solvers with Qiskit Optimization

This Qiskit Optimization tutorial shows how to solve the library's optimization models with classical solvers and modeling tools, an essential capability both for benchmarking quantum optimizers and for handling the parts of a workflow where classical methods remain best. While Qiskit Optimization is built for quantum approaches, every QuadraticProgram can also be handed to mature classical optimization software, and doing so provides exact or high-quality reference solutions to validate quantum results against. The tutorial demonstrates converting between the QuadraticProgram and IBM's DOcplex modeling language, solving models with the CPLEX classical optimizer where available, and using the library's classical optimizer wrappers (such as the CplexOptimizer) within the same interface used for quantum solvers. It shows how to compare a quantum optimizer's output against the classical optimum to assess approximation quality. By integrating classical solvers into the same framework, the tutorial gives users the tools to benchmark, validate, and build hybrid workflows, an honest and necessary complement to quantum optimization in Qiskit.
Optimization
Qubit
Circuit-based
Uploaded 3 days ago
6
Views
GitHub282
Citing this entry? Use this QCR ID
Uploaded by
QL
QCR Librarian

Overview

qiskit-community/qiskit-optimization
282149
In [ ]:
# --- Setup cell added by QCR (not part of the original tutorial) ---
# Source: qiskit-community/qiskit-optimization @ 0.7.0, Apache License 2.0.
# Installs the example's dependencies. If a later cell still reports a missing
# package, restart the runtime/kernel and run again from the top.
%pip install -q qiskit-optimization==0.7.0 cplex docplex gurobipy

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.

In [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

In [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 2026-11-23
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.

In [3]:
result = CplexOptimizer(disp=True, cplex_parameters={"threads": 1, "timelimit": 0.1}).solve(qp)
print(result.prettyprint())
Version identifier: 22.1.1.0 | 2023-06-15 | d64d5bd77
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.

In [4]:
from qiskit.primitives import StatevectorSampler
from qiskit_optimization.algorithms import MinimumEigenOptimizer
from qiskit_optimization.minimum_eigensolvers import QAOA
from qiskit_optimization.optimizers import COBYLA

meo = MinimumEigenOptimizer(
    QAOA(sampler=StatevectorSampler(seed=123), optimizer=COBYLA(maxiter=100), initial_point=[1, 1])
)
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=np.float64(4.0), probability=0.1533203125, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 3.]), fval=np.float64(3.0), probability=0.12890625, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 2.]), fval=np.float64(2.0), probability=0.05859375, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([1., 1.]), fval=np.float64(1.0), probability=0.095703125, status=<OptimizationResultStatus.SUCCESS: 0>)
SolutionSample(x=array([0., 2.]), fval=np.float64(0.0), probability=0.1865234375, 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.

In [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;

}
In [6]:
# gurobi model
from io import StringIO
from os import remove
from tempfile import NamedTemporaryFile

import gurobipy as gp


def gpy_display(mdl):
    """Convenience function to pretty-print a Gurobipy-Model."""
    with NamedTemporaryFile(suffix=".lp") as tmp_file:
        mdl.write(tmp_file.name)

        with open(tmp_file.name, "r") as f:
            print(f.read())


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()
gpy_display(gurobipy_model)
\ Model gurobi
\ LP format - for model browsing. Use MPS format to capture full model detail.
Maximize
 [ 2 x * y ] / 2 
Subject To
 R0: x - y <= 0
Bounds
 -1 <= y <= 4
Binaries
 x
Generals
 y
End

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.

In [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.

In [8]:
from qiskit_optimization.translators import to_docplex_mp, to_gurobipy

gmod = to_gurobipy(from_docplex_mp(docplex_model))
print("convert docplex to gurobipy via QuadraticProgram")
gpy_display(gmod)

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
\ Model docplex
\ LP format - for model browsing. Use MPS format to capture full model detail.
Maximize
 [ 2 x * y ] / 2 
Subject To
 c0: x - y <= 0
Bounds
 -1 <= y <= 4
Binaries
 x
Generals
 y
End

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.

In [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

  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.

In [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

In [11]:
import tutorial_magics

%qiskit_version_table
%qiskit_copyright

Version Information

SoftwareVersion
qiskit2.1.1
qiskit_optimization0.7.0
System information
Python version3.11.13
OSDarwin
Mon Aug 18 14:22:04 2025 JST

This code is a part of a Qiskit project

© Copyright IBM 2017, 2025.

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.

Join the Discussion

Comments (0)

No comments yet. Be the first to share your thoughts!

Indexed by QCR Librarian

This entry was created automatically from publicly available records. QCR links to public sources and only stores repository content where the license permits redistribution.

Versions

v1 Latest
Jun 16, 2026
qcr:2606.29483.1

Cite all versions? Use the base QCR ID to always reference the latest version of this entry.

Tools used

Qiskit

Keywords

classical-solvers
cplex
optimization
benchmarking
qiskit

You may also like5