我负责一系列非线性优化的练习。我认为从一些优化问题的例子开始,用pyomo
+一些黑匣子解决它们是很酷的。
然而,随着学生们对优化算法的了解越来越多,我希望他们也能实现一些简单的方法,并对相同的例子进行测试。我希望有一种“简单”的方式来向pyomo
添加一个自定义的解决程序,但是我找不到有关这方面的任何信息。
基本上,这将允许学生通过更改代码中的一行代码来检查其实现,并将其与经过良好测试的求解器进行比较。
我也会尝试自己实现一个简单的包装器,但是我对pyomo
内部组件一无所知。
pyomo
**?问:我可以把用python编写的自己的求解器添加到中吗?求解器可以有一个类似于** scipy.optimize
**.**的接口
是为了读书,
弗兰兹
相关信息:
发布于 2022-10-24 14:55:26
简短的回答是:“是的: Pyomo被设计成可扩展的,并且用户定义的解决器绝对是支持的。”
细节涉及得更多一些。虽然Pyomo定义了几个“解决器”类层次结构,但它们绝不是必需的。在注册和使用解决程序时,核心Pyomo依赖于鸭子类型,而不是继承。目前,最简单的解决程序接口只需要实现以下方法:
class GenericSolverInterface(object):
def solve(self,
model: _BlockData,
tee: bool = False,
load_solutions: bool = True,
logfile: Optional[str] = None,
solnfile: Optional[str] = None,
timelimit: Optional[float] = None,
report_timing: bool = False,
solver_io: Optional[str] = None,
suffixes: Optional[Sequence] = None,
options: Optional[Dict] = None,
keepfiles: bool = False,
symbolic_solver_labels: bool = False):
pass
def available(self, exception_flag=True) -> bool:
pass
def license_is_valid(self) -> bool:
pass
def version(self) -> Tuple:
pass
@property
def options(self) -> ConfigDict:
pass
@options.setter
def options(self, val):
pass
求解者通过装饰类来在SolverFactory
中“注册”:
from pyomo.opt import SolverFactory
@SolverFactory.register('demo', doc='DEMO Solver interface')
class DemoSolver(GenericSolverInterface):
#...
或者通过显式调用注册函数
SolverFactory.register('demo', doc='DEMO Solver Interface')(DemoSolver)
现在真正的诀窍是如何实现solve()
方法。Pyomo将向solve()
传递用户希望解决的模型(或Block
)。然后,solve()
需要将Pyomo模型/块转换为求解器所需的格式。这一步(显然)非常特定于解决程序,尽管对于一些常见的解决程序接口标准(例如LP文件、MPS文件、NL文件、BAR文件等)有一些标准化的方法。还有其他的“开发中”接口,它们更适合于特定的用例(直接内存中的解决器接口、APPSI、PyNumero)。
最简单(而且性能不太好)的方法可能是定义一个助手类,该类将Pyomo数据结构映射到一组简单的列表:
from pyomo.core.base import Objective, Constraint
from pyomo.core.expr.visitor import identify_variables
class model_interface(object):
def __init__(self, model):
self.model = model
self._obj = list(model.component_data_objects(Objective, active=True))
self._con = list(model.component_data_objects(Constraint, active=True))
self._var = {}
for c in self._con:
self._var.update({id(v): v for v in identify_variables(c.body)})
self._var = list(self._var.values())
@property
def x(self):
"""Return the current list of variable values"""
return [v.value for v in self._var]
@x.setter
def x(self, values):
"""Set the variables to new values"""
for v, val in zip(self._var, values):
v.set_value(val)
@property
def x_lb(self):
"""Return the list of variable lower bounds (may include None)"""
return [v.lb for v in self._var]
@property
def x_ub(self):
"""Return the list of variable upper bounds (may include None)"""
return [v.ub for v in self._var]
@property
def obj(self):
"""Return the list of objective values (computed using the current
variable values)"""
return [value(o) for o in self._obj]
@property
def con(self):
"""Return the list of constraint 'body' values (computed using the
current variable values)
"""
return [value(c) for c in self._con]
@property
def con_lb(self):
"""Return the list of constraint lower bounds (may include None)"""
return [c.lb for c in self._con]
@property
def con_ub(self):
"""Return the list of constraint upper bounds (may include None)"""
return [c.ub for c in self._con]
发布于 2022-10-24 15:00:05
是的,我们在Pyomo中有很多方法可以做到这一点,在pyomo.contrib
中的各个模块中也有很多例子。我认为对学生来说最简单的方法是利用一个叫做PyNumero的Pyomo扩展模块,它是为用Python编写非线性优化算法而设计的,可以在这里找到:https://github.com/Pyomo/pyomo/tree/main/pyomo/contrib/pynumero。
下面是使用PyNumero的几个实现示例:
SQP -> https://github.com/Pyomo/pyomo/blob/main/pyomo/contrib/pynumero/examples/sqp.py
内点-> https://github.com/Pyomo/pyomo/tree/main/pyomo/contrib/interior_point
与枕木方解器的接口--> https://github.com/Pyomo/pyomo/blob/main/pyomo/contrib/pynumero/algorithms/solvers/scipy_solvers.py
https://stackoverflow.com/questions/74179391
复制相似问题