def test_zzx_factor():
    f = [1, 0, 0, 1, 1]

    for i in xrange(0, 20):
        assert zzx_factor(f) == (1, [(f, 1)])

    assert zzx_factor([2,4,2]) == \
        (2, [([1, 1], 2)])

    assert zzx_factor([1,-6,11,-6]) == \
        (1, [([1,-3], 1),
             ([1,-2], 1),
             ([1,-1], 1)])

    assert zzx_factor([-1,0,0,0,1,0,0]) == \
        (-1, [([1,-1], 1),
              ([1, 1], 1),
              ([1, 0], 2),
              ([1, 0, 1], 1)])

    assert zzx_factor(zzx_from_dict({10:1, 0:-1})) == \
        (1, [([1,-1], 1),
             ([1, 1], 1),
             ([1,-1, 1,-1, 1], 1),
             ([1, 1, 1, 1, 1], 1)])
def test_zzx_factor():
    f = [1,0,0,1,1]

    for i in xrange(0, 20):
        assert zzx_factor(f) == (1, [(f, 1)])

    assert zzx_factor([2,4,2]) == \
        (2, [([1, 1], 2)])

    assert zzx_factor([1,-6,11,-6]) == \
        (1, [([1,-3], 1),
             ([1,-2], 1),
             ([1,-1], 1)])

    assert zzx_factor([-1,0,0,0,1,0,0]) == \
        (-1, [([1,-1], 1),
              ([1, 1], 1),
              ([1, 0], 2),
              ([1, 0, 1], 1)])

    assert zzx_factor(zzx_from_dict({10:1, 0:-1})) == \
        (1, [([1,-1], 1),
             ([1, 1], 1),
             ([1,-1, 1,-1, 1], 1),
             ([1, 1, 1, 1, 1], 1)])
Beispiel #3
0
def poly_factors(f, *symbols, **flags):
    """Factor polynomials over rationals.

       >>> from sympy import *
       >>> x, y = symbols("x y")

       >>> poly_factors(x**2 - y**2, x, y)
       (1, [(Poly(x - y, x, y), 1), (Poly(x + y, x, y), 1)])

    """
    if not isinstance(f, Poly):
        f = Poly(f, *symbols)
    elif symbols:
        raise SymbolsError("Redundant symbols were given")

    denom, f = f.as_integer()

    if f.is_univariate:
        coeffs = map(int, f.iter_all_coeffs())
        content, factors = zzx_factor(coeffs)

        for i in xrange(len(factors)):
            factor, k = factors[i]
            n = zzx_degree(factor)

            terms = {}

            for j, coeff in enumerate(factor):
                if coeff != 0:
                    terms[(n - j, )] = Integer(coeff)

            factors[i] = Poly(terms, *f.symbols), k
    else:
        content, factors = kronecker_mv(f, **flags)

    return Rational(content, denom), factors
Beispiel #4
0
def poly_factors(f, *symbols, **flags):
    """Factor polynomials over rationals.

       >>> from sympy import *
       >>> x, y = symbols("x y")

       >>> poly_factors(x**2 - y**2, x, y)
       (1, [(Poly(x - y, x, y), 1), (Poly(x + y, x, y), 1)])

    """
    if not isinstance(f, Poly):
        f = Poly(f, *symbols)
    elif symbols:
        raise SymbolsError("Redundant symbols were given")

    denom, f = f.as_integer()

    if f.is_univariate:
        coeffs = map(int, f.iter_all_coeffs())
        content, factors = zzx_factor(coeffs)

        for i in xrange(len(factors)):
            factor, k = factors[i]
            n = zzx_degree(factor)

            terms = {}

            for j, coeff in enumerate(factor):
                if coeff != 0:
                    terms[(n-j,)] = Integer(coeff)

            factors[i] = Poly(terms, *f.symbols), k
    else:
        content, factors = kronecker_mv(f, **flags)

    return Rational(content, denom), factors
