示例#1
0
文件: giac.py 项目: mcognetta/sage
def groebner_basis(gens, proba_epsilon=None, threads=None, prot=False, *args, **kwds):
    """
    Computes a Groebner Basis of an ideal using giacpy_sage. The result is
    automatically converted to sage.

    INPUT:

    - ``gens`` - an ideal (or a list) of polynomials over a prime field
      of characteristic 0 or p<2^31

    - ``proba_epsilon`` - (default: None) majoration of the probability
       of a wrong answer when probabilistic algorithms are allowed.

        * if ``proba_epsilon`` is None, the value of
          ``sage.structure.proof.all.polynomial()`` is taken. If it is
          false then the global ``giacpy_sage.giacsettings.proba_epsilon`` is
          used.

        * if ``proba_epsilon`` is 0, probabilistic algorithms are
          disabled.

    - ``threads`` - (default: None) Maximal number of threads allowed
      for giac. If None, the global ``giacpy_sage.giacsettings.threads`` is
      considered.

    - ``prot`` - (default: False) if True print detailled informations

    OUTPUT:

    Polynomial sequence of the reduced Groebner basis.

    EXAMPLES::

        sage: from sage.libs.giac import groebner_basis as gb_giac # optional - giacpy_sage
        sage: P = PolynomialRing(GF(previous_prime(2**31)), 6, 'x') # optional - giacpy_sage
        sage: I = sage.rings.ideal.Cyclic(P) # optional - giacpy_sage
        sage: B=gb_giac(I.gens());B # optional - giacpy_sage
        <BLANKLINE>
        // Groebner basis computation time ...
        Polynomial Sequence with 45 Polynomials in 6 Variables
        sage: B.is_groebner() # optional - giacpy_sage
        True

    Computations over QQ can benefit from

    * a probabilistic lifting::

        sage: P = PolynomialRing(QQ,5, 'x') # optional - giacpy_sage
        sage: I = ideal([P.random_element(3,7) for j in range(5)]) # optional - giacpy_sage
        sage: B1 = gb_giac(I.gens(),1e-16) # optional - giacpy_sage, long time (1s)
        Running a probabilistic check for the reconstructed Groebner basis.
        If successfull, error probability is less than 1e-16 ...
        sage: sage.structure.proof.all.polynomial(True) # optional - giacpy_sage
        sage: B2 = gb_giac(I.gens()) # optional - giacpy_sage, long time (4s)
        <BLANKLINE>
        // Groebner basis computation time...
        sage: B1==B2 # optional - giacpy_sage, long time
        True
        sage: B1.is_groebner() # optional - giacpy_sage, long time (20s)
        True

    * multi threaded operations::

        sage: P = PolynomialRing(QQ, 8, 'x') # optional - giacpy_sage
        sage: I=sage.rings.ideal.Cyclic(P) # optional - giacpy_sage
        sage: time B = gb_giac(I.gens(),1e-6,threads=2) # doctest: +SKIP
        Running a probabilistic check for the reconstructed Groebner basis...
        Time: CPU 168.98 s, Wall: 94.13 s

    You can get detailled information by setting ``prot=True``

    ::

        sage: I=sage.rings.ideal.Katsura(P) # optional - giacpy_sage
        sage: gb_giac(I,prot=True)  # optional - giacpy_sage, random, long time (3s)
        9381383 begin computing basis modulo 535718473
        9381501 begin new iteration zmod, number of pairs: 8, base size: 8
        ...end, basis size 74 prime number 1
        G=Vector [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,...
        ...creating reconstruction #0
        ...
        ++++++++basis size 74
        checking pairs for i=0, j=
        checking pairs for i=1, j=2,6,12,17,19,24,29,34,39,42,43,48,56,61,64,69,
        ...
        checking pairs for i=72, j=73,
        checking pairs for i=73, j=
        Number of critical pairs to check 373
        +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++...
        Successfull check of 373 critical pairs
        12380865 end final check
        Polynomial Sequence with 74 Polynomials in 8 Variables


    TESTS::

        sage: from giacpy_sage import libgiac # optional - giacpy_sage
        sage: libgiac("x2:=22; x4:='whywouldyoudothis'") # optional - giacpy_sage
        22,whywouldyoudothis
        sage: gb_giac(I) # optional - giacpy_sage
        Traceback (most recent call last):
        ...
        ValueError: Variables names ['x2', 'x4'] conflict in giac. Change them or purge them from in giac with libgiac.purge('x2')
        sage: libgiac.purge('x2'),libgiac.purge('x4') # optional - giacpy_sage
        (22, whywouldyoudothis)
        sage: gb_giac(I) # optional - giacpy_sage, long time (3s)
        <BLANKLINE>
        // Groebner basis computation time...
        Polynomial Sequence with 74 Polynomials in 8 Variables

        sage: I=ideal(P(0),P(0)) # optional - giacpy_sage
        sage: I.groebner_basis() == gb_giac(I) # optional - giacpy_sage
        True

    """
    try:
        from giacpy_sage import libgiac, giacsettings
    except ImportError:
        raise ImportError("""One of the optional packages giac or giacpy_sage is missing""")

    try:
        iter(gens)
    except TypeError:
        gens = gens.gens()

    # get the ring from gens
    P = next(iter(gens)).parent()
    K = P.base_ring()
    p = K.characteristic()

    # check if the ideal is zero. (giac 1.2.0.19 segfault)
    from sage.rings.ideal import Ideal
    if (Ideal(gens)).is_zero():
        return PolynomialSequence([P(0)], P, immutable=True)

    # check for name confusions
    blackgiacconstants = ['i', 'e'] # NB e^k is expanded to exp(k)
    blacklist = blackgiacconstants + [str(j) for j in libgiac.VARS()]
    problematicnames = list(set(P.gens_dict().keys()).intersection(blacklist))

    if(len(problematicnames)>0):
        raise ValueError("Variables names %s conflict in giac. Change them or purge them from in giac with libgiac.purge(\'%s\')"
                         %(problematicnames, problematicnames[0]))

    if K.is_prime_field() and p == 0:
        F = libgiac(gens)
    elif K.is_prime_field() and p < 2**31:
        F = (libgiac(gens) % p)
    else:
        raise NotImplementedError("Only prime fields of cardinal < 2^31 are implemented in Giac for Groebner bases.")

    if P.term_order() != "degrevlex":
        raise NotImplementedError("Only degrevlex term orderings are supported in Giac Groebner bases.")

    # proof or probabilistic reconstruction
    if proba_epsilon is None:
        if proof_polynomial():
            giacsettings.proba_epsilon = 0
        else:
            giacsettings.proba_epsilon = 1e-15
    else:
        giacsettings.proba_epsilon = proba_epsilon

    # prot
    if prot:
        libgiac('debug_infolevel(2)')

    # threads
    if threads is not None:
        giacsettings.threads = threads

    # compute de groebner basis with giac
    gb_giac = F.gbasis([P.gens()], "revlex")

    return PolynomialSequence(gb_giac, P, immutable=True)
