0
# Mathematical Functions
1
2
Nonlinear mathematical functions for advanced optimization modeling. These functions integrate with PySCIPOpt's expression system to enable modeling of nonlinear optimization problems including exponential, logarithmic, trigonometric, and power functions.
3
4
## Capabilities
5
6
### Exponential Functions
7
8
Exponential function for modeling exponential growth, decay, and other exponential relationships in optimization problems.
9
10
```python { .api }
11
def exp(expr):
12
"""
13
Exponential function: e^expr
14
15
Creates a nonlinear expression representing the exponential function
16
applied to the input expression. Commonly used in nonlinear programming,
17
portfolio optimization, and exponential utility functions.
18
19
Parameters:
20
- expr: Expression, variable, or numeric value to exponentiate
21
22
Returns:
23
GenExpr: General expression representing e^expr
24
25
Example:
26
# Exponential utility function
27
utility = -exp(-risk_aversion * portfolio_return)
28
29
# Exponential decay constraint
30
model.addCons(concentration <= initial_amount * exp(-decay_rate * time))
31
"""
32
```
33
34
### Logarithmic Functions
35
36
Natural logarithm function for modeling logarithmic relationships and transformations.
37
38
```python { .api }
39
def log(expr):
40
"""
41
Natural logarithm function: ln(expr)
42
43
Creates a nonlinear expression representing the natural logarithm
44
of the input expression. Used in logarithmic utility functions,
45
entropy maximization, and geometric programming.
46
47
Parameters:
48
- expr: Expression, variable, or numeric value (must be positive)
49
50
Returns:
51
GenExpr: General expression representing ln(expr)
52
53
Example:
54
# Logarithmic utility function
55
utility = log(consumption)
56
57
# Entropy constraint
58
model.addCons(quicksum(p[i] * log(p[i]) for i in range(n)) >= min_entropy)
59
60
# Log barrier for interior point methods
61
barrier = -quicksum(log(x[i]) for i in range(n))
62
"""
63
```
64
65
### Square Root Function
66
67
Square root function for modeling quadratic relationships and Euclidean distances.
68
69
```python { .api }
70
def sqrt(expr):
71
"""
72
Square root function: √expr
73
74
Creates a nonlinear expression representing the square root
75
of the input expression. Used in distance calculations,
76
geometric constraints, and quadratic transformations.
77
78
Parameters:
79
- expr: Expression, variable, or numeric value (must be non-negative)
80
81
Returns:
82
GenExpr: General expression representing √expr
83
84
Example:
85
# Euclidean distance constraint
86
distance = sqrt((x1 - x2)**2 + (y1 - y2)**2)
87
model.addCons(distance <= max_distance)
88
89
# Quadratic mean constraint
90
quad_mean = sqrt(quicksum(x[i]**2 for i in range(n)) / n)
91
92
# Risk measure (standard deviation)
93
risk = sqrt(variance_expr)
94
"""
95
```
96
97
### Trigonometric Functions
98
99
Sine and cosine functions for modeling periodic phenomena and geometric relationships.
100
101
```python { .api }
102
def sin(expr):
103
"""
104
Sine function: sin(expr)
105
106
Creates a nonlinear expression representing the sine function
107
applied to the input expression (in radians). Used in periodic
108
optimization problems, signal processing, and geometric modeling.
109
110
Parameters:
111
- expr: Expression, variable, or numeric value (angle in radians)
112
113
Returns:
114
GenExpr: General expression representing sin(expr)
115
116
Example:
117
# Periodic production constraint
118
seasonal_demand = base_demand + amplitude * sin(2 * pi * time / period)
119
120
# Signal processing constraint
121
signal = quicksum(amplitude[i] * sin(frequency[i] * time + phase[i])
122
for i in range(n))
123
"""
124
125
def cos(expr):
126
"""
127
Cosine function: cos(expr)
128
129
Creates a nonlinear expression representing the cosine function
130
applied to the input expression (in radians). Used alongside sine
131
for complete trigonometric modeling.
132
133
Parameters:
134
- expr: Expression, variable, or numeric value (angle in radians)
135
136
Returns:
137
GenExpr: General expression representing cos(expr)
138
139
Example:
140
# Circular constraint (unit circle)
141
model.addCons(cos(angle)**2 + sin(angle)**2 == 1)
142
143
# Harmonic oscillator
144
position = amplitude * cos(frequency * time + phase)
145
146
# Geometric positioning
147
x_coord = radius * cos(angle)
148
y_coord = radius * sin(angle)
149
"""
150
```
151
152
## Usage Examples
153
154
### Exponential Utility Functions
155
156
```python
157
from pyscipopt import Model, exp, quicksum
158
159
model = Model("exponential_utility")
160
161
# Investment variables
162
investments = [model.addVar(name=f"invest_{i}", lb=0) for i in range(5)]
163
total_investment = quicksum(investments)
164
165
# Risk aversion parameter
166
risk_aversion = 2.0
167
168
# Expected returns (given)
169
expected_returns = [0.05, 0.08, 0.12, 0.15, 0.20]
170
171
# Portfolio expected return
172
portfolio_return = quicksum(expected_returns[i] * investments[i]
173
for i in range(5)) / total_investment
174
175
# Exponential utility function (risk-averse)
176
utility = -exp(-risk_aversion * portfolio_return)
177
178
# Maximize utility (minimize negative utility)
179
model.setObjective(utility, "minimize")
180
181
# Budget constraint
182
model.addCons(total_investment == 100000, name="budget")
183
184
model.optimize()
185
```
186
187
### Logarithmic Barrier Methods
188
189
```python
190
from pyscipopt import Model, log, quicksum
191
192
model = Model("log_barrier")
193
194
# Variables with positivity constraints
195
x = [model.addVar(name=f"x_{i}", lb=0.001) for i in range(3)] # Small lower bound
196
197
# Original objective
198
original_obj = quicksum((i+1) * x[i] for i in range(3))
199
200
# Logarithmic barrier to enforce positivity
201
barrier_param = 0.1
202
barrier_term = -barrier_param * quicksum(log(x[i]) for i in range(3))
203
204
# Combined objective with barrier
205
model.setObjective(original_obj + barrier_term, "minimize")
206
207
# Linear constraints
208
model.addCons(x[0] + 2*x[1] + x[2] <= 10, name="constraint1")
209
model.addCons(2*x[0] + x[1] + 3*x[2] <= 15, name="constraint2")
210
211
model.optimize()
212
```
213
214
### Distance and Geometric Constraints
215
216
```python
217
from pyscipopt import Model, sqrt
218
219
model = Model("geometric_constraints")
220
221
# Facility locations
222
facilities = [(0, 0), (10, 0), (5, 8)] # Fixed facility coordinates
223
n_customers = 5
224
225
# Customer assignment variables
226
customer_x = [model.addVar(name=f"customer_{i}_x", lb=0, ub=10)
227
for i in range(n_customers)]
228
customer_y = [model.addVar(name=f"customer_{i}_y", lb=0, ub=10)
229
for i in range(n_customers)]
230
231
# Assignment variables (which facility serves each customer)
232
assignment = {}
233
for i in range(n_customers):
234
for j in range(3):
235
assignment[i, j] = model.addVar(name=f"assign_{i}_{j}", vtype="B")
236
237
# Each customer assigned to exactly one facility
238
for i in range(n_customers):
239
model.addCons(quicksum(assignment[i, j] for j in range(3)) == 1,
240
name=f"assign_customer_{i}")
241
242
# Distance constraints
243
max_distance = 6.0
244
for i in range(n_customers):
245
for j in range(3):
246
# Distance from customer i to facility j
247
distance = sqrt((customer_x[i] - facilities[j][0])**2 +
248
(customer_y[i] - facilities[j][1])**2)
249
250
# If assigned, distance must be within limit
251
# Using big-M constraint: distance <= max_distance + M*(1 - assignment[i,j])
252
big_M = 20.0 # Large enough constant
253
model.addCons(distance <= max_distance + big_M * (1 - assignment[i, j]),
254
name=f"distance_{i}_{j}")
255
256
# Minimize total assignment cost (example)
257
model.setObjective(quicksum(assignment[i, j] for i in range(n_customers)
258
for j in range(3)), "minimize")
259
260
model.optimize()
261
```
262
263
### Trigonometric Signal Processing
264
265
```python
266
from pyscipopt import Model, sin, cos, quicksum
267
import math
268
269
model = Model("signal_processing")
270
271
# Time points
272
time_points = [i * 0.1 for i in range(100)] # 0.0, 0.1, 0.2, ..., 9.9
273
n_time = len(time_points)
274
275
# Signal parameters to optimize
276
amplitude = [model.addVar(name=f"amp_{i}", lb=0, ub=5) for i in range(3)]
277
frequency = [model.addVar(name=f"freq_{i}", lb=0.1, ub=2.0) for i in range(3)]
278
phase = [model.addVar(name=f"phase_{i}", lb=0, ub=2*math.pi) for i in range(3)]
279
280
# Target signal (given data)
281
target_signal = [math.sin(0.5*t) + 0.3*math.cos(1.2*t + 0.5) for t in time_points]
282
283
# Approximation error variables
284
error = [model.addVar(name=f"error_{t}", lb=-10, ub=10) for t in range(n_time)]
285
286
# Signal approximation constraints
287
for t in range(n_time):
288
# Approximate signal as sum of sinusoids
289
approx_signal = quicksum(
290
amplitude[i] * sin(frequency[i] * time_points[t] + phase[i])
291
for i in range(3)
292
)
293
294
# Error definition
295
model.addCons(error[t] == approx_signal - target_signal[t],
296
name=f"error_def_{t}")
297
298
# Minimize sum of squared errors
299
model.setObjective(quicksum(error[t]**2 for t in range(n_time)), "minimize")
300
301
model.optimize()
302
```
303
304
### Conic Constraints with Square Root
305
306
```python
307
from pyscipopt import Model, sqrt, quicksum
308
309
model = Model("conic_constraints")
310
311
# Variables
312
x = [model.addVar(name=f"x_{i}", lb=-5, ub=5) for i in range(3)]
313
t = model.addVar(name="t", lb=0)
314
315
# Second-order cone constraint: ||x|| <= t
316
# Equivalent to: sqrt(x[0]^2 + x[1]^2 + x[2]^2) <= t
317
norm_x = sqrt(quicksum(x[i]**2 for i in range(3)))
318
model.addCons(norm_x <= t, name="second_order_cone")
319
320
# Minimize the norm
321
model.setObjective(t, "minimize")
322
323
# Additional linear constraints
324
model.addCons(x[0] + x[1] + x[2] >= 2, name="linear_constraint")
325
model.addCons(2*x[0] - x[1] + x[2] <= 3, name="another_constraint")
326
327
model.optimize()
328
```
329
330
### Logarithmic Mean Constraints
331
332
```python
333
from pyscipopt import Model, log, exp, quicksum
334
335
model = Model("logarithmic_mean")
336
337
# Positive variables
338
x = [model.addVar(name=f"x_{i}", lb=0.1) for i in range(5)]
339
340
# Geometric mean constraint using logarithms
341
# Geometric mean: (x[0] * x[1] * ... * x[4])^(1/5)
342
# Taking log: (1/5) * (log(x[0]) + log(x[1]) + ... + log(x[4]))
343
# Then exp to get back to original scale
344
345
log_geometric_mean = (1/5) * quicksum(log(x[i]) for i in range(5))
346
geometric_mean = exp(log_geometric_mean)
347
348
# Constraint: geometric mean >= target
349
target_geometric_mean = 2.0
350
model.addCons(geometric_mean >= target_geometric_mean, name="geo_mean_constraint")
351
352
# Arithmetic mean constraint for comparison
353
arithmetic_mean = quicksum(x[i] for i in range(5)) / 5
354
model.addCons(arithmetic_mean <= 10, name="arith_mean_constraint")
355
356
# Minimize sum of variables
357
model.setObjective(quicksum(x[i] for i in range(5)), "minimize")
358
359
model.optimize()
360
```
361
362
### Compound Interest and Growth Models
363
364
```python
365
from pyscipopt import Model, exp, log
366
367
model = Model("compound_interest")
368
369
# Investment variables over time periods
370
periods = 10
371
investments = [model.addVar(name=f"invest_period_{t}", lb=0)
372
for t in range(periods)]
373
374
# Interest rate (annual)
375
interest_rate = 0.05
376
377
# Compound growth using exponential function
378
final_values = []
379
for t in range(periods):
380
# Value after compound interest: investment * e^(rate * remaining_time)
381
remaining_time = periods - t
382
final_value = investments[t] * exp(interest_rate * remaining_time)
383
final_values.append(final_value)
384
385
# Total final value
386
total_final_value = quicksum(final_values)
387
388
# Target final value
389
target_value = 100000
390
model.addCons(total_final_value >= target_value, name="target_achievement")
391
392
# Budget constraints for each period
393
period_budgets = [5000, 6000, 7000, 8000, 9000, 10000, 8000, 6000, 4000, 2000]
394
for t in range(periods):
395
model.addCons(investments[t] <= period_budgets[t],
396
name=f"budget_period_{t}")
397
398
# Minimize total investment
399
model.setObjective(quicksum(investments[t] for t in range(periods)), "minimize")
400
401
model.optimize()
402
403
# Print results
404
if model.getStatus() == 'optimal':
405
print(f"Total investment needed: {model.getObjVal():.2f}")
406
print(f"Final value achieved: {sum(model.getVal(fv) for fv in final_values):.2f}")
407
```