use std::fs::File;
use std::io::Write;
use forge_core::testfn::{Dtlz2, Zdt1};
use forge_core::{NsgaII, NsgaIII, ParetoFront, Termination};
const SEEDS: std::ops::RangeInclusive<u64> = 1..=15;
fn write_csv(path: &str, front: &ParetoFront) {
let mut f = File::create(path).expect("create csv");
let m = front.solutions[0].objectives.len();
let header: Vec<String> = (0..m).map(|j| format!("f{}", j + 1)).collect();
writeln!(f, "{}", header.join(",")).unwrap();
for o in front.objective_vectors() {
let row: Vec<String> = o.iter().map(|v| format!("{v:.10}")).collect();
writeln!(f, "{}", row.join(",")).unwrap();
}
}
fn main() {
let args: Vec<String> = std::env::args().collect();
let out_dir = args
.get(1)
.cloned()
.unwrap_or_else(|| std::env::temp_dir().to_string_lossy().into_owned());
for seed in SEEDS {
let zdt1 = Zdt1::new(30);
let nsga2 = NsgaII {
pop_size: 100,
seed,
..NsgaII::default()
};
let f1 = nsga2.optimize(&zdt1, &Termination::budget(20_000));
let p1 = format!("{out_dir}/forge_zdt1_s{seed}.csv");
write_csv(&p1, &f1);
eprintln!(
"NSGA-II/ZDT1 seed {seed:2}: {} solutions, {} evals -> {p1}",
f1.len(),
f1.evaluations
);
let dtlz2 = Dtlz2::new(3, 12);
let nsga3 = NsgaIII {
pop_size: 92,
divisions: 12,
seed,
..NsgaIII::default()
};
let f2 = nsga3.optimize(&dtlz2, &Termination::budget(40_000));
let p2 = format!("{out_dir}/forge_dtlz2_s{seed}.csv");
write_csv(&p2, &f2);
eprintln!(
"NSGA-III/DTLZ2 seed {seed:2}: {} solutions, {} evals -> {p2}",
f2.len(),
f2.evaluations
);
}
}