如何在Pyomo中使用Xpress求解非线性模型?
问题描述
我用Pyomo编写了一个简单的非线性模型示例:
import pyomo.environ as pyo model = pyo.ConcreteModel() model.N = pyo.RangeSet(0, 2) model.x = pyo.Var(model.N, within=pyo.NonNegativeReals, bounds=[5, 1000]) model.objective = pyo.Objective(expr=pyo.quicksum(model.x[j] for j in model.N)) def constraint_rule(model): return pyo.sqrt(model.x[0] + model.x[1]) == model.x[2] # return model.x[0] + model.x[1] <= model.x[2] model.constraint = pyo.Constraint(rule=constraint_rule) # solver = pyo.SolverFactory('knitroampl') solver = pyo.SolverFactory('xpress_direct') results = solver.solve(model, tee=True)
我可以用Knitro求解这个模型,也能用Xpress求解线性模型,但不知道如何用Xpress求解该非线性模型,运行时出现以下错误:
Traceback (most recent call last): File "/home/florian/.local/lib/python3.8/site-packages/pyomo/solvers/plugins/solvers/xpress_direct.py", line 258, in _get_expr_from_pyomo_expr xpress_expr, referenced_vars = self._get_expr_from_pyomo_repn(repn, max_degree) File "/home/florian/.local/lib/python3.8/site-packages/pyomo/solvers/plugins/solvers/xpress_direct.py", line 231, in _get_expr_from_pyomo_repn raise DegreeError('XpressDirect does not support expressions of degree {0}.'.format(degree)) pyomo.solvers.plugins.solvers.xpress_direct.DegreeError: XpressDirect does not support expressions of degree None. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "pyomo_xpress.py", line 12, in <module> results = solver.solve(model, tee=True) File "/home/florian/.local/lib/python3.8/site-packages/pyomo/solvers/plugins/solvers/direct_solver.py", line 120, in solve self._presolve(*args, **kwds) File "/home/florian/.local/lib/python3.8/site-packages/pyomo/solvers/plugins/solvers/direct_solver.py", line 63, in _presolve self._set_instance(model, kwds) File "/home/florian/.local/lib/python3.8/site-packages/pyomo/solvers/plugins/solvers/xpress_direct.py", line 319, in _set_instance self._add_block(model) File "/home/florian/.local/lib/python3.8/site-packages/pyomo/solvers/plugins/solvers/xpress_direct.py", line 322, in _add_block DirectOrPersistentSolver._add_block(self, block) File "/home/florian/.local/lib/python3.8/site-packages/pyomo/solvers/plugins/solvers/direct_or_persistent_solver.py", line 218, in _add_block self._add_constraint(con) File "/home/florian/.local/lib/python3.8/site-packages/pyomo/solvers/plugins/solvers/xpress_direct.py", line 339, in _add_constraint xpress_expr, referenced_vars = self._get_expr_from_pyomo_expr( File "/home/florian/.local/lib/python3.8/site-packages/pyomo/solvers/plugins/solvers/xpress_direct.py", line 262, in _get_expr_from_pyomo_expr raise DegreeError(msg) pyomo.solvers.plugins.solvers.xpress_direct.DegreeError: XpressDirect does not support expressions of degree None. expr: sqrt(x[0] + x[1]) - x[2]
解决方法
问题根源
xpress_direct是Pyomo与Xpress的直接绑定接口,它仅支持多项式形式的非线性表达式,像sqrt这类超越函数无法被识别为固定次数的多项式,因此触发DegreeError。
方案1:改用Xpress的AMPL接口
替换求解器初始化代码,使用Xpress的AMPL格式接口,该接口对非线性表达式的兼容性更好:
# 替换xpress_direct为xpress solver = pyo.SolverFactory('xpress') results = solver.solve(model, tee=True)
需要确保你的Xpress安装包含AMPL接口支持,Pyomo能正确找到Xpress的可执行文件。
方案2:等价转化非线性约束
将sqrt(x[0]+x[1]) = x[2]等价转化为二次约束,避免使用超越函数,这样xpress_direct可直接处理:
def constraint_rule(model): # 等价转化为平方形式,利用变量已设置NonNegativeReals的特性 return model.x[0] + model.x[1] == model.x[2] ** 2 model.constraint = pyo.Constraint(rule=constraint_rule)
转化后的问题属于二次规划,求解效率通常比原始超越函数问题更高。
内容的提问来源于stack exchange,提问作者fontanf
相关产品推荐
相关产品推荐

