Как использовать sympy.lambdify с функцией Max для замены numpy .maximum вместо numpy .amax? - PullRequest
1 голос
/ 17 марта 2020

Я пытаюсь выразить большое 1011 * аналитическое выражение с sp.Max (x, 0) внутри. Я хочу использовать numpy для векторизации моих вычислений, поэтому x будет массивом. Мне нужны поэлементные максимальные значения x и 0. Тем не менее, sympy меняет sp.Max на np.amax по умолчанию. Он находит максимум вдоль оси, это не то, что мне нужно. Ключевое слово "modules" в lambdify не работает, как я ожидаю. Я пробовал:

import numpy as np
import sympy as sp

arr = np.array([1, 2, 3])
expr = sp.sin(x) + sp.Max(x, 0)
f = sp.lambdify(x, expr, modules=[{'Max': np.maximum}, 'numpy'])  # docs say, priority of modules matters
help(f)

Это дает:

Help on function _lambdifygenerated:
_lambdifygenerated(x)
    Created with lambdify. Signature:

    func(x)

    Expression:

    sin(x) + Max(0, x)

    Source code:

    def _lambdifygenerated(x):
        return (sin(x) + amax((0,x)))


    Imported modules:

sp. Макс почему-то изменился на amax.

Если 'numpy' не включенный в список «модулей», он просто пропускает все остальные функции. Я также пытался поменять dict и 'numpy' в списке, но это не помогло. Пожалуйста, уточните, что не так? Это ошибка в sympy?

Ответы [ 2 ]

1 голос
/ 17 марта 2020

При использовании lambdify для создания numpy функций, предназначенных для работы в векторизации, часто возникают тонкие проблемы , особенно когда переменные (x) и константы (0) смешаны.

В этом случае sp.max предполагает, что все его возможные многие параметры являются отдельными значениями. np.amax получает максимум один плоский массив. np.maximum получает поэлементный максимум из двух массивов. Проблема в том, что константа 0 автоматически не расширяется до массива numpy.

Мой обходной путь - заменить sp.max пользовательской функцией, основанной на sp.Piecewise. Обратите внимание, что вам потребуется отдельная функция, если для sp.max.

import numpy as np
import sympy as sp
from sympy.abc import x

def sympy_max2(a, b):
    return sp.Piecewise((b, a < b), (a, True))

arr = np.array([11, 22, 33, -1, -2])
expr = sp.sin(x) + sympy_max2(0, x)
f = sp.lambdify(x, expr, modules=['numpy'])

print(f(arr)) # [10.00000979 21.99114869 33.99991186 -0.84147098 -0.90929743]
будет более 2 аргументов.
0 голосов
/ 17 марта 2020

В текущей версии SymPy я получаю return (sin(x) + amax((0,x), axis=0)) в подписи. Это то, что вы хотите?

...