Experiments: what breaks a PH W-oscillation cycle (sizes)#787
Open
DLWoodruff wants to merge 4 commits into
Open
Experiments: what breaks a PH W-oscillation cycle (sizes)#787DLWoodruff wants to merge 4 commits into
DLWoodruff wants to merge 4 commits into
Conversation
A self-contained research harness (not a product feature, not CI-wired) that establishes which PH interruption actually breaks a W-vector oscillation on the sizes model. This is the empirical evidence behind shipping slamming as the only interruption remedy (see PR Pyomo#780 and doc/designs/w_oscillation_design.md §9). Reuses the merged PR1 detection primitives (zero_crossings_detect, etc.) and scores every arm by two metrics: the detector's scale-free zc count and the PH primal gap sum_s p_s |x_s - xbar| (the ground truth). Findings (results/summary.md): only fixing a variable (the slam analogue) and using a larger rho converge the primal gap. W-damping, W-reset, rho reduction, and rho jitter all leave the cycle intact, decouple the scenarios (gap explodes while W freezes -- a detector false positive), or worsen it. Root cause: the cycle is a small-rho artifact; sizes' _rho_setter uses cost x 0.001, and rho >= 0.1 converges with no interruption at all. - w_osc_experiment_ext.py: PH extension (detect / intervene / record) - _run_one_arm.py: worker (PH-only hub on sizes, one arm) - run_experiments.py: orchestrator (all arms -> summary + per-iter CSV) - README.md: writeup; results/: captured summary + per-iteration CSV Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #787 +/- ##
==========================================
+ Coverage 76.00% 76.16% +0.16%
==========================================
Files 169 169
Lines 22096 22224 +128
==========================================
+ Hits 16794 16928 +134
+ Misses 5302 5296 -6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Extend the sizes cycle-breaking harness with a prox-only lever and a
solution-quality axis, answering not just "does it stop the cycle" but
"is the answer any good, in x and in W".
New intervention `prox_boost` scales only the quadratic penalty (the
`prox_on` coefficient on ProxExpr), leaving rho -- and hence the dual
update W += rho*(x-xbar) -- untouched. Four schedules:
- one-shot / re-firing: a temporary window (revert after N iters, or
re-open on each re-detected cycle). Transient only: the small-rho
cycle snaps back the moment the penalty relaxes.
- held: near-permanent boost; damps the cycle to a residual but plateaus.
- escalating: hold and ramp the multiplier (x10 -> x160) while the gap
persists. The only prox-only schedule that converges outright
(primal gap -> 0, PH self-terminates ~iter 32).
New section 4 measures quality vs the monolithic EF optimum z*: the inner
bound (expected cost of committing to the consensus xbar; x-quality) via
fix-to-xbar + solve + Eobjective, and the outer/Lagrangian bound from the
final W (W-quality) via post_solve_bound. Per-iteration CSV also logs the
live prox multiplier.
Finding: convergence and solution quality are different axes. A larger
uniform rho converges fastest but lands the worst decision (x-gap ~3%) and
an overshot bound; the native small-rho cycle never "converges" yet orbits
the optimum (near-optimal x, tightest W). Escalating prox is the sweet
spot for the decision (x-gap ~0.3%, keeps the small dual step) but freezes
W off-optimum -> loose dual certificate. So: for a good decision,
escalating prox beats raising rho; for a tight bound, nothing beats
letting the cycle run.
Default budget bumped to 80 iters so `python run_experiments.py`
reproduces the committed summary. README and summary rewritten to match.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…break it) Test mpi-sppy's built-in smoothing (cfg.smoothing: smoothed PH, penalty p = smoothing_rho_ratio * rho anchoring each scenario's x to its own EMA trajectory z, memory beta) as a cycle-breaker on sizes. Wired through the worker (set on cfg before ph_hub) and added as a group-1 arm. Finding: smoothing does NOT break the cycle -- it AMPLIFIES it. At native (small) rho the primal gap grows to ~968 at ratio 0.1 (vs plain PH ~34), worse as the ratio rises, and numerically catastrophic by ratio 100. It anchors each scenario to its own lagged EMA, a per-scenario momentum that fights consensus, so zc stays high AND the gap explodes -- distinct from the "decoupled" mode (rho reduction: zc low, gap high). The center still orbits the optimum (rounded average is a fine decision, x-gap ~0.65%), so it is strictly worse than plain PH: bigger swings, no convergence. Refine the >500-gap reading to split "decoupled (gap exploded)" (zc low) from "cycle amplified" (zc high) so both failure modes read correctly. README/summary updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a `w_average` intervention: on a detected cycle, replace each cycling nonant's W, in every scenario, with that scenario's mean W over the captured cycle (a warm restart to the cycle's centre rather than to zero, the counterpart to w_reset). Averaging is a per-scenario linear combination of past iterates, so it trivially preserves PH's dual invariant sum_s p_s W_s = 0: every buffered W already has expectation zero and expectation is linear. Empirically it does not break the sizes cycle: restarting W at the centre kicks the primal gap ~3 -> ~5200, then slowly re-damps but re-enters the same oscillation (last-10 gap ~113) -- another fixed-magnitude perturbation that keeps the cycle's near-optimal profile (x-gap +0.27%, W-gap +0.7%). README §1/§4 tables, a "why it is a legal PH move" section, and conclusion #1 updated; results/summary.md and interventions_by_iteration.csv regenerated. Co-Authored-By: Claude Opus 4.8 <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.
Self-contained research experiments (not a product feature, not wired into
CI) establishing which PH interruption actually breaks a W-vector oscillation on
the
sizesmodel. This is the empirical evidence behind scaling #780 back toslamming as the only interruption remedy.
What
examples/sizes/w_oscillation_experiments/— a harness that reuses the mergeddetection primitives (PR1, #778) and scores each would-be remedy by two metrics:
zc— how many nonants the zero-crossings detector still flags. Scale-free(counts sign changes), so it can be fooled by anything that freezes W.
sum_s p_s |x_s - xbar|— the ground truth: low only when thescenarios actually agree.
Run (needs a MIP solver; gurobi_persistent by default):
Findings (sizes-3, 60 iters; see
results/summary.md)fix(slam analogue)fix(changing the problem structure) and a larger rho converge theprimal gap. Every state-perturbing move leaves the cycle intact, decouples the
scenarios, or worsens it.
zcdrops while the gapexplodes — a detector false positive (driving rho → 0 freezes W).
sizes's_rho_setteruses
rho = cost × 0.001, and rho ≥ 0.1 converges with no interruption at all.freezes W; confirming an interruption converged (vs decoupled) needs a
primal-side check like the gap used here.
Relationship to #780
#780 ships the W-oscillation interruption with slamming as the only remedy —
these experiments are why (they showed the dual-side remedies do not break the
cycle). The extension's design doc (§9) points here for the evidence. Kept out
of CI because it needs a MIP solver.
🤖 Generated with Claude Code