perf: scale solver objective 1e4; hard SOC bounds for in-range starts#90
Open
andig wants to merge 1 commit into
Open
perf: scale solver objective 1e4; hard SOC bounds for in-range starts#90andig wants to merge 1 commit into
andig wants to merge 1 commit into
Conversation
Two changes that compound with the tightened big-Ms underneath: Objective scaling: the optimum sits at ~0.5-18 currency units with tie-break coefficients down at 1e-8, so CBC's absolute tolerances (integrality 1e-6, cutoff increment 1e-5) cannot separate near-tie nodes and the search wanders the alternate-optima plateau. Scaling the solver-facing objective by 1e4 lets those tolerances bite; reported values are recomputed from variable values and stay unscaled. Hard SOC bounds: when s_initial lies within [s_min, s_max], the soft penalty construction (2 penalty columns + 2 rows per battery per step) is dead weight — the penalty (0.27/Wh) exceeds any achievable gain (<3e-4/Wh) by three orders of magnitude, so the penalties are zero at every optimum and [s_min, s_max] can be variable bounds instead. The soft path remains for out-of-range starts (cases 015/018). Full suite (bundled CBC, single-thread, median of 3): total 1.70s -> 1.36s vs the big-M base, 1.93s -> 1.36s vs main; every case equal or better than main (021 root-solves again: 0 nodes/0.09s, healing the base branch's 10-node drift; 017 root-solves; 016 1256 -> 189 iterations). Full objectives match the base to <= 3e-6. Golden objective_value for 013/019 re-lands on other plateau points (019 back to main's original value) — optimum unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Member
Author
|
@ekkea found this during model optimization when porting CBC to Go. |
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.
Stacked on #88 (base
model/tight-big-m; merge that first). Independent of #89.Two changes, validated together against the full golden suite:
1. Solver-facing objective ×1e4 (one line). The optimum sits at ~0.5–18 currency units with tie-break coefficients down at 1e-8; CBC's absolute tolerances (integrality 1e-6, cutoff increment 1e-5) can't separate near-tie nodes, so the search wanders the alternate-optima plateau. Scaling lets the tolerances bite.
get_clean_objective_valuerecomputes from variable values, so reported numbers stay unscaled.2. Hard SOC bounds when
s_min ≤ s_initial ≤ s_max. The soft-penalty construction (2 penalty columns + 2 rows per battery per time step) is provably dead weight for in-range starts: the penalty (0.27/Wh) exceeds any achievable gain (<3e-4/Wh) by three orders of magnitude, so penalties are zero at every optimum and[s_min, s_max]can live on the variable bounds. The soft path stays for out-of-range starts (015/018 exercise it).Full-suite benchmark (bundled CBC, single-thread, app-faithful build, median of 3)
Every case is equal-or-better than main — notably this heals the base branch's 021 drift (10 nodes → root-solved, faster than main ever was), and side effects each change shows alone (SOC bounds alone push 009 to 770 iterations) cancel under scaling. Stable across reruns.
Equivalence: full pulp objectives (÷1e4) match the base branch to ≤3e-6 absolute, 016/017/020/021 exact. The 013/019 golden
objective_values land on different points of the same optimal plateau (019 returns to main's original value); optimum unchanged.🤖 Generated with Claude Code