给定公式,我想将其转换为 Poly 对象并最小化生成器的大小。例如,如果我的公式是x^2+x+sqrt(x)
,我希望只有sqrt(x)
在生成器中。但在我的大部分尝试中,生成器都包含x
和sqrt(x)
。
from sympy import *
print('first attempt:',Poly('x^2+x+sqrt(x)'))
x=Symbol('x', positive=True)
print('second attempt:',Poly(x**2+x+sqrt(x)))
print('third attempt:',str(Poly({1:1,2:1,4:1},gens=S('sqrt(x)'))))
first attempt: Poly(x**2 + x + (sqrt(x)), x, sqrt(x), domain='ZZ')
second attempt: Poly(x**2 + x + (sqrt(x)), x, sqrt(x), domain='ZZ')
third attempt: Poly((sqrt(x))**4 + (sqrt(x))**2 + (sqrt(x)), sqrt(x), domain='ZZ')
只有第三种方法是成功的,但是它的代码很难自动化(我想转换它,因为我想轻松提取系数和幂,所以它什么也没给我)。有更好的方法吗?
编辑
基于 smichr 响应,我创建了一个函数来减小生成器的大小。
def _powr(formula):
if formula.func==Pow:
return formula.args
else:
return [formula,S('1')]
def reducegens(formula):
pol=Poly(formula)
newgens={}
ind={}
for gen in pol.gens:
base,pw=_powr(gen)
coef,_=pw.as_coeff_mul()
ml=pw/coef
if base**ml in newgens:
newgens[base**ml]=gcd(newgens[base**ml],coef)
else:
newgens[base**ml]=coef
ind[base**ml]=S('tmp'+str(len(ind)))
for gen in pol.gens:
base,pw=_powr(gen)
coef,_=pw.as_coeff_mul()
ml=pw/coef
pol=pol.replace(gen,ind[base**ml]**(coef/newgens[base**ml]))
newpol=Poly(pol.as_expr())
for gen in newgens:
newpol=newpol.replace(ind[gen],gen**newgens[gen])
return newpol
我已经在几个例子上试过了,还不错,但还有改进的余地。
print(reducegens(S('x^2+x+sqrt(x)')))
print(reducegens(S('x**2+y**2+x**(1/2)+x**(1/3)')))
print(reducegens(S('sqrt(x)+sqrt(z)+sqrt(x)*sqrt(z)')))
print(reducegens(S('sqrt(2)+sqrt(3)+sqrt(6)')))
Poly((sqrt(x))**4 + (sqrt(x))**2 + (sqrt(x)), sqrt(x), domain='ZZ')
Poly((x**(1/6))**12 + (x**(1/6))**3 + (x**(1/6))**2 + y**2, x**(1/6), y, domain='ZZ')
Poly((sqrt(x))*(sqrt(z)) + (sqrt(x)) + (sqrt(z)), sqrt(x), sqrt(z), domain='ZZ')
Poly((sqrt(2)) + (sqrt(3)) + (sqrt(6)), sqrt(2), sqrt(3), sqrt(6), domain='ZZ')
前三个示例是可以的,但最好将 sqrt(6) 表示为 sqrt(2)*sqrt(3) 而不是另一个生成器的元素。