示例#2
0
文件: giac.py 项目: BrentBaccala/sage
def groebner_basis(gens,
                   proba_epsilon=None,
                   threads=None,
                   prot=False,
                   *args,
                   **kwds):
    """
    Computes a Groebner Basis of an ideal using giacpy_sage. The result is
    automatically converted to sage.

    INPUT:

    - ``gens`` - an ideal (or a list) of polynomials over a prime field
      of characteristic 0 or p<2^31

    - ``proba_epsilon`` - (default: None) majoration of the probability
       of a wrong answer when probabilistic algorithms are allowed.

        * if ``proba_epsilon`` is None, the value of
          ``sage.structure.proof.all.polynomial()`` is taken. If it is
          false then the global ``giacpy_sage.giacsettings.proba_epsilon`` is
          used.

        * if ``proba_epsilon`` is 0, probabilistic algorithms are
          disabled.

    - ``threads`` - (default: None) Maximal number of threads allowed
      for giac. If None, the global ``giacpy_sage.giacsettings.threads`` is
      considered.

    - ``prot`` - (default: False) if True print detailled informations

    OUTPUT:

    Polynomial sequence of the reduced Groebner basis.

    EXAMPLES::

        sage: from sage.libs.giac import groebner_basis as gb_giac # optional - giacpy_sage
        sage: P = PolynomialRing(GF(previous_prime(2**31)), 6, 'x') # optional - giacpy_sage
        sage: I = sage.rings.ideal.Cyclic(P) # optional - giacpy_sage
        sage: B=gb_giac(I.gens());B # optional - giacpy_sage
        <BLANKLINE>
        // Groebner basis computation time ...
        Polynomial Sequence with 45 Polynomials in 6 Variables
        sage: B.is_groebner() # optional - giacpy_sage
        True

    Computations over QQ can benefit from

    * a probabilistic lifting::

        sage: P = PolynomialRing(QQ,5, 'x') # optional - giacpy_sage
        sage: I = ideal([P.random_element(3,7) for j in range(5)]) # optional - giacpy_sage
        sage: B1 = gb_giac(I.gens(),1e-16) # optional - giacpy_sage, long time (1s)
        Running a probabilistic check for the reconstructed Groebner basis.
        If successfull, error probability is less than 1e-16 ...
        sage: sage.structure.proof.all.polynomial(True) # optional - giacpy_sage
        sage: B2 = gb_giac(I.gens()) # optional - giacpy_sage, long time (4s)
        <BLANKLINE>
        // Groebner basis computation time...
        sage: B1==B2 # optional - giacpy_sage, long time
        True
        sage: B1.is_groebner() # optional - giacpy_sage, long time (20s)
        True

    * multi threaded operations::

        sage: P = PolynomialRing(QQ, 8, 'x') # optional - giacpy_sage
        sage: I=sage.rings.ideal.Cyclic(P) # optional - giacpy_sage
        sage: time B = gb_giac(I.gens(),1e-6,threads=2) # doctest: +SKIP
        Running a probabilistic check for the reconstructed Groebner basis...
        Time: CPU 168.98 s, Wall: 94.13 s

    You can get detailled information by setting ``prot=True``

    ::

        sage: I=sage.rings.ideal.Katsura(P) # optional - giacpy_sage
        sage: gb_giac(I,prot=True)  # optional - giacpy_sage, random, long time (3s)
        9381383 begin computing basis modulo 535718473
        9381501 begin new iteration zmod, number of pairs: 8, base size: 8
        ...end, basis size 74 prime number 1
        G=Vector [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,...
        ...creating reconstruction #0
        ...
        ++++++++basis size 74
        checking pairs for i=0, j=
        checking pairs for i=1, j=2,6,12,17,19,24,29,34,39,42,43,48,56,61,64,69,
        ...
        checking pairs for i=72, j=73,
        checking pairs for i=73, j=
        Number of critical pairs to check 373
        +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++...
        Successfull check of 373 critical pairs
        12380865 end final check
        Polynomial Sequence with 74 Polynomials in 8 Variables


    TESTS::

        sage: from giacpy_sage import libgiac # optional - giacpy_sage
        sage: libgiac("x2:=22; x4:='whywouldyoudothis'") # optional - giacpy_sage
        22,whywouldyoudothis
        sage: gb_giac(I) # optional - giacpy_sage
        Traceback (most recent call last):
        ...
        ValueError: Variables names ['x2', 'x4'] conflict in giac. Change them or purge them from in giac with libgiac.purge('x2')
        sage: libgiac.purge('x2'),libgiac.purge('x4') # optional - giacpy_sage
        (22, whywouldyoudothis)
        sage: gb_giac(I) # optional - giacpy_sage, long time (3s)
        <BLANKLINE>
        // Groebner basis computation time...
        Polynomial Sequence with 74 Polynomials in 8 Variables

        sage: I=ideal(P(0),P(0)) # optional - giacpy_sage
        sage: I.groebner_basis() == gb_giac(I) # optional - giacpy_sage
        True

    """
    try:
        from giacpy_sage import libgiac, giacsettings
    except ImportError:
        raise ImportError(
            """One of the optional packages giac or giacpy_sage is missing""")

    try:
        iter(gens)
    except TypeError:
        gens = gens.gens()

    # get the ring from gens
    P = next(iter(gens)).parent()
    K = P.base_ring()
    p = K.characteristic()

    # check if the ideal is zero. (giac 1.2.0.19 segfault)
    from sage.rings.ideal import Ideal
    if (Ideal(gens)).is_zero():
        return PolynomialSequence([P(0)], P, immutable=True)

    # check for name confusions
    blackgiacconstants = ['i', 'e']  # NB e^k is expanded to exp(k)
    blacklist = blackgiacconstants + [str(j) for j in libgiac.VARS()]
    problematicnames = list(set(P.gens_dict().keys()).intersection(blacklist))

    if (len(problematicnames) > 0):
        raise ValueError(
            "Variables names %s conflict in giac. Change them or purge them from in giac with libgiac.purge(\'%s\')"
            % (problematicnames, problematicnames[0]))

    if K.is_prime_field() and p == 0:
        F = libgiac(gens)
    elif K.is_prime_field() and p < 2**31:
        F = (libgiac(gens) % p)
    else:
        raise NotImplementedError(
            "Only prime fields of cardinal < 2^31 are implemented in Giac for Groebner bases."
        )

    if P.term_order() != "degrevlex":
        raise NotImplementedError(
            "Only degrevlex term orderings are supported in Giac Groebner bases."
        )

    # proof or probabilistic reconstruction
    if proba_epsilon is None:
        if proof_polynomial():
            giacsettings.proba_epsilon = 0
        else:
            giacsettings.proba_epsilon = 1e-15
    else:
        giacsettings.proba_epsilon = proba_epsilon

    # prot
    if prot:
        libgiac('debug_infolevel(2)')

    # threads
    if threads is not None:
        giacsettings.threads = threads

    # compute de groebner basis with giac
    gb_giac = F.gbasis([P.gens()], "revlex")

    return PolynomialSequence(gb_giac, P, immutable=True)
