Tutorials
qcr:2606.17573.1

Quadratic Programs in Qiskit Optimization

This tutorial is the foundation of Qiskit Optimization, introducing the QuadraticProgram, the library's universal representation for optimization problems. A quadratic program captures an objective that is linear or quadratic in the decision variables, subject to linear constraints, and supports binary, integer, and continuous variables, a formulation broad enough to express a huge range of practical problems (and the natural target for quantum optimization, since binary quadratic programs map directly onto Ising Hamiltonians). The tutorial shows how to build a QuadraticProgram from scratch by adding variables, setting a linear or quadratic objective, and adding equality and inequality constraints, as well as how to import problems from popular modeling languages such as IBM's DOcplex and the LP file format. It demonstrates inspecting and printing the resulting model and explains how this single data structure is the input that every optimizer and converter in the library consumes. By establishing how to express problems precisely, the tutorial gives the essential starting point for everything else in Qiskit Optimization. It is the recommended first stop before exploring converters and quantum optimizers.
Optimization
Qubit
Circuit-based
Uploaded 3 days ago
16
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 docplex

Quadratic Programs

Introduction

In this tutorial, we briefly introduce how to build optimization problems using Qiskit optimization module. Qiskit optimization introduces the QuadraticProgram class to make a model of an optimization problem. More precisely, it deals with quadratically constrained quadratic programs given as follows:

where the are matrices, is a matrix , , and are -dimensional vectors, is an -dimensional vector, and where can be defined as binary, integer, or continuous variables. In addition to "" constraints QuadraticProgram also supports "" and "".

Loading a QuadraticProgram from an LP file

As setup, you need to import the following module.

In [1]:
from qiskit_optimization import QuadraticProgram
from qiskit_optimization.translators import from_docplex_mp

You start with an empty model. How to add variables and constraints to a model is explained in the section Directly constructing a QuadraticProgram.

Qiskit optimization module supports the conversion from Docplex model. You can easily make a model of an optimization problem with Docplex. You can find the documentation of Docplex at https://ibmdecisionoptimization.github.io/docplex-doc/mp/index.html

You can load a Docplex model to QuadraticProgram by using from_docplex_mp function.

Loading a QuadraticProgram from a docplex model

In [2]:
# Make a Docplex model
from docplex.mp.model import Model

mdl = Model("docplex model")
x = mdl.binary_var("x")
y = mdl.integer_var(lb=-1, ub=5, name="y")
mdl.minimize(x + 2 * y)
mdl.add_constraint(x - y == 3)
mdl.add_constraint((x + y) * (x - y) <= 1)
print(mdl.export_as_lp_string())
\ This file has been generated by DOcplex
\ ENCODING=ISO-8859-1
\Problem name: docplex model

Minimize
 obj: x + 2 y
Subject To
 c1: x - y = 3
 qc1: [ x^2 - y^2 ] <= 1

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

Binaries
 x

Generals
 y
End

QuadraticProgram has a method prettyprint to generate a comprehensive string representation.

In [3]:
# load from a Docplex model
mod = from_docplex_mp(mdl)
print(type(mod))
print()
print(mod.prettyprint())
<class 'qiskit_optimization.problems.quadratic_program.QuadraticProgram'>

Problem name: docplex model

Minimize
  x + 2*y

Subject to
  Linear constraints (1)
    x - y == 3  'c0'

  Quadratic constraints (1)
    x^2 - y^2 <= 1  'q0'

  Integer variables (1)
    -1 <= y <= 5

  Binary variables (1)
    x

Directly constructing a QuadraticProgram

We then explain how to make model of an optimization problem directly using QuadraticProgram. Let's start from an empty model.

In [4]:
# make an empty problem
mod = QuadraticProgram("my problem")
print(mod.prettyprint())
Problem name: my problem

Minimize
  0

Subject to
  No constraints

  No variables

The QuadraticProgram supports three types of variables:

  • Binary variable
  • Integer variable
  • Continuous variable

When you add variables, you can specify names, types, lower bounds and upper bounds.

In [5]:
# Add variables
mod.binary_var(name="x")
mod.integer_var(name="y", lowerbound=-1, upperbound=5)
mod.continuous_var(name="z", lowerbound=-1, upperbound=5)
print(mod.prettyprint())
Problem name: my problem

Minimize
  0

Subject to
  No constraints

  Integer variables (1)
    -1 <= y <= 5

  Continuous variables (1)
    -1 <= z <= 5

  Binary variables (1)
    x

You can set the objective function by invoking QuadraticProgram.minimize or QuadraticProgram.maximize. You can add a constant term as well as linear and quadratic objective function by specifying linear and quadratic terms with either list, matrix or dictionary.

Note that in the LP format the quadratic part has to be scaled by a factor . Thus, when printing as LP format, the quadratic part is first multiplied by 2 and then divided by 2 again.

For quadratic programs, there are 3 pieces that have to be specified: a constant (offset), a linear term (), and a quadratic term ().

The cell below shows how to declare an objective function using a dictionary. For the linear term, keys in the dictionary correspond to variable names, and the corresponding values are the coefficients. For the quadratic term, keys in the dictionary correspond to the two variables being multiplied, and the values are again the coefficients.

