符号简化,加上至少数和乘法运算
最近我有一个长了很多象征性的表达与算法的工作,如这一个符号简化,加上至少数和乘法运算
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 + ...这样的东西。我试图对表达式进行因式分解,但不幸的是表达式不是因式分解的。
如果任何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
似乎是一个好方法, –
感谢编辑〜 –
那么会是怎样的输出? –
我希望产品和加法的结合(例如,(e + n)(te + tp)+ te + n ...)。我们的目标是找到一种方法来计算所述数量,以尽可能少地涉及CPU操作。 –
您删除了'Python'标记,但在您的问题中仍然提到了'Python'。哪一个是错误的或不相关的? –