def test_zzx_factor():
    assert zzx_factor([ ]) == (0, [])
    assert zzx_factor([7]) == (7, [])

    f = [1,0,0,1,1]

    for i in xrange(0, 20):
        assert zzx_factor(f) == (1, [(f, 1)])

    assert zzx_factor([2,4]) == \
        (2, [([1, 2], 1)])

    assert zzx_factor([1,2,2]) == \
        (1, [([1,2,2], 1)])

    assert zzx_factor([18,12,2]) == \
        (2, [([3, 1], 2)])

    assert zzx_factor([-9,0,1]) == \
        (-1, [([3,-1], 1),
              ([3, 1], 1)])

    assert zzx_factor_sqf([-9,0,1]) == \
        (-1, [[3,-1],
              [3, 1]])

    assert zzx_factor([1,-6,11,-6]) == \
        (1, [([1,-3], 1),
             ([1,-2], 1),
             ([1,-1], 1)])

    assert zzx_factor_sqf([1,-6,11,-6]) == \
        (1, [[1,-3],
             [1,-2],
             [1,-1]])

    assert zzx_factor([-1,0,0,0,1,0,0]) == \
        (-1, [([1,-1], 1),
              ([1, 1], 1),
              ([1, 0], 2),
              ([1, 0, 1], 1)])

    f = [1080, 5184, 2099, 744, 2736, -648, 129, 0, -324]

    assert zzx_factor(f) == \
        (1, [([5, 24, 9, 0, 12], 1),
             ([216, 0, 31, 0, -27], 1)])

    f = [-29802322387695312500000000000000000000,
          0, 0, 0, 0,
          2980232238769531250000000000000000,
          0, 0, 0, 0,
          1743435859680175781250000000000,
          0, 0, 0, 0,
          114142894744873046875000000,
          0, 0, 0, 0,
          -210106372833251953125,
          0, 0, 0, 0,
          95367431640625]

    assert zzx_factor(f) == \
        (-95367431640625, [([5, -1], 1),
                           ([100, 10, -1], 2),
                           ([625, 125, 25, 5, 1], 1),
                           ([10000, -3000, 400, -20, 1], 2),
                           ([10000,  2000, 400,  30, 1], 2)])

    f = zzx_from_dict({10:1, 0:-1})

    F_0 = zzx_factor(f, cyclotomic=True)
    F_1 = zzx_factor(f, cyclotomic=False)

    assert F_0 == F_1 == \
        (1, [([1,-1], 1),
             ([1, 1], 1),
             ([1,-1, 1,-1, 1], 1),
             ([1, 1, 1, 1, 1], 1)])

    f = zzx_from_dict({10:1, 0:1})

    F_0 = zzx_factor(f, cyclotomic=True)
    F_1 = zzx_factor(f, cyclotomic=False)

    assert F_0 == F_1 == \
        (1, [([1, 0, 1], 1),
             ([1, 0, -1, 0, 1, 0, -1, 0, 1], 1)])
