Пример #1
0
def f5_reduce(f, B, u, O, K):
    """
    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 (sdp_rem)
    need not be F5-reducible, e.g.:

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

    >>> f = lbp(sig((1, 1, 1), 4), [((1, 0, 0), QQ(1))], 3)
    >>> g = lbp(sig((0, 0, 0), 2), [((1, 0, 0), QQ(1))], 2)

    >>> sdp_rem(Polyn(f), [Polyn(g)], 2, lex, QQ)
    []
    >>> f5_reduce(f, [g], 2, lex, QQ)
    (((1, 1, 1), 4), [((1, 0, 0), 1/1)], 3)

    """
    if Polyn(f) == []:
        return f

    if K.has_Field:
        term_div = _term_ff_div
    else:
        term_div = _term_rr_div

    while True:
        g = f

        for h in B:
            if Polyn(h) != []:
                if monomial_divides(sdp_LM(Polyn(f), u), sdp_LM(Polyn(h), u)):
                    t = term_div(
                        sdp_LT(Polyn(f), u, K), sdp_LT(Polyn(h), u, K), K)
                    if sig_cmp(sig_mult(Sign(h), t[0]), Sign(f), O) < 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, u, K):
                        hp = lbp_mul_term(h, t, u, O, K)
                        f = lbp_sub(f, hp, u, O, K)
                        break

        if g == f or Polyn(f) == []:
            return f
Пример #2
0
def f5_reduce(f, B, u, O, K):
    """
    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 (sdp_rem)
    need not be F5-reducible, e.g.:

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

    >>> f = lbp(sig((1, 1, 1), 4), [((1, 0, 0), QQ(1))], 3)
    >>> g = lbp(sig((0, 0, 0), 2), [((1, 0, 0), QQ(1))], 2)

    >>> sdp_rem(Polyn(f), [Polyn(g)], 2, lex, QQ)
    []
    >>> f5_reduce(f, [g], 2, lex, QQ)
    (((1, 1, 1), 4), [((1, 0, 0), 1/1)], 3)

    """
    if Polyn(f) == []:
        return f

    if K.has_Field:
        term_div = _term_ff_div
    else:
        term_div = _term_rr_div

    while True:
        g = f

        for h in B:
            if Polyn(h) != []:
                if monomial_divides(sdp_LM(Polyn(f), u), sdp_LM(Polyn(h), u)):
                    t = term_div(sdp_LT(Polyn(f), u, K),
                                 sdp_LT(Polyn(h), u, K), K)
                    if sig_cmp(sig_mult(Sign(h), t[0]), Sign(f), O) < 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, u, K):
                        hp = lbp_mul_term(h, t, u, O, K)
                        f = lbp_sub(f, hp, u, O, K)
                        break

        if g == f or Polyn(f) == []:
            return f
Пример #3
0
def critical_pair(f, g, u, O, K):
    """
    Compute the critical pair corresponding to two labeled polynomials.

    A critical pair is a tuple (um, f, vm, g), where um and vm are
    terms such that um * f - vm * g is the S-polynomial of f and g (so,
    wlog assume um * f > vm * g).
    For performance sake, a critical pair is represented as a tuple
    (Sign(um * f), um, f, Sign(vm * g), vm, g), since um * f creates
    a new, relatively expensive object in memory, whereas Sign(um *
    f) and um are lightweight and f (in the tuple) is a reference to
    an already existing object in memory.
    """
    ltf = sdp_LT(Polyn(f), u, K)
    ltg = sdp_LT(Polyn(g), u, K)
    lt = (monomial_lcm(ltf[0], ltg[0]), K.one)

    if K.has_Field:
        term_div = _term_ff_div
    else:
        term_div = _term_rr_div

    um = term_div(lt, ltf, K)
    vm = term_div(lt, ltg, K)

    # The full information is not needed (now), so only the product
    # with the leading term is considered:
    fr = lbp_mul_term(lbp(Sign(f), [sdp_LT(Polyn(f), u, K)], Num(f)), um, u, O,
                      K)
    gr = lbp_mul_term(lbp(Sign(g), [sdp_LT(Polyn(g), u, K)], Num(g)), vm, u, O,
                      K)

    # return in proper order, such that the S-polynomial is just
    # u_first * f_first - u_second * f_second:
    if lbp_cmp(fr, gr, O) == -1:
        return (Sign(gr), vm, g, Sign(fr), um, f)
    else:
        return (Sign(fr), um, f, Sign(gr), vm, g)
Пример #4
0
def critical_pair(f, g, u, O, K):
    """
    Compute the critical pair corresponding to two labeled polynomials.

    A critical pair is a tuple (um, f, vm, g), where um and vm are
    terms such that um * f - vm * g is the S-polynomial of f and g (so,
    wlog assume um * f > vm * g).
    For performance sake, a critical pair is represented as a tuple
    (Sign(um * f), um, f, Sign(vm * g), vm, g), since um * f creates
    a new, relatively expensive object in memory, whereas Sign(um *
    f) and um are lightweight and f (in the tuple) is a reference to
    an already existing object in memory.
    """
    ltf = sdp_LT(Polyn(f), u, K)
    ltg = sdp_LT(Polyn(g), u, K)
    lt = (monomial_lcm(ltf[0], ltg[0]), K.one)

    if K.has_Field:
        term_div = _term_ff_div
    else:
        term_div = _term_rr_div

    um = term_div(lt, ltf, K)
    vm = term_div(lt, ltg, K)

    # The full information is not needed (now), so only the product
    # with the leading term is considered:
    fr = lbp_mul_term(
        lbp(Sign(f), [sdp_LT(Polyn(f), u, K)], Num(f)), um, u, O, K)
    gr = lbp_mul_term(
        lbp(Sign(g), [sdp_LT(Polyn(g), u, K)], Num(g)), vm, u, O, K)

    # return in proper order, such that the S-polynomial is just
    # u_first * f_first - u_second * f_second:
    if lbp_cmp(fr, gr, O) == -1:
        return (Sign(gr), vm, g, Sign(fr), um, f)
    else:
        return (Sign(fr), um, f, Sign(gr), vm, g)
Пример #5
0
def test_sdp_LT():
    assert sdp_LT([], 1, QQ) == ((0, 0), QQ(0))
    assert sdp_LT([((1, 0), QQ(1, 2))], 1, QQ) == ((1, 0), QQ(1, 2))
    assert sdp_LT(
        [((1, 1), QQ(1, 4)), ((1, 0), QQ(1, 2))], 1, QQ) == ((1, 1), QQ(1, 4))