feat: wire #120's aspect-ratio buckets into recommend_config() - #121
Merged
Conversation
Extends _bucket() to take both n and p, routing extreme p/n or n/p regimes to one of four new buckets (wide_moderate/wide_extreme for p>>n genomics-scale data, tall_moderate/tall_extreme for n>>p ecological/survey-scale data) derived by #120's NSGA-II search, instead of falling back to smallp/trans/large (validated only up to p=200, p/n=2.0) or silently extrapolating past it. recommend_config() still warns when it returns one of the four -- each is validated at only one example regime, not a dense grid -- but now returns a real, empirically better recommendation rather than just a warning. Also fixes two real bugs found while wiring this in (neither was exercised by #120's own validation script, which called VBPCASimulator.generate() directly rather than round-tripping through recommend_config()): - criterion_order/active_criteria were stored as trade-study preset *names* ("cost_angle", "all"), not the list/dict VBPCA's constructor actually accepts -- `VBPCA(**recommend_config(n=30, p=2000))` raised TypeError immediately. Resolved to real values at module load, and active_criteria renamed to convergence_criteria (VBPCA's actual kwarg name) to match. - rmsstop_window/rmsstop_atol/rmsstop_rtol were three separate keys; VBPCA takes one compound `rmsstop=[window, atol, rtol]` kwarg. - (found alongside, same root cause -- untested round-trip): the shallow `dict(_BUCKET_CONFIGS[bucket])` copy left the new buckets' nested list/dict values (criterion_order, convergence_criteria, rmsstop) as shared references -- mutating a returned config would have corrupted the module-level bucket for every future call. Now a deep copy. Also closes the tall-direction gap in #117's extrapolation warning: it only checked p/n (wide direction), never n/p, despite the original Option A grid's own tested n/p ceiling (15.0) being much tighter than naive intuition suggests. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
Summary
Closes the last piece of #116:
recommend_config()now actually returns an aspect-ratio-aware recommendation for genomics/ecological-scale data, instead of just warning that the standard buckets don't cover it.Change
_bucket()now takesn(not justp), routing extreme-aspect-ratio regimes to one of #120's four new buckets:wide_extremep/n > 10wide_moderatep > 200orp/n > 2.0tall_extremen/p > 50tall_moderaten/p > 15Falls back to
smallp/trans/largeotherwise, unchanged.recommend_config()still warns when it returns one of the four new buckets (each validated at a single example regime, not a dense grid like the original three) -- but now it's a real, empirically better recommendation rather than a warning with nothing behind it.Also closes a gap in #117's warning: it only checked
p/n(the wide direction), nevern/p-- the original Option A grid's own testedn/pceiling (15.0) is much tighter than thep/none (2.0), son >> pdata was silently extrapolating too.Two real bugs found while wiring this in
Neither was exercised by #120's own validation script, which called
VBPCASimulator.generate()directly rather than round-tripping throughrecommend_config():criterion_order/active_criteriawere stored as trade-study preset names ("cost_angle","all"), not the list/dict VBPCA's constructor actually accepts --VBPCA(**recommend_config(n=30, p=2000))raisedTypeErrorimmediately. Resolved to real values;active_criteriarenamed toconvergence_criteria(VBPCA's actual kwarg).rmsstop_window/rmsstop_atol/rmsstop_rtolwere three separate keys; VBPCA takes one compoundrmsstop=[window, atol, rtol]kwarg.Found a third issue alongside (same root cause): the shallow
dict(_BUCKET_CONFIGS[bucket])copy left the new buckets' nested list/dict values as shared references across calls -- mutating a returned config would corrupt the module-level bucket for every future caller. Now a deep copy.Test plan
just cipasses,defaults.pyat 100% coverageVBPCA(**cfg).fit()without error (regression test for both bugs above), mutation-safety (regression test for the third), bucket routing at each threshold (wide_extreme/wide_moderate/tall_extreme/tall_moderate), boundary values stay in the non-extreme bucket, extreme configs differ from their moderate siblings🤖 Generated with Claude Code