0

我有五个变量,我想根据、、、和scipy.optimize.minimize来找到我正在寻找的解决方案。首先,我导入并定义了初始猜测(基于实验室实验,因此它们应该是有效的)。ABCDEminimizescipy

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]

其次,我定义了组成目标函数的各个函数,命名方便Objective。我还尝试将F, G, H, and组合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(ie (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})

如果 sol 要由 打印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这似乎是问题所在,但由于缺乏经验,我不确定minimize

  • 我做错了什么?
  • 为什么它没有成功执行?
  • root_scalar在这种情况下,按照@fuglede 的建议使用会更好吗?
  • 是否可以将所有单独的功能包含在一个功能中以避免造成混乱?

请注意D0d不包含在任何功能中,但作为五个自变量之一在事物的宏伟计划中很重要。

4

1 回答 1

1

这里发生了几件事:

首先,出于口味的考虑,我可能会将函数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因为您正在尝试查找函数的根objective - 1

现在最后,这实际上很简单:您的函数objective在任何定义的地方都等于 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,所以1 = (F/G)*(I/H) = (F/G)/(H/I)

于 2019-07-20T16:52:07.180 回答