Пример #1
0
def is_rewritable_or_comparable(sign, num, B):
    """
    Check if a labeled polynomial is redundant by checking if its
    signature and number imply rewritability or comparability.

    (sign, num) is comparable if there exists a labeled polynomial
    h in B, such that sign[1] (the index) is less than Sign(h)[1]
    and sign[0] is divisible by the leading monomial of h.

    (sign, num) is rewritable if there exists a labeled polynomial
    h in B, such thatsign[1] is equal to Sign(h)[1], num < Num(h)
    and sign[0] is divisible by Sign(h)[0].
    """
    for h in B:
        # comparable
        if sign[1] < Sign(h)[1]:
            if monomial_divides(Polyn(h).LM, sign[0]):
                return True

        # rewritable
        if sign[1] == Sign(h)[1]:
            if num < Num(h):
                if monomial_divides(Sign(h)[0], sign[0]):
                    return True
    return False
Пример #2
0
def red_groebner(G, ring):
    """
    Compute reduced Groebner basis, from BeckerWeispfenning93, p. 216

    Selects a subset of generators, that already generate the ideal
    and computes a reduced Groebner basis for them.
    """
    def reduction(P):
        """
        The actual reduction algorithm.
        """
        Q = []
        for i, p in enumerate(P):
            h = p.rem(P[:i] + P[i + 1:])
            if h:
                Q.append(h)

        return [p.monic() for p in Q]

    F = G
    H = []

    while F:
        f0 = F.pop()

        if not any(monomial_divides(f.LM, f0.LM) for f in F + H):
            H.append(f0)

    # Becker, Weispfenning, p. 217: H is Groebner basis of the ideal generated by G.
    return reduction(H)
Пример #3
0
def f5_reduce(f, B):
    """
    F5-reduce a labeled polynomial f by B.

    Continously searches for non-zero labeled polynomial h in B, such
    that the leading term lt_h of h divides the leading term lt_f of
    f and Sign(lt_h * h) < Sign(f). If such a labeled polynomial h is
    found, f gets replaced by f - lt_f / lt_h * h. If no such h can be
    found or f is 0, f is no further F5-reducible and f gets returned.

    A polynomial that is reducible in the usual sense need not be
    F5-reducible, e.g.:

    >>> from sympy.polys.groebnertools import lbp, sig, f5_reduce, Polyn
    >>> from sympy.polys.monomialtools import lex
    >>> from sympy.polys import ring, QQ

    >>> R, x,y,z = ring("x,y,z", QQ)

    >>> f = lbp(sig((1, 1, 1), 4), x, 3)
    >>> g = lbp(sig((0, 0, 0), 2), x, 2)

    >>> Polyn(f).rem([Polyn(g)])
    0
    >>> f5_reduce(f, [g])
    (((1, 1, 1), 4), x, 3)

    """
    order = Polyn(f).ring.order
    domain = Polyn(f).ring.domain

    if not Polyn(f):
        return f

    while True:
        g = f

        for h in B:
            if Polyn(h):
                if monomial_divides(Polyn(h).LM, Polyn(f).LM):
                    t = term_div(Polyn(f).LT, Polyn(h).LT, domain)
                    if sig_cmp(sig_mult(Sign(h), t[0]), Sign(f), order) < 0:
                        # The following check need not be done and is in general slower than without.
                        #if not is_rewritable_or_comparable(Sign(gp), Num(gp), B):
                        hp = lbp_mul_term(h, t)
                        f = lbp_sub(f, hp)
                        break

        if g == f or not Polyn(f):
            return f
Пример #4
0
 def prune(P, S, h):
     """
     Prune the pair-set by applying the chain criterion
     [SCA, remark 2.5.11].
     """
     remove = set()
     for (a, b, c) in permutations(S, 3):
         A = sdm_LM(a)
         B = sdm_LM(b)
         C = sdm_LM(c)
         if len(set([A[0], B[0], C[0]])) != 1 or not h in [a, b, c]:
             continue
         if monomial_divides(B[1:], monomial_lcm(A[1:], C[1:])):
             remove.add((tuple(a), tuple(c)))
     return [(f, g) for (f, g) in P if (h not in [f, g]) or \
                 ((tuple(f), tuple(g)) not in remove and \
                  (tuple(g), tuple(f)) not in remove)]
Пример #5
0
def is_minimal(G, ring):
    """
    Checks if G is a minimal Groebner basis.
    """
    order = ring.order
    domain = ring.domain

    G.sort(key=lambda g: order(g.LM))

    for i, g in enumerate(G):
        if g.LC != domain.one:
            return False

        for h in G[:i] + G[i + 1:]:
            if monomial_divides(h.LM, g.LM):
                return False

    return True
Пример #6
0
 def prune(P, S, h):
     """
     Prune the pair-set by applying the chain criterion
     [SCA, remark 2.5.11].
     """
     remove = set()
     retain = set()
     for (a, b, c) in permutations(S, 3):
         A = sdm_LM(a)
         B = sdm_LM(b)
         C = sdm_LM(c)
         if len(set([A[0], B[0], C[0]])) != 1 or not h in [a, b, c] or \
            any(tuple(x) in retain for x in [a, b, c]):
             continue
         if monomial_divides(B[1:], monomial_lcm(A[1:], C[1:])):
             remove.add((tuple(a), tuple(c)))
             retain.update([tuple(b), tuple(c), tuple(a)])
     return [(f, g) for (f, g) in P if (h not in [f, g]) or \
                 ((tuple(f), tuple(g)) not in remove and \
                  (tuple(g), tuple(f)) not in remove)]
Пример #7
0
def test_monomial_divides():
    assert monomial_divides((1, 2, 3), (4, 5, 6)) is True
    assert monomial_divides((1, 2, 3), (0, 5, 6)) is False
Пример #8
0
def test_monomial_divides():
    assert monomial_divides((1, 2, 3), (4, 5, 6)) is True
    assert monomial_divides((1, 2, 3), (0, 5, 6)) is False