Repository navigation
fix: fetch and store duals only when save_duals is on - #390
SutubraResearch wants to merge 2 commits into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
WalkthroughThe solve path prevents non-appsi_highs solvers from importing duals unless requested. The myopic sequencer requests duals when ChangesDual suffix handling
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix · Severity of issue fixed: Medium Merge Risk: ⚪ Minimal · up to
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Fixes #389.
What happens now
build_instancealways declaresmodel.dualas an import suffix, and Pyomo asks the solver forevery active import suffix on the model, whatever suffix list it is passed, and adds it to that
list. So with
save_duals = false, every solve throughsolve_instancestill asks the solver forall duals and loads them into the model. Then, because
'dual'is now in the list Temoa passed,store_tocopies every variable value and dual into the results object. Nothing uses them.What this changes
solve_instance(temoa/_internal/run_actions.py): when'dual'is not in the requestedsuffixes, the model's
dualsuffix is set toSuffix.LOCALfor the solve and set backafterwards. Pyomo then does not ask for duals, does not load them, and does not add
'dual'tothe list, so
store_tois not called. This is the same thing theappsi_highsbranch justabove already does.
solver_suffixes=['dual'] if self.config.save_duals else Nonetosolve_instance, as the perfect-foresight and single-vector MGA sequencers already do. It usedto get its duals only through the behaviour above. Without this line, a myopic run with
save_duals = truewould write no duals and give no error.Measured saving
A representative-day capacity expansion model (2.4 million variables, 2.8 million constraints),
solver = "gurobi"(LP file),save_duals = false, 32 cores, same node, one run each.PYTHONHASHSEED=0in both, so both runs build the same model:store_toGurobi received the same model in both runs (same fingerprint, same 66 barrier iterations, same
objective). All output tables were identical row for row: every column, exact values, including
2,005,248 rows in each flow table. Writing results took 8 s longer in the second run, in code
this change does not touch. Gurobi itself also varied by 3 s on the same work, so I read that as
run-to-run variation, but with one run each I can't show it.
What doesn't change
save_duals = true: the same suffix list reaches Pyomo, the solver is asked for the sameduals,
store_toruns, and the dual table is identical row for row. Checked on utopia inperfect foresight with
gurobiandgurobi_direct, and in myopic mode.build_instanceis unchanged and still hasmodel.dual.appsi_highsbranch is unchanged.solve_instance, so thischange does not affect them. Method of Morris does call
solve_instance, without asking forduals (it turns
save_dualsoff), so it now skips them too; I haven't run it.Testing
tests/test_save_duals.py. It runs utopia in myopic mode (two steps) withsolver = "gurobi", once withsave_duals = trueand once withfalse.output_dual_variable(931 and 887).
results object, and no duals are written.
unstablewithout this change, thefalsecase fails (931 duals in the first step). Withonly the
run_actions.pychange, thetruecase fails (no duals): that is the myopic line'sjob. With the whole change both pass.
gurobibecauseappsi_highsdoes not return duals. Utopia fits in the size-limitedlicence that comes with gurobipy, which CI installs through the
solverextra; both casespass under that licence. Without
gurobithe test is skipped.Python 3.13.
pyteston v4.1.0 with this change: 291 passed (289 before it, plus the 2 new ones). Onunstablewith this change, in a fresh environment (uv sync --extra solver, Python 3.14.3):291 passed.
ruffandmypypass on the three files.gurobi,gurobi_directandappsi_highs, and myopic withgurobi, each withsave_dualsoff and onwhere supported. All output tables are identical row for row. With
save_dualsoff, no dualsare now requested or stored. With it on, the same 1,499 duals (1,818 in myopic) are written as
before. Done on the test suite's copy of utopia, and again on the database
temoa tutorialmakes (every case except
appsi_highs), with the same result.Summary by CodeRabbit