diff --git a/crates/ml-hyperopt/src/optimizer.rs b/crates/ml-hyperopt/src/optimizer.rs index d2f3c396e..43f3d0d17 100644 --- a/crates/ml-hyperopt/src/optimizer.rs +++ b/crates/ml-hyperopt/src/optimizer.rs @@ -374,8 +374,18 @@ impl ArgminOptimizer { let lower_bounds: Vec = bounds.iter().map(|(min, _)| *min).collect(); let upper_bounds: Vec = bounds.iter().map(|(_, max)| *max).collect(); - // Create Particle Swarm solver - let solver = ParticleSwarm::new((lower_bounds, upper_bounds), self.n_particles); + // Create Particle Swarm solver with tuned parameters. + // Default argmin: inertia=0.72, cognitive=1.19, social=1.19 + // Problem: social >> inertia → premature convergence to global best. + // Fix: higher inertia (0.9) for exploration, lower social (0.8) to + // reduce collapse toward the single LHS best point. + let solver = ParticleSwarm::new((lower_bounds, upper_bounds), self.n_particles) + .with_inertia_factor(0.9) + .map_err(|e| anyhow::anyhow!("PSO inertia: {e}"))? + .with_cognitive_factor(1.5) + .map_err(|e| anyhow::anyhow!("PSO cognitive: {e}"))? + .with_social_factor(0.8) + .map_err(|e| anyhow::anyhow!("PSO social: {e}"))?; // Run optimization (parallel execution enabled via rayon feature) // CRITICAL FIX (2025-11-03): Removed .target_cost(0.0) to prevent early termination @@ -798,7 +808,13 @@ impl ArgminOptimizer { let lower_bounds: Vec = bounds.iter().map(|(min, _)| *min).collect(); let upper_bounds: Vec = bounds.iter().map(|(_, max)| *max).collect(); - let solver = ParticleSwarm::new((lower_bounds, upper_bounds), effective_particles); + let solver = ParticleSwarm::new((lower_bounds, upper_bounds), effective_particles) + .with_inertia_factor(0.9) + .map_err(|e| anyhow::anyhow!("PSO inertia: {e}"))? + .with_cognitive_factor(1.5) + .map_err(|e| anyhow::anyhow!("PSO cognitive: {e}"))? + .with_social_factor(0.8) + .map_err(|e| anyhow::anyhow!("PSO social: {e}"))?; let res = Executor::new(cost_fn, solver) .configure(|state| state.max_iters(max_iters as u64))