PuLP is a linear and mixed integer programming modeler that provides an intuitive Python interface for creating, manipulating, and solving mathematical optimization problems.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Fundamental classes for creating and manipulating linear and mixed integer programming problems in PuLP. These classes provide the foundation for mathematical optimization modeling with intuitive Python syntax.
The LpProblem class serves as the main container for optimization problems, managing variables, constraints, objectives, and solution processes.
class LpProblem:
def __init__(self, name="NoName", sense=LpMinimize):
"""
Create a new optimization problem.
Parameters:
- name (str): Problem name for identification
- sense (int): Optimization direction (LpMinimize=1 or LpMaximize=-1)
"""
def solve(self, solver=None, **kwargs):
"""
Solve the optimization problem.
Parameters:
- solver: Solver instance (defaults to LpSolverDefault)
- **kwargs: Additional solver-specific parameters
Returns:
int: Status code (LpStatusOptimal=1, LpStatusInfeasible=-1, etc.)
"""
def writeLP(self, filename):
"""
Export problem to LP format file.
Parameters:
- filename (str): Output file path
"""
def writeMPS(self, filename):
"""
Export problem to MPS format file.
Parameters:
- filename (str): Output file path
"""
def copy(self):
"""
Create a deep copy of the problem.
Returns:
LpProblem: Copy of the problem
"""
def deepcopy(self):
"""
Create a deep copy of the problem with all components.
Returns:
LpProblem: Deep copy of the problem
"""
def variables(self):
"""
Get all variables in the problem.
Returns:
list: List of LpVariable objects
"""
@property
def objective(self):
"""Get or set the objective function (LpAffineExpression)."""
@property
def constraints(self):
"""Get dictionary of all constraints in the problem."""
@property
def status(self):
"""Get the solution status of the problem."""
def sequentialSolve(self, objectives):
"""
Solve problem with multiple objectives sequentially.
Parameters:
- objectives (list): List of LpAffineExpression objectives to optimize in order
Returns:
int: Status code of final solve
"""
def toJson(self, filename):
"""
Export problem to JSON format file.
Parameters:
- filename (str): Output JSON file path
"""
def fromJson(self, filename):
"""
Load problem from JSON format file.
Parameters:
- filename (str): Input JSON file path
"""
def roundSolution(self, epsilon=1e-7):
"""
Round variable values in solution to remove numerical precision artifacts.
Parameters:
- epsilon (float): Tolerance for rounding near-integer values
"""
def checkDuplicateVars(self):
"""
Check for duplicate variable names in the problem.
Returns:
bool: True if duplicates found, False otherwise
"""
def numVariables(self):
"""
Get the number of variables in the problem.
Returns:
int: Number of variables
"""
def numConstraints(self):
"""
Get the number of constraints in the problem.
Returns:
int: Number of constraints
"""
def isMIP(self):
"""
Check if problem is a Mixed Integer Program.
Returns:
bool: True if problem contains integer or binary variables
"""
def valid(self):
"""
Check if problem is valid and well-formed.
Returns:
bool: True if problem is valid
"""
def assignStatus(self, status):
"""
Assign solution status to the problem.
Parameters:
- status (int): Status code to assign
"""
def toDict(self):
"""
Convert problem to dictionary representation.
Returns:
dict: Dictionary representation of the problem
"""
def fromDict(self, data):
"""
Load problem from dictionary representation.
Parameters:
- data (dict): Dictionary containing problem data
"""
def toDataclass(self):
"""
Convert problem to dataclass representation.
Returns:
Dataclass representation of the problem
"""
def fromDataclass(self, data):
"""
Load problem from dataclass representation.
Parameters:
- data: Dataclass containing problem data
"""
def variablesDict(self):
"""
Get dictionary of all variables keyed by name.
Returns:
dict: Dictionary mapping variable names to LpVariable objects
"""
def addVariable(self, var):
"""
Add a single variable to the problem.
Parameters:
- var (LpVariable): Variable to add
"""
def addVariables(self, vars):
"""
Add multiple variables to the problem.
Parameters:
- vars (list): List of LpVariable objects to add
"""
def addConstraint(self, constraint):
"""
Add a constraint to the problem.
Parameters:
- constraint (LpConstraint): Constraint to add
"""
def extend(self, other):
"""
Extend problem with variables and constraints from another problem.
Parameters:
- other (LpProblem): Problem to merge into this problem
"""
def setObjective(self, obj):
"""
Set the objective function for the problem.
Parameters:
- obj (LpAffineExpression): Objective expression to minimize/maximize
"""
def resolve(self):
"""
Re-solve the problem with the same solver and parameters.
Returns:
int: Status code
"""
def getSense(self):
"""
Get the optimization sense (minimize or maximize).
Returns:
int: LpMinimize (1) or LpMaximize (-1)
"""Usage example:
# Create minimization problem
prob = LpProblem("Production_Planning", LpMinimize)
# Add variables and constraints
x = LpVariable("production", 0, 1000)
prob += 2*x >= 100 # Minimum production constraint
prob += 3*x # Objective: minimize cost
# Solve
status = prob.solve()
print(f"Status: {LpStatus[status]}")The LpVariable class represents decision variables in optimization problems with support for bounds, categories, and bulk creation methods.
class LpVariable:
def __init__(self, name, lowBound=None, upBound=None, cat=LpContinuous, e=None):
"""
Create a decision variable.
Parameters:
- name (str): Variable name
- lowBound (float, optional): Lower bound (default: None = -infinity)
- upBound (float, optional): Upper bound (default: None = +infinity)
- cat (str): Variable category (LpContinuous, LpInteger, LpBinary)
- e (LpElement, optional): Associated element for column generation
"""
@classmethod
def dicts(cls, name, indices, lowBound=None, upBound=None, cat=LpContinuous):
"""
Create dictionary of variables with shared properties.
Parameters:
- name (str): Base name for variables
- indices: Iterable of indices for variable names
- lowBound (float, optional): Lower bound for all variables
- upBound (float, optional): Upper bound for all variables
- cat (str): Variable category for all variables
Returns:
dict: Dictionary mapping indices to LpVariable objects
"""
@classmethod
def dict(cls, name, indices, lowBound=None, upBound=None, cat=LpContinuous):
"""
Alias for dicts() method.
"""
@classmethod
def matrix(cls, name, indices1, indices2, lowBound=None, upBound=None, cat=LpContinuous):
"""
Create 2D matrix of variables.
Parameters:
- name (str): Base name for variables
- indices1: First dimension indices
- indices2: Second dimension indices
- lowBound (float, optional): Lower bound for all variables
- upBound (float, optional): Upper bound for all variables
- cat (str): Variable category for all variables
Returns:
dict: Nested dictionary of LpVariable objects
"""
def bounds(self, low, up):
"""
Set variable bounds.
Parameters:
- low (float): Lower bound
- up (float): Upper bound
"""
def positive(self):
"""
Make variable non-negative (set lower bound to 0).
"""
def value(self):
"""
Get the solution value of the variable.
Returns:
float: Variable value in solution (None if not solved)
"""
def setInitialValue(self, val):
"""
Set initial value for warm starts.
Parameters:
- val (float): Initial value
"""
@property
def lowBound(self):
"""Get or set the lower bound of the variable."""
@property
def upBound(self):
"""Get or set the upper bound of the variable."""
@property
def cat(self):
"""Get or set the category of the variable."""
@property
def name(self):
"""Get the name of the variable."""
def roundedValue(self, epsilon=1e-7):
"""
Get rounded solution value of the variable.
Parameters:
- epsilon (float): Tolerance for rounding near-integer values
Returns:
float: Rounded variable value
"""
def valueOrDefault(self):
"""
Get variable value or default within bounds if not solved.
Returns:
float: Variable value or default within bounds
"""
def fixValue(self, value=None):
"""
Fix variable to a specific value.
Parameters:
- value (float, optional): Value to fix variable to (uses current value if None)
"""
def unfixValue(self):
"""
Unfix variable, restoring original bounds.
"""
def isFixed(self):
"""
Check if variable is fixed to a specific value.
Returns:
bool: True if variable is fixed
"""
def isBinary(self):
"""
Check if variable is binary (0 or 1).
Returns:
bool: True if variable category is LpBinary
"""
def isInteger(self):
"""
Check if variable is integer.
Returns:
bool: True if variable category is LpInteger or LpBinary
"""
def isFree(self):
"""
Check if variable is free (unbounded).
Returns:
bool: True if variable has no bounds
"""
def isConstant(self):
"""
Check if variable has constant value (both bounds equal).
Returns:
bool: True if lower bound equals upper bound
"""
def isPositive(self):
"""
Check if variable is constrained to be positive.
Returns:
bool: True if lower bound >= 0
"""
def getLb(self):
"""
Get lower bound of the variable.
Returns:
float: Lower bound value
"""
def getUb(self):
"""
Get upper bound of the variable.
Returns:
float: Upper bound value
"""
def valid(self, eps=1e-7):
"""
Check if variable value is within bounds.
Parameters:
- eps (float): Tolerance for bound checking
Returns:
bool: True if variable value is valid
"""
def infeasibilityGap(self):
"""
Calculate infeasibility gap for variable bounds.
Returns:
float: Gap value if infeasible, 0 if feasible
"""
def toDict(self):
"""
Convert variable to dictionary representation.
Returns:
dict: Dictionary representation of the variable
"""
def fromDict(self, data):
"""
Load variable from dictionary representation.
Parameters:
- data (dict): Dictionary containing variable data
"""
def toDataclass(self):
"""
Convert variable to dataclass representation.
Returns:
Dataclass representation of the variable
"""
def fromDataclass(self, data):
"""
Load variable from dataclass representation.
Parameters:
- data: Dataclass containing variable data
"""Usage examples:
# Single variables
x = LpVariable("x", 0, 10) # 0 <= x <= 10
y = LpVariable("y", cat="Binary") # Binary variable
z = LpVariable("z", lowBound=0) # Non-negative variable
# Dictionary of variables
plants = ["A", "B", "C"]
production = LpVariable.dicts("prod", plants, 0, 1000)
# Creates: prod_A, prod_B, prod_C with bounds [0, 1000]
# Matrix of variables
supply_points = ["S1", "S2"]
demand_points = ["D1", "D2", "D3"]
transport = LpVariable.matrix("transport", supply_points, demand_points, 0)
# Creates: transport_S1_D1, transport_S1_D2, etc.The LpConstraint class handles mathematical relationships between variables with support for different constraint senses and elastic subproblems.
class LpConstraint:
def __init__(self, e=None, sense=LpConstraintEQ, name=None, rhs=None):
"""
Create a constraint.
Parameters:
- e (LpAffineExpression, optional): Left-hand side expression
- sense (int): Constraint sense (LpConstraintLE=-1, LpConstraintEQ=0, LpConstraintGE=1)
- name (str, optional): Constraint name
- rhs (float, optional): Right-hand side value
"""
def changeRHS(self, RHS):
"""
Change the right-hand side value.
Parameters:
- RHS (float): New right-hand side value
"""
def copy(self):
"""
Create a copy of the constraint.
Returns:
LpConstraint: Copy of the constraint
"""
def makeElasticSubProblem(self, penalty=1e6, proportionFreeBound=1e-4, proportionFreeBoundList=None):
"""
Create elastic version of constraint for infeasibility analysis.
Parameters:
- penalty (float): Penalty coefficient for constraint violations
- proportionFreeBound (float): Proportion of constraint bound that can be violated freely
- proportionFreeBoundList (list, optional): List of proportion bounds for multiple constraints
Returns:
FixedElasticSubProblem: Elastic subproblem object
"""
def emptyCopy(self):
"""
Create an empty copy of the constraint without coefficients.
Returns:
LpConstraint: Empty constraint with same sense and name
"""
def addInPlace(self, other):
"""
Add another constraint or expression to this constraint in place.
Parameters:
- other (LpConstraint or LpAffineExpression): Expression to add
"""
def getLb(self):
"""
Get lower bound equivalent of constraint.
Returns:
float: Lower bound value based on constraint sense
"""
def getUb(self):
"""
Get upper bound equivalent of constraint.
Returns:
float: Upper bound value based on constraint sense
"""
def valid(self):
"""
Check if constraint is valid and well-formed.
Returns:
bool: True if constraint is valid
"""
def value(self):
"""
Calculate the value of the constraint's left-hand side.
Returns:
float: Current value of constraint expression
"""
def keys(self):
"""
Get variables in the constraint.
Returns:
dict_keys: Variable keys in constraint
"""
def values(self):
"""
Get coefficients in the constraint.
Returns:
dict_values: Coefficient values in constraint
"""
def items(self):
"""
Get variable-coefficient pairs in the constraint.
Returns:
dict_items: Variable-coefficient pairs
"""
def get(self, var, default=0):
"""
Get coefficient for a variable.
Parameters:
- var (LpVariable): Variable to get coefficient for
- default (float): Default value if variable not in constraint
Returns:
float: Coefficient value
"""
def toDataclass(self):
"""
Convert constraint to dataclass representation.
Returns:
Dataclass representation of the constraint
"""
def fromDataclass(self, data):
"""
Load constraint from dataclass representation.
Parameters:
- data: Dataclass containing constraint data
"""Usage examples:
# Create constraints using operators
prob += x + 2*y <= 10 # Less than or equal
prob += 3*x - y == 5 # Equality
prob += x >= 0 # Greater than or equal
# Named constraints
constraint1 = LpConstraint(x + y, LpConstraintLE, "capacity", 100)
prob += constraint1
# Modify constraint
constraint1.changeRHS(120) # Change right-hand side to 120The LpAffineExpression class represents linear combinations of variables with constant terms, supporting arithmetic operations and solution value extraction.
class LpAffineExpression:
def __init__(self, e=None, constant=0.0, name=None):
"""
Create a linear expression.
Parameters:
- e (dict or LpVariable, optional): Initial variable coefficients
- constant (float): Constant term
- name (str, optional): Expression name
"""
def addterm(self, var, coeff):
"""
Add a term to the expression.
Parameters:
- var (LpVariable): Variable to add
- coeff (float): Coefficient for the variable
"""
def copy(self):
"""
Create a copy of the expression.
Returns:
LpAffineExpression: Copy of the expression
"""
def value(self):
"""
Calculate the value of the expression using current variable values.
Returns:
float: Expression value (None if variables not solved)
"""
def valueOrDefault(self):
"""
Get expression value or default if variables not solved.
Returns:
float: Expression value or constant term
"""
@property
def constant(self):
"""Get or set the constant term."""
def emptyCopy(self):
"""
Create an empty copy of the expression.
Returns:
LpAffineExpression: Empty expression with same name
"""
def addInPlace(self, other):
"""
Add another expression to this expression in place.
Parameters:
- other (LpAffineExpression or LpVariable): Expression to add
"""
def isAtomic(self):
"""
Check if expression contains only one variable with coefficient 1.
Returns:
bool: True if expression is atomic
"""
def isNumericalConstant(self):
"""
Check if expression is a numerical constant (no variables).
Returns:
bool: True if expression contains no variables
"""
def atom(self):
"""
Get the single variable if expression is atomic.
Returns:
LpVariable: Single variable if atomic, None otherwise
"""
def sorted_keys(self):
"""
Get variables sorted by name.
Returns:
list: List of variables sorted by name
"""
def keys(self):
"""
Get variables in the expression.
Returns:
dict_keys: Variable keys in expression
"""
def values(self):
"""
Get coefficients in the expression.
Returns:
dict_values: Coefficient values in expression
"""
def items(self):
"""
Get variable-coefficient pairs in the expression.
Returns:
dict_items: Variable-coefficient pairs
"""
def get(self, var, default=0):
"""
Get coefficient for a variable.
Parameters:
- var (LpVariable): Variable to get coefficient for
- default (float): Default value if variable not in expression
Returns:
float: Coefficient value
"""
def clear(self):
"""
Clear all variables and constant from the expression.
"""
def toDict(self):
"""
Convert expression to dictionary representation.
Returns:
dict: Dictionary representation of the expression
"""
def toDataclass(self):
"""
Convert expression to dataclass representation.
Returns:
Dataclass representation of the expression
"""Usage examples:
# Create expressions
expr1 = 2*x + 3*y + 5 # Linear expression with constant
expr2 = LpAffineExpression([x, y], [2, 3], 5) # Equivalent creation
# Build expressions incrementally
expr = LpAffineExpression()
expr.addterm(x, 2)
expr.addterm(y, 3)
expr.constant = 5
# Use in constraints and objectives
prob += expr <= 100 # As constraint
prob += expr # As objective functionAdditional constraint types for advanced modeling scenarios including fraction constraints and elastic formulations.
class LpConstraintVar:
"""
Special constraint type for column-wise modeling where constraints
are treated as variables in the dual problem.
"""
def __init__(self, name=None, sense=None, rhs=None, e=None): ...
class LpFractionConstraint:
"""
Constraint enforcing fraction requirement: numerator/denominator = target.
Used for ratio optimization problems.
"""
def __init__(self, numerator, denominator, name=None, sense=LpConstraintEQ, rhs=None): ...
class FixedElasticSubProblem:
"""
Elastic constraint subproblem for handling infeasible constraints
by allowing violations with penalty costs.
"""
def reConstrain(self, newRHS): ...
class FractionElasticSubProblem:
"""
Elastic version of fraction constraints with violation penalties.
"""
def reConstrain(self, newRHS): ...
class LpElement:
"""
Base class for LpVariable and LpConstraintVar, providing common
functionality for problem elements.
"""
def __init__(self, name): ...These specialized classes enable advanced modeling techniques including column generation, ratio optimization, and robust optimization with constraint relaxation.
Install with Tessl CLI
npx tessl i tessl/pypi-pulp