Pyomo / pyomo

An object-oriented algebraic modeling language in Python for structured optimization problems.
https://www.pyomo.org
Other
1.91k stars 490 forks source link

`SolverFactory('gams', **kwds)` ignores keyword arguments #2757

Open shermanjasonaf opened 1 year ago

shermanjasonaf commented 1 year ago

Summary

When attempting to construct an instance of an interface to a GAMS solver with optional keyword arguments (such as 'executable' and 'options') passed, the keyword arguments appear to be ignored. This behavior differs from that of other solver types, such as SolverFactory("baron").

Steps to reproduce the issue

For a solver type which inherits from opt.base.solvers.OptSolver, such as the BARON shell interface, we can construct an instance and initialize options in one line like this:

>>> from pyomo.environ import SolverFactory
>>> baron = SolverFactory("baron", options={"MaxTime":  100})
>>> baron.options
Bunch(MaxTime = 100)

However, attempting to initialize GAMS with a custom subsolver setting through the 'options' keyword argument to GAMSSolver does not yield a similar outcome:

>>> gams = SolverFactory("gams", options={"solver": "ipopt"})
>>> gams.options
Bunch()

Note that this doesn't affect updating options later:

>>> gams.options["solver"] = "ipopt"
>>> gams.options
Bunch(solver = 'ipopt')

Also, no problem attempting to initialize with a custom subsolver like this:

>>> gams2 = SolverFactory("gams:ipopt")
>>> gams2.options
Bunch(solver = 'ipopt')

Information on your system

Pyomo version: 6.5.1dev0 Python version: 3.9.13 Operating system: Ubuntu 20.04 How Pyomo was installed (PyPI, conda, source): source Solver (if applicable): GAMS

Additional information

alexchandel commented 10 months ago

I did not know SolverFactory takes subsolvers like "gams:ipopt". The Pyomo documentation makes no mention of it.

Could you please fix the documentation as well?

alexchandel commented 10 months ago

The problem is that:

  1. GAMS does not inherit from OptSolver (Pyomo needs to define a base protocol that all solvers inherit from, including GAMS)
  2. GAMS initializes its options with self.options = Bunch() instead of checking kwds. This is probably a bug. It could also be cured by inheriting from a common base class that initialized options.
alexchandel commented 10 months ago

Note that AsynchronousActionManager has the same problem, except that it doesn't have an options either.

This behavior of default options for solve() should be standardized across all solvers.

blnicho commented 10 months ago

@alexchandel we have been working to redesign/refactor our core solver API for some time (see https://github.com/Pyomo/pyomo/issues/1030) and we have had design discussions internally that noted many of the same issues with the current interfaces that you have (especially around standardization). Our development efforts are constrained and prioritized based on our currently funded projects and unfortunately this solver refactor hasn't been a top priority for any of them. We appreciate your feedback and suggestions and if you have additional comments or thoughts about what you would like to see in a standardized solver API please add them to the issue I linked above.