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
Essential constants for variable categories, problem senses, constraint types, and status codes used throughout PuLP's modeling system. These constants provide standardized values for optimization problem specification and solution interpretation.
Version information and precision constants for the PuLP package.
VERSION: str = "3.2.2" # PuLP package version
EPS: float = 1e-7 # Default numerical precision toleranceConstants defining the types of decision variables supported in optimization problems.
LpContinuous: str = "Continuous" # Continuous variables (real numbers)
LpInteger: str = "Integer" # Integer variables (whole numbers)
LpBinary: str = "Binary" # Binary variables (0 or 1)
LpCategories: dict = {
LpContinuous: "Continuous",
LpInteger: "Integer",
LpBinary: "Binary"
} # Mapping of category constants to string representationsUsage examples:
# Create variables with different categories
x_cont = LpVariable("x", cat=LpContinuous) # Can take any real value
y_int = LpVariable("y", cat=LpInteger) # Must be whole number
z_bin = LpVariable("z", cat=LpBinary) # Must be 0 or 1
# Check variable category
if x_cont.cat == LpContinuous:
print("x is a continuous variable")
# Use in bulk creation
binary_vars = LpVariable.dicts("decision", range(10), cat=LpBinary)Constants specifying whether the optimization problem seeks to minimize or maximize the objective function.
LpMinimize: int = 1 # Minimize the objective function
LpMaximize: int = -1 # Maximize the objective function
LpSenses: dict = {
LpMinimize: "Minimize",
LpMaximize: "Maximize"
} # Mapping of sense constants to string representations
LpSensesMPS: dict = {
LpMaximize: "MAX",
LpMinimize: "MIN"
} # MPS format sense representationsUsage examples:
# Create problems with different senses
min_prob = LpProblem("Cost_Minimization", LpMinimize)
max_prob = LpProblem("Profit_Maximization", LpMaximize)
# Check problem sense
if min_prob.sense == LpMinimize:
print("This is a minimization problem")
# Convert sense to string
print(f"Problem sense: {LpSenses[min_prob.sense]}")Status codes returned after solving optimization problems, indicating the solution state.
LpStatusNotSolved: int = 0 # Problem has not been solved yet
LpStatusOptimal: int = 1 # Optimal solution found
LpStatusInfeasible: int = -1 # Problem has no feasible solution
LpStatusUnbounded: int = -2 # Problem is unbounded (infinite optimum)
LpStatusUndefined: int = -3 # Solution status is undefined/unknown
LpStatus: dict = {
LpStatusNotSolved: "Not Solved",
LpStatusOptimal: "Optimal",
LpStatusInfeasible: "Infeasible",
LpStatusUnbounded: "Unbounded",
LpStatusUndefined: "Undefined"
} # Mapping of status codes to descriptive stringsUsage examples:
# Solve problem and check status
status = prob.solve()
if status == LpStatusOptimal:
print("Optimal solution found!")
print(f"Objective value: {value(prob.objective)}")
elif status == LpStatusInfeasible:
print("Problem is infeasible - no solution exists")
elif status == LpStatusUnbounded:
print("Problem is unbounded - infinite optimum")
else:
print(f"Solution status: {LpStatus[status]}")
# Robust status checking
def interpret_solution(status):
return LpStatus.get(status, f"Unknown status: {status}")
print(interpret_solution(status))Detailed solution status codes providing more granular information about the solution quality and type.
LpSolutionNoSolutionFound: int = 0 # No solution found by solver
LpSolutionOptimal: int = 1 # Optimal solution found
LpSolutionIntegerFeasible: int = 2 # Integer feasible solution (may not be optimal)
LpSolutionInfeasible: int = -1 # No feasible solution exists
LpSolutionUnbounded: int = -2 # Unbounded solution
LpSolution: dict = {
LpSolutionNoSolutionFound: "No Solution Found",
LpSolutionOptimal: "Optimal",
LpSolutionIntegerFeasible: "Integer Feasible",
LpSolutionInfeasible: "Infeasible",
LpSolutionUnbounded: "Unbounded"
} # Solution status to string mappings
LpStatusToSolution: dict = {
LpStatusNotSolved: LpSolutionNoSolutionFound,
LpStatusOptimal: LpSolutionOptimal,
LpStatusInfeasible: LpSolutionInfeasible,
LpStatusUnbounded: LpSolutionUnbounded,
LpStatusUndefined: LpSolutionNoSolutionFound
} # Mapping from problem status to solution statusUsage examples:
# Get detailed solution information
status = prob.solve()
solution_status = LpStatusToSolution[status]
print(f"Problem status: {LpStatus[status]}")
print(f"Solution status: {LpSolution[solution_status]}")
# Handle different solution qualities
if solution_status == LpSolutionOptimal:
print("Found proven optimal solution")
elif solution_status == LpSolutionIntegerFeasible:
print("Found feasible integer solution (may not be optimal)")Constants defining the mathematical relationship types for constraints (less than or equal, equal, greater than or equal).
LpConstraintLE: int = -1 # Less than or equal constraint (<=)
LpConstraintEQ: int = 0 # Equality constraint (=)
LpConstraintGE: int = 1 # Greater than or equal constraint (>=)
LpConstraintSenses: dict = {
LpConstraintLE: "<=",
LpConstraintEQ: "=",
LpConstraintGE: ">="
} # Constraint sense to symbol mapping
LpConstraintTypeToMps: dict = {
LpConstraintLE: "L",
LpConstraintEQ: "E",
LpConstraintGE: "G"
} # MPS format constraint type codesUsage examples:
# Create constraints with explicit senses
constraint1 = LpConstraint(x + y, LpConstraintLE, "capacity", 100) # x + y <= 100
constraint2 = LpConstraint(2*x, LpConstraintEQ, "balance", 50) # 2*x = 50
constraint3 = LpConstraint(y, LpConstraintGE, "minimum", 10) # y >= 10
# Add to problem
prob += constraint1
prob += constraint2
prob += constraint3
# Check constraint sense
print(f"Constraint sense: {LpConstraintSenses[constraint1.sense]}")
# Programmatic constraint generation
def create_constraint(expr, sense_type, rhs):
if sense_type == "<=":
sense = LpConstraintLE
elif sense_type == "=":
sense = LpConstraintEQ
elif sense_type == ">=":
sense = LpConstraintGE
else:
raise ValueError(f"Unknown constraint sense: {sense_type}")
return LpConstraint(expr, sense, rhs=rhs)
# Use constraint senses in loops
capacity_constraints = []
for i in range(n_facilities):
constraint = LpConstraint(
lpSum(production[i]),
LpConstraintLE,
f"capacity_{i}",
facility_capacity[i]
)
capacity_constraints.append(constraint)
prob += constraintConstants for file formatting and solver compatibility, particularly for MPS and LP file formats.
LpCplexLPLineSize: int = 78 # Maximum line length for CPLEX LP format filesUsage example:
# Used internally when writing LP format files
# Ensures compatibility with CPLEX and other solvers that expect specific line lengths
prob.writeLP("problem.lp") # Automatically handles line length constraintsUtility functions and patterns for robust status checking and error handling.
# Common status checking patterns
def check_solution_status(problem):
"""Check and report problem solution status."""
status = problem.status
if status == LpStatusOptimal:
return True, "Optimal solution found"
elif status == LpStatusInfeasible:
return False, "Problem is infeasible"
elif status == LpStatusUnbounded:
return False, "Problem is unbounded"
elif status == LpStatusNotSolved:
return False, "Problem not solved yet"
else:
return False, f"Unknown status: {LpStatus.get(status, status)}"
# Robust solution extraction
def safe_get_values(variables):
"""Safely extract variable values with status checking."""
results = {}
for var in variables:
val = value(var)
if val is not None:
results[var.name] = val
else:
results[var.name] = "Not solved"
return results
# Status-based decision making
def handle_solution(prob):
status = prob.solve()
if status in [LpStatusOptimal, LpSolutionIntegerFeasible]:
# Process successful solution
return extract_solution(prob)
elif status == LpStatusInfeasible:
# Analyze infeasibility
return analyze_infeasibility(prob)
elif status == LpStatusUnbounded:
# Handle unbounded case
return add_bounds_and_retry(prob)
else:
# Handle other cases
return handle_solve_failure(prob, status)class PulpError(Exception):
"""
Base exception class for PuLP-specific errors.
Raised for general PuLP modeling and solving errors.
"""
class PulpSolverError(Exception):
"""
Exception class for solver-specific errors.
Raised when solver execution fails or returns unexpected results.
"""Usage examples:
try:
status = prob.solve(CPLEX_CMD())
except PulpSolverError as e:
print(f"Solver error: {e}")
# Try alternative solver
status = prob.solve(PULP_CBC_CMD())
except PulpError as e:
print(f"PuLP error: {e}")
# Handle general PuLP errorsInstall with Tessl CLI
npx tessl i tessl/pypi-pulp