【问题标题】:Excel Solver solution in Python. Scipy not workingPython 中的 Excel Solver 解决方案。 Scipy 不工作
【发布时间】:2019-04-21 09:46:18
【问题描述】:

我有一个简单的非线性优化项目。我想找到未来现金流量和终值的贴现率,使总和等于指定的 NPV。以下是我尝试过的一些实验。

两家公司的固定现金流量均为 10,且 NPV 不同。贴现率结果应分别为 1.074 (7.4%) 和 1.052 (5.2%)。 Excel Solver 在 Scipy 返回 NoConvergence 时迅速找到了根源。

import numpy as np
from scipy.optimize import newton_krylov
from scipy.optimize.nonlin import NoConvergence


cf_fy1 = [10]*2
cf_fy2 = [10]*2
cf_fy3 = [10]*2
cf_fy4 = [10]*2
cf_fy5 = [10]*2
cf_fy6 = [10]*2
npv = [200, 400]

def mydr(dr):
    terminal_value = np.divide(cf_fy6, np.subtract(dr, 1.03))
    ev = np.sum([np.divide(cf_fy1, np.power(dr, 1)),
                 np.divide(cf_fy2, np.power(dr, 2)),
                 np.divide(cf_fy3, np.power(dr, 3)),
                 np.divide(cf_fy4, np.power(dr, 4)),
                 np.divide(cf_fy5, np.power(dr, 5)),
                 np.divide(terminal_value, np.power(dr, 5))], axis=0)
    z = np.subtract(ev, npv)
    return abs(z)

try:
    sol = newton_krylov(mydr, [1.1] * len(npv))
    converged = True
except NoConvergence as e:
    sol = e.args[0]
    converged = False

提前谢谢大家!

【问题讨论】:

    标签: python optimization scipy


    【解决方案1】:

    根据文档,Newton-Krylov 方法(仅?)适用于解决大规模问题。并且 Newton-Krylov 方法不会与您的初始点收敛。由于这是一个非常简单的问题,我会使用通用的root 方法来代替:

    In [13]: from scipy.optimize import root
    
    In [14]: root(mydr, x0 = [1.1, 1.1])                                                                 
    Out[14]: 
        fjac: array([[-9.99999700e-01,  7.74730469e-04],
           [-7.74730469e-04, -9.99999700e-01]])
         fun: array([9.03350275e-06, 1.53610404e-06])
     message: 'The solution converged.'
        nfev: 40
         qtf: array([-9.03230997e-06, -1.54310211e-06])
           r: array([ -4128.02172068, -37514.05364792,  19083.3896212 ])
      status: 1
     success: True
           x: array([1.07391362, 1.05176871])
    

    如果需要,您可以通过method 选项设置使用的求解器(注意不同的初始点):

    In [15]: root(mydr, x0 = [1.05, 1.05], method="krylov")                                              
    Out[15]: 
         fun: array([3.97903932e-13, 1.68824954e-11])
     message: 'A solution was found at the specified tolerance.'
         nit: 7
      status: 1
     success: True
           x: array([1.07391362, 1.05176871])
    

    【讨论】:

    • 谢谢吨。它现在正在工作。用root替换可以大大提高准确性。我发现当我与更少的公司合作时,“root”结果往往更准确。一种廉价的解决方案是使用之前的输出作为下一次运行的猜测,并重复该过程多次以最终获得最准确的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-09
    • 2019-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多