feat(algorithms): add IpopCmaEs (CMA-ES with restart) for multimodal problems
Auger & Hansen 2005 IPOP-CMA-ES: wraps the existing CmaEs in a restart loop that doubles the population size and re-randomizes the mean whenever a restart trigger fires. Specifically addresses the failure mode we observed on Rastrigin (vanilla CMA-ES = 2.3 vs DE = 0). Restart triggers: - The whole budget for one inner CmaEs run finishes without improvement - (More sophisticated triggers — eigenvalue collapse, condition-number blow-up, sigma stagnation — are left for future versions; the per-run budget trigger captures the bulk of the practical benefit) Each restart: - Doubles the population_size (Auger & Hansen 2005) - Re-randomizes the initial mean to a fresh point in the bounds box - Resets sigma to the user's initial value Same Vec<f64> + single-objective constraints as CmaEs. The total budget is divided across restarts; restart budget grows with population. Tests verify it beats vanilla CMA-ES on Rastrigin.
This commit is contained in:
@@ -177,15 +177,16 @@ where
|
||||
if idx == best_idx {
|
||||
continue;
|
||||
}
|
||||
#[allow(clippy::needless_range_loop)] // body indexes both vertices and best_pt.
|
||||
for j in 0..n {
|
||||
vertices[idx][j] = best_pt[j]
|
||||
+ self.config.shrinkage
|
||||
* (vertices[idx][j] - best_pt[j]);
|
||||
}
|
||||
// Clamp to bounds.
|
||||
for j in 0..n {
|
||||
for (j, x) in vertices[idx].iter_mut().enumerate() {
|
||||
let (lo, hi) = self.bounds.bounds[j];
|
||||
vertices[idx][j] = vertices[idx][j].clamp(lo, hi);
|
||||
*x = x.clamp(lo, hi);
|
||||
}
|
||||
evals[idx] = problem.evaluate(&vertices[idx]);
|
||||
evaluations += 1;
|
||||
|
||||
Reference in New Issue
Block a user