Sympy - Simplify expression within domain

痴心易碎 提交于 2021-02-05 10:50:50

问题


Can Sympy automatically simplify an expression that includes terms like this one:

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

which can be simplified to 1 in the domain that I am interested in 0 <= x <= pi/2 ?

(Examples of other terms that could be simplified in that domain: acos(cos(x)); sqrt(sin(x)**2); sqrt(cos(2*x) + 1); etc.)


回答1:


If you know the functions that are in your expression (such as sin, cos and tan), you can do the following according to this stack overflow question:

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)

Note that Q.positive(x*(pi/2-x)) did not help in the process of simplification for trig functions even though this is exactly what you want in general.

But what if you might have crazy functions like polygamma? The following works for some arbitrary choices for ex according to my understanding.

It wouldn't be a problem if the expression was already generated before by SymPy, but if you are inputting the expression manually, I suggest using S(1)/2 or Rational(1, 2) to describe one half.

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)

This trick can also be used to define other ranges. For example, if you wanted 1 < x, then you could have x = exp(y) where y = Symbol("y", positive=True).

I think subs() will also work instead of replace() but I just like to be forceful with substitutions, since SymPy can sometimes ignore the subs() command for some variable types like lists and stuff.




回答2:


You can substitute for a symbol that has the assumptions you want:

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


来源:https://stackoverflow.com/questions/62882489/sympy-simplify-expression-within-domain

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!