Skip to content

GDPopt LBB sends linear MIP relaxed-node subproblem to minlp_solver #3952

@bernalde

Description

@bernalde

Summary

gdpopt.lbb can create a linear MIP relaxed-node subproblem and then dispatch it through minlp_solver instead of mip_solver. When the MINLP role is configured as GAMS/DICOPT and the MIP role is configured as GAMS/Gurobi, this fails before solve because the GAMS writer rejects DICOPT for a MIP model.

This appears specific to the LBB relaxed-node path. In the same environment, the LOA/GLOA/RIC paths route linear discrete or fixed subproblems through the MIP solver role.

Related but distinct: #3941 tracks the LBB time-limit finalization path calling stale _get_final_results_object.

Steps to reproduce the issue

The following small linear GDP reproduces the dispatch problem. It requires GAMS with DICOPT, IPOPTH, and Gurobi solver names available; the important point is that DICOPT is assigned to the MINLP role while Gurobi is assigned to the MIP role.

$ python lbb_mip_dispatch_repro.py
# lbb_mip_dispatch_repro.py
import pyomo.environ as pyo
from pyomo.gdp import Disjunct, Disjunction

m = pyo.ConcreteModel()
m.x = pyo.Var(bounds=(0, 10))
m.y = pyo.Var(bounds=(0, 10))

m.d1 = Disjunct()
m.d2 = Disjunct()
m.d1.c = pyo.Constraint(expr=m.x + m.y <= 2)
m.d2.c = pyo.Constraint(expr=m.x - m.y >= 1)
m.disj = Disjunction(expr=[m.d1, m.d2])
m.obj = pyo.Objective(expr=m.x + 2 * m.y, sense=pyo.maximize)

pyo.SolverFactory("gdpopt.lbb").solve(
    m,
    tee=True,
    time_limit=10,
    mip_solver="gams",
    mip_solver_args={
        "solver": "gurobi",
        "add_options": ["option reslim=10;"],
        "tee": True,
    },
    nlp_solver="gams",
    nlp_solver_args={
        "solver": "ipopth",
        "add_options": ["option reslim=10;"],
        "tee": True,
    },
    minlp_solver="gams",
    minlp_solver_args={
        "solver": "dicopt",
        "add_options": [
            "option reslim=10;",
            "option nlp=ipopth;",
            "option mip=gurobi;",
        ],
        "tee": True,
    },
    local_minlp_solver="gams",
    local_minlp_solver_args={
        "solver": "dicopt",
        "add_options": [
            "option reslim=10;",
            "option nlp=ipopth;",
            "option mip=gurobi;",
        ],
        "tee": True,
    },
)

Error Message

Starting GDPopt version 22.5.13 using LBB algorithm
...
Original model has 2 constraints (0 nonlinear) and 1 disjunctions, with 4 variables, of which 2 are binary, 0 are integer, and 2 are continuous.
Nodes: 0 LB -inf Unbranched 1
Nodes: 1 LB -inf Unbranched 1
Exploring node 0 with LB -inf UB inf and 1 inactive disjunctions.

Solved in 0 iterations and 0.30524 seconds
Optimal objective value -inf
Relative optimality gap nan%
09/06/22: The GDPopt LBB algorithm currently has known issues. Please use the results with caution and report any bugs!
No feasible solutions found.
Traceback (most recent call last):
  File "<stdin>", line 15, in <module>
  File "/home/bernalde/repos/gdplib/.pixi/envs/default/lib/python3.12/site-packages/pyomo/contrib/gdpopt/branch_and_bound.py", line 90, in solve
    return super().solve(model, **kwds)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bernalde/repos/gdplib/.pixi/envs/default/lib/python3.12/site-packages/pyomo/contrib/gdpopt/algorithm_base_class.py", line 128, in solve
    self._solve_gdp(model, config)
  File "/home/bernalde/repos/gdplib/.pixi/envs/default/lib/python3.12/site-packages/pyomo/contrib/gdpopt/branch_and_bound.py", line 255, in _solve_gdp
    new_node_data = self._evaluate_node(node_data, node_model, config)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bernalde/repos/gdplib/.pixi/envs/default/lib/python3.12/site-packages/pyomo/contrib/gdpopt/branch_and_bound.py", line 410, in _evaluate_node
    new_lb, new_ub = self._solve_rnGDP_subproblem(node_model, config)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bernalde/repos/gdplib/.pixi/envs/default/lib/python3.12/site-packages/pyomo/contrib/gdpopt/branch_and_bound.py", line 441, in _solve_rnGDP_subproblem
    result = SolverFactory(config.minlp_solver).solve(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bernalde/repos/gdplib/.pixi/envs/default/lib/python3.12/site-packages/pyomo/solvers/plugins/solvers/GAMS.py", line 882, in solve
    _, smap_id = model.write(
                 ^^^^^^^^^^^^
  File "/home/bernalde/repos/gdplib/.pixi/envs/default/lib/python3.12/site-packages/pyomo/core/base/block.py", line 1995, in write
    filename, smap = problem_writer(self, filename, solver_capability, io_options)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/bernalde/repos/gdplib/.pixi/envs/default/lib/python3.12/site-packages/pyomo/repn/plugins/gams_writer.py", line 542, in __call__
    self._write_model(
  File "/home/bernalde/repos/gdplib/.pixi/envs/default/lib/python3.12/site-packages/pyomo/repn/plugins/gams_writer.py", line 783, in _write_model
    raise ValueError(
ValueError: GAMS writer passed solver (dicopt) unsuitable for model type (mip)

Information on your system

Pyomo version: 6.10.0
Python version: 3.12.13
Operating system: Linux-6.6.114.1-microsoft-standard-WSL2-x86_64-with-glibc2.39
How Pyomo was installed (PyPI, conda, source): Pixi-managed environment
Solver (if applicable): GAMS 51.2.1 with DICOPT, IPOPTH, and Gurobi roles

Additional information

The direct cause appears to be pyomo/contrib/gdpopt/branch_and_bound.py: _solve_rnGDP_subproblem() creates a Big-M transformed subproblem and calls SolverFactory(config.minlp_solver).solve(...) unconditionally. For a linear GDP, that transformed relaxed-node subproblem is a MIP, so the configured MIP solver role is the natural fit.

Expected behavior: LBB should either dispatch a linear relaxed-node subproblem through mip_solver, or fail earlier with a clearer configuration error/documentation that the minlp_solver role may receive MIP models in LBB.

Downstream GDPlib context:

In GDPlib's med_term_purchasing benchmark case, the direct gdp.bigm and gdp.hull reformulations are linear MIPs. A bounded LBB probe with gams_minlp_solver=dicopt reproduced the same GAMS writer passed solver (dicopt) unsuitable for model type (mip) error. Re-running with the MINLP role set to Gurobi got past this solver-type failure, then reached the separate LBB time-limit finalization issue tracked in #3941.

For comparison, short GDPlib probes for gdpopt.loa, gdpopt.gloa, and gdpopt.ric on the same model completed without this routing failure; their logs showed GAMS generating MIP models and executing Gurobi through the MIP role.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions