// Generic loss computation using Metrics (Map[String, Double])
/// Squared relative error
pub fn sq_err(actual : Double, target : Double) -> Double {
if target.abs() < 0.001 {
return actual * actual
}
let err = (actual - target) / target
err * err
}
/// Compute loss from metrics against targets
pub fn compute_loss(metrics : Metrics, targets : Array[BalanceTarget]) -> Double {
let mut loss = 0.0
for t in targets {
let actual = metrics.get(t.metric)
loss = loss + t.weight * sq_err(actual, t.target)
}
loss
}
/// Run multiple seeds, compute averaged loss and metrics
pub fn compute_loss_averaged(
sim : (Array[Double], Int) -> Metrics,
params : Array[Double],
targets : Array[BalanceTarget],
seeds : Array[Int],
) -> (Double, Metrics) {
let all_metrics : Array[Metrics] = []
let mut total_loss = 0.0
for seed in seeds {
let m = sim(params, seed)
total_loss = total_loss + compute_loss(m, targets)
all_metrics.push(m)
}
let avg = average_metrics(all_metrics)
(total_loss / seeds.length().to_double(), avg)
}