Examples
Real-world examples and use cases.
Engineering Design Optimization
Pressure Vessel Design
Minimize the cost of a pressure vessel while satisfying constraints:
import numpy as np
from pyrade import DifferentialEvolution
def pressure_vessel_cost(x):
"""
Minimize cost of pressure vessel design.
x[0]: shell thickness
x[1]: head thickness
x[2]: inner radius
x[3]: length
"""
# Material and welding costs
cost = (
0.6224 * x[0] * x[2] * x[3] +
1.7781 * x[1] * x[2]**2 +
3.1661 * x[0]**2 * x[3] +
19.84 * x[0]**2 * x[2]
)
# Constraint penalties
penalty = 0
# Minimum thickness constraints
if x[0] < 0.0625:
penalty += 1000 * (0.0625 - x[0])**2
if x[1] < 0.0625:
penalty += 1000 * (0.0625 - x[1])**2
# Volume constraint
volume = np.pi * x[2]**2 * x[3] + 4/3 * np.pi * x[2]**3
if volume < 1296000:
penalty += 10 * (1296000 - volume)**2
return cost + penalty
# Define bounds
bounds = [
(0.0625, 99), # shell thickness
(0.0625, 99), # head thickness
(10, 200), # inner radius
(10, 200) # length
]
# Optimize
optimizer = DifferentialEvolution(
objective_func=pressure_vessel_cost,
bounds=bounds,
pop_size=40,
max_iter=500
)
result = optimizer.optimize()
print(f"Optimal cost: ${result['best_fitness']:.2f}")
print(f"Design: {result['best_solution']}")
Machine Learning Hyperparameter Tuning
Optimize neural network hyperparameters:
from pyrade import DifferentialEvolution
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import cross_val_score
def optimize_nn(x):
"""Optimize neural network hyperparameters"""
hidden_layer_sizes = int(x[0])
learning_rate = 10 ** x[1]
alpha = 10 ** x[2]
model = MLPClassifier(
hidden_layer_sizes=(hidden_layer_sizes,),
learning_rate_init=learning_rate,
alpha=alpha,
max_iter=1000,
random_state=42
)
# Return negative accuracy (we minimize)
score = cross_val_score(model, X_train, y_train, cv=5)
return -np.mean(score)
bounds = [
(10, 200), # hidden layer size
(-5, -1), # log10(learning_rate)
(-5, -1) # log10(alpha)
]
optimizer = DifferentialEvolution(
objective_func=optimize_nn,
bounds=bounds,
pop_size=20,
max_iter=50
)
result = optimizer.optimize()
print(f"Best accuracy: {-result['best_fitness']:.4f}")
Portfolio Optimization
Optimize asset allocation:
import numpy as np
from pyrade import DifferentialEvolution
def portfolio_risk(weights, returns, cov_matrix):
"""
Minimize portfolio risk while targeting return.
weights: asset allocation (must sum to 1)
"""
# Normalize weights to sum to 1
weights = weights / np.sum(weights)
# Portfolio return
portfolio_return = np.dot(weights, returns)
# Portfolio variance (risk)
portfolio_variance = np.dot(weights, np.dot(cov_matrix, weights))
# Minimize variance with return penalty
target_return = 0.10
return_penalty = 1000 * max(0, target_return - portfolio_return)**2
return portfolio_variance + return_penalty
# Example data
n_assets = 5
returns = np.random.rand(n_assets) * 0.15
cov_matrix = np.random.rand(n_assets, n_assets)
cov_matrix = (cov_matrix + cov_matrix.T) / 2
bounds = [(0, 1)] * n_assets
optimizer = DifferentialEvolution(
objective_func=lambda w: portfolio_risk(w, returns, cov_matrix),
bounds=bounds,
pop_size=50,
max_iter=300
)
result = optimizer.optimize()
optimal_weights = result['best_solution'] / np.sum(result['best_solution'])
print(f"Optimal allocation: {optimal_weights}")
Function Approximation
Find parameters for a model to fit data:
import numpy as np
from pyrade import DifferentialEvolution
def model(x, params):
"""Model: y = a*sin(b*x + c) + d"""
a, b, c, d = params
return a * np.sin(b * x + c) + d
def fit_error(params):
"""MSE between model and data"""
predictions = model(x_data, params)
return np.mean((y_data - predictions)**2)
# Generate noisy data
x_data = np.linspace(0, 10, 100)
true_params = [2, 0.5, 1, 0.5]
y_data = model(x_data, true_params) + np.random.normal(0, 0.1, 100)
# Optimize
bounds = [
(-5, 5), # amplitude
(0, 2), # frequency
(0, 2*np.pi), # phase
(-2, 2) # offset
]
optimizer = DifferentialEvolution(
objective_func=fit_error,
bounds=bounds,
pop_size=50,
max_iter=200
)
result = optimizer.optimize()
print(f"True params: {true_params}")
print(f"Found params: {result['best_solution']}")
print(f"MSE: {result['best_fitness']:.6f}")
Custom Strategy Example
Create and use a custom adaptive mutation strategy:
from pyrade.operators import MutationStrategy
import numpy as np
class AdaptiveMutation(MutationStrategy):
"""Adapts F based on fitness improvement"""
def __init__(self, F_min=0.4, F_max=1.0):
self.F_min = F_min
self.F_max = F_max
self.F = F_max
self.prev_best = float('inf')
def apply(self, population, fitness, best_idx, target_indices):
pop_size, dim = population.shape
# Adapt F based on improvement
current_best = fitness[best_idx]
if current_best < self.prev_best:
# Improving: increase exploration
self.F = min(self.F * 1.1, self.F_max)
else:
# Stagnating: increase exploitation
self.F = max(self.F * 0.9, self.F_min)
self.prev_best = current_best
# Standard DE/rand/1 with adaptive F
indices = np.arange(pop_size)
r1 = np.random.choice(indices, size=pop_size)
r2 = np.random.choice(indices, size=pop_size)
r3 = np.random.choice(indices, size=pop_size)
mutants = population[r1] + self.F * (population[r2] - population[r3])
return mutants
# Use custom strategy
from pyrade import DifferentialEvolution
from pyrade.benchmarks import Rastrigin
func = Rastrigin(dim=20)
optimizer = DifferentialEvolution(
objective_func=func,
bounds=func.get_bounds_array(),
mutation=AdaptiveMutation(),
pop_size=100,
max_iter=500
)
result = optimizer.optimize()
print(f"Result: {result['best_fitness']:.6e}")
Parallel Evaluation
For expensive objective functions, use multiprocessing:
from multiprocessing import Pool
import numpy as np
from pyrade import DifferentialEvolution
def expensive_function(x):
"""Simulated expensive computation"""
import time
time.sleep(0.01) # Simulate delay
return np.sum(x**2)
def parallel_objective(population):
"""Evaluate population in parallel"""
with Pool() as pool:
results = pool.map(expensive_function, population)
return np.array(results)
# Note: You'd need to modify DE to accept batch evaluation
# This is conceptual - shows the pattern