Интеграция 1 / х в SymPy - PullRequest
       119

Интеграция 1 / х в SymPy

0 голосов
/ 31 августа 2018

Я думаю, что хорошо, что SymPy возвращает log (x) при интегрировании 1 / x вместо log (abs (x)). Это делает его простым и позволяет пользователю беспокоиться о знаках.

Однако бывают ситуации, когда это приводит к неправильному ответу. Например,

from sympy import *
x = Symbol('x')
integrate(cos(x)**2/sin(x), x)

Результаты в

log(cos(x) - 1)/2 - log(cos(x) + 1)/2 + cos(x)

пока должно (ясно?) Быть

log(1 - cos(x))/2 - log(1 + cos(x))/2 + cos(x)

Есть ли обходной путь, который даст второй ответ?

1 Ответ

0 голосов
/ 31 августа 2018

Отсутствие abs не просто для того, чтобы "все было просто". Как написал ведущий разработчик SymPy ,

SymPy не возвращает log(abs(x)) для integrate(1/x), поскольку оно недопустимо для комплексных чисел. Вместо этого ответ является правильным вплоть до константы интегрирования (которая может быть сложной). Все операции SymPy предполагают, что переменные являются сложными по умолчанию.

Остальная часть связанной проблемы также относится к вашему вопросу. С определенной точки зрения, log(cos(x) - 1): так же действителен, как и log(1 - cos(x)) в результате интегрирования: разница между этими двумя выражениями равна I*pi, которая поглощается константой интегрирования. Кроме того, cos(x) может быть больше 1 для комплексного x, например cos(I) = 1.54...

Тем не менее, следующий способ заставить постоянный член в логах быть неотрицательным.

def fix_logs(expr):
    replacements = {}
    for a in expr.atoms(log):
        if a.args[0].as_coeff_add()[0].is_negative:
            replacements[a] = log(-a.args[0]) + log(-1)
    return expr.xreplace(replacements)

Вот как это работает:

rv = integrate(cos(x)**2/sin(x), x)
rv2 = fix_logs(rv)
rv3 = Add(*fix_logs(rv2).as_coeff_add(x)[1])

Здесь rv, rv2 и rv3:

log(cos(x) - 1)/2 - log(cos(x) + 1)/2 + cos(x)
log(-cos(x) + 1)/2 - log(cos(x) + 1)/2 + cos(x) + I*pi/2
log(-cos(x) + 1)/2 - log(cos(x) + 1)/2 + cos(x)

Функция fix_logs не удаляет часть журнала (-1), поскольку это может быть важно: x*log(x-1) становится x*(log(1-x) + I*pi/2), где константа не может быть просто отброшена. Но при желании аддитивную константу можно удалить, как показано в расчете rv3.

Ссылка для as_coeff_add метода

...