Если вы знаете функции, которые есть в вашем выражении (например, sin
, cos
и tan
), вы можете сделать следующее в соответствии с этим вопросом о переполнении стека :
from sympy import *
x = symbols("x", positive=True)
ex = cos(x)/(cos(x)**2)**(S(1)/2)
ex = refine(ex, Q.positive(sin(x)))
ex = refine(ex, Q.positive(cos(x)))
ex = refine(ex, Q.positive(tan(x)))
print(ex)
Обратите внимание, что Q.positive(x*(pi/2-x))
не помог в процессе упрощения триггерных функций, хотя в целом это именно то, что вам нужно.
Но что, если у вас могут быть сумасшедшие функции, такие как polygamma
? Следующее работает для некоторых произвольных вариантов ex
в соответствии с моим пониманием.
Не было бы проблем, если бы выражение уже было сгенерировано ранее с помощью SymPy, но если вы вводите выражение вручную, я предлагаю используя S(1)/2
или Rational(1, 2)
для описания одной половины.
from sympy import *
# define everything as it would have come from previous code
# also define another variable y to be positive
x, y = symbols("x y", positive=True)
ex = cos(x)/(cos(x)**2)**(S(1)/2)
# If you can, always try to use S(1) or Rational(1, 2)
# if you are defining fractions.
# If it's already a pre-calculated variable in sympy,
# it will already understand it as a half, and you
# wouldn't have any problems.
# ex = cos(x)/(cos(x)**2)**(S(1)/2)
# if x = arctan(y) and both are positive,
# then we have implicitly that 0 < x < pi/2
ex = simplify(ex.replace(x, atan(y)))
# revert back to old variable x if x is still present
ex = simplify(ex.replace(y, tan(x)))
print(ex)
Этот трюк также можно использовать для определения других диапазонов. Например, если вы хотите 1 < x
, тогда вы можете иметь x = exp(y)
, где y = Symbol("y", positive=True)
.
Я думаю, что subs()
также будет работать вместо replace()
, но мне просто нравится быть настойчивым с заменами , поскольку SymPy иногда может игнорировать команду subs()
для некоторых типов переменных, таких как списки и т. д.