use crate::grid::Grid;
pub fn fitness_heatmap(grid: &Grid) -> Vec<Vec<f64>> {
let (rows, cols) = grid.dimensions();
let mut min_fit = f64::INFINITY;
let mut max_fit = f64::NEG_INFINITY;
for r in 0..rows {
for c in 0..cols {
if let Some(cell) = grid.get(r, c) {
min_fit = min_fit.min(cell.fitness);
max_fit = max_fit.max(cell.fitness);
}
}
}
let range = max_fit - min_fit;
let mut heatmap = Vec::with_capacity(rows);
for r in 0..rows {
let mut row = Vec::with_capacity(cols);
for c in 0..cols {
let normalized = if let Some(cell) = grid.get(r, c) {
if range.abs() < f64::EPSILON {
0.5 } else {
(cell.fitness - min_fit) / range
}
} else {
0.0
};
row.push(normalized);
}
heatmap.push(row);
}
heatmap
}
pub fn fitness_heatmap_range(grid: &Grid, r1: usize, c1: usize, r2: usize, c2: usize) -> Vec<Vec<f64>> {
let (r_min, r_max) = (r1.min(r2), r1.max(r2));
let (c_min, c_max) = (c1.min(c2), c1.max(c2));
let mut min_fit = f64::INFINITY;
let mut max_fit = f64::NEG_INFINITY;
for r in r_min..=r_max {
for c in c_min..=c_max {
if let Some(cell) = grid.get(r, c) {
min_fit = min_fit.min(cell.fitness);
max_fit = max_fit.max(cell.fitness);
}
}
}
let range = max_fit - min_fit;
let mut heatmap = Vec::new();
for r in r_min..=r_max {
let mut row = Vec::new();
for c in c_min..=c_max {
let normalized = if let Some(cell) = grid.get(r, c) {
if range.abs() < f64::EPSILON {
0.5
} else {
(cell.fitness - min_fit) / range
}
} else {
0.0
};
row.push(normalized);
}
heatmap.push(row);
}
heatmap
}