Sympy - Упростите выражение в домене - PullRequest
0 голосов
/ 13 июля 2020

Может ли Sympy автоматически упростить выражение, которое включает такие термины, как этот:

cos(x)/(cos(x)**2)**(1/2)

, которое может быть упрощено до 1 в интересующей меня области 0 <= x <= pi/2?

(Примеры других терминов, которые можно было бы упростить в этой области: acos (cos (x)); sqrt (sin (x) ** 2); sqrt (cos (2 * x) + 1); et c. )

Ответы [ 2 ]

1 голос
/ 19 июля 2020

Если вы знаете функции, которые есть в вашем выражении (например, 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() для некоторых типов переменных, таких как списки и т. д.

1 голос
/ 14 июля 2020

Вы можете заменить символ, который имеет нужные вам предположения:

In [27]: e = cos(x)/(cos(x)**2)**(S(1)/2) + cos(x)                                                                     

In [28]: e                                                                                                             
Out[28]: 
            cos(x)   
cos(x) + ────────────
            _________
           ╱    2    
         ╲╱  cos (x) 

In [29]: cosx = Dummy('cosx', positive=True)                                                                           

In [30]: e.subs(cos(x), cosx).subs(cosx, cos(x))                                                                       
Out[30]: cos(x) + 1
...