Skip to content

Fix GDPopt LBB solver error handling - #4041

Open
william-xue wants to merge 1 commit into
Pyomo:mainfrom
william-xue:fix/gdpopt-runtimeerror-status
Open

william-xue wants to merge 1 commit into
Pyomo:mainfrom
william-xue:fix/gdpopt-runtimeerror-status

Conversation

@william-xue

Copy link
Copy Markdown

Fixes #4023.

Summary/Motivation:

GDPopt LBB currently catches every RuntimeError raised by a node subproblem solver and converts it into infeasible bounds:

except RuntimeError as e:
    logger.debug("Solver encountered RuntimeError. Treating as infeasible. ...")

A solver infrastructure, licensing, or interface failure is not proof of mathematical infeasibility. Treating it as such can prune a feasible branch of the search tree, and hides a failed local screening solve — the user sees infeasible/a converged bound instead of an infrastructure error. This affects both the evaluated-node path and the local-screening path in pyomo/contrib/gdpopt/branch_and_bound.py.

Changes proposed in this PR:

  • Re-raise RuntimeError from both the evaluated-node solve and the local-screening solve instead of converting it into synthetic infeasible bounds.
  • Add solver-independent regression tests in pyomo/contrib/gdpopt/tests/test_LBB.py covering both paths with a fake subsolver that raises RuntimeError (one-variable bounded model, SubproblemErrors test class).
  • Leave the existing handling of FBBT-proven infeasibility and explicit infeasible termination conditions untouched.

AI-Use Disclosure

  • AI tools were NOT used during the preparation of this PR

or

  • AI tools contributed to the development of this PR

    • AI tools generated documentation (including the PR description/comments, code comments, and/or Sphinx documentation)
    • AI tools generated tests (baselines, examples, and/or code)
    • AI tools generated code (apart from tests)

    Review process (select ONE):

    • Rewritten: All AI-generated content was rewritten by me before being committed.
    • Reviewed/verified: I retained AI-generated content and verified it before committing. Verification included (as applicable):
      • Ran the code and fixed issues
      • Added and ran tests
      • Checked correctness/logic of code and tests
      • Checked for alignment with the contribution guide
      • Considered security implications
    • As-is: AI-generated content was commited directly to the repository

Notes for reviewers (optional):
Least confident point, and the reason for the focused question below: whether re-raising is the preferred contract here, or whether LBB should instead catch a narrower exception and surface a distinct status. I kept the change minimal (re-raise + regressions) so the decision stays with the maintainers. Note also that the local-screening path is behavior-visible: a subsolver RuntimeError there previously produced a bound that could hide the failure, and now propagates out of solve().

Supersedes #4032, which was closed by policy because its description did not use this repository's PR template. Same commit and same diff; the template is now used unmodified, as requested.

Validation (re-run on current main, no upstream changes in pyomo/contrib/gdpopt since the branch point)

  • .venv/bin/python -m pytest -q pyomo/contrib/gdpopt/tests/test_LBB.py -k "SubproblemErrors"2 passed, 13 deselected
  • .venv/bin/python -m pytest -q pyomo/contrib/gdpopt/tests/test_LBB.py2 passed, 11 skipped, 2 deselected
  • .venv/bin/python -m black --check pyomo/contrib/gdpopt/branch_and_bound.py pyomo/contrib/gdpopt/tests/test_LBB.py2 files would be left unchanged
  • git diff --check — clean

Legal Acknowledgement

By contributing to this software project, I have read the contribution guide and agree to the following terms and conditions for my contribution:

  1. I agree my contributions are submitted under the BSD license.
  2. I represent I am authorized to make the contributions and grant the license. If my employer has rights to intellectual property that includes these contributions, I represent that I have received permission to make contributions and grant the required license on behalf of that employer.

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.

GDPopt LBB treats solver RuntimeError as node infeasibility

1 participant