0
# Mathematical Operations
1
2
Essential functions for building linear expressions and extracting solution values from optimization problems. These operations form the mathematical foundation for PuLP's modeling capabilities.
3
4
## Capabilities
5
6
### Linear Expression Building
7
8
Functions for constructing complex linear expressions from lists of variables and coefficients, enabling efficient formulation of optimization problems.
9
10
```python { .api }
11
def lpSum(vector):
12
"""
13
Calculate the sum of a list of linear expressions or variables.
14
15
Parameters:
16
- vector (list): List of LpVariable, LpAffineExpression, or numeric values
17
18
Returns:
19
LpAffineExpression: Sum of all elements in the vector
20
21
Examples:
22
lpSum([x, y, z]) # x + y + z
23
lpSum([2*x, 3*y, 5]) # 2*x + 3*y + 5
24
lpSum(vars[i] for i in range(n)) # Sum over generated variables
25
"""
26
27
def lpDot(v1, v2):
28
"""
29
Calculate the dot product of two lists of linear expressions.
30
31
Parameters:
32
- v1 (list): First vector of LpVariable, LpAffineExpression, or numeric values
33
- v2 (list): Second vector of LpVariable, LpAffineExpression, or numeric values
34
35
Returns:
36
LpAffineExpression: Dot product v1[0]*v2[0] + v1[1]*v2[1] + ...
37
38
Examples:
39
lpDot([x, y], [2, 3]) # 2*x + 3*y
40
lpDot(costs, production) # Cost calculation
41
"""
42
```
43
44
Usage examples:
45
46
```python
47
# Sum multiple variables
48
x = [LpVariable(f"x_{i}", 0, 10) for i in range(5)]
49
total_x = lpSum(x) # x_0 + x_1 + x_2 + x_3 + x_4
50
51
# Sum with coefficients
52
costs = [10, 15, 20]
53
production = [LpVariable(f"prod_{i}", 0) for i in range(3)]
54
total_cost = lpSum([costs[i] * production[i] for i in range(3)])
55
56
# Dot product for cost calculations
57
unit_costs = [5.5, 7.2, 3.8, 9.1]
58
quantities = [LpVariable(f"qty_{i}", 0) for i in range(4)]
59
total_cost = lpDot(unit_costs, quantities)
60
61
# Complex expressions in constraints
62
prob += lpSum(production) <= 1000 # Total production constraint
63
prob += lpDot(weights, items) <= max_weight # Weight constraint
64
```
65
66
### Solution Value Extraction
67
68
Functions for retrieving and validating solution values from solved optimization problems with robust handling of unsolved states.
69
70
```python { .api }
71
def value(x):
72
"""
73
Get the value of a variable, expression, or number.
74
75
Parameters:
76
- x (LpVariable, LpAffineExpression, or number): Object to evaluate
77
78
Returns:
79
float: Value of x in the current solution, or x itself if it's a number
80
None: If x is a variable/expression and the problem hasn't been solved
81
82
Examples:
83
value(x) # Get variable value
84
value(2*x + 3*y) # Get expression value
85
value(5) # Returns 5 (unchanged)
86
"""
87
88
def valueOrDefault(x):
89
"""
90
Get the value of a variable/expression or return a default within bounds.
91
92
Parameters:
93
- x (LpVariable or LpAffineExpression): Object to evaluate
94
95
Returns:
96
float: Value of x, or a default value if not solved
97
98
Note: For variables, returns a value within the variable's bounds.
99
For expressions, returns the constant term or calculated default.
100
"""
101
102
def isNumber(x):
103
"""
104
Check if x is a numeric value (int or float).
105
106
Parameters:
107
- x: Object to check
108
109
Returns:
110
bool: True if x is int or float, False otherwise
111
"""
112
```
113
114
Usage examples:
115
116
```python
117
# After solving a problem
118
status = prob.solve()
119
120
if status == LpStatusOptimal:
121
# Get individual variable values
122
x_val = value(x)
123
y_val = value(y)
124
125
# Get expression values
126
obj_val = value(prob.objective)
127
constraint_lhs = value(2*x + 3*y)
128
129
# Check if values are available
130
if x_val is not None:
131
print(f"Optimal x = {x_val}")
132
133
# Use in calculations
134
total_profit = value(lpDot(profit_margins, production_vars))
135
136
# Handle mixed types
137
mixed_expr = 100 + 2*x # Constant + variable
138
mixed_val = value(mixed_expr) # Handles both parts correctly
139
140
# Robust value checking
141
for var in prob.variables():
142
var_value = value(var)
143
if var_value is not None:
144
print(f"{var.name} = {var_value}")
145
else:
146
print(f"{var.name} = Not solved")
147
```
148
149
### Expression Arithmetic
150
151
Mathematical operations are directly supported on PuLP objects through operator overloading, enabling natural mathematical syntax.
152
153
```python
154
# Arithmetic operations (built into LpVariable and LpAffineExpression)
155
# Addition
156
result = x + y # Variable + Variable -> LpAffineExpression
157
result = x + 5 # Variable + Number -> LpAffineExpression
158
result = expr1 + expr2 # Expression + Expression -> LpAffineExpression
159
160
# Subtraction
161
result = x - y # Variable - Variable -> LpAffineExpression
162
result = x - 10 # Variable - Number -> LpAffineExpression
163
164
# Multiplication (by scalars only - linear programming)
165
result = 3 * x # Number * Variable -> LpAffineExpression
166
result = 2.5 * expr # Number * Expression -> LpAffineExpression
167
168
# Division (by scalars only)
169
result = x / 2 # Variable / Number -> LpAffineExpression
170
171
# Negation
172
result = -x # Negate variable -> LpAffineExpression
173
174
# Comparison operations (create constraints)
175
constraint = x <= 10 # Creates LpConstraint with LpConstraintLE sense
176
constraint = x == 5 # Creates LpConstraint with LpConstraintEQ sense
177
constraint = x >= 0 # Creates LpConstraint with LpConstraintGE sense
178
```
179
180
### Advanced Mathematical Utilities
181
182
Additional mathematical functions for handling numeric precision and type validation in optimization contexts.
183
184
```python { .api }
185
def resource_clock():
186
"""
187
Return the current resource usage time for performance monitoring.
188
189
Returns:
190
float: Resource time in seconds
191
192
Note: Used internally for solver performance tracking.
193
"""
194
```
195
196
Usage examples:
197
198
```python
199
# Performance monitoring
200
start_time = resource_clock()
201
status = prob.solve()
202
solve_time = resource_clock() - start_time
203
print(f"Solve time: {solve_time:.3f} seconds")
204
205
# Type checking for robust code
206
def build_constraint(variables, coefficients):
207
if all(isNumber(c) for c in coefficients):
208
return lpDot(variables, coefficients) <= 100
209
else:
210
raise ValueError("All coefficients must be numeric")
211
212
# Complex mathematical expressions
213
# PuLP handles operator precedence correctly
214
complex_expr = 2*x + 3*(y - z) + 5*w/2
215
prob += complex_expr <= value_limit
216
217
# Multi-dimensional problem formulation
218
facilities = ["F1", "F2", "F3"]
219
customers = ["C1", "C2", "C3", "C4"]
220
flow = LpVariable.matrix("flow", facilities, customers, 0)
221
222
# Total flow constraint using lpSum
223
for f in facilities:
224
prob += lpSum([flow[f][c] for c in customers]) <= capacity[f]
225
226
# Demand satisfaction using lpSum
227
for c in customers:
228
prob += lpSum([flow[f][c] for f in facilities]) >= demand[c]
229
230
# Transportation cost objective using nested lpSum
231
transport_cost = lpSum([
232
lpSum([cost[f][c] * flow[f][c] for c in customers])
233
for f in facilities
234
])
235
prob += transport_cost
236
```