【发布时间】:2020-07-13 18:57:11
【问题描述】:
Sympy 能否自动简化包含以下术语的表达式:
cos(x)/(cos(x)**2)**(1/2)
在我感兴趣的0 <= x <= pi/2的域中可以简化为1?
(可以在该域中简化的其他术语示例:acos(cos(x)); sqrt(sin(x)**2); sqrt(cos(2*x) + 1); 等等)
【问题讨论】:
Sympy 能否自动简化包含以下术语的表达式:
cos(x)/(cos(x)**2)**(1/2)
在我感兴趣的0 <= x <= pi/2的域中可以简化为1?
(可以在该域中简化的其他术语示例:acos(cos(x)); sqrt(sin(x)**2); sqrt(cos(2*x) + 1); 等等)
【问题讨论】:
如果你知道你的表达式中有哪些函数(如sin、cos和tan),你可以根据这个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)
请注意,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) where y = Symbol("y", positive=True)。
我认为 subs() 也可以代替 replace() 工作,但我只是喜欢强制替换,因为 SymPy 有时会忽略 subs() 命令来处理某些变量类型,例如列表和其他东西。
【讨论】:
您可以替换具有您想要的假设的符号:
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
【讨论】:
e = (cos(x)+1)/(cos(x)**2)**(S(1)/2),它成功了。我用apart(e.subs(cos(x), cosx).subs(cosx, cos(x))) 得到1 + 1/cos(x)。注意S(1)/2 而不是1/2
refine(expr, (0 <= x) & (x<= pi /2)) 之类的东西来实现这一点,但这还没有实现。