如何正确地使用带有多重变量的scipy最小化?

时间:2019-07-18 19:38:02

标签: python scipy scipy-optimize scipy-optimize-minimize

我想对scipy.optimize.minimize进行五个变量处理,以便根据ABC,{ {1}}和D。首先,我从E导入了minimize并定义了初始猜测(基于实验室实验,因此它们应该是有效的)。

scipy

第二,我定义了组成目标函数的各个函数,方便地命名为from scipy.optimize import minimize A0 = 1.90 B0 = 6.40 C0 = 11.7 D0 = 3.70 E0 = 2.50 ABCDE0 = [A0, B0, C0, D0, E0] 。我还尝试将ObjectiveFGH组合成一个函数,但没有任何运气,所以我决定暂时将其保留为这样。< / p>

I

第三,为简单起见,我定义了def F(abcde): a, b, c, d, e = abcde return c - (b ** 2) / (a - e) def G(abcde): a, b, c, d, e = abcde return (4 * e * ((a - e) * c - b ** 2)) / (a * c - b ** 2) def H(abcde): a, b, c, d, e = abcde return b / (2 * (a - e)) def I(abcde): a, b, c, d, e = abcde return (2 * e * b) / (a * c - b ** 2) def Objective(abcde): return (F(abcde) / G(abcde)) / (H(abcde) / I(abcde)) (即constraint)和名为(F/G)/(H/I)=1的边界作为初始猜测的bnds

+/- 10%

第四,最后,def constraint(x): F = x[0] G = x[1] H = x[2] I = x[3] return (F / G) / (H / I) - 1 con = {'type': 'eq', 'fun': constraint1} min_per = 0.9 max_per = 1.1 bnds = ((A0*min_per, A0*max_per), (B0*min_per, B0*max_per), (C0*min_per, C0*max_per), (D0*min_per, D0*max_per), (E0*min_per, E0*max_per)) 为我提供了一个名为minimize的解决方案。

sol

如果用sol = minimize(Objective, ABCDE0, method='SLSQP', bounds=bnds, constraints=con1, options={'disp':True}) 打印溶胶,则会显示以下消息。

print(sol)

在我的新手看来,Positive directional derivative for linesearch (Exit mode 8) Current function value: 1.0 Iterations: 18 Function evaluations: 188 Gradient evaluations: 14 fun: 1.0 jac: array([ 0.00000000e+00, 1.49011612e-08, -7.45058060e-09, 0.00000000e+00, 0.00000000e+00]) message: 'Positive directional derivative for linesearch' nfev: 188 nit: 18 njev: 14 status: 8 success: False x: array([ 2.09 , 5.76 , 10.53 , 4.07 , 2.50000277]) 似乎是问题所在,但我不确定由于constraint的经验不足。

  • 我做错了什么?
  • 为什么执行不成功?
  • 在这种情况下,最好使用@fuglede建议的minimize吗?
  • 是否可以将所有单个功能都包含在一个功能中,以免造成混乱?

请注意,root_scalarD0未包含在任何函数中,但在事物的总体方案中作为五个独立变量之一很重要。

1 个答案:

答案 0 :(得分:0)

这里发生了几件事:

首先,出于个人喜好,我可能会将函数F,...,I留给了多个输入,以免拆开列表。目标函数确实需要一个列表作为其参数。即您可以做类似的事情

def F(a, b, c, d, e):
    return c - (b ** 2) / (a - e)

...

def objective(abcde):
    return (F(*abcde) / G(*abcde)) / (H(*abcde) / I(*abcde))

那只是样式。更重要的是,您的constraint方法不会完全满足您的要求:据我了解,您想对输入中的函数F,...,I进行评估,但是永远不会发生相反,变量F的值(这是一个不幸的名称,因为它遮盖了函数的名称)最终仅是a。相反,您会做类似

的操作
def constraint(x):
    return (F(*x) / G(*x)) / (H(*x) / I(*x)) - 1

现在,constraint(x)只是objective(x) - 1,因此您的约束最终表明,在可行的解决方案中,objective必须等于1。这意味着根本没有进行任何优化:任何可行的解决方案都是最优的。先验minimize确实会为您找到可行的解决方案,但您很有可能会尝试使用scipy.optimize的{​​{3}}中的某些内容这样做是在寻找函数objective - 1的根。

现在,最终,这实际上变得非常简单:无论您定义的函数objective等于1,所以 any 输入都是可行的解决方案:首先,通过编写{{ 1}},请注意F = ((a-e)c - (b**2))/(a-e)。然后,(a*c-b**2) / (4*e*(a-e))(F/G)*I = (2*e*b)/(4*e*(a-e)) = b/(2*(a-e)) = H