Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

scipy.optimize.linprog solves continuous linear programs by minimizing an objective such as c @ x, subject to linear inequalities, equalities, and variable bounds. To use it, put the objective coefficients in c, encode each inequality and equality as a row of its own constraint matrix, set bounds for each decision variable, then check the returned solver status before using the result.

How linprog represents a linear program

The function minimizes a linear objective over a decision vector x. Its standard form is:

minimize    c @ x
subject to  A_ub @ x <= b_ub
            A_eq @ x == b_eq
            lb <= x <= ub

c contains one objective coefficient per variable. Each row of A_ub describes one less-than-or-equal constraint and the matching entry in b_ub is its right-hand side. Equalities use the separate pair A_eq and b_eq. Bounds apply to individual variables. The function minimizes; for a maximization model, negate the objective coefficients and interpret the resulting objective with the sign reversed. See the linprog reference for the current API details.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Translate a model into arrays

Suppose a business chooses quantities x and y to minimize cost, with the constraints x + 2y >= 8 and 3x + y >= 9. Because linprog expects inequalities in less-than-or-equal form, multiply each constraint by -1:

import numpy as np
from scipy.optimize import linprog

# Minimize 2x + 3y
c = np.array([2, 3])

# -(x + 2y) <= -8; -(3x + y) <= -9
A_ub = np.array([
    [-1, -2],
    [-3, -1],
])
b_ub = np.array([-8, -9])

# x and y are nonnegative
bounds = [(0, None), (0, None)]

result = linprog(c, A_ub=A_ub, b_ub=b_ub, bounds=bounds, method="highs")

Array positions must stay aligned: the first column of each constraint matrix corresponds to x, the second to y, and the entries of c and bounds follow that same order. The example is a formulation, not a claim about a computed optimum; run it in your environment and inspect the solver result.

Adding equality constraints

For a requirement such as x + y = 5, provide a row in A_eq and its target in b_eq. If the model has no equalities, omit both arguments.

A_eq = np.array([[1, 1]])
b_eq = np.array([5])

result = linprog(
    c,
    A_ub=A_ub,
    b_ub=b_ub,
    A_eq=A_eq,
    b_eq=b_eq,
    bounds=bounds,
    method="highs",
)

The corresponding right-hand-side vector must have one entry per matrix row. SciPy’s optimization tutorial demonstrates assembling these inputs and passing them to linprog.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Set variable bounds deliberately

By default, each variable has bounds (0, None): it cannot be negative and has no finite upper limit. This default fits nonnegative quantities, but not every model. Pass a bounds pair for each variable to allow negative values or impose limits; None means that side has no finite bound.

# x may be negative; y is between 0 and 10
bounds = [(None, None), (0, 10)]

Bounds are not a substitute for the model’s other constraints: use them for individual-variable limits and use A_ub or A_eq for relationships among variables.

Choose a method

The documented default is method="highs". It selects automatically between HiGHS dual simplex ("highs-ds") and HiGHS interior-point ("highs-ipm"). Starting with "highs" is appropriate for a general model; the documentation does not establish one alternative as universally faster or better, so choose a specific method only when you have a workload-specific reason to do so.

Check whether the solver succeeded

linprog returns an OptimizeResult. Check success before treating its solution fields as a valid optimum. An unsuccessful result may reflect an infeasible model or another solver outcome; inspect message and status rather than assuming that a vector exists or is usable.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
if result.success:
    print("Solution:", result.x)
    print("Objective:", result.fun)
    print("Inequality slack:", result.slack)
    print("Equality residual:", result.con)
else:
    print("Solver did not report success:", result.message)
    print("Status:", result.status)

x contains the reported decision-variable values, fun the objective value, slack the inequality slack values, and con the equality residuals. Use these fields to interpret a successful result in light of your original model. A solver’s infeasibility message means the supplied constraints and bounds do not admit the reported feasible solution; revisit their signs, units, right-hand sides, and bounds. The official tutorial includes an infeasible example, underscoring that not every formulation has a feasible solution.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

When linprog is not the right solver

linprog is for continuous linear programming: its variables are not constrained to integer values. Rounding a continuous solution afterward does not impose integrality during optimization and is not generally equivalent to solving an integer model. For mixed-integer linear programming, SciPy lists scipy.optimize.milp separately from its continuous linear-programming tools. Consult the SciPy optimization reference to choose the appropriate function.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.