删除 SymPy 系列扩展中的混合变量项

Oni*_*iow 5 python big-o sympy polynomial-approximations

考虑 SymPy 符号e和 的两个函数i

from sympy import Symbol, expand, Order
i = Symbol('i')
e = Symbol('e')
f = (i**3 + i**2 + i + 1)
g = (e**3 + e**2 + e + 1)
z = expand(f*g)
Run Code Online (Sandbox Code Playgroud)

这将产生

z = e**3*i**3 + e**3*i**2 + e**3*i + e**3 + e**2*i**3 + e**2*i**2 + e**2*i + e**2 + e*i**3 + e*i**2 + e*i + e + i**3 + i**2 + i + 1
Run Code Online (Sandbox Code Playgroud)

然而,假设ei都很小,我们可以忽略三阶或更高阶的两个项。使用 Sympy 的系列工具或简单地添加一个 O-notationOrder类可以解决这个问题:

In : z = expand(f*g + Order(i**3) + Order(e**3))
Out: 1 + i + i**2 + e + e*i + e*i**2 + e**2 + e**2*i + e**2*i**2 + O(i**3) + O(e**3)
Run Code Online (Sandbox Code Playgroud)

看起来很棒。但是,我仍然留下了混合术语e**2 * i**2。这些术语中的单个变量小于所需的截止值,因此 SymPy 保留它们。然而,数学上的 small²·small² = small?。同样,e·i² = small·small² = small³。

至少就我的目的而言,我希望删除这些混合术语。添加一个混合Order不会产生想要的结果(它似乎忽略了前两个命令)。

In : expand(f*g + Order(i**3) + Order(e**3) + Order((i**2)*(e**2)))
Out: 1 + i + i**2 + i**3 + e + e*i + e*i**2 + e*i**3 + e**2 + e**2*i + e**3 + e**3*i + O(e**2*i**2, e, i)
Run Code Online (Sandbox Code Playgroud)

问题: SymPy 是否有一个简单的系统来快速删除 n 阶项,以及 (e^a)·(i^b) 其中 a+b > n 的项?

凌乱的解决方案:我找到了解决这个问题的方法,但它很凌乱,而且可能不通用。

z = expand(f*g + Order((e**2)*i) + Order(e*(i**2)))
zz = expand(z.removeO() + Order(e**3) + Order(i**3))
Run Code Online (Sandbox Code Playgroud)

产生

zz = 1 + i + i**2 + e + e*i + e**2 + O(i**3) + O(e**3)
Run Code Online (Sandbox Code Playgroud)

这正是我想要的。所以要具体说明我的问题:有没有一种方法可以在一步中做到这一点,可以推广到任何 n?此外,我的解决方案丢失了表示混合项丢失的大 O 符号。这不是必需的,但会很好。

Wrz*_*mft 2

由于您有双重限制,因此您必须在所有对象中指定无穷小变量 (ei) Order,即使它们没有出现在第一个参数中。

\n\n

这样做的原因是,Order(expr)仅自动选择那些实际出现在 中的无穷小符号expr,因此,例如,O(e)仅适用于限制 e\xe2\x86\x920。\n现在,Order具有不同限制的对象不\xe2\x80\x99t充分混合,例如:

\n\n
O(e*i)+O(e) == O(e*i) != O(e)+O(e*i) == O(e) # True\n
Run Code Online (Sandbox Code Playgroud)\n\n

这会导致结果取决于加法顺序的混乱,这是一个很好的指示,表明这是应该避免的事情。\n这可以通过显式指定无穷小符号(作为 的加法参数Order)来避免,例如:

\n\n
O(e*i)+O(e,e,i) == O(e,e,i)+O(e*i) == O(e,e,i) # True\n
Run Code Online (Sandbox Code Playgroud)\n\n

我还没有\xe2\x80\x99t 找到一种方法来避免手动遍历e和的所有组合i,但这可以通过简单的迭代来完成:

\n\n
orders = sum( Order(e**a*i**(n-a),e,i) for a in range(n+1) )\nexpand(f*g+orders)\n# 1 + i + i**2 + e + e*i + e**2 + O(e**2*i, e, i) + O(e*i**2, e, i) + O(i**3, e, i) + O(e**3, e, i)\n
Run Code Online (Sandbox Code Playgroud)\n