罚函数法

Mak*_*sov 4 python math

我正在尝试实现最小化函数的惩罚函数方法。我需要找到Rosenbrok's function的最小值。

我正在使用这个惩罚函数:

惩罚函数

惩罚函数

首先,我使用scipy.optimize.minimize以下方法找到了最小值:

from scipy.optimize import minimize, rosen
rz = lambda x: (1-x[0])**2 + 100*(x[1] - x[0]**2)**2;
h_1 = lambda x: (x[0] - 2 * x[1] + 2);
h_2 = lambda x: (-x[0] - 2 * x[1] + 6);
h_3 = lambda x: (-x[0] + 2 * x[1] + 2);

x0 = [2.3, 5];
cons = ({'type': 'ineq', 'fun': h_1},
       {'type': 'ineq', 'fun': h_2},
       {'type': 'ineq', 'fun': h_3}) 
minimize(rz, x0, constraints=cons)
Run Code Online (Sandbox Code Playgroud)

答案是xarray([ 0.99971613, 0.99942073])

然后我试图使用我的惩罚方法的实现来找到最小值:

x_c = [2.3, 3];
i = 1;
while i < 1000:
    curr_func = lambda x: rz(x) + i*(h_1(x)**2 + h_2(x)**2 + h_3(x)**2)
    x_c = minimize(curr_func, x_c).x;
    i  *= 1.2;
print(answer.x);
Run Code Online (Sandbox Code Playgroud)

这给了我[ 2.27402022 1.4157964 ](如果我增加迭代次数,最终值甚至更大)。

我的实现中的错误在哪里?谢谢。

PS Functioncurr_func特定于我的约束,当然,当它们都是“不等”类型时。

小智 5

您遇到的问题是h_i公式中的 用于等式约束,而您正在解决的问题是不等式约束,它们对应g_i于公式中的 。因此,您的惩罚函数应该使用类似的术语min(0, h_1(x))**2而不是h_1(x)**2。要了解为什么会出现这种情况,只需考虑如果i = 1000并且x是所需的解决方案会发生什么(1, 1)。然后,惩罚将包括一个术语i * h_1(x)**2 = 1000,这是巨大的。

请注意,我使用了min而不是max因为看起来您要强制执行的不等式是h_1(x) >= 0. 这意味着只要h_1(x) >= 0,惩罚应该为零,但是一旦h_1(x)变为负值,您就开始惩罚。如果它确实是h_1(x) <= 0你想要的,那么你就使用max(然后你在h_1使用-h_1时必须切换scipy.optimize.minimize)。

顺便说一句,由于i通常是一个索引变量,因此最好将惩罚权重命名为其他名称,例如a.