我正在尝试使用pyomo 5.3版和bonmin实现“扩展支持超平面算法”(https://link.springer.com/article/10.1007/s10898-015-0322-3)。该算法用线性目标函数求解凸MINLP。本质上,该算法会创建超平面,从而对可行集进行严格的圈套高估。之所以可行,是因为可行集是凸的。
对于算法的第二步,作为解决两个子问题的结果,我有两点。第一点x_NLP
是原始问题的可行点。如果忽略了非线性约束并且放宽了整数变量,则第二点x_LP
是获得的解决方案。如果x_LP
违反了非线性约束,则将在点x_k = lambda_k*x_NLP + (1-lambda_k)*x_LP
处创建一个新的超平面,因此max(g(x_k))==0
用于所有非线性约束。因此,x_k
位于连接x_NLP
和x_LP
的线上。
我当时正在考虑使用二等分法(类似:https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.bisect.html)。我已经有一个工作函数,可将所有违反模型的非线性约束保存在列表中。因此,我可以为每个违反的约束计算lambda_k
并使用最小的lambda(因为可行集是凸的)来获得x_k
现在,有没有一种方法可以将约束主体提取为数学函数?
这是我正在使用的示例(整个代码将相当长,因为我定义了许多用于pyomo模型的函数):
model_ESH = ConcreteModel(name = "Example 1")
model_ESH.x1 = Var(bounds=(1,20), domain=Reals)
model_ESH.x2 = Var(bounds=(1,20), domain=Integers)
model_ESH.obj = Objective(expr=(-1)*model_ESH.x1-model_ESH.x2)
model_ESH.g1 = Constraint(expr=0.15*((model_ESH.x1 - 8)**2)+0.1*((model_ESH.x2 - 6)**2)+0.025*exp(model_ESH.x1)*((model_ESH.x2)**(-2))-5<=0)
model_ESH.g2 = Constraint(expr=(model_ESH.x1)**(-1) + (model_ESH.x2)**(-1) - ((model_ESH.x1)**(0.5)) * ((model_ESH.x2) ** (0.5))+4<=0)
model_ESH.l1 = Constraint(expr=2 * (model_ESH.x1) - 3 * (model_ESH.x2) -2<=0)
model_ESH.pprint()
2 Var Declarations
x1 : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : 1 : None : 20 : False : True : Reals
x2 : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : 1 : None : 20 : False : True : Integers
1 Objective Declarations
obj : Size=1, Index=None, Active=True
Key : Active : Sense : Expression
None : True : minimize : - x1 - x2
3 Constraint Declarations
g1 : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : -Inf : -5 + 0.15*( -8 + x1 )**2.0 + 0.1*( -6 + x2 )**2.0 + 0.025 * exp( x1 ) * x2**-2.0 : 0.0 : True
g2 : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : -Inf : 4 + x1**-1.0 + x2**-1.0 - x1**0.5 * x2**0.5 : 0.0 : True
l1 : Size=1, Index=None, Active=True
Key : Lower : Body : Upper : Active
None : -Inf : -2 + 2*x1 - 3*x2 : 0.0 : True
6 Declarations: x1 x2 obj g1 g2 l1
我已经获得的两点保存为数组:
x_NLP = [7.44903017 8.53504579]
x_LP = [20 20]
违反x_LP
的非线性约束是g1
。如上所述,通常可以违反多个非线性约束。
现在我想找到要点
x_k = lambda_k*x_NLP + (1-lambda_k)*x_LP
这样
g1(x_k)==0
。
我可以通过类似以下方式使用scipy做到这一点吗?
``scipy.optimize.bisect(g1.body,x_NLP,x_LP)`''?
上面链接上的示例显示了此功能的简单功能。我可以用这种方式提取g1.body
以便工作吗?
我愿意接受其他建议来找到x_k
。重要的是要获得该点,以便可以使用它来创建超平面。