SymPy Laurent多项式因式分解

5
我认为这个问题肯定有一个简单的答案,但我搜索了很久也没有找到。例如:一个简单的劳伦多项式,如下所示: >> p = 2*y*x**2+4*y/x 通过分解得到 >> factor(p) 2*y*(x**3 + 2)/x 如何提取因子2*y/x?当表达式不是多项式时,是否有一种简单的方法来获取表达式中的公共因子?我尝试了很多次,但都没有找到令人满意的答案。因子必须存在于factor()的步骤中吧?请帮忙确认一下。

3
factor(p).args 返回乘积中的顶层项:(2, y, 1/x, x**3 + 2)。这是你要找的吗? - unutbu
是的!!非常感谢你... - Felix
@unutbu 不完全是因为 factor_list 仅适用于多项式本身,而 factor 对有理函数很聪明,并单独分解分子和分母。 - asmeurer
1个回答

3
如@unutbu所指出的,从这个问题中可以看到,factor_list以更易于使用的方式给出了多项式的因数。
不幸的是,SymPy实际上并没有处理劳伦特多项式(参见https://github.com/sympy/sympy/issues/5131)。对于高阶项,您可能无法得到预期结果。 SymPy所做的是看到p是有理函数,因此将分子和分母分别因式分解。
如果您也想这样做,可以使用以下内容:
n, d = fraction(cancel(p))
factor_list(n)
factor_list(d)

并且可以单独操作这些因子。

cancel 会确保没有重复项,否则 factor(p) 会自动产生重复。它还将表达式转换为有理数形式,以便 fraction 函数能够正常工作。如果这一步骤最终变得过慢,您还可以使用 p.as_numer_denom() 来跳过此步骤。

或者,您可能希望将 x1/x 视为多项式的不同生成器。以下是从上述问题中进行了更正的函数:

def aspoly1t(p, t, z=Symbol('z')):
    """
    Rewrite p, a polynomial in t and 1/t, as a polynomial in t and z=1/t
    """
    pa, pd = cancel(p).as_numer_denom()
    pa, pd = Poly(pa, t), Poly(pd, t)
    assert pd.is_monomial
    d = pd.degree(t)
    one_t_part = pa.slice(0, d + 1)
    t_part = pa - one_t_part
    t_part = t_part.to_field().quo(pd)
    one_t_part = Poly.from_list(reversed(one_t_part.rep.rep), *one_t_part.gens, domain=one_t_part.domain)
    one_t_part = one_t_part.replace(t, z) # z will be 1/t
    ans = t_part.as_poly(t, z) + one_t_part.as_poly(t, z)
    return ans

(有一天Poly将本地支持这一点Poly(p,x,1/x))然后你可以使用factor_list

>>> aspoly1t(p, x)
Poly(2*y*x**2 + 4*y*z, x, z, domain='ZZ[y]')
>>> factor_list(aspoly1t(p, x))
(2, [(Poly(y, x, y, z, domain='ZZ'), 1), (Poly(x**2 + 2*z, x, y, z, domain='ZZ'), 1)])

请注意,这里的因子并不相同,因此重要的是您如何解释和分解您的 Laurent 多项式。

谢谢,这似乎是一个更优雅的解决方案。目前,我将使用一个简单的修复:使用 factor.args 获取最大负幂的度数,并在评估从 all_coeffs(Poly(px)) 获得的多项式系数时记住这个“偏移量”,其中 px 现在是多项式部分。 - Felix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接