feat(algorithms): add RandomSearch baseline optimizer

The reference baseline and the spec's recommended starting example. Per
iteration it asks the initializer for `batch_size` decisions, evaluates
each, and accumulates them. At the end it returns the full population
plus the Pareto front and (if single-objective) the best feasible
candidate. `generations` equals `iterations`; `evaluations` equals
`iterations * batch_size` (spec §12.1).

Includes a tiny single-objective sphere test problem under
`tests_support` that later algorithm tests will reuse.
This commit is contained in:
2026-05-04 19:23:20 -06:00
parent 4882e1865d
commit f17c960ec7
5 changed files with 173 additions and 0 deletions
+40
View File
@@ -0,0 +1,40 @@
//! Shared, deliberately tiny test problems used by algorithm unit tests.
//!
//! Not part of the public API.
use crate::core::evaluation::Evaluation;
use crate::core::objective::{Objective, ObjectiveSpace};
use crate::core::problem::Problem;
/// 1-D minimization sphere `f(x) = x^2`. Single objective, always feasible.
pub struct Sphere1D;
impl Problem for Sphere1D {
type Decision = Vec<f64>;
fn objectives(&self) -> ObjectiveSpace {
ObjectiveSpace::new(vec![Objective::minimize("f")])
}
fn evaluate(&self, decision: &Vec<f64>) -> Evaluation {
Evaluation::new(vec![decision[0] * decision[0]])
}
}
/// Schaffer N.1 — the textbook two-objective minimization warm-up:
///
/// `f1(x) = x^2`, `f2(x) = (x - 2)^2`. Always feasible.
pub struct SchafferN1;
impl Problem for SchafferN1 {
type Decision = Vec<f64>;
fn objectives(&self) -> ObjectiveSpace {
ObjectiveSpace::new(vec![Objective::minimize("f1"), Objective::minimize("f2")])
}
fn evaluate(&self, x: &Vec<f64>) -> Evaluation {
let v = x[0];
Evaluation::new(vec![v * v, (v - 2.0).powi(2)])
}
}