In [6]:
# Add objective function using dictionaries
mod.minimize(constant=3, linear={"x": 1}, quadratic={("x", "y"): 2, ("z", "z"): -1})
print(mod.prettyprint())
Problem name: my problem

Minimize
  2*x*y - z^2 + x + 3

Subject to
  No constraints

  Integer variables (1)
    -1 <= y <= 5

  Continuous variables (1)
    -1 <= z <= 5

  Binary variables (1)
    x

Another way to specify the quadratic program is using arrays. For the linear term, the array corresponds to the vector in the mathematical formulation. For the quadratic term, the array corresponds to the matrix . Note that the ordering of the variables ( in the mathematical formulation) is the order in which the variables were originally declared in the QuadraticProgram object.

In [7]:
# Add objective function using lists/arrays
mod.minimize(constant=3, linear=[1, 0, 0], quadratic=[[0, 1, 0], [1, 0, 0], [0, 0, -1]])
print(mod.prettyprint())
Problem name: my problem

Minimize
  2*x*y - z^2 + x + 3

Subject to
  No constraints

  Integer variables (1)
    -1 <= y <= 5

  Continuous variables (1)
    -1 <= z <= 5

  Binary variables (1)
    x

You can access the constant, the linear term, and the quadratic term by looking at Quadratic.objective.{constant, linear, quadratic}, respectively. As for linear and quadratic terms, you can get a dense matrix (to_array), a sparse matrix (coefficients), and a dictionary (to_dict). For dictionaries, you can specify whether to use variable indices or names as keys. Note that the quadratic terms are stored in a compressed way, e.g., {('x', 'y'): 1, ('y', 'x'): 2} is stored as {('x', 'y'): 3}. You can get the quadratic term as a symmetric matrix by calling to_array(symmetric=True) or to_dict(symmetric=True). If you call to_dict(name=True), you can get a dictionary whose keys are pairs of variable names.

In [8]:
print("constant:\t\t\t", mod.objective.constant)
print("linear dict:\t\t\t", mod.objective.linear.to_dict())
print("linear array:\t\t\t", mod.objective.linear.to_array())
print("linear array as sparse matrix:\n", mod.objective.linear.coefficients, "\n")
print("quadratic dict w/ index:\t", mod.objective.quadratic.to_dict())
print("quadratic dict w/ name:\t\t", mod.objective.quadratic.to_dict(use_name=True))
print(
    "symmetric quadratic dict w/ name:\t",
    mod.objective.quadratic.to_dict(use_name=True, symmetric=True),
)
print("quadratic matrix:\n", mod.objective.quadratic.to_array(), "\n")
print("symmetric quadratic matrix:\n", mod.objective.quadratic.to_array(symmetric=True), "\n")
print("quadratic matrix as sparse matrix:\n", mod.objective.quadratic.coefficients)
constant:			 3
linear dict:			 {np.int32(0): np.int64(1)}
linear array:			 [1 0 0]
linear array as sparse matrix:
 <Dictionary Of Keys sparse matrix of dtype 'int64'
	with 1 stored elements and shape (1, 3)>
  Coords	Values
  (0, 0)	1 

quadratic dict w/ index:	 {(0, 1): np.int64(2), (2, 2): np.int64(-1)}
quadratic dict w/ name:		 {('x', 'y'): np.int64(2), ('z', 'z'): np.int64(-1)}
symmetric quadratic dict w/ name:	 {('x', 'y'): np.int64(1), ('y', 'x'): np.int64(1), ('z', 'z'): np.int64(-1)}
quadratic matrix:
 [[ 0  2  0]
 [ 0  0  0]
 [ 0  0 -1]] 

symmetric quadratic matrix:
 [[ 0  1  0]
 [ 1  0  0]
 [ 0  0 -1]] 

quadratic matrix as sparse matrix:
 <Dictionary Of Keys sparse matrix of dtype 'int64'
	with 2 stored elements and shape (3, 3)>
  Coords	Values
  (0, 1)	2
  (2, 2)	-1

Adding/removing linear and quadratic constraints

You can add linear constraints by setting name, linear expression, sense and right-hand-side value (rhs). You can use senses 'EQ', 'LE', and 'GE' as Docplex supports.

In [9]:
# Add linear constraints
mod.linear_constraint(linear={"x": 1, "y": 2}, sense="==", rhs=3, name="lin_eq")
mod.linear_constraint(linear={"x": 1, "y": 2}, sense="<=", rhs=3, name="lin_leq")
mod.linear_constraint(linear={"x": 1, "y": 2}, sense=">=", rhs=3, name="lin_geq")
print(mod.prettyprint())
Problem name: my problem

Minimize
  2*x*y - z^2 + x + 3

Subject to
  Linear constraints (3)
    x + 2*y == 3  'lin_eq'
    x + 2*y <= 3  'lin_leq'
    x + 2*y >= 3  'lin_geq'

  Integer variables (1)
    -1 <= y <= 5

  Continuous variables (1)
    -1 <= z <= 5

  Binary variables (1)
    x

You can add quadratic constraints as well as objective function and linear constraints.

