如何替代部分权力?

How to substitute partial powers?

我有一个表达式,其中包含像 expr = a**m * b**n 这样的术语,其中 a,b 是符号,m,n 是整数。如果 a**i * b**ja**m * b**n 的因数(这里 i,j 也是整数),我想使用 expr.subs(a**i * b**j, 0) 将表达式设置为零。这在某些情况下有效,但当仅使用一个符号进行替换时则无效:

>>> from sympy import symbols
>>> a, b = symbols('a b')
>>> (a**2 * b**3).subs(a**2 * b**2, 0)  # (1) works
0
>>> (a**2 * b**3).subs(a * b**2, 0)  # (2) works
0
>>> (a**2 * b**3).subs(b**2, 0)  # (3) does not work
a**2*b**3
>>> (a**3).subs(a**2, 0)  # (4) does not work
a**3
>>> (a**4).subs(a**2, 0)  # (5) works
0

我希望这个替换在上述所有情况下都有效,并且从逻辑上讲它应该(因为例如 a**2 * b**3 等同于 a**2 * b * (b**2) 因此替换 (b**2, 0) 应该产生0)。但是,如果在替换中使用单个符号,它似乎只适用于表达式包含提升为次幂的子项的情况;例如:

>>> (a**2 * b**4).subs(b**2, 0)  # (6) works
0
>>> (a**2 * b**4).subs(b**3, 0)  # (7) does not work
a**2*b**4

这种行为似乎有点奇怪,因为它适用于 b**1 并且当人为地增加实际表达式和子项时,还有一些其他符号:

>>> (a**2 * b**4).subs(b, 0)  # (8) works
0
>>> c = symbols('c')
>>> (c * (a**2 * b**4)).subs(c * (b**3), 0)  # (9) works
0

虽然我可以使用最后的观察结果(增强表达式)作为解决方法,但它似乎既不清晰也不高效。 因此,是否有另一种方法可以使替换适用于实际表达式中包含子项的所有情况?


>>> sympy.__version__
'1.10.1'
  1. 有效,因为 a2 = 0 是 0 * b3 导致 0
  2. a = 0 表示 a**2 = 0 -> 0
  3. b2 = 0 但 b2 不在 b**3 中,所以它不起作用
  4. 与 3 相同的问题
  5. a4 在 a2 中所以 0
  6. 与 5 相同,但带有 b´s
  7. 与 3 相同的问题
  8. b 在 b**4
  9. c = c 所以它变成 0 因为只有符号被替换

一切如期进行

要检查某物是否是产品的因素,您可以使用 extract_multiplicatively:

>>> expr = a**3*b**3*c
>>> 0 if expr.extract_multiplicatively(a*b**2) else expr
0

您也可以使用rem函数查看余数是否为0:

>>> rem(expr, a*b**2)
0

如果您的表达式出现在一个更大的表达式中,那么它们可以合并到 replace 调用中,expr.replace(...)。如果你试图忽略表达式中的 high-order 项,你可以创建一个函数来添加一个项中所有 symbol-based 幂的顺序:

>>> expr = expand((x + 1)**3*(y + 1)**2)
>>> def order(m):
...     return sum([degree(m, x) for x in m.free_symbols])
...
>>> expr.replace(lambda x: not x.is_Add,
...     lambda x: 0 if order(x)>2 else x)
3*x**2 + 6*x*y + 3*x + y**2 + 2*y + 1