Eliminate mixed variables in the SymPy series extension

Consider the two SymPy eand character functions 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)

This will create

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

However, suppose that eand iare small, and we can neglect both terms, which are of the order of three or higher. Using the Sympys series toolkit or just adding the O-notation class Ordercan handle this:

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)

It looks great. However, mixed terms still leave me e**2 * i**2. Individual variables in these terms are less than the desired clipping, so SymPy saves them. However, mathematically small ² · small² = small⁴. Similarly, 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)

: SymPy n- , , (e ^ a) · (i ^ b), a + b > ?

: , .

z = expand(f*g + Order((e**2)*i) + Order(e*(i**2)))
zz = expand(z.removeO() + Order(e**3) + Order(i**3))

zz = 1 + i + i**2 + e + e*i + e**2 + O(i**3) + O(e**3)

. , : , n?. Big-O, , . , .

+4
2

, (e, i) Order, .

, Order(expr) , expr, , , , O(e) e → 0. Order , :

O(e*i)+O(e) == O(e*i) != O(e)+O(e*i) == O(e) # True

, , , . , ( Order), :

O(e*i)+O(e,e,i) == O(e,e,i)+O(e*i) == O(e,e,i) # True

e i , :

orders = sum( Order(e**a*i**(n-a),e,i) for a in range(n+1) )
expand(f*g+orders)
# 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)
+1

- :

>>> eq = expand(f*g)  # as you defined
>>> def total_degree(e):
...     x = Dummy()
...     free = e.free_symbols
...     if not free: return S.Zero
...     for f in free:
...         e = e.subs(f, x)
...     return degree(e)
>>> eq.replace(lambda x: total_degree(x) > 2, lambda x: S.Zero)
e**2 + e*i + e + i**2 + i + 1
+1

Source: https://habr.com/ru/post/1684676/


All Articles