且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用sympy lambdify和scipy进行Python优化

更新时间:2023-02-26 16:32:49

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

As @Dair pointed out, sympy's lambdify in general requires more than one arguments, while scipy expects only one argument, a list (or an array) that contains all the values of each variable. Because my objective function is most conveniently defined using sympy, I need to find a way to get around this incompatibility of sympy and scipy.

@lhcgeneva指出了类似问题的答案.这个答案不能方便地处理大量的自变量,特别是当自变量的数量可以更改时,这就要求写出要重新定义的目标函数的向量化"版本.但是,受本文的启发,我使用* tuple()找出了以下解决方案:

@lhcgeneva pointed out the answer to a similar question. This answer does not conveniently handle a large number of independent variables, especially when the number of independent variables can change, requiring writing out the "vectorized" version of the objective function to be redefined. However, inspired by this post, I figured out the following solution using *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(),但是对于我要解决的问题,它节省了很多麻烦.这是一个更类似于我要解决的问题的示例

In the example I gave, it seems unnecessary to use *tuple(), but for the problem I want to solve, it saves a lot of hassle. Here's an example that is more similar to the question that I want to solve

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):

This *tuple() thing can save me from writing out all the elements of x like the following (for the case of 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.

Also, we don't need to change my_func_v when NUM_VAR changes.