Оптимизация Python с использованием sympy lambdify и scipy

Я пытаюсь максимизировать функцию, определенную 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 ответ

Как указал @Dair, lambdify sympy в общем случае требует более одного аргумента, тогда как scipy ожидает только один аргумент, список (или массив), который содержит все значения каждой переменной. Поскольку моя целевая функция наиболее удобно определяется с помощью sympy, мне нужно найти способ обойти эту несовместимость sympy и scipy.

@lhcgeneva указал на ответ на аналогичный вопрос. Этот ответ удобно не обрабатывать большим количеством независимых переменных, особенно когда число независимых переменных может измениться, что требует переписывания "векторизованной" версии целевой функции, которая должна быть переопределена. Однако, вдохновленный этим постом, я нашел следующее решение с использованием *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])

Кроме того, нам не нужно изменять my_func_v при изменении NUM_VAR.

Другие вопросы по тегам