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.
Summary
gdpopt.lbbcan create a linear MIP relaxed-node subproblem and then dispatch it throughminlp_solverinstead ofmip_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.pyError Message
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 callsSolverFactory(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 theminlp_solverrole may receive MIP models in LBB.Downstream GDPlib context:
med_term_purchasingto fix benchmark issues SECQUOIA/gdplib#69In GDPlib's
med_term_purchasingbenchmark case, the directgdp.bigmandgdp.hullreformulations are linear MIPs. A bounded LBB probe withgams_minlp_solver=dicoptreproduced the sameGAMS 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, andgdpopt.ricon the same model completed without this routing failure; their logs showed GAMS generating MIP models and executing Gurobi through the MIP role.