我正在使用 SymPy 在 Python 中对非常大的表达式进行符号操作。我正在操作的大多数符号代表小于或等于一的非负实数。
我如何告诉 SymPy 这些假设?我发现在创建符号时我可以执行以下操作。
import sympy as sym
x = sym.symbols('x', real=True, nonnegative=True)
但我不知道如何施加 1 的上限。
不幸的是,当前实施的假设系统没有提供施加这种限制的方法。出于某些目的,引入隐含界限的代数结构可能是合理的:例如,
t = sym.symbols('t', nonnegative=True)
x = t/(1+t)
现在 SymPy 知道 x 介于 0 和 1 之间:
>>> x < 1
True
>>> x >= 0
True
这是否有帮助取决于您正在使用的表达式的替换程度。另一种选择是
x = sym.exp(-t)
这是一个与已接受的答案在精神上相似的技巧,但保留了表达式中的原始符号。
考虑:
from sympy import symbols, sqrt, conjugate, Q
x = symbols('x', real=True, nonnegative=True)
expr = sqrt(1-x) * conjugate( sqrt(1-x) )
假设
0 <= x <= 1
,我们知道expr
会简化为1-x
,但我们不能直接在sympy中使用这个假设:
expr.simplify()
>>> sqrt(1 - x)*conjugate(sqrt(1 - x))
expr.refine(Q.positive(1-x))
>>> sqrt(1 - x)*conjugate(sqrt(1 - x))
我们希望传达给 sympy,
1-x
始终为正值或零。如果我们可以用声明为 1-x
的符号 y
替换 nonnegative=True
,那么 simplify()
可以识别 sqrt(1-x) = sqrt(y)
是实数并简化共轭和乘积。
我们可以做到这一点,而且我们甚至不需要使用新的符号!我们替换
x -> 1-x
,使子表达式 f(1-x)
变成 f(x)
,现在可以利用它们的参数为正来简化。然后,我们通过再次替换 1-x -> x
来恢复 x -> 1-x
。
expr = expr.subs(x, 1-x).simplify().subs(x, 1-x)
>>> 1 - x
这看起来很安全;我们的替换在数学上相当于断言
x <= 1
,再加上我们明确的 sympy 假设 x >= 0
,达到了预期的界限。
我们可以轻松扩展它以简化表达式,假设
0 <= x <= b
为正界 b
:
expr = expr.subs(x, b-x).simplify().subs(x, b-x)