示例#3
0
def groebner_basis(gens,
                   proba_epsilon=None,
                   threads=None,
                   prot=False,
                   elim_variables=None,
                   *args,
                   **kwds):
    """
    Compute a Groebner Basis of an ideal using ``giacpy_sage``. The result is
    automatically converted to sage.

    Supported term orders of the underlying polynomial ring are ``lex``,
    ``deglex``, ``degrevlex`` and block orders with 2 ``degrevlex`` blocks.

    INPUT:

    - ``gens`` - an ideal (or a list) of polynomials over a prime field
      of characteristic 0 or p<2^31

    - ``proba_epsilon`` - (default: None) majoration of the probability
       of a wrong answer when probabilistic algorithms are allowed.

        * if ``proba_epsilon`` is None, the value of
          ``sage.structure.proof.all.polynomial()`` is taken. If it is
          false then the global ``giacpy_sage.giacsettings.proba_epsilon`` is
          used.

        * if ``proba_epsilon`` is 0, probabilistic algorithms are
          disabled.

    - ``threads`` - (default: None) Maximal number of threads allowed
      for giac. If None, the global ``giacpy_sage.giacsettings.threads`` is
      considered.

    - ``prot`` - (default: False) if True print detailled informations

    - ``elim_variables`` - (default: None) a list of variables to eliminate
      from the ideal.

        * if ``elim_variables`` is None, a Groebner basis with respect to the
          term ordering of the parent polynomial ring of the polynomials
          ``gens`` is computed.

        * if ``elim_variables`` is a list of variables, a Groebner basis of the
          elimination ideal with respect to a ``degrevlex`` term order is
          computed, regardless of the term order of the polynomial ring.

    OUTPUT:

    Polynomial sequence of the reduced Groebner basis.

    EXAMPLES::

        sage: from sage.libs.giac import groebner_basis as gb_giac
        sage: P = PolynomialRing(GF(previous_prime(2**31)), 6, 'x')
        sage: I = sage.rings.ideal.Cyclic(P)
        sage: B=gb_giac(I.gens());B
        <BLANKLINE>
        // Groebner basis computation time ...
        Polynomial Sequence with 45 Polynomials in 6 Variables
        sage: B.is_groebner()
        True

    Elimination ideals can be computed by passing ``elim_variables``::

        sage: P = PolynomialRing(GF(previous_prime(2**31)), 5, 'x')
        sage: I = sage.rings.ideal.Cyclic(P)
        sage: B = gb_giac(I.gens(), elim_variables=[P.gen(0), P.gen(2)])
        <BLANKLINE>
        // Groebner basis computation time ...
        sage: B.is_groebner()
        True
        sage: B.ideal() == I.elimination_ideal([P.gen(0), P.gen(2)])
        True

    Computations over QQ can benefit from

    * a probabilistic lifting::

        sage: P = PolynomialRing(QQ,5, 'x')
        sage: I = ideal([P.random_element(3,7) for j in range(5)])
        sage: B1 = gb_giac(I.gens(),1e-16) # long time (1s)
        ...
        sage: sage.structure.proof.all.polynomial(True)
        sage: B2 = gb_giac(I.gens()) # long time (4s)
        <BLANKLINE>
        // Groebner basis computation time...
        sage: B1 == B2 # long time
        True
        sage: B1.is_groebner() # long time (20s)
        True

    * multi threaded operations::

        sage: P = PolynomialRing(QQ, 8, 'x')
        sage: I = sage.rings.ideal.Cyclic(P)
        sage: time B = gb_giac(I.gens(),1e-6,threads=2) # doctest: +SKIP
        ...
        Time: CPU 168.98 s, Wall: 94.13 s

    You can get detailled information by setting ``prot=True``

    ::

        sage: I = sage.rings.ideal.Katsura(P)
        sage: gb_giac(I,prot=True)  # random, long time (3s)
        9381383 begin computing basis modulo 535718473
        9381501 begin new iteration zmod, number of pairs: 8, base size: 8
        ...end, basis size 74 prime number 1
        G=Vector [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,...
        ...creating reconstruction #0
        ...
        ++++++++basis size 74
        checking pairs for i=0, j=
        checking pairs for i=1, j=2,6,12,17,19,24,29,34,39,42,43,48,56,61,64,69,
        ...
        checking pairs for i=72, j=73,
        checking pairs for i=73, j=
        Number of critical pairs to check 373
        +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++...
        Successful... check of 373 critical pairs
        12380865 end final check
        Polynomial Sequence with 74 Polynomials in 8 Variables


    TESTS::

        sage: from sage.libs.giac.giac import libgiac
        sage: libgiac("x2:=22; x4:='whywouldyoudothis'")
        22,whywouldyoudothis
        sage: gb_giac(I)
        Traceback (most recent call last):
        ...
        ValueError: Variables names ['x2', 'x4'] conflict in giac. Change them or purge them from in giac with libgiac.purge('x2')
        sage: libgiac.purge('x2'),libgiac.purge('x4')
        (22, whywouldyoudothis)
        sage: gb_giac(I) # long time (3s)
        <BLANKLINE>
        // Groebner basis computation time...
        Polynomial Sequence with 74 Polynomials in 8 Variables

        sage: I = ideal(P(0),P(0))
        sage: I.groebner_basis() == gb_giac(I)
        True

    Test the supported term orderings::

        sage: from sage.rings.ideal import Cyclic
        sage: P = PolynomialRing(QQ, 'x', 4, order='lex')
        sage: B = gb_giac(Cyclic(P))
        ...
        sage: B.is_groebner(), B.ideal() == Cyclic(P)
        (True, True)
        sage: P = P.change_ring(order='deglex')
        sage: B = gb_giac(Cyclic(P))
        ...
        sage: B.is_groebner(), B.ideal() == Cyclic(P)
        (True, True)
        sage: P = P.change_ring(order='degrevlex(2),degrevlex(2)')
        sage: B = gb_giac(Cyclic(P))
        ...
        sage: B.is_groebner(), B.ideal() == Cyclic(P)
        (True, True)

    """
    try:
        iter(gens)
    except TypeError:
        gens = gens.gens()

    # get the ring from gens
    P = next(iter(gens)).parent()
    K = P.base_ring()
    p = K.characteristic()

    # check if the ideal is zero. (giac 1.2.0.19 segfault)
    from sage.rings.ideal import Ideal
    if (Ideal(gens)).is_zero():
        return PolynomialSequence([P(0)], P, immutable=True)

    # check for name confusions
    blackgiacconstants = ['i', 'e']  # NB e^k is expanded to exp(k)
    blacklist = blackgiacconstants + [str(j) for j in libgiac.VARS()]
    problematicnames = sorted(set(P.gens_dict()).intersection(blacklist))

    if problematicnames:
        raise ValueError(
            "Variables names %s conflict in giac. Change them or purge them from in giac with libgiac.purge(\'%s\')"
            % (problematicnames, problematicnames[0]))

    if K.is_prime_field() and p == 0:
        F = libgiac(gens)
    elif K.is_prime_field() and p < 2**31:
        F = (libgiac(gens) % p)
    else:
        raise NotImplementedError(
            "Only prime fields of cardinal < 2^31 are implemented in Giac for Groebner bases."
        )

    # proof or probabilistic reconstruction
    if proba_epsilon is None:
        if proof_polynomial():
            giacsettings.proba_epsilon = 0
        else:
            giacsettings.proba_epsilon = 1e-15
    else:
        giacsettings.proba_epsilon = proba_epsilon

    # prot
    if prot:
        libgiac('debug_infolevel(2)')

    # threads
    if threads is not None:
        giacsettings.threads = threads

    if elim_variables is None:
        var_names = P.variable_names()
        order_name = P.term_order().name()
        if order_name == "degrevlex":
            giac_order = "revlex"
        elif order_name == "lex":
            giac_order = "plex"
        elif order_name == "deglex":
            giac_order = "tdeg"
        else:
            blocks = P.term_order().blocks()
            if (len(blocks) == 2
                    and all(order.name() == "degrevlex" for order in blocks)):
                giac_order = "revlex"
                var_names = var_names[:len(blocks[0])]
            else:
                raise NotImplementedError(
                    "%s is not a supported term order in "
                    "Giac Groebner bases." % P.term_order())

        # compute de groebner basis with giac
        gb_giac = F.gbasis(list(var_names), giac_order)

    else:
        gb_giac = F.eliminate(list(elim_variables), 'gbasis')

    return PolynomialSequence(gb_giac, P, immutable=True)