In [10]:
# Add quadratic constraints
mod.quadratic_constraint(
    linear={"x": 1, "y": 1},
    quadratic={("x", "x"): 1, ("y", "z"): -1},
    sense="==",
    rhs=1,
    name="quad_eq",
)
mod.quadratic_constraint(
    linear={"x": 1, "y": 1},
    quadratic={("x", "x"): 1, ("y", "z"): -1},
    sense="<=",
    rhs=1,
    name="quad_leq",
)
mod.quadratic_constraint(
    linear={"x": 1, "y": 1},
    quadratic={("x", "x"): 1, ("y", "z"): -1},
    sense=">=",
    rhs=1,
    name="quad_geq",
)
print(mod.prettyprint())
Problem name: my problem

Minimize
  2*x*y - z^2 + x + 3

Subject to
  Linear constraints (3)
    x + 2*y == 3  'lin_eq'
    x + 2*y <= 3  'lin_leq'
    x + 2*y >= 3  'lin_geq'

  Quadratic constraints (3)
    x^2 - y*z + x + y == 1  'quad_eq'
    x^2 - y*z + x + y <= 1  'quad_leq'
    x^2 - y*z + x + y >= 1  'quad_geq'

  Integer variables (1)
    -1 <= y <= 5

  Continuous variables (1)
    -1 <= z <= 5

  Binary variables (1)
    x

You can access linear and quadratic terms of linear and quadratic constraints as in the same way as the objective function.

In [11]:
lin_geq = mod.get_linear_constraint("lin_geq")
print("lin_geq:", lin_geq.linear.to_dict(use_name=True), lin_geq.sense, lin_geq.rhs)
quad_geq = mod.get_quadratic_constraint("quad_geq")
print(
    "quad_geq:",
    quad_geq.linear.to_dict(use_name=True),
    quad_geq.quadratic.to_dict(use_name=True),
    quad_geq.sense,
    lin_geq.rhs,
)
lin_geq: {'x': np.float64(1.0), 'y': np.float64(2.0)} ConstraintSense.GE 3
quad_geq: {'x': np.float64(1.0), 'y': np.float64(1.0)} {('x', 'x'): np.float64(1.0), ('y', 'z'): np.float64(-1.0)} ConstraintSense.GE 3

You can also remove linear/quadratic constraints by remove_linear_constraint and remove_quadratic_constraint.

In [12]:
# Remove constraints
mod.remove_linear_constraint("lin_eq")
mod.remove_quadratic_constraint("quad_leq")
print(mod.prettyprint())
Problem name: my problem

Minimize
  2*x*y - z^2 + x + 3

Subject to
  Linear constraints (2)
    x + 2*y <= 3  'lin_leq'
    x + 2*y >= 3  'lin_geq'

  Quadratic constraints (2)
    x^2 - y*z + x + y == 1  'quad_eq'
    x^2 - y*z + x + y >= 1  'quad_geq'

  Integer variables (1)
    -1 <= y <= 5

  Continuous variables (1)
    -1 <= z <= 5

  Binary variables (1)
    x

You can substitute some of variables with constants or other variables. More precisely, QuadraticProgram has a method substitute_variables(constants=..., variables=...) to deal with the following two cases.

  • : when constants have a dictionary {x: c}.
  • : when variables have a dictionary {x: (y, c)}.

Substituting Variables

In [13]:
sub = mod.substitute_variables(constants={"x": 0}, variables={"y": ("z", -1)})
print(sub.prettyprint())
Problem name: my problem

Minimize
  -z^2 + 3

Subject to
  Linear constraints (2)
    -2*z <= 3  'lin_leq'
    -2*z >= 3  'lin_geq'

  Quadratic constraints (2)
    z^2 - z == 1  'quad_eq'
    z^2 - z >= 1  'quad_geq'

  Continuous variables (1)
    -1 <= z <= 1

If the resulting problem is infeasible due to lower bounds or upper bounds, the methods returns the status Status.INFEASIBLE. We try to replace variable x with -1, but -1 is out of range of x (0 <= x <= 1). So, it returns Status.INFEASIBLE.

In [14]:
sub = mod.substitute_variables(constants={"x": -1})
print(sub.status)
Infeasible substitution for variable: x
QuadraticProgramStatus.INFEASIBLE

You cannot substitute variables multiple times. The method raises an error in such a case.

In [15]:
from qiskit_optimization import QiskitOptimizationError

try:
    sub = mod.substitute_variables(constants={"x": -1}, variables={"y": ("x", 1)})
except QiskitOptimizationError as e:
    print("Error: {}".format(e))
Error: 'Cannot substitute by variable that gets substituted itself: y <- x 1'
In [16]:
import tutorial_magics

%qiskit_version_table
%qiskit_copyright

Version Information

SoftwareVersion
qiskit2.1.1
qiskit_optimization0.7.0
System information
Python version3.11.12
OSDarwin
Sat Aug 09 16:56:54 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.

In [ ]:

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 15, 2026
qcr:2606.17573.1

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

Tools used

Qiskit

Keywords

quadratic-program
optimization
qiskit
modeling
docplex

You may also like5