2017-08-29 67 views
4

考慮SymPy符號的兩個功能ei刪除在SymPy級數展開混合變量項

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) 

這將產生

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 

然而,假設ei都是小和我們可以忽略三個或三個以上的術語。使用Sympy的一系列工具或簡單地增加一個O形符號Order類可以處理這個問題:

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) 

看起來不錯。但是,我仍然留有混合條款e**2 * i**2。這些術語中的單個變量小於期望的截止點,所以SymPy保留它們。但是,數學上小2·小2 =小4。同樣,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?另外,我的解決方案失去了表示混合條款丟失的大O符號。這不是必需的,但會很好。

回答

1

當你有一個雙重限制,您必須在所有Order對象同時指定無窮小變量(ei),即使它們不會出現在第一個參數。

這樣做的原因是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 

我還沒有找到一種方法,以避免通過ei手動所有組合去,但是這可以通過一個簡單的迭代來完成:

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