Skip to content

Add LBB relaxed NLP node solver - #4012

Open
bernalde wants to merge 1 commit into
Pyomo:mainfrom
SECQUOIA:fix/issue-3945-lbb-relaxed-nlp-solver
Open

Add LBB relaxed NLP node solver#4012
bernalde wants to merge 1 commit into
Pyomo:mainfrom
SECQUOIA:fix/issue-3945-lbb-relaxed-nlp-solver

Conversation

@bernalde

Copy link
Copy Markdown
Contributor

Fixes #3945.

Summary/Motivation:

GDPopt LBB routes every transformed node subproblem through minlp_solver (or local_minlp_solver for optional local screening), even at nodes where every discrete variable has already been fixed by branching. Those nodes are continuous NLPs, so sending them to a MINLP solver is unnecessary and forces users to have a MINLP solver configured for work a continuous NLP solver could do.

This adds an explicit, opt-in solver role for that case rather than changing the default dispatch, so existing LBB configurations keep their current global-bounding behavior.

This is a replacement for #3946, which GitHub would not allow me to reopen after it was closed. The prior discussion and history remain available there.

Changes proposed in this PR:

  • Declare relaxed_nlp_solver and relaxed_nlp_solver_args on GDP_LBB_Solver.CONFIG in pyomo/contrib/gdpopt/branch_and_bound.py, for transformed node subproblems with no unfixed discrete variables.
  • Add _get_rnGDP_subproblem_solver(), which reuses GDPopt's existing detect_unfixed_discrete_vars() helper to choose between the relaxed NLP solver and the mixed-integer node solver, and logs which one it picked.
  • Preserve current behavior when relaxed_nlp_solver is unset: such nodes continue to go to minlp_solver / local_minlp_solver.
  • Apply the same dispatch to the optional local node screening path.
  • Factor the existing GAMS reslim time-limit handling into _apply_rnGDP_subproblem_time_limit() so it applies to whichever subsolver is dispatched.
  • Tighten MindtPy's continuous short-circuit in pyomo/contrib/mindtpy/algorithm_base_class.py to test for no unfixed discrete variables rather than an empty discrete variable list, and update the surrounding docstring.
  • Add TestGDPoptLBBNodeSolverDispatch in pyomo/contrib/gdpopt/tests/test_LBB.py and a MindtPy GOA fixed-discrete routing regression in pyomo/contrib/mindtpy/tests/test_mindtpy_no_discrete.py.
  • Validation performed locally on this branch, rebased onto current main:
    • python -m pytest -q pyomo/contrib/gdpopt/tests/ pyomo/contrib/mindtpy/tests/test_mindtpy_no_discrete.py
      • Result: 108 passed, 35 skipped, 5 deselected in 196.51s
    • python -m black --check pyomo/contrib/gdpopt/branch_and_bound.py pyomo/contrib/gdpopt/tests/test_LBB.py pyomo/contrib/mindtpy/algorithm_base_class.py pyomo/contrib/mindtpy/tests/test_mindtpy_no_discrete.py
      • Result: passed, 4 files would be left unchanged
    • typos --config ./.github/workflows/typos.toml on the four changed files
      • Result: passed, no findings

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): This replacement PR carries over the implementation and tests from #3946 unchanged, then refreshes the branch against current main. The replacement PR description and branch-refresh workflow were prepared with AI assistance and reviewed before posting.

Three things I would like focused feedback on, since this PR is larger than the other GDPopt fixes I have open:

  1. relaxed_nlp_solver defaults to None specifically so that nonconvex nodes keep their current global-bounding behavior. Please confirm that opt-in default is the semantics you want, rather than defaulting to the existing nlp_solver.
  2. Extracting the GAMS reslim logic into _apply_rnGDP_subproblem_time_limit() means the local node screening path now also gets a GAMS time limit applied; previously that path passed local_minlp_solver_args through untouched. I believe that is the correct behavior, but it is a behavior change beyond the strict dispatch fix and should be a deliberate decision.
  3. The MindtPy short-circuit change (len(discrete_variable_list) == 0 becoming "no unfixed discrete variables") alters when MindtPy short-circuits to a direct solve. It is needed for consistency with the LBB dispatch rule, but it touches MindtPy rather than GDPopt, so it may warrant a separate reviewer.

Related: this PR touches pyomo/contrib/gdpopt/tests/test_LBB.py near the same imports as #4010 (replacement for #3942, already approved by @emma58). The runtime changes are independent and do not overlap. I recommend merging #4010 first; I will then rebase this branch and resolve the small test-file conflict.

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 routes continuous node subproblems through minlp_solver

1 participant