Python优化使用sympy lambdify和scipy

时间:2015-12-06 07:50:24

标签: python optimization lambda scipy sympy

我正在尝试最大化由sympy定义的函数,但无法使其工作。基本思路可归纳如下:

    import sympy
    from scipy.optimize import minimize
    from sympy.utilities.lambdify import lambdify

    a,b,G = sympy.symbols('a b G')
    func = (G - a)**2 + b
    my_func = lambdify((G,a,b), -1*func)
    results = minimize(my_func,[0.1,0.1,0.1])

如果我定义单变量函数,代码可以工作,但只要我有多个变量,我就会收到以下错误消息。

    TypeError: <lambda>() takes exactly 3 arguments (1 given)

有人可以帮我确定哪里出错了吗?

1 个答案:

答案 0 :(得分:3)

正如@Dair所指出的,sympy的lambdify一般需要多个参数,而scipy只需要一个参数,一个包含每个变量所有值的列表(或数组)。因为我的目标函数最方便地使用sympy来定义,所以我需要找到一种方法来解决这种与sympy和scipy不兼容的问题。

@lhcgeneva指出the answer to a similar question。这个答案不方便处理大量的自变量,特别是当自变量的数量可以改变时,需要写出&#34;矢量化的&#34;要重新定义的目标函数的版本。但是,受到这篇文章的启发,我使用* tuple()找出了以下解决方案:

    import sympy
    from scipy.optimize import minimize
    from sympy.utilities.lambdify import lambdify

    a,b,G = sympy.symbols('a b G')
    func = -1*((G - a)**2 + b)
    my_func = lambdify((G,a,b), func)

    def my_func_v(x):
        return my_func(*tuple(x))

    results = minimize(my_func_v,[0.1,0.1,0.1])

在我给出的示例中,似乎没有必要使用* tuple(),但对于我想要解决的问题,它可以节省很多麻烦。这是一个与我想要解决的问题更相似的例子

NUM_VAR = 10
x = np.array(sympy.symbols('x0:%d'%NUM_VAR))
func = np.sum((x-1)**2)
my_func = lambdify(x, func)


def my_func_v(x):
    return my_func(*tuple(x))

results = minimize(my_func_v,np.zeros(NUM_VAR))

这个*元组()的东西可以让我免于写出x的所有元素,如下所示(对于NUM_VAR = 10的情况):

def my_func_v(x):
    return my_func(x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9])

另外,当NUM_VAR更改时,我们不需要更改my_func_v。