5 python performance sympy python-3.x polynomials
我正在 sympy 中处理非常大的多项式,我需要将它们以展开形式来查找某些项和系数。然而,这些多项式的展开需要很长时间。是否有一种快速的方法来展开多项式或以不同的方式获得某些项和系数?
我可以很好地找到展开多项式中的项,但展开多项式的时间是限制因素。
多项式非常大,例如:
(x + y + z + a + b + c) ** 24
我尝试过 sympy.expand() 和 Add.as_poly()。并发现 Add.as_poly() 速度更快,但仍然很慢。
my_poly = (x + y + z + a + b + c) ** 24
# expand using Add.as_poly()
my_poly.as_poly()
# this takes multiple minutes to execute
我希望能够搜索扩展多项式中的项以查找包含其他项的项:(
伪代码)是 x**3*y z a**2 包含在 500*x**5*y* 中*2*z*a**4*b*c**2
如果包含它,我想检索该项的系数。
我希望加快扩展速度,或者使用不同的方法在更短的时间内找到所需的术语。
无需实际扩展表达式即可确定多项式的系数。(a + b + c + x + y + z)**5例如,将有指数总和为 5 的项。您给出的示例必须是系数为 15 时的项(但系数将为 113513400)。
def mcoeff(*args):
    """return multinomial coefficient of a terms in the expansion of
    (x_1 + x_2 + x_3 + ... x_n)**m from the given exponents in the
    term of interest
    EXAMPLES
    ========
    >>> from sympy import expand
    >>> from sympy.abc import x, y, z
    >>> eq = (x + y + z)**4
    >>> eq.expand().coeff(x**2*y**2)
    6
    >>> mcoeff(2,2)
    6
    >>> 
    """
    from sympy import binomial
    from sympy.utilities.misc import as_int
    assert all(as_int(i)>=0 for i in args)
    if len(args) == 2:
        return binomial(sum(args), sorted(args)[0])
    if len(set(args)) == 1:
        return factorial(sum(args))/factorial(args[0])**len(args)
    def runsum(a):
        t = 0
        for i in a:
            t += i
            yield t
    return Mul(*[
        binomial(j, k) for j, k in zip(runsum(args), args)])
如果你想找到包含诸如F = x**3*yza**2......之类的符号的系数,那么这更难,但并非不可能。如果你在 ( 的展开式中寻找这些因子,(a + b + c + x + y + z)**8我选择了 8,那么就会有不止一项具有该因子;如果指数为 7,则只有一项这样的项,因为 3 + 1 + 1 + 2 = 总和项的指数 = 7) 那么该因子将与x,y,z,a,b,c该因子的任何其他因子一起出现,从而得到总指数 8。在这种情况下,这很容易,因为我们只需要添加 1,因此具有因子的潜在项F是
x*F, y*F, z*F, a*F, b*F, c*F。考虑指数元组会更容易,其中x,y,z,a,b,cinF为 (3,1,1,2,0,0):
x*F -> (4,1,1,2,0,0)
y*F -> (3,2,1,2,0,0)
z*F -> (3,1,2,2,0,0)
a*F -> (3,1,1,3,0,0)
b*F -> (3,1,1,2,1,0)
c*F -> (3,1,1,2,0,1)
其中每一个都有一个数字系数和一个符号残差(因子相乘F),因此展开式中的系数F将是这些系数的总和:
>>> from sympy.abc import x, y, z, a, b, c, e
>>> coeff = []; t = [3,1,1,2,0,0]
for i,f in enumerate((x, y, z, a, b, c)):
...     t[i] += 1
...     coeff.append(f*mcoeff(*t))
...     t[i] -= 1
>>> Add(*coeff)
1120*a + 3360*b + 3360*c + 840*x + 1680*y + 1680*z
>>> F = x**3*y*z*a**2
>>> ((x + y + z + a + b + c)**8).expand().subs(F, e).coeff(e)  # wait for it...
1120*a + 3360*b + 3360*c + 840*x + 1680*y + 1680*z
当您想要找到具有较小因数的项时,一切都会变得更加复杂,因为您必须将指数和不足(在本例中仅比 8 差 1)分配给所有符号,但想法是相同的。
(mcoeff取自此处并进行了一些修改)
| 归档时间: | 
 | 
| 查看次数: | 655 次 | 
| 最近记录: |