问题描述
当利用pyomo与ipopt求解的非线性凸优化问题形式类似以下形式时:
min
∑
i
=
0
N
−
1
x
i
s
.
t
.
x
≥
1.0
\min \sum_{i=0}^{N-1} x_i \\ s.t. \text{ } \sqrt{x}\geq 1.0
mini=0∑N−1xis.t. x≥1.0
from pyomo.environ import *
from pyomo.dae import *
N = 5
m = ConcreteModel()
m.s = Var(RangeSet(0, N-1))
m.s_cons = Constraint(RangeSet(0, N-1), rule=lambda m, i: m.s[i]**(0.5) >= 1.0)
m.obj = Objective(expr=sum(m.s[i] for i in RangeSet(0, N-1)), sense=minimize)
%time SolverFactory('ipopt').solve(m)
会报错Error evaluating constraint 1: can't evaluate pow'(0,0.5).
问题分析
错误提示信息为Error evaluating constraint 1: can't evaluate pow'(0,0.5).
,也即无法评估pow'(0, 0.5)
。此函数中的'
字符表示一阶导数。我们对
x
\sqrt{x}
x求导得
1
2
x
\frac{1}{2\sqrt{x}}
2x1。此时如果
x
=
0
x=0
x=0时,计算机求得
x
\sqrt{x}
x导数的值。所以才会报错。我们发现
x
n
x^{n}
xn中的
n
<
1
n<1
n<1时,都会出现以上错误。
解决方法
当
x
n
x^{n}
xn中的
n
<
1
n<1
n<1时,将变量绑定到非零值:m.s = Var(RangeSet(0, N-1), bounds=(1e-20,None))
from pyomo.environ import *
from pyomo.dae import *
N = 5
m = ConcreteModel()
m.s = Var(RangeSet(0, N-1), bounds=(1e-20,None))
m.s_cons = Constraint(RangeSet(0, N-1), rule=lambda m, i: m.s[i]**(0.5) >= 1.0)
m.obj = Objective(expr=sum(m.s[i] for i in RangeSet(0, N-1)), sense=minimize)
%time SolverFactory('ipopt').solve(m)
m.display()
print("the opt x is:", [m.s[i]() for i in range(N)])
运行结果如下: