SciPy Optimization
Optimization means finding the best value: the lowest cost, the highest profit, or the point where an equation equals zero.
What scipy.optimize Can Do
| Function | Finds |
|---|---|
minimize_scalar(f) | The minimum of a function of one variable |
minimize(f, x0) | The minimum of a function of several variables |
root_scalar(f, bracket) | Where a one-variable function equals zero |
root(f, x0) | Roots of equations, including systems |
curve_fit(model, x, y) | The best parameters to fit a curve to data |
Finding a Minimum of One Variable
A shop's cost to make x hundred items is cost(x) = x² - 8x + 20 thousand rupees. Which x gives the lowest cost?
Example
from scipy.optimize import minimize_scalar
def cost(x):
return x ** 2 - 8 * x + 20
result = minimize_scalar(cost)
print("Best x:", round(result.x, 3))
print("Lowest cost:", round(result.fun, 3))Best x: 4.0 Lowest cost: 4.0
The result object holds the answer: x is where the minimum is and fun is the value of the function there.
Finding a Maximum
SciPy only minimises. To find a maximum, minimise the negative of your function.
Profit from selling at price p is profit(p) = -2p² + 400p. Which price gives the most profit?
Example
from scipy.optimize import minimize_scalar
def profit(p):
return -2 * p ** 2 + 400 * p
result = minimize_scalar(lambda p: -profit(p))
print("Best price:", round(result.x, 2))
print("Max profit:", round(profit(result.x), 2))Best price: 100.0 Max profit: 20000.0
Several Variables With minimize
minimize() needs a starting guess x0. Here we find the lowest point of f(x, y) = (x - 1)² + (y + 2)²:
Example
import numpy as np
from scipy.optimize import minimize
def f(v):
x, y = v
return (x - 1) ** 2 + (y + 2) ** 2
result = minimize(f, x0=[0, 0])
print(np.round(result.x, 3))
print(result.success)[ 1. -2.] True
Always check result.success. If it is False, try a different starting guess or a different method.
Finding Roots
A root is where a function equals zero. Solve x³ - 2x - 5 = 0:
Example
from scipy.optimize import root_scalar
result = root_scalar(lambda x: x ** 3 - 2 * x - 5, bracket=[2, 3])
print(round(result.root, 4))2.0946
bracket=[2, 3] tells SciPy the root lies between 2 and 3. The function must have different signs at the two ends.
Fitting a Curve to Data
curve_fit() finds the parameters of a model that best match your data. A shop's monthly customers grow roughly in a straight line. Let us fit y = a·x + b:
Example
import numpy as np
from scipy.optimize import curve_fit
months = np.array([1, 2, 3, 4, 5, 6])
customers = np.array([110, 132, 149, 171, 188, 212])
def line(x, a, b):
return a * x + b
params, _ = curve_fit(line, months, customers)
a, b = params
print(f"a = {a:.2f}, b = {b:.2f}")
print("Month 9 forecast:", round(line(9, a, b)))a = 20.00, b = 90.33 Month 9 forecast: 270
The shop gains about 20 customers each month, and the model predicts about 270 customers in month 9.
Exercise
Exercise
SciPy's optimize functions only find minimums. How do you find the maximum of a function f?
