Function worst_constraints
pub fn worst_constraints<S: AsRef<[f64]>>(replicates: &[S]) -> Vec<f64>Expand description
The conservative aggregate of several evaluations’ constraint vectors: the componentwise worst (maximum) value.
This is how a multi-seed fan’s k replicate vectors become the one vector the trial carries. Maximum, and not the mean or the last one, because the sign convention makes the largest value the worst one, and because “this configuration is feasible” must mean feasible under every seed: a configuration that satisfies a constraint on two replicates and violates it on the third has not satisfied it. Averaging would let two comfortable replicates pay for one violation, and keeping the last would make feasibility a function of replicate order.
If every replicate recorded nothing (including when there are no
replicates), the result is empty: the fan is unconstrained. Once one
replicate declares a width N, every replicate must declare exactly N
values, including the replicates that recorded nothing. A missing or ragged
row therefore returns an all-NaN marker with the maximum declared width.
That marker is deliberately unmistakably invalid: it is not feasible and
has infinite total violation, so it cannot rank as feasible. Its shape is
stable under replicate permutation. For equal-width rows, a NaN wins over
any finite value in its component, so an unevaluated constraint cannot be
averaged away either — though
TrialCtx::record_constraints
refuses a non-finite value at the source, so it should never get this far.
use atune_core::pareto::worst_constraints;
// Satisfied on two seeds, violated on the third: the trial is infeasible.
let fan = [vec![-1.0, -2.0], vec![-3.0, 0.5], vec![2.0, -1.0]];
assert_eq!(worst_constraints(&fan), vec![2.0, 0.5]);
// Feasible on every replicate stays feasible.
let clean = [vec![-1.0], vec![-0.5]];
assert_eq!(worst_constraints(&clean), vec![-0.5]);
// Nothing recorded is not a declaration.
let silent: [Vec<f64>; 2] = [Vec::new(), Vec::new()];
assert!(worst_constraints(&silent).is_empty());