使用 sympy lambdify 和 scipy 进行 Python 优化

标签 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)

谁能帮我找出哪里出了问题?

最佳答案

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

@lhcgeneva 指出 the answer to a similar question .这个答案不方便处理大量的自变量,特别是当自变量的数量可以改变时,需要写出目标函数的“矢量化”版本以重新定义。然而,受这篇文章的启发,我使用 *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))

这个 *tuple() 东西可以让我免于像下面这样写出 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。

关于使用 sympy lambdify 和 scipy 进行 Python 优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34115233/

相关文章:

haskell - GHC优化: Collatz conjecture

c++ - Haskell 可以像 Clang/GCC 一样优化函数调用吗?

java - 如何在 Kotlin 中将函数式接口(interface)操作作为参数传递?

c++ - 在 C++ 中将参数传递给 lambda

python - 全局变量的使用

python - 打印功能在继续之前不会打印完整列表

python - 从字典计算欧氏距离(sklearn)

python - “twistd”不是可识别的内部或外部命令

performance - 写入多个套接字连接的最快方法

java - 如果 Java 程序员想要传递一个函数,他们在 Java 8 之前做了什么?