Beispiel #6
0
def kronecker_mv(f, **flags):
    """Kronecker method for Z[X] polynomials.

       NOTE: This function is very slow even on small input.
             Use debug=True flag to see its progress, if any.
    """
    symbols = f.symbols

    def mv_int_div(f, g):
        q = Poly((), *symbols)
        r = Poly((), *symbols)

        while not f.is_zero:
            lc_f, lc_g = f.LC, g.LC

            dv = lc_f % lc_g
            cf = lc_f / lc_g

            monom = monomial_div(f.LM, g.LM)

            if dv == 0 and monom is not None:
                q = q.add_term(cf, monom)
                f -= g.mul_term(cf, monom)
            else:
                r = r.add_term(*f.LT)
                f = f.kill_lead_term()

        return q, r

    def combinations(lisp, m):
        def recursion(fa, lisp, m):
            if m == 0:
                yield fa
            else:
                for i, fa2 in enumerate(lisp[0:len(lisp) + 1 - m]):
                    for el in recursion(zzx_mul(fa2, fa), list(lisp[i + 1:]),
                                        m - 1):
                        yield el

        for i, fa in enumerate(lisp[0:len(lisp) + 1 - m]):
            for el in recursion(fa, list(lisp[i + 1:]), m - 1):
                yield el

    debug = flags.get('debug', False)

    cont, f = f.as_primitive()
    N = len(symbols)

    max_exp = {}

    for v in symbols:
        max_exp[v] = 0

    for coeff, monom in f.iter_terms():
        for v, exp in zip(symbols, monom):
            if exp > max_exp[v]:
                max_exp[v] = exp

    symbols = sorted(symbols, reverse=True, key=lambda v: max_exp[v])

    f = Poly(f, *symbols)

    d = max_exp[symbols[0]] + 1

    terms, exps = {}, []

    for i in xrange(0, len(symbols)):
        exps.append(d**i)

    for coeff, monom in f.iter_terms():
        exp = 0

        for i, expi in enumerate(monom):
            exp += expi * exps[i]

        terms[exp] = int(coeff)

    g, factors = zzx_from_dict(terms), []

    try:
        for ff, k in zzx_factor(g)[1]:
            for i in xrange(0, k):
                factors.append(ff)
    except OverflowError:
        raise PolynomialError(
            "input too large for multivariate Kronecker method")

    const, result, tested = 1, [], []

    if debug: print "KRONECKER-MV: Z[x] #factors = %i ..." % (len(factors))

    for k in range(1, len(factors) // 2 + 1):
        for h in combinations(factors, k):
            if h in tested:
                continue

            n = zzx_degree(h)
            terms = {}

            for coeff in h:
                if not coeff:
                    n = n - 1
                    continue
                else:
                    coeff = Integer(coeff)

                y_deg, n = n, n - 1
                monom = [0] * N

                for i in xrange(N):
                    v_deg = y_deg % d
                    y_deg = (y_deg - v_deg) // d
                    monom[i] = v_deg

                monom = tuple(monom)

                if terms.has_key(monom):
                    terms[monom] += coeff
                else:
                    terms[monom] = coeff

            cand = Poly(terms, *symbols)

            if cand.is_one:
                continue

            if cand.LC.is_negative:
                cand = -cand

            q, r = mv_int_div(f, cand)

            if r.is_zero:
                if debug: print "KRONECKER-MV: Z[X] factor found %s" % cand
                result.append(cand)
                f = q
            else:
                tested.append(h)

            if f.is_constant:
                const, f = f.LC, Poly(1, *symbols)
                break

        if f.is_one:
            break

    if not f.is_one:
        if debug: print "KRONECKER-MV: Z[X] factor found %s" % f
        result.append(f)

    factors = {}

    for ff in result:
        if factors.has_key(ff):
            factors[ff] += 1
        else:
            factors[ff] = 1

    return cont * const, sorted(factors.items())
Beispiel #7
0
def test_zzx_factor():
    assert zzx_factor([]) == (0, [])
    assert zzx_factor([7]) == (7, [])

    f = [1, 0, 0, 1, 1]

    for i in xrange(0, 20):
        assert zzx_factor(f) == (1, [(f, 1)])

    assert zzx_factor([2,4]) == \
        (2, [([1, 2], 1)])

    assert zzx_factor([1,2,2]) == \
        (1, [([1,2,2], 1)])

    assert zzx_factor([18,12,2]) == \
        (2, [([3, 1], 2)])

    assert zzx_factor([-9,0,1]) == \
        (-1, [([3,-1], 1),
              ([3, 1], 1)])

    assert zzx_factor_sqf([-9,0,1]) == \
        (-1, [[3,-1],
              [3, 1]])

    assert zzx_factor([1,-6,11,-6]) == \
        (1, [([1,-3], 1),
             ([1,-2], 1),
             ([1,-1], 1)])

    assert zzx_factor_sqf([1,-6,11,-6]) == \
        (1, [[1,-3],
             [1,-2],
             [1,-1]])

    assert zzx_factor([-1,0,0,0,1,0,0]) == \
        (-1, [([1,-1], 1),
              ([1, 1], 1),
              ([1, 0], 2),
              ([1, 0, 1], 1)])

    f = [1080, 5184, 2099, 744, 2736, -648, 129, 0, -324]

    assert zzx_factor(f) == \
        (1, [([5, 24, 9, 0, 12], 1),
             ([216, 0, 31, 0, -27], 1)])

    f = [
        -29802322387695312500000000000000000000, 0, 0, 0, 0,
        2980232238769531250000000000000000, 0, 0, 0, 0,
        1743435859680175781250000000000, 0, 0, 0, 0,
        114142894744873046875000000, 0, 0, 0, 0, -210106372833251953125, 0, 0,
        0, 0, 95367431640625
    ]

    assert zzx_factor(f) == \
        (-95367431640625, [([5, -1], 1),
                           ([100, 10, -1], 2),
                           ([625, 125, 25, 5, 1], 1),
                           ([10000, -3000, 400, -20, 1], 2),
                           ([10000,  2000, 400,  30, 1], 2)])

    f = zzx_from_dict({10: 1, 0: -1})

    F_0 = zzx_factor(f, cyclotomic=True)
    F_1 = zzx_factor(f, cyclotomic=False)

    assert F_0 == F_1 == \
        (1, [([1,-1], 1),
             ([1, 1], 1),
             ([1,-1, 1,-1, 1], 1),
             ([1, 1, 1, 1, 1], 1)])

    f = zzx_from_dict({10: 1, 0: 1})

    F_0 = zzx_factor(f, cyclotomic=True)
    F_1 = zzx_factor(f, cyclotomic=False)

    assert F_0 == F_1 == \
        (1, [([1, 0, 1], 1),
             ([1, 0, -1, 0, 1, 0, -1, 0, 1], 1)])
Beispiel #8
0
def kronecker_mv(f, **flags):
    """Kronecker method for Z[X] polynomials.

       NOTE: This function is very slow even on small input.
             Use debug=True flag to see its progress, if any.
    """
    symbols = f.symbols

    def mv_int_div(f, g):
        q = Poly((), *symbols)
        r = Poly((), *symbols)

        while not f.is_zero:
            lc_f, lc_g = f.LC, g.LC

            dv = lc_f % lc_g
            cf = lc_f / lc_g

            monom = monomial_div(f.LM, g.LM)

            if dv == 0 and monom is not None:
                q  = q.add_term(cf, monom)
                f -= g.mul_term(cf, monom)
            else:
                r = r.add_term(*f.LT)
                f = f.kill_lead_term()

        return q, r

    def combinations(lisp, m):
        def recursion(fa, lisp, m):
            if m == 0:
                 yield fa
            else:
                for i, fa2 in enumerate(lisp[0 : len(lisp) + 1 - m]):
                    for el in recursion(zzx_mul(fa2, fa), list(lisp[i + 1:]), m - 1):
                        yield el

        for i, fa in enumerate(lisp[0 : len(lisp) + 1 - m]):
            for el in recursion(fa, list(lisp[i + 1:]), m - 1):
                yield el

    debug = flags.get('debug', False)

    cont, f = f.as_primitive()
    N = len(symbols)

    max_exp = {}

    for v in symbols:
        max_exp[v] = 0

    for coeff, monom in f.iter_terms():
        for v, exp in zip(symbols, monom):
            if exp > max_exp[v]:
                max_exp[v] = exp

    symbols = sorted(symbols, reverse=True,
        key=lambda v: max_exp[v])

    f = Poly(f, *symbols)

    d = max_exp[symbols[0]] + 1

    terms, exps = {}, []

    for i in xrange(0, len(symbols)):
        exps.append(d**i)

    for coeff, monom in f.iter_terms():
        exp = 0

        for i, expi in enumerate(monom):
            exp += expi * exps[i]

        terms[exp] = int(coeff)

    g, factors = zzx_from_dict(terms), []

    try:
        for ff, k in zzx_factor(g)[1]:
            for i in xrange(0, k):
                factors.append(ff)
    except OverflowError:
        raise PolynomialError("input too large for multivariate Kronecker method")

    const, result, tested = 1, [], []

    if debug: print "KRONECKER-MV: Z[x] #factors = %i ..." % (len(factors))

    for k in range(1, len(factors)//2 + 1):
        for h in combinations(factors, k):
            if h in tested:
                continue

            n = zzx_degree(h)
            terms = {}

            for coeff in h:
                if not coeff:
                    n = n-1
                    continue
                else:
                    coeff = Integer(coeff)

                y_deg, n = n, n-1
                monom = [0] * N

                for i in xrange(N):
                    v_deg =  y_deg % d
                    y_deg = (y_deg - v_deg) // d
                    monom[i] = v_deg

                monom = tuple(monom)

                if terms.has_key(monom):
                    terms[monom] += coeff
                else:
                    terms[monom] = coeff

            cand = Poly(terms, *symbols)

            if cand.is_one:
                continue

            if cand.LC.is_negative:
                cand = -cand;

            q, r = mv_int_div(f, cand)

            if r.is_zero:
                if debug: print "KRONECKER-MV: Z[X] factor found %s" % cand
                result.append(cand)
                f = q
            else:
                tested.append(h)

            if f.is_constant:
                const, f = f.LC, Poly(1, *symbols)
                break

        if f.is_one:
            break

    if not f.is_one:
        if debug: print "KRONECKER-MV: Z[X] factor found %s" % f
        result.append(f)

    factors = {}

    for ff in result:
        if factors.has_key(ff):
            factors[ff] += 1
        else:
            factors[ff] = 1

    return cont*const, sorted(factors.items())