This tutorial covers optimizing functions with real-valued variables. You'll learn how to set up, run, and analyze continuous optimization problems.
We'll start with the Sphere function, a simple unimodal benchmark:
f(x) = Σxᵢ² = x₁² + x₂² + ... + xₙ²
Properties:
- Global minimum: 0 at origin (all zeros)
- Unimodal: Single optimum, no local minima
- Convex: Any local minimum is global
- Separable: Each variable is independent
{{#include ../../../examples/sphere_optimization.rs}}Source:
examples/sphere_optimization.rs
cargo run --example sphere_optimizationlet bounds = MultiBounds::symmetric(5.12, DIM);This creates bounds [-5.12, 5.12] for each of the 10 dimensions. The Sphere function is typically tested in this range.
Simulated Binary Crossover (SBX)
SbxCrossover::new(20.0)SBX creates offspring similar to parent values. The distribution index (eta = 20.0) controls spread:
- Higher eta → offspring closer to parents (exploitation)
- Lower eta → more diverse offspring (exploration)
Polynomial Mutation
PolynomialMutation::new(20.0)Adds bounded perturbations to gene values. The distribution index controls mutation magnitude.
let fitness = Sphere::new(DIM);Built-in Sphere computes the sum of squares. Since GAs maximize by default, the function is negated internally.
println!("Best fitness: {:.6}", result.best_fitness);
println!("Generations: {}", result.generations);
println!("Evaluations: {}", result.evaluations);Key metrics:
- Best fitness: Should approach 0 (the global minimum)
- Generations: How many evolutionary cycles completed
- Evaluations: Total fitness function calls
println!("{}", result.stats.summary());The summary shows:
- Mean and standard deviation per generation
- Diversity metrics
- Improvement trends
.population_size(100)| Size | Trade-off |
|---|---|
| Small (20-50) | Fast generations, less diversity |
| Medium (100-200) | Good balance |
| Large (500+) | More exploration, slower per generation |
For Sphere (unimodal), smaller populations work well. Multimodal functions need larger populations.
SBX Distribution Index
.crossover(SbxCrossover::new(eta))| eta | Effect |
|---|---|
| 1-5 | High exploration |
| 15-25 | Balanced |
| 50+ | High exploitation |
Mutation Probability
.mutation(PolynomialMutation::new(20.0).with_probability(0.1))Default is 1/dimension. Increase for more exploration.
.elitism(true)
.elite_count(2)Elitism preserves the best individuals across generations, preventing loss of good solutions.
Symptoms: Population converges too quickly, stuck at suboptimal solution
Solutions:
- Increase population size
- Lower selection pressure (smaller tournament size)
- Increase mutation probability
Symptoms: Fitness improves very slowly
Solutions:
- Increase selection pressure
- Reduce mutation (more exploitation)
- Use elitism to preserve progress
- Change dimensions: Modify
DIMto 30 and observe how convergence changes - Adjust operators: Try eta values of 5 and 50 for crossover
- Compare selections: Replace
TournamentSelectionwithRouletteWheelSelection
- Multimodal Optimization - Handle functions with local optima
- CMA-ES Tutorial - State-of-the-art continuous optimization