【问题标题】:indexing in lambda function to optimize multiple variables of a sum在 lambda 函数中进行索引以优化总和的多个变量
【发布时间】:2017-11-13 23:07:42
【问题描述】:

我想解决this 线程中提出的优化问题。现在,我不仅要求解x[1]...x[n],还要求解变量y。索引似乎有问题。

from sympy import Sum, symbols, Indexed, lambdify
from scipy.optimize import minimize
import numpy as np

def _eqn(y, variables, periods, sign=-1.0):
    x, i = symbols("x i")
    n = periods-1
    s = Sum(Indexed('x', i)/(1+0.06)**i, (i, 1, n))
    f = lambdify(x, s, modules=['sympy'])
    return float(sign*(y + f(variables)))

z = 3
results = minimize(lambda xy: _eqn(xy[0], xy[1:z], z),np.zeros(z))
print(results.x)

【问题讨论】:

    标签: python lambda scipy sympy


    【解决方案1】:

    从错误消息看来,您的索引存在问题。总和从 1 到 n,但默认情况下 Python 中列表类型对象的索引从 0 到 n-1。如果我在您的代码中更改它似乎可以工作。看看吧。

    import sympy as sp
    from scipy.optimize import minimize
    import numpy as np
    
    sp.init_printing()
    
    def _eqn(y, variables, periods, sign=-1.0):
        x, i = sp.symbols("x i")
        n = periods-1
        s = sp.Sum(sp.Indexed('x', i)/(1+0.06)**(i+1), (i, 0, n-1)).doit()
        f = sp.lambdify(x, s, modules=['sympy'])
        return float(sign*(y + f(variables)))
    
    z = 3
    results = minimize(lambda xy: _eqn(xy[0], xy[1:z], z),np.zeros(z))
    print(results.x)
    

    【讨论】:

    • 好的,我明白你的意思了。它应该是 (i+1) 。所以在一些我现在有 x[0] 和 x[1] 作为变量。你在最小化函数中的索引真的正确吗?假设我们改变 _eqn 中的 y 和变量,会不会是最小化(lambda xy: _eqn(xy[:z-1], xy[z-1], z),np.zeros(z))?因为索引匹配总和变量?!我可以以某种方式检查结果,因为它在这些情况下会出现偏差。
    • 索引似乎是正确的。在_eqn 函数中,x[0]x[1] 指代variables[0]variables[1],它们又指代xy[1]xy[2]。您已经将xy[0] 分离到函数_eqn 的输入参数y 中。
    • 好的,我想我可以跟上。但是为什么结果(i+1)和你的第一个答案不同?这真的有影响吗? x = [var('x'+ str(i)) for i in range(z)]
    • 现在我明白了。您在分母的指数中谈论(i + 1)。我已经更新了我的两个答案。您正在求解的方程没有 sign=-1.0 的最小值,因为随着我们使 yx 变大,总函数变得越来越负。如果你设置sign=1.0,那么这两种方法都会给出相同的答案。
    • 很抱歉,您尝试最小化的函数具有恒定的雅可比行列式。最小化需要求解 Jacobian = 0。因此,sign=+1.0sign=-1.0 没有唯一的最小值。从这个意义上说,我的两个答案都是无用的。
    【解决方案2】:

    如果您只需要可变数量的最小化参数,那么以下代码对您有用吗?

    from sympy import var
    from scipy.optimize import minimize
    import numpy as np
    
    def _eqn(y, variables, periods, sign=-1.0):    
        f = 0
        for i,x in enumerate(variables):
            f += x/(1+0.06)**(i+1)
        return float(sign*(y + f))
    
    z = 3
    results = minimize(lambda xy: _eqn(xy[0], xy[1:z], z),np.zeros(z))
    print(results.x)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-28
      • 2020-05-08
      • 2019-04-21
      • 2019-01-21
      • 1970-01-01
      • 1970-01-01
      • 2018-08-05
      相关资源
      最近更新 更多