fix: gate NSGA feasibility at the pool median instead of the 75th percentile - #19
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Settles the doc/code split over the constraint-first score gate. The README claimed the gate treated the top 25% by visual error as feasible;
_percentile_75actually admitted roughly the best 75% — measured, 7 of 10 candidates. Neither number survives.Picking 25% looked like the obvious reading of the intent, and it is wrong. Measured over the real
select_parent, moving the gate from 75% to 25% buys almost nothing, because with a tiny feasible group most binary-tournament comparisons are between two infeasible candidates, where the gate contributes nothing and three-objective dominance is already weak. At the loose end the gate barely filters. Splitting at the median maximises the share of comparisons the gate actually decides, and it measures better than either extreme.Through the real
select_parent, share of parents drawn from the better-scoring half of a 20-node pool:_percentile_75becomes_feasibility_threshold, with the fraction as a namedFEASIBLE_FRACTIONconstant — the old name hardcoded a percentile into the identifier, so it could not survive changing the fraction. Both call sites (select_parent,epoch_seeds) pick the change up, so parent selection and epoch re-seeding stay consistent.Tests now pin the property rather than the arithmetic: that the gate admits exactly
FEASIBLE_FRACTIONof the pool, that the admitted set is the best-scoring prefix rather than an arbitrary subset, and that the gate is scale-free (a quantile of the pool, not a fixed error value — it must behave the same for errors around 0.001 and around 1000).README: the gate's fraction is now named instead of left vague, with the reasoning for the median split recorded since it is not self-evident. Two other corrections in that section. The extensibility claim read "adding a fourth objective is a matter of extending the vector", which overstated things — only the algorithm is arity-agnostic; a new measure still has to be threaded through the worker, node model, and run artifacts, and the text now says so. And it now warns that dominance dilutes as objectives multiply, with the measured first-front growth (8 nodes at three objectives to 11 at five on a 12-node pool) as the reason to be sparing.
Two caveats I could not settle here. The percentages come from uncorrelated synthetic objectives; in a real run score and complexity correlate and the pool is the survivor set of prior selection, so the ranking of options should hold but the magnitudes will not. And sharper selection is not automatically better output — it converges faster and raises premature-convergence risk, which feeds into the
--epoch-diversitytransitions. Confirming the end-to-end effect needs a real search; a local LLM-free sweep is possible and is the obvious follow-up.Not changed here: tournament size is still hardcoded at 2, and it is the larger lever — at the existing gate, raising it to 4 moved score primacy from 76% to 91% in simulation. Left alone deliberately, since it is a behavioural change nobody asked for yet.
402 passed, 13 skipped, ruff clean.