2017-02-22 61 views
1

最近我有一個長了很多象徵性的表達與算法的工作,如這一個符號簡化,加上至少數和乘法運算

upperside = ( e * e * n * p * tn * tn + 
      2 * e * e * n * p * tn * tp + 
       e * e * n * p * tp * tp + 
      2 * e * n * n * p * te * tn + 
      2 * e * n * n * p * te * tp + 
       N * e * n * n * tp * tp + 
      2 * e * n * p * p * te * tn + 
      2 * e * n * p * p * te * tp - 
      2 * N * e * n * p * tn * tp + 
       N * e * p * p * tn * tn + 
       n * n * n * p * te * te + 
      2 * n * n * p * p * te * te + 
       n * p * p * p * te * te) 

remformated

upperside = (  e * e * n   * p     * tn * tn   + 
      2  * e * e * n   * p     * tn  * tp  + 
        e * e * n   * p       * tp * tp + 
      2  * e  * n * n  * p   * te  * tn    + 
      2  * e  * n * n  * p   * te    * tp  + 
       N * e  * n * n         * tp * tp + 
      2  * e  * n   * p * p  * te  * tn    + 
      2  * e  * n   * p * p  * te    * tp  - 
      2 * N * e  * n   * p     * tn  * tp  + 
       N * e     * p * p    * tn * tn   + 
          n * n * n * p   * te * te     + 
      2    * n * n  * p * p  * te * te     + 
          n   * p * p * p * te * te) 

這些表達式推導從簡化後的MATLAB符號例程開始。在這種情況下很明顯,例如通過合併因子來簡化代數表達式是不可能的。但是,似乎很可能簡化該表達式,以便大大減少實際的操作次數。不幸的是,我無法在MATLAB或Python中找到這樣的選項。

任何幫助表示讚賞。

編輯 目標是最大限度地減少CPU需要對這些表達式執行的操作。由於操作只涉及加法和乘法,所以我希望得到像(e + tn)*(te + tp)+ n + ...這樣的東西。我試圖對錶達式進行因式分解,但不幸的是表達式不是因式分解的。

+0

那麼會是怎樣的輸出? –

+0

我希望產品和加法的結合(例如,(e + n)(te + tp)+ te + n ...)。我們的目標是找到一種方法來計算所述數量,以儘可能少地涉及CPU操作。 –

+1

您刪除了'Python'標記,但在您的問題中仍然提到了'Python'。哪一個是錯誤的或不相關的? –

回答

3

如果任何Python包可以提供幫助,它很可能是Sympy

from sympy import init_printing, symbols, simplify, collect, factor 

e,n,p,tn,te,tp,N = symbols("e,n,p,tn,te,tp,N") 

upperside = (e * e * n * p * tn * tn + 
     2 * e * e * n * p * tn * tp + 
      e * e * n * p * tp * tp + 
     2 * e * n * n * p * te * tn + 
     2 * e * n * n * p * te * tp + 
      N * e * n * n * tp * tp + 
     2 * e * n * p * p * te * tn + 
     2 * e * n * p * p * te * tp - 
     2 * N * e * n * p * tn * tp + 
      N * e * p * p * tn * tn + 
      n * n * n * p * te * te + 
     2 * n * n * p * p * te * te + 
      n * p * p * p * te * te) 

print collect(upperside, e*n) 

它輸出:

N*e*p**2*tn**2 + 
e**2*n*(p*tn**2 + 2*p*tn*tp + p*tp**2) + 
e*n**2*(N*tp**2 + 2*p*te*tn + 2*p*te*tp) + 
e*n*(-2*N*p*tn*tp + 2*p**2*te*tn + 2*p**2*te*tp) + 
n**3*p*te**2 + 
2*n**2*p**2*te**2 + 
n*p**3*te**2 

在此page描述的所有方法中,collect看起來最有前途的。

這裏有一個快速和骯髒的方式來遍歷符號的所有組合,並顯示找到最短的表達:

from sympy import init_printing, symbols, collect, pprint 
import itertools 

init_printing() 

e,n,p,tn,te,tp,big_n = symbols("e,n,p,tn,te,tp,big_n") 

upperside = (e * e * n * p * tn * tn + 2 * e * e * n * p * tn * tp + 
       e * e * n * p * tp * tp + 2 * e * n * n * p * te * tn + 2 * e * n * n * p * te * tp + 
       big_n * e * n * n * tp * tp + 2 * e * n * p * p * te * tn + 
       2 * e * n * p * p * te * tp - 2 * big_n * e * n * p * tn * tp + big_n * e * p * p * tn * tn + 
       n * n * n * p * te * te + 2 * n * n * p * p * te * te + n * p * p * p * te * te) 

my_symbols = [e, n, p, tn, te, tp, big_n] 

min_length = float('inf') 

for i in range(len(my_symbols)): 
    for symbol_subsets in itertools.combinations(my_symbols, i+1): 
     collect_by = '*'.join(str(symbol) for symbol in symbol_subsets) 
     expression = collect(upperside, collect_by) 
     length = len(str(expression)) 
     if length < min_length: 
      min_length = length 
      print "With '%s' :" % collect_by 
      pprint(expression) 
      print 

它輸出:

With 'e' : 
e**2*(n*p*tn**2 + 2*n*p*tn*tp + n*p*tp**2) + e*(big_n*n**2*tp**2 - 2*big_n*n*p*tn*tp + big_n*p**2*tn**2 + 2*n**2*p*te*tn + 2*n**2*p*te*tp + 2*n*p**2*te*tn + 2*n*p**2*te*tp) + n**3*p*te**2 + 2*n**2*p**2*te**2 + n*p**3*te**2 

With 'n' : 
big_n*e*p**2*tn**2 + n**3*p*te**2 + n**2*(big_n*e*tp**2 + 2*e*p*te*tn + 2*e*p*te*tp + 2*p**2*te**2) + n*(-2*big_n*e*p*tn*tp + e**2*p*tn**2 + 2*e**2*p*tn*tp + e**2*p*tp**2 + 2*e*p**2*te*tn + 2*e*p**2*te*tp + p**3*te**2) 

With 'e*n' : 
big_n*e*p**2*tn**2 + e**2*n*(p*tn**2 + 2*p*tn*tp + p*tp**2) + e*n**2*(big_n*tp**2 + 2*p*te*tn + 2*p*te*tp) + e*n*(-2*big_n*p*tn*tp + 2*p**2*te*tn + 2*p**2*te*tp) + n**3*p*te**2 + 2*n**2*p**2*te**2 + n*p**3*te**2 

With 'e*n*p' : 
big_n*e*n**2*tp**2 - 2*big_n*e*n*p*tn*tp + big_n*e*p**2*tn**2 + e**2*n*p*(tn**2 + 2*tn*tp + tp**2) + e*n**2*p*(2*te*tn + 2*te*tp) + e*n*p**2*(2*te*tn + 2*te*tp) + n**3*p*te**2 + 2*n**2*p**2*te**2 + n*p**3*te**2 
+0

似乎是一個好方法, –

+0

感謝編輯〜 –