0
# Constants and Enums
1
2
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.
3
4
## Capabilities
5
6
### Package Metadata
7
8
Version information and precision constants for the PuLP package.
9
10
```python { .api }
11
VERSION: str = "3.2.2" # PuLP package version
12
EPS: float = 1e-7 # Default numerical precision tolerance
13
```
14
15
### Variable Categories
16
17
Constants defining the types of decision variables supported in optimization problems.
18
19
```python { .api }
20
LpContinuous: str = "Continuous" # Continuous variables (real numbers)
21
LpInteger: str = "Integer" # Integer variables (whole numbers)
22
LpBinary: str = "Binary" # Binary variables (0 or 1)
23
24
LpCategories: dict = {
25
LpContinuous: "Continuous",
26
LpInteger: "Integer",
27
LpBinary: "Binary"
28
} # Mapping of category constants to string representations
29
```
30
31
Usage examples:
32
33
```python
34
# Create variables with different categories
35
x_cont = LpVariable("x", cat=LpContinuous) # Can take any real value
36
y_int = LpVariable("y", cat=LpInteger) # Must be whole number
37
z_bin = LpVariable("z", cat=LpBinary) # Must be 0 or 1
38
39
# Check variable category
40
if x_cont.cat == LpContinuous:
41
print("x is a continuous variable")
42
43
# Use in bulk creation
44
binary_vars = LpVariable.dicts("decision", range(10), cat=LpBinary)
45
```
46
47
### Optimization Senses
48
49
Constants specifying whether the optimization problem seeks to minimize or maximize the objective function.
50
51
```python { .api }
52
LpMinimize: int = 1 # Minimize the objective function
53
LpMaximize: int = -1 # Maximize the objective function
54
55
LpSenses: dict = {
56
LpMinimize: "Minimize",
57
LpMaximize: "Maximize"
58
} # Mapping of sense constants to string representations
59
60
LpSensesMPS: dict = {
61
LpMaximize: "MAX",
62
LpMinimize: "MIN"
63
} # MPS format sense representations
64
```
65
66
Usage examples:
67
68
```python
69
# Create problems with different senses
70
min_prob = LpProblem("Cost_Minimization", LpMinimize)
71
max_prob = LpProblem("Profit_Maximization", LpMaximize)
72
73
# Check problem sense
74
if min_prob.sense == LpMinimize:
75
print("This is a minimization problem")
76
77
# Convert sense to string
78
print(f"Problem sense: {LpSenses[min_prob.sense]}")
79
```
80
81
### Problem Status Constants
82
83
Status codes returned after solving optimization problems, indicating the solution state.
84
85
```python { .api }
86
LpStatusNotSolved: int = 0 # Problem has not been solved yet
87
LpStatusOptimal: int = 1 # Optimal solution found
88
LpStatusInfeasible: int = -1 # Problem has no feasible solution
89
LpStatusUnbounded: int = -2 # Problem is unbounded (infinite optimum)
90
LpStatusUndefined: int = -3 # Solution status is undefined/unknown
91
92
LpStatus: dict = {
93
LpStatusNotSolved: "Not Solved",
94
LpStatusOptimal: "Optimal",
95
LpStatusInfeasible: "Infeasible",
96
LpStatusUnbounded: "Unbounded",
97
LpStatusUndefined: "Undefined"
98
} # Mapping of status codes to descriptive strings
99
```
100
101
Usage examples:
102
103
```python
104
# Solve problem and check status
105
status = prob.solve()
106
107
if status == LpStatusOptimal:
108
print("Optimal solution found!")
109
print(f"Objective value: {value(prob.objective)}")
110
elif status == LpStatusInfeasible:
111
print("Problem is infeasible - no solution exists")
112
elif status == LpStatusUnbounded:
113
print("Problem is unbounded - infinite optimum")
114
else:
115
print(f"Solution status: {LpStatus[status]}")
116
117
# Robust status checking
118
def interpret_solution(status):
119
return LpStatus.get(status, f"Unknown status: {status}")
120
121
print(interpret_solution(status))
122
```
123
124
### Solution Status Constants
125
126
Detailed solution status codes providing more granular information about the solution quality and type.
127
128
```python { .api }
129
LpSolutionNoSolutionFound: int = 0 # No solution found by solver
130
LpSolutionOptimal: int = 1 # Optimal solution found
131
LpSolutionIntegerFeasible: int = 2 # Integer feasible solution (may not be optimal)
132
LpSolutionInfeasible: int = -1 # No feasible solution exists
133
LpSolutionUnbounded: int = -2 # Unbounded solution
134
135
LpSolution: dict = {
136
LpSolutionNoSolutionFound: "No Solution Found",
137
LpSolutionOptimal: "Optimal",
138
LpSolutionIntegerFeasible: "Integer Feasible",
139
LpSolutionInfeasible: "Infeasible",
140
LpSolutionUnbounded: "Unbounded"
141
} # Solution status to string mappings
142
143
LpStatusToSolution: dict = {
144
LpStatusNotSolved: LpSolutionNoSolutionFound,
145
LpStatusOptimal: LpSolutionOptimal,
146
LpStatusInfeasible: LpSolutionInfeasible,
147
LpStatusUnbounded: LpSolutionUnbounded,
148
LpStatusUndefined: LpSolutionNoSolutionFound
149
} # Mapping from problem status to solution status
150
```
151
152
Usage examples:
153
154
```python
155
# Get detailed solution information
156
status = prob.solve()
157
solution_status = LpStatusToSolution[status]
158
159
print(f"Problem status: {LpStatus[status]}")
160
print(f"Solution status: {LpSolution[solution_status]}")
161
162
# Handle different solution qualities
163
if solution_status == LpSolutionOptimal:
164
print("Found proven optimal solution")
165
elif solution_status == LpSolutionIntegerFeasible:
166
print("Found feasible integer solution (may not be optimal)")
167
```
168
169
### Constraint Senses
170
171
Constants defining the mathematical relationship types for constraints (less than or equal, equal, greater than or equal).
172
173
```python { .api }
174
LpConstraintLE: int = -1 # Less than or equal constraint (<=)
175
LpConstraintEQ: int = 0 # Equality constraint (=)
176
LpConstraintGE: int = 1 # Greater than or equal constraint (>=)
177
178
LpConstraintSenses: dict = {
179
LpConstraintLE: "<=",
180
LpConstraintEQ: "=",
181
LpConstraintGE: ">="
182
} # Constraint sense to symbol mapping
183
184
LpConstraintTypeToMps: dict = {
185
LpConstraintLE: "L",
186
LpConstraintEQ: "E",
187
LpConstraintGE: "G"
188
} # MPS format constraint type codes
189
```
190
191
Usage examples:
192
193
```python
194
# Create constraints with explicit senses
195
constraint1 = LpConstraint(x + y, LpConstraintLE, "capacity", 100) # x + y <= 100
196
constraint2 = LpConstraint(2*x, LpConstraintEQ, "balance", 50) # 2*x = 50
197
constraint3 = LpConstraint(y, LpConstraintGE, "minimum", 10) # y >= 10
198
199
# Add to problem
200
prob += constraint1
201
prob += constraint2
202
prob += constraint3
203
204
# Check constraint sense
205
print(f"Constraint sense: {LpConstraintSenses[constraint1.sense]}")
206
207
# Programmatic constraint generation
208
def create_constraint(expr, sense_type, rhs):
209
if sense_type == "<=":
210
sense = LpConstraintLE
211
elif sense_type == "=":
212
sense = LpConstraintEQ
213
elif sense_type == ">=":
214
sense = LpConstraintGE
215
else:
216
raise ValueError(f"Unknown constraint sense: {sense_type}")
217
218
return LpConstraint(expr, sense, rhs=rhs)
219
220
# Use constraint senses in loops
221
capacity_constraints = []
222
for i in range(n_facilities):
223
constraint = LpConstraint(
224
lpSum(production[i]),
225
LpConstraintLE,
226
f"capacity_{i}",
227
facility_capacity[i]
228
)
229
capacity_constraints.append(constraint)
230
prob += constraint
231
```
232
233
### File Format Constants
234
235
Constants for file formatting and solver compatibility, particularly for MPS and LP file formats.
236
237
```python { .api }
238
LpCplexLPLineSize: int = 78 # Maximum line length for CPLEX LP format files
239
```
240
241
Usage example:
242
243
```python
244
# Used internally when writing LP format files
245
# Ensures compatibility with CPLEX and other solvers that expect specific line lengths
246
prob.writeLP("problem.lp") # Automatically handles line length constraints
247
```
248
249
### Status and Error Checking Utilities
250
251
Utility functions and patterns for robust status checking and error handling.
252
253
```python
254
# Common status checking patterns
255
def check_solution_status(problem):
256
"""Check and report problem solution status."""
257
status = problem.status
258
259
if status == LpStatusOptimal:
260
return True, "Optimal solution found"
261
elif status == LpStatusInfeasible:
262
return False, "Problem is infeasible"
263
elif status == LpStatusUnbounded:
264
return False, "Problem is unbounded"
265
elif status == LpStatusNotSolved:
266
return False, "Problem not solved yet"
267
else:
268
return False, f"Unknown status: {LpStatus.get(status, status)}"
269
270
# Robust solution extraction
271
def safe_get_values(variables):
272
"""Safely extract variable values with status checking."""
273
results = {}
274
for var in variables:
275
val = value(var)
276
if val is not None:
277
results[var.name] = val
278
else:
279
results[var.name] = "Not solved"
280
return results
281
282
# Status-based decision making
283
def handle_solution(prob):
284
status = prob.solve()
285
286
if status in [LpStatusOptimal, LpSolutionIntegerFeasible]:
287
# Process successful solution
288
return extract_solution(prob)
289
elif status == LpStatusInfeasible:
290
# Analyze infeasibility
291
return analyze_infeasibility(prob)
292
elif status == LpStatusUnbounded:
293
# Handle unbounded case
294
return add_bounds_and_retry(prob)
295
else:
296
# Handle other cases
297
return handle_solve_failure(prob, status)
298
```
299
300
## Exception Types
301
302
```python { .api }
303
class PulpError(Exception):
304
"""
305
Base exception class for PuLP-specific errors.
306
Raised for general PuLP modeling and solving errors.
307
"""
308
309
class PulpSolverError(Exception):
310
"""
311
Exception class for solver-specific errors.
312
Raised when solver execution fails or returns unexpected results.
313
"""
314
```
315
316
Usage examples:
317
318
```python
319
try:
320
status = prob.solve(CPLEX_CMD())
321
except PulpSolverError as e:
322
print(f"Solver error: {e}")
323
# Try alternative solver
324
status = prob.solve(PULP_CBC_CMD())
325
except PulpError as e:
326
print(f"PuLP error: {e}")
327
# Handle general PuLP errors
328
```