Skip to content

Codebase review: refactor, cleanup, dedup, and behavior-risk resolution#9

Merged
blankjul merged 5 commits into
pyclawd-migrationfrom
refactor-cleanup
Jul 16, 2026
Merged

Codebase review: refactor, cleanup, dedup, and behavior-risk resolution#9
blankjul merged 5 commits into
pyclawd-migrationfrom
refactor-cleanup

Conversation

@blankjul

@blankjul blankjul commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Codebase review + refactor/cleanup

A full review of the repo (8 parallel reviewers across core / algorithms / experimental /
sampling / tests / quality / dead-code) turned up ~60 findings. This PR lands all of them
across five waves. Net ~−450 lines.

Every wave was gated by the strongest oracle for what it touched:

  • reproducibility tests — bit-identical same-seed runs for all 11 algorithms,
  • pyclawd golden — the seed-1 performance scores of every algorithm pair,
  • pyclawd check — format / lint / typecheck / descriptions / tests.

Wave 1 — remove dead code, fix latent bugs, mechanical cleanup

  • Delete dead modules: core/archive.py, vendor/ego.py, vendor/smac.py + usage_smac.py.
  • Slim knockout.py to the one live helper; delete the broken GPSAFAnimation (dragged
    matplotlib into every import), the always-False restart machinery, debug prints, dead branches.
  • Remove dead surface across core (Target.model/benchmarks, algorithm.validation,
    tcv.estm_scale, the unread *_estm_error hot path, commented model-zoo blocks).
  • Latent bug fixes: the unseeded acquisition GA (made SAASBO flaky), the niching sampler that
    raised on every call + its samping= typo, dead early-stop in the energy sampler.
  • Drop the undeclared autograd dependency; fix stale setup.py metadata (python_requires ≥3.10).

Wave 2 — docs & naming consistency

model_selectionselection, missing module docstrings, shared mutable default args, shadowed vars.

Wave 3a — build_default_surrogate hook

Split the base _setup so DOE sizing is no longer welded to the default-pool build; 9 duplicated
DOE blocks → 0
. Side benefit: the reproducibility suite is ~4× faster.

Wave 3b — shared EGO machinery (algorithms/_ego.py)

Extract six near-verbatim blocks (default_kriging, fit_per_objective, predict_mu_sigma,
lhs_local_pool, front_and_hv, pareto_optimum/best_optimum). predict_mu_sigma also halves
the Kriging predict cost in 3 algorithms (mean is bit-identical, verified). Exact RNG order preserved.

Wave 4 — resolve the behavior-risk findings (measured, not assumed)

Two "obvious fixes" turned out to be intentional behaviour and were preserved — measuring first
is what caught it:

  • PSAF max(rho_max, r2) is a floor, not a cap, by design: the surrogate is exploited at a
    base rate and only raised when it clearly beats the KNN baseline. The "cap" reinterpretation
    collapsed PSAF(GA) from ~4× better to no better. Kept the operator; renamed rho_maxrho_min.
  • PSAF Kriging pool — the string-regr entries silently never fit, so PSAF has always run
    RBF+KNN; re-enabling Kriging regressed it. Removed the dead entries (honest RBF+KNN pool).
  • Genuine improvements (golden re-blessed; assertions still pass by a wide margin):
    KRVEA now tops up its diversity batch to spend the full budget (paper-faithful; seed-1 IGD
    0.132→0.144); SSANSGA2 derives its KMeans seed from the run RNG like its inner NSGA2
    (0.0079→0.0094). Both remain ~60–90× better than NSGA2.
  • defaults.py applies Plog as norm_y (a constraint-violation target transform) and keeps
    the caller's design-space norm_X.
  • Sampling reproducibilityrandom_state threaded through the rejection/energy samplers.
  • PSAF constructor-seed honoured (mirrors GPSAF); golden made its own tier + CI step.

Notes

  • The CI git-install of the unreleased surrogate stack (from the previous PR) still stands; the
    clean fix remains releasing/pinning pysurrogate/pydacefit/pysampling/ezmodel.
  • Research artifacts (findings.md, runs/, docs/*.png, .claude/skills/) intentionally left
    uncommitted.

🤖 Generated with Claude Code

blankjul added 5 commits July 15, 2026 05:33
Behavior-preserving cleanup from a full codebase review. Gated by the
reproducibility suite (bit-identical same-seed runs) and pyclawd golden
(indicators, tcv, and all seed-1 performance scores unchanged).

Dead-code removal:
- Delete unused core/archive.py (never imported).
- Slim knockout.py to the one live helper (noisy); drop the dead
  tournament machinery (is_better/comp/pcomp/knockout/NoisyReplacement/
  calc_prob_relation).
- Delete vendor/ego.py and vendor/smac.py (unimportable, undeclared deps)
  plus usage_smac.py and its permanently-skipped test scenario.
- gpsaf.py: remove the broken GPSAFAnimation (referenced attributes that
  never exist, dragged matplotlib into every import), the always-False
  restart machinery, stdout debug prints, write-only attributes, dead
  _infill_prob_tourn best/random branches, the no-op _initialize_infill
  override, and all commented-out blocks.
- Remove dead code across core: Target.model / Target.benchmarks,
  algorithm.validation, tcv.estm_scale, surrogate hot-path *_estm_error
  computation (nothing reads it), commented-out model-zoo blocks in
  defaults.py, and a stale line in indicator.kendall_tau.

Latent bug fixes (no committed baseline to preserve):
- optimizer.GeneticAlgorithm.optimize ran the inner pymoo GA unseeded,
  making SAASBO / BayesianOptimization irreproducible under global-RNG
  contamination; thread the run's seed in. Fixes flaky saasbo repro test.
- sampling/niching.py: set n_ieq_constr (n_constr is read-only in pinned
  pymoo, so the fallback raised on every call) and fix the samping= typo
  that discarded the sampling operator.
- sampling/energy.py: drop the provably-dead early-stop branch (loop always
  ran n_max_iter) and unused calc_potential_energy; warn instead of print.
- sampling/rejection.py: drop the dead CustomLHS._calc_score override
  (pymoo LHS has no such hook) and the mutable default arg.

Mechanical cleanup:
- tcv.py: drop the undeclared autograd dependency (numpy alias only), so a
  clean install no longer needs autograd.
- Google-style docstrings for the touched core modules; fix stale base-class
  docstring (wrong DOE formula and parameter name).
- surrogate.py / energy.py: raise precise RuntimeError, not bare Exception.
- setup.py: python_requires >=3.10, prune 3.7-3.9 classifiers, drop the
  __name__ reassignment hack.
- test_performance.py: fix PSAF kwargs (rho_max, not the misspelled max_rho;
  drop GPSAF-only kwargs pymoo silently swallowed) -- effective config
  unchanged.
- selection.py: rename stale model_selection references (docstrings + error
  message) to the actual kwarg name, selection.
- Add missing module docstrings: experimental/__init__.py (was empty) and
  experimental/acquisition.py.
- Update the algorithms package docstring to cover the EGO-style family.
- Remove a leftover commented-out import in ssansga2.py.
- Replace shared mutable default arguments (sampling=LHS(), output=Output())
  with the None-and-construct pattern in the base algorithm and SSANSGA2, and
  rename shadowed loop variables in the PSAF tournament.
The base _setup coupled two unrelated things: sizing the initial DOE and
building the default multi-target model pool. Every EGO-style algorithm
manages its own per-objective models, so each overrode _setup only to skip
the pool build -- and had to re-copy the identical n_initial_doe default line
(8 algorithms + experimental/bo.py).

Split the base _setup: it now always sizes the DOE, and builds the default
surrogate only when the new class attribute build_default_surrogate is True
(extracted into _build_default_surrogate). The EGO algorithms set the flag to
False and drop the copied DOE line -- ehvi/tsemo/csea/saasbo/bo lose their
_setup override entirely; parego/krvea/turbo/moead_ego keep only their real
setup (ref_dirs, trust-region tolerances) behind a super() call.

Behaviour is preserved: the DOE value is identical, surrogate construction
consumes no run RNG, and the EGO algorithms never used the default pool they
now skip. Verified by all 11 reproducibility tests (bit-identical same-seed)
and pyclawd golden (seed-1 performance scores unchanged). Side benefit: the
reproducibility suite is ~4x faster now that those algorithms no longer build
a ~40-model pool they discard.
The eight EGO-style algorithms were written in one session and shared several
near-verbatim blocks. Extract them into a private _ego.py module:

- default_kriging():   the Kriging(Exponential()) prototype (6 copies)
- fit_per_objective(): deepcopy-per-objective fit loop (4 copies)
- predict_mu_sigma():  mean+std prediction -- now ONE predict(var=True) per
                       model instead of two (the mean from var=True is
                       bit-identical to a plain predict, verified), halving the
                       Kriging predict cost in ehvi/moead_ego/tsemo (3 copies)
- lhs_local_pool():    LHS + elite-perturbation candidate pool, drawing the RNG
                       strictly LHS -> integers -> standard_normal (3 copies)
- front_and_hv():      non-dominated front + HV reference point (2 copies)
- pareto_optimum() / best_optimum(): the _set_optimum bodies (7 copies)

Every extraction is a literal move preserving the exact RNG draw order, so
same-seed runs stay bit-identical: verified by all 11 reproducibility tests,
the fidelity suite, and pyclawd golden (seed-1 performance scores unchanged).
Each finding was resolved by measuring the effect, not just applying the
"obvious" fix -- two of them turned out to be intentional and were preserved.

PSAF (kept the effective behavior, fixed the naming/dead code):
- The `bias = max(rho_max, r2)` "cap vs floor" was a floor by design: PSAF
  exploits the surrogate at a base rate and only raises it when the surrogate
  clearly beats the KNN baseline. Reinterpreting it as a cap (min) collapsed
  PSAF(GA) from ~4x better than GA to no better. Kept the operator, renamed the
  parameter rho_max -> rho_min to match the floor semantics, documented why.
- The two Kriging pool members used a string regr that pydacefit silently
  failed to fit, so PSAF has always run an RBF+KNN pool. Re-enabling Kriging
  with proper regression objects *regressed* PSAF on the benchmarks, so the
  dead entries are removed rather than "fixed" -- the pool is honestly RBF+KNN.
- Thread the run seed into the inner algorithm so a constructor-set seed (not
  only minimize(seed=)) is honoured, matching GPSAF. (minimize path unchanged.)

Genuine fixes (golden updated -- intended, assertions still pass by wide margin):
- KRVEA diversity branch topped up from the uncertainty ranking so the batch
  always spends its full budget (paper-faithful): seed-1 IGD 0.132 -> 0.144.
- SSANSGA2 KMeans seed derived from the run RNG instead of a fixed 0, matching
  the file's own inner-NSGA2 seeding philosophy: seed-1 IGD 0.0079 -> 0.0094.

Constraint modelling and sampling reproducibility:
- defaults.py: apply Plog as norm_y (a target transform for constraint
  violations) instead of norm_X, and keep the caller's design-space norm_X.
- rejection/energy sampling: thread random_state through the LHS draw and the
  max-distance first pick, replacing a global np.random.randint.

Tooling:
- Separate golden into its own tier (excluded from fast/default) per AGENTS.md,
  and split CI's test step into a unit run and a dedicated golden run.
@blankjul blankjul changed the title Codebase review: refactor, cleanup, and dedup (behavior-preserving) Codebase review: refactor, cleanup, dedup, and behavior-risk resolution Jul 15, 2026
@blankjul
blankjul merged commit a7f9d1b into pyclawd-migration Jul 16, 2026
2 checks passed
@blankjul
blankjul deleted the refactor-cleanup branch July 16, 2026 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant