GAMS writer: map non-finite float values to GAMS special values (NA / INF) - #4029
Open
cjck944084735-dot wants to merge 1 commit into
Open
GAMS writer: map non-finite float values to GAMS special values (NA / INF)#4029cjck944084735-dot wants to merge 1 commit into
cjck944084735-dot wants to merge 1 commit into
Conversation
Python renders non-finite floats as the strings 'nan'/'inf', which are not valid GAMS numeric literals, so exporting a model whose variables or fixed expressions hold such values produces a .gms file that GAMS rejects with errors like "the symbol nan is undefined". Route all numeric output in the GAMS writer through a gams_ftoa() wrapper that maps them to GAMS's special values NA and INF. Fixes Pyomo#3911
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
The GAMS writer emits Python's string rendering of non-finite floats (
nan,inf,-inf), which are not valid GAMS numeric literals, so the exported.gmsfile fails in GAMS with errors likethe symbol nan is undefined.Fixes #3911.
Root cause
All numeric output in
pyomo/repn/plugins/gams_writer.pygoes throughftoa(), which formats with'%.17g'. Non-finite floats therefore render asnan/inf/-inf, e.g. (currentmain, defaultwarmstart=True):GAMS's special numeric literals are
NA,INF/+INF/-INF(andEPS), so every one of those lines is rejected by GAMS. This hits all value-emitting paths of the writer: constraint bounds, expression constants (fixed Vars/Params), warmstart.lvalues, and fixed-variable.fxvalues.The fix
Route every numeric output site in the writer through a small wrapper that post-processes the
ftoa()result:After the change the same model exports as:
Two notes on float semantics that the new tests document:
-1 * nanisnan(the sign is lost), so- zwithz = nanexports as+ NA.-infvalues in monomials are parenthesized byftoa, hence+ (-INF).Testing
test_nonfinite_var_to_string(expression path: fixednan/inf/-infVars) andtest_nonfinite_var_values_write_gams(full model write:.lwarmstart values and the fixed-expression constant, plus assertions that no barenan/infappears anywhere in the file).pyomo/repn/tests/gams/passes (24 passed, 1 skipped) andblack --checkis clean.Var(initialize=float('nan'))+ GAMS solve script) no longer emits invalid literals.Note:
gams_writer_v2pyomo/repn/plugins/gams_writer_v2.pyhas the same pattern for warmstart values (ostream.write(f"{v}.l = {pyomo_v.value}; "), line ~537). I left it untouched to keep this PR focused on the defaultgamswriter from the issue; happy to apply the equivalent mapping there in this PR or a follow-up, whichever the maintainers prefer.