Как проверить, имеет ли выражение SymPy аналитический интеграл - PullRequest
0 голосов
/ 26 апреля 2018

Я хочу решить другой мой вопрос здесь , поэтому мне нужно, чтобы sympy возвращал ошибку всякий раз, когда нет аналитического / символического решения для и интеграла.

Например, если я попытаюсь:

from sympy import *
init_printing(use_unicode=False, wrap_line=False, no_global=True)
x = Symbol('x')
integrate(1/cos(x**2), x)

Он просто [довольно] печатает сам интеграл

enter image description here

без решения и / или выдачи ошибки о невозможности ее решить!

P.S. Я также задавал этот вопрос здесь, на Reddit .

1 Ответ

0 голосов
/ 26 апреля 2018

«Символическое» решение всегда существует: я только что изобрел новую функцию intcos(x), которая по определению является антипроизводной 1/cos(x**2). Теперь этот интеграл имеет символическое решение!

Чтобы вопрос был строго ответным, нужно ограничить класс функций, разрешенных в ответе. Обычно рассматривают элементарные функции . Как объясняет интегральная ссылка SymPy , алгоритм Risch, который он использует, может доказать , что некоторые функции не имеют элементарных антипроизводных. Используйте параметр risch=True и проверьте, является ли возвращаемое значение экземпляром sympy.integrals.risch.NonElementaryIntegral

from sympy.integrals.risch import NonElementaryIntegral
isinstance(integrate(1/exp(x**2), x, risch=True), NonElementaryIntegral)  # True

Однако, поскольку реализация алгоритма Риша является неполной, во многих случаях, таких как 1/cos(x**2), он возвращает обычный объект Integral. Это означает, что он не смог ни найти элементарного антидериватива, ни доказать, что он не существует.

Для этого примера, это помогает переписать тригонометрическую функцию в терминах экспоненциального, с rewrite(cos, exp):

isinstance(integrate((1/cos(x**2)).rewrite(cos, exp), x, risch=True), NonElementaryIntegral)  

возвращает True, поэтому мы знаем, что интеграл неэлементарен.

Неэлементарные анти-производные

Но часто нам не нужна элементарная функция; что-то вроде функций Gamma или Erf или Bessel может быть в порядке; до тех пор, пока это некая «известная» функция (что, конечно, нечеткий термин). Возникает вопрос: как определить, удалось ли SymPy интегрировать конкретное выражение или нет? Используйте для проверки .has(Integral):

integrate(2/cos(x**2), x).has(Integral)   # True

(не isinstance(Integral), потому что возвращаемое значение может быть, как здесь, 2*Integral(1/cos(x**2), x).) Это не доказывает ничего, кроме неспособности SymPy найти антипроизводное. Антидериватив вполне может быть известной функцией, даже элементарной.

...