fmin_slsqp为同一系统返回不同的解决方案

时间:2014-08-20 16:21:06

标签: python numpy scipy mathematical-optimization

以下是我可以把它煮沸的。

我试图用18个方程和18个变量求解方程组。目前,我已经修复了其中4个变量。最初,我得到了奇怪的结果。所以我到目前为止简化了这个问题,以便前9个和后9个方程是分开且相同的。此外,问题已确切确定:应该有一个独特的解决方案。

解决方案向量包含14个元素(18减去4个固定变量)。由于这些是正确排序的,因此前7个解决方案变量应与最后7个解决方案变量相同。但是,他们不是。

  • 我通过输入相同的向量x[:7] = x[7:]并检查res[:9] == res[9:]是否都是真的来检查方程的身份。

以下是我得到的输出:

Optimization terminated successfully.    (Exit mode 0)
            Current function value: 0.125393271845
            Iterations: 18
            Function evaluations: 297
            Gradient evaluations: 18
Out[223]: 
          J         W         w         v         U         u         Y
0  0.663134  0.237578  0.251245  10.00126  0.165647  0.093939  0.906657
1  0.022635  0.825547  1.000000  10.00340  0.512898  0.089790  0.909918

我将前7个变量堆叠到第一行,接下来的7个变量堆积到第二行。显然,这些并不完全相同。

复制代码如下

import numpy as np

# parameters

class Parameters(object):
    r = 1.03
    sBar = 0.1
    sB = 0.1
    c = 0.1
    z = 0.001
    H = 1
    epsilon = 1
    beta = 0.1

def q(theta):
    if theta <= 0:
        return 999
    return float(1)/theta

def f(theta):
    if theta < 1:
        return 0
    return 1 - float(1)/theta

# sum_all allows to see residual as vector, not summed
def twoSectorFake(x, Param, sum_all=True):
    JBar, WBar, wBar, vBar, UBar, uBar, YBar = x[:7]
    JB, WB, wB, vB, UB, uB, YB = x[7:]
    VBar = 0
    VB = 0
    pB = 1
    pBar = 1
    #theta = float(vB + vBar)/u
    thetaBar = float(vBar)/uBar
    thetaB = float(vB)/uB
    res = np.empty(18,)
    res[0] = Param.r*JBar - (pBar - wBar - Param.sBar*(JBar - VBar) )
    res[1] = Param.r * VBar - ( -Param.c + q(thetaBar) * (JBar - VBar) )
    res[2] = Param.r * WBar - (wBar - Param.sBar * (WBar - UBar) )
    res[3] = Param.r * UBar - (Param.z + f(thetaBar) * (WBar - UBar) )
    res[4] = Param.sBar * YBar - vBar * q(thetaBar)
    res[5] = Param.sBar * YBar - uBar * f(thetaBar)
    res[6] = JBar - (1 - Param.beta) * (JBar + WBar - UBar)
    res[7] = Param.H - YBar - uBar
    res[8] = thetaBar * uBar - vBar

    res[9] = Param.r*JB - (pB - wB - Param.sB*(JB - VB))
    res[10] = Param.r*VB - ( -Param.c + q(thetaB) * (JB - VB))
    res[11] = Param.r * WB - (wB - Param.sB * (WB - UB))
    res[12] = Param.r * UB - (Param.z + f(thetaB) * (WB - UB))
    res[13] = Param.sB * YB - vB*q(thetaB)
    res[14] = Param.sB * YB - uB * f(thetaB)
    res[15] = JB - (1 - Param.beta) * (JB + WB - UB)
    res[16] = Param.H - YB - uB
    res[17] = thetaB * uB - vB

    idx = abs(res > 10000)
    # don't square too big numbers, they may become INF and the problem won't solve
    res[idx] = abs(res[idx])
    res[~idx] = res[~idx]**2
    if (sum_all==False):
        return res
    return sum(res)

Param = Parameters()

x2 = np.empty(0,)
boundaries2 = []
# JBar
x2 = np.append(x2, 1)
boundaries2.append([0, 100])
# WBar
x2 = np.append(x2, 1)
boundaries2.append([0, 100])
# wBar
x2 = np.append(x2, 0.5)
boundaries2.append([0.01, 100])
# vBar
x2 = np.append(x2, 10)
boundaries2.append([0.01, 100000])
# UBar
x2 = np.append(x2, float(Param.z)/(Param.r-1)+1)
boundaries2.append([float(Param.z)/(Param.r-1) - 0.1, 100])
# uBar
x2 = np.append(x2, 0.5*Param.H)
boundaries2.append([0.0000001, Param.H])
# YBar
x2 = np.append(x2, 0.5*Param.H)
boundaries2.append([0.0001, Param.H])
# JB
x2 = np.append(x2, 1)
boundaries2.append([0, 100])
# WB
x2 = np.append(x2, 1)
boundaries2.append([0, 100])
# wB
x2 = np.append(x2, 0.5)
boundaries2.append([1, 100])
# vB
x2 = np.append(x2, 10)
boundaries2.append([0.01, 100])
# UB
x2 = np.append(x2, float(Param.z)/(Param.r-1)+1)
boundaries2.append([float(Param.z)/(Param.r-1) - 0.1, 100])
# uB
x2 = np.append(x2, 0.5*Param.H)
boundaries2.append([0.0000001, Param.H])
# YB
x2 = np.append(x2, 0.5*Param.H)
boundaries2.append([0.0001, Param.H])

result = optimize.fmin_slsqp(func=twoSectorFake, x0=x2, bounds=boundaries2, args=(Param,), iter=200)
res1 = result[:7]
res2 = result[7:]
df = pd.DataFrame(np.reshape(res1, (1,7)), columns=['J', 'W', 'w', 'v', 'U', 'u','Y'])
df.loc[1] = np.reshape(res2, (1,7))
print df

1 个答案:

答案 0 :(得分:1)

编辑:

您的变量boundaries2不是对称的,即boundaries2[7:]!=boundaries2[:7]

尝试写作

boundaries2 = boundaries2[7:]*2

在您致电fmin_slsqp之前,您将获得对称的本地最低要求。我在下面的设置中留下以前的一般性评论,因为它们适用于任何情况。

首先,您确定您的问题只有一个解决方案吗?如果没有,我不会期望scipy数字例程必须返回你想到的解决方案。它可以收敛到任何其他非对称解决方案。

在第二种情况下,你没有解决方程组。如果您在代码末尾评估twoSectorFake(result,Param),则会获得0.15。使用其他根解算器可能会更好,请参阅root finding部分。

这意味着您将查看目标函数的局部最小值,即不是零。同样,没有理由为什么数值例程必须计算对称的局部最小值。