예제 #1
0
파일: linear.py 프로젝트: hahaXD/TDK
 def gidentify(self, idedge, eql_edges=None):
     import sage.all
     if eql_edges is not None:
         eql_edges_uf = edges_union_find (eql_edges)
     else:
         eql_edges_uf = []
     from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
     from sage.rings.rational_field import QQ
     from sage.rings.ideal import Ideal
     from sage.symbolic.ring import var
     e  = generateEdges(self)
     e2 = generateEdges(self, "X_", "e_")
     variables = list(e2.values()) + list(e.values())
     ring = PolynomialRing(QQ, variables)
     gens = ring.gens()
     e = replaceDictVals(e, variables, gens)
     e2 = replaceDictVals(e2, variables, gens)
     if eql_edges is not None:
         for eql_edge in eql_edges:
             e[eql_edge[1]] = e[eql_edges_uf[eql_edge[1]]]
             e[eql_edge[0]] = e[eql_edges_uf[eql_edge[0]]]
     cov1 = generateCovarianceEquations(self, e)
     cov2 = generateCovarianceEquations(self, e2)
     eqns = [cov1[k] - cov2[k] for k in cov1]
     dc_vars  = [e2[k] for k in e2 if k != idedge and k not in eql_edges_uf]
     core_basis = Ideal(eqns).elimination_ideal(dc_vars).groebner_basis()
     if eql_edges is not None:
         eql_vars = [e2[k] for k in e2 if k != idedge and k in eql_edges_uf]
         core_eqns = [k for k in core_basis]
         for eql_edge in eql_edges:
             core_eqns.append(e2[eql_edge[0]] - e2[eql_edge[1]])
         core_basis = Ideal(core_eqns).elimination_ideal(eql_vars).groebner_basis()
     return core_basis, e2[idedge], e
예제 #2
0
def _possible_gens(coeffs, ideal, var=0):
    coeff_gens = list(ideal.gens())
    poly_ring = coeffs[var].parent()
    if coeffs[var] == poly_ring.zero():
        return []
    for i, coeff in enumerate(coeffs):
        if not i == var:
            coeff_gens.append(coeff)
    poss_ideal = (Ideal(poly_ring, coeff_gens)).intersection(
        Ideal(poly_ring, coeffs[var]))
    poss_gens = []
    for g in poss_ideal.gens():
        poss_gens.append(g // coeffs[var])
    return poss_gens
예제 #3
0
            def sage_ideal(vars, eqns):

                polynomialRing = PolynomialRing(RationalField(),
                                                vars,
                                                order='lex')

                return Ideal(polynomialRing, [sage_eqn(eqn) for eqn in eqns])
예제 #4
0
파일: linear.py 프로젝트: hahaXD/TDK
    def solve_by_random_weights(self, idedge, eql_edge):

        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        from sage.rings.rational_field import QQ
        from sage.rings.ideal import Ideal
        from sage.symbolic.ring import var
        e  = generateEdges(self)
        e2 = generateEdges(self, "X_", "e_")
        variables = list(e2.values())
        ring = PolynomialRing(QQ, variables)
        gens = ring.gens()
        q = [i for i in range(1, len(e) + 2)]
        rnd.shuffle(q)
        for idx, e_t in enumerate(e):
            e[e_t] = q[idx]
        e[eql_edge[0]] = q[-1]
        e[eql_edge[1]] = e[eql_edge[0]]
        e2 = replaceDictVals(e2, variables, gens)
        cov1 = generateCovarianceEquations(self, e)
        cov2 = generateCovarianceEquations(self, e2)
        eqns = [cov1[k] - cov2[k] for k in cov1]
        eqns.append(e2[eql_edge[0]] - e2[eql_edge[1]])
        dc_vars  = [e2[k] for k in e2 if k != idedge]
        core_basis = Ideal(eqns).elimination_ideal(dc_vars).groebner_basis()
        return core_basis, e2[idedge]
예제 #5
0
 def test_create_relations_satisfy(self):
     x = self.x
     y = self.y
     z = self.z
     zero = self.poly_ring.zero()
     relations = [[x**2, z * y], [y**2, -x]]
     ideals = [
         Ideal(self.poly_ring, [x**2 * y - z**2]),
         Ideal(self.poly_ring, [x * y - z])
     ]
     mod = SingularModule.create_from_relations(relations, ideals)
     for relation, ideal in zip(relations, ideals):
         for gen in mod.gens:
             sum = zero
             for g, rel in zip(gen, relation):
                 sum = sum + g * rel
         self.assertTrue(sum in ideal)
예제 #6
0
 def test_create_relationB(self):
     #From an error uncovered in log derivations
     x = self.x
     y = self.y
     z = self.z
     zero = self.poly_ring.zero()
     relation = [y * z, x * z, x * y]
     ideal = Ideal(self.poly_ring, [x * y * z])
     mod = SingularModule.create_from_relation(relation, ideal)
     true_mod = SingularModule([[x, zero, zero], [zero, y, zero],
                                [zero, zero, z]])
     self.assertTrue(mod.equals(true_mod))
예제 #7
0
    def __init__(self, S, P, check=False):
        """
        INPUT:
        
        
        -  ``S`` - an affine scheme
        
        -  ``P`` - a prime ideal of the coordinate ring of S

        TESTS::

            sage: from sage.schemes.generic.point import SchemeTopologicalPoint_prime_ideal
            sage: S = Spec(ZZ)
            sage: P = SchemeTopologicalPoint_prime_ideal(S, 3); P
            Point on Spectrum of Integer Ring defined by the Principal ideal (3) of Integer Ring
            sage: SchemeTopologicalPoint_prime_ideal(S, 6, check=True)
            Traceback (most recent call last):
            ...
            ValueError: The argument Principal ideal (6) of Integer Ring must be a prime ideal of Integer Ring
            sage: SchemeTopologicalPoint_prime_ideal(S, ZZ.ideal(7))
            Point on Spectrum of Integer Ring defined by the Principal ideal (7) of Integer Ring
            
        We define a parabola in the projective plane as a point
        corresponding to a prime ideal::

            sage: P2.<x, y, z> = ProjectiveSpace(2, QQ)
            sage: SchemeTopologicalPoint_prime_ideal(P2, y*z-x^2)
            Point on Projective Space of dimension 2 over Rational Field defined by the Ideal (-x^2 + y*z) of Multivariate Polynomial Ring in x, y, z over Rational Field
        """
        R = S.coordinate_ring()
        from sage.rings.ideal import Ideal
        P = Ideal(R, P)
        # ideally we would have check=True by default, but
        # unfortunately is_prime() is only implemented in a small
        # number of cases
        if check and not P.is_prime():
            raise ValueError, "The argument %s must be a prime ideal of %s" % (
                P, R)
        SchemeTopologicalPoint.__init__(self, S)
        self.__P = P
예제 #8
0
 def test_create_relation_satisfy_A(self):
     x = self.x
     y = self.y
     z = self.z
     zero = self.poly_ring.zero()
     relation = [x + x**4 - y, (y + z)**3, -2 * y + self.poly_ring.one()]
     ideal = Ideal(self.poly_ring, [x**2 * y - z**2])
     mod = SingularModule.create_from_relation(relation, ideal)
     for gen in mod.gens:
         sum = zero
         for g, rel in zip(gen, relation):
             sum = sum + g * rel
     self.assertTrue(sum in ideal)
예제 #9
0
 def test_create_relationA(self):
     x = self.x
     y = self.y
     z = self.z
     one = self.poly_ring.one()
     zero = self.poly_ring.zero()
     relation = [x**2, one + z**2, y]
     ideal = Ideal(self.poly_ring, [x**2 * y - z**2])
     mod = SingularModule.create_from_relation(relation, ideal)
     true_mod = SingularModule([[one, -x**2, x**4], [zero, y, -z**2 - 1],
                                [zero, z**2, -x**2 * z**2 - x**2],
                                [zero, zero, x**2 * y - z**2]])
     self.assertTrue(mod.equals(true_mod))
 def __init__(self, divisor):
     self.divisor = divisor
     poly_ring = divisor.parent()
     #Compute gen set
     rel = [poly_ring.zero() for _ in range(poly_ring.ngens())]
     for _, mon in divisor:
         exp = mon.exponents()[0]
         for i in range(poly_ring.ngens()):
             rel[i] = rel[i] + exp[i] * mon // poly_ring.gens()[i]
     ideal = Ideal(poly_ring, [divisor])
     base_mod = SingularModule.create_from_relation(rel, ideal)
     SingularModule.__init__(self, base_mod.gens)
     self.relation = rel
예제 #11
0
파일: point.py 프로젝트: CETHop/sage
    def __init__(self, S, P, check=False):
        """
        INPUT:


        -  ``S`` - an affine scheme

        -  ``P`` - a prime ideal of the coordinate ring of S

        TESTS::

            sage: from sage.schemes.generic.point import SchemeTopologicalPoint_prime_ideal
            sage: S = Spec(ZZ)
            sage: P = SchemeTopologicalPoint_prime_ideal(S, 3); P
            Point on Spectrum of Integer Ring defined by the Principal ideal (3) of Integer Ring
            sage: SchemeTopologicalPoint_prime_ideal(S, 6, check=True)
            Traceback (most recent call last):
            ...
            ValueError: The argument Principal ideal (6) of Integer Ring must be a prime ideal of Integer Ring
            sage: SchemeTopologicalPoint_prime_ideal(S, ZZ.ideal(7))
            Point on Spectrum of Integer Ring defined by the Principal ideal (7) of Integer Ring

        We define a parabola in the projective plane as a point
        corresponding to a prime ideal::

            sage: P2.<x, y, z> = ProjectiveSpace(2, QQ)
            sage: SchemeTopologicalPoint_prime_ideal(P2, y*z-x^2)
            Point on Projective Space of dimension 2 over Rational Field defined by the Ideal (-x^2 + y*z) of Multivariate Polynomial Ring in x, y, z over Rational Field
        """
        R = S.coordinate_ring()
        from sage.rings.ideal import Ideal
        P = Ideal(R, P)
        # ideally we would have check=True by default, but
        # unfortunately is_prime() is only implemented in a small
        # number of cases
        if check and not P.is_prime():
            raise ValueError, "The argument %s must be a prime ideal of %s"%(P, R)
        SchemeTopologicalPoint.__init__(self, S)
        self.__P = P
예제 #12
0
 def reverse_map(item):
     if isinstance(item, Ideal_generic):
         return Ideal([reverse_map(g) for g in item.gens()])
     elif isinstance(item, Polynomial):
         return item.map_coefficients(morphism)
     elif isinstance(item, MPolynomial):
         return item.map_coefficients(morphism)
     elif isinstance(item, list):
         return map(reverse_map, item)
     elif isinstance(item, tuple):
         return tuple(map(reverse_map, item))
     elif isinstance(item, set):
         return set(map(reverse_map, list(item)))
     else:
         return item
예제 #13
0
 def forward_map(item):
     if isinstance(item, Ideal_generic):
         return Ideal([forward_map(g) for g in item.gens()])
     elif isinstance(item, Polynomial):
         return item.map_coefficients(elem_dict.__getitem__,
                                      new_base_ring=numfield)
     elif isinstance(item, MPolynomial):
         return item.map_coefficients(elem_dict.__getitem__,
                                      new_base_ring=numfield)
     elif isinstance(item, list):
         return map(forward_map, item)
     elif isinstance(item, tuple):
         return tuple(map(forward_map, item))
     elif isinstance(item, set):
         return set(map(forward_map, list(item)))
     else:
         return item
예제 #14
0
파일: linear.py 프로젝트: hahaXD/TDK
 def g_relevent_basis(self, idedge, eql_edge):
     from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
     from sage.rings.rational_field import QQ
     from sage.rings.ideal import Ideal
     from sage.symbolic.ring import var
     e  = generateEdges(self)
     e2 = generateEdges(self, "X_", "e_")
     cr_vars = [k for k in e2.keys() if k in eql_edge or k == idedge]
     dc_vars = [k for k in e2.keys() if k not in eql_edge and k != idedge]
     variables = [e2[v] for v in dc_vars] + [e2[v] for v in cr_vars] + list(e.values())
     ring = PolynomialRing(QQ, variables)
     gens = ring.gens()
     e = replaceDictVals(e, variables, gens)
     e2 = replaceDictVals(e2, variables, gens)
     cov1 = generateCovarianceEquations(self, e)
     cov2 = generateCovarianceEquations(self, e2)
     eqns = [cov1[k] - cov2[k] for k in cov1]
     dc_symbols  = [e2[v] for v in dc_vars]
     core_basis  = Ideal(eqns).elimination_ideal(dc_symbols).groebner_basis()
     return core_basis, e2[idedge], (e2[eql_edge[0]], e2[eql_edge[1]]), e
예제 #15
0
 def forward_map(item):
     if isinstance(item, Ideal_generic):
         return Ideal([forward_map(g) for g in item.gens()])
     elif isinstance(item, Polynomial):
         return item.map_coefficients(elem_dict.__getitem__,
                                      new_base_ring=numfield)
     elif isinstance(item, MPolynomial):
         return item.map_coefficients(elem_dict.__getitem__,
                                      new_base_ring=numfield)
     elif is_PolynomialSequence(item):
         return PolynomialSequence(map(forward_map, item),
                                   immutable=item.is_immutable())
     elif isinstance(item, list):
         return list(map(forward_map, item))
     elif isinstance(item, dict):
         return {k: forward_map(v) for k, v in item.items()}
     elif isinstance(item, tuple):
         return tuple(map(forward_map, item))
     elif isinstance(item, set):
         return set(map(forward_map, list(item)))
     else:
         return item
예제 #16
0
def _generators_from_relation(rel_coeffs, ideal):
    poly_ring = rel_coeffs[0].parent()
    #possible first values
    poss_gens_0 = _possible_gens(rel_coeffs, ideal, 0)
    #Particulars for these values
    part_ideal = Ideal(poly_ring, rel_coeffs[1:] + list(ideal.gens()))
    poss_gens = []
    if not rel_coeffs[0].is_zero():
        for g in poss_gens_0:
            part_lift = (-g * rel_coeffs[0]).lift(part_ideal)
            part_lift = part_lift[:(len(rel_coeffs) - 1)]  # Drop ideal stuff
            poss_gens.append([g] + part_lift)
    else:
        poss_gens = [[poly_ring.one()] +
                     [poly_ring.zero() for _ in rel_coeffs[1:]]]
    #Solve for when first value is zero
    if len(rel_coeffs) > 1:
        red_coeffs = rel_coeffs[1:]
        red_gens = _generators_from_relation(red_coeffs, ideal)
        for red_gen in red_gens:
            poss_gens.append([poly_ring.zero()] + red_gen)
    return poss_gens
예제 #17
0
    def polynomials(self, X=None, Y=None, degree=2, groebner=False):
        """
        Return a list of polynomials satisfying this S-box.

        First, a simple linear fitting is performed for the given
        ``degree`` (cf. for example [BC2003]_). If ``groebner=True`` a
        Groebner basis is also computed for the result of that
        process.

        INPUT:

        - ``X`` - input variables

        - ``Y`` - output variables

        - ``degree`` - integer > 0 (default: ``2``)

        - ``groebner`` - calculate a reduced Groebner basis of the
          spanning polynomials to obtain more polynomials (default:
          ``False``)

        EXAMPLES::

            sage: from sage.crypto.sbox import SBox
            sage: S = SBox(7,6,0,4,2,5,1,3)
            sage: P = S.ring()

        By default, this method returns an indirect representation::

            sage: S.polynomials()
            [x0*x2 + x1 + y1 + 1,
             x0*x1 + x1 + x2 + y0 + y1 + y2 + 1,
             x0*y1 + x0 + x2 + y0 + y2,
             x0*y0 + x0*y2 + x1 + x2 + y0 + y1 + y2 + 1,
             x1*x2 + x0 + x1 + x2 + y2 + 1,
             x0*y0 + x1*y0 + x0 + x2 + y1 + y2,
             x0*y0 + x1*y1 + x1 + y1 + 1,
             x1*y2 + x1 + x2 + y0 + y1 + y2 + 1,
             x0*y0 + x2*y0 + x1 + x2 + y1 + 1,
             x2*y1 + x0 + y1 + y2,
             x2*y2 + x1 + y1 + 1,
             y0*y1 + x0 + x2 + y0 + y1 + y2,
             y0*y2 + x1 + x2 + y0 + y1 + 1,
             y1*y2 + x2 + y0]

        We can get a direct representation by computing a
        lexicographical Groebner basis with respect to the right
        variable ordering, i.e. a variable ordering where the output
        bits are greater than the input bits::

            sage: P.<y0,y1,y2,x0,x1,x2> = PolynomialRing(GF(2),6,order='lex')
            sage: S.polynomials([x0,x1,x2],[y0,y1,y2], groebner=True)
            [y0 + x0*x1 + x0*x2 + x0 + x1*x2 + x1 + 1,
             y1 + x0*x2 + x1 + 1,
             y2 + x0 + x1*x2 + x1 + x2 + 1]
        """
        def nterms(nvars, deg):
            """
            Return the number of monomials possible up to a given
            degree.

            INPUT:

            - ``nvars`` - number of variables

            - ``deg`` - degree

            TESTS::

                sage: from sage.crypto.sbox import SBox
                sage: S = SBox(7,6,0,4,2,5,1,3)
                sage: F = S.polynomials(degree=3) # indirect doctest
            """
            total = 1
            divisor = 1
            var_choices = 1

            for d in range(1, deg+1):
                var_choices *= (nvars - d + 1)
                divisor *= d
                total += var_choices/divisor
            return total

        m = self.m
        n = self.n
        F = self._F

        if X is None and Y is None:
            P = self.ring()
            X = P.gens()[:m]
            Y = P.gens()[m:]
        else:
            P = X[0].parent()

        gens = X+Y

        bits = []
        for i in range(1<<m):
            bits.append( self.to_bits(i,m) + self(self.to_bits(i,m)) )

        ncols = (1<<m)+1

        A = Matrix(P, nterms(m+n, degree), ncols)

        exponents = []
        for d in range(degree+1):
            exponents += IntegerVectors(d, max_length=m+n, min_length=m+n, min_part=0, max_part=1).list()

        row = 0
        for exponent in exponents:
            A[row,ncols-1] = mul([gens[i]**exponent[i] for i in range(len(exponent))])
            for col in range(1<<m):
                A[row,col] = mul([bits[col][i] for i in range(len(exponent)) if exponent[i]])
            row +=1

        for c in range(ncols):
            A[0,c] = 1

        RR = A.echelon_form(algorithm='row_reduction')

        # extract spanning stet
        gens = (RR.column(ncols-1)[1<<m:]).list()

        if not groebner:
            return gens

        FI = set(FieldIdeal(P).gens())
        I = Ideal(gens + list(FI))
        gb = I.groebner_basis()

        gens = []
        for f in gb:
            if f not in FI: # filter out field equations
                gens.append(f)
        return gens
예제 #18
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)
예제 #19
0
파일: sbox.py 프로젝트: robertwb/sage
    def polynomials(self, X=None, Y=None, degree=2, groebner=False):
        """
        Return a list of polynomials satisfying this S-box.

        First, a simple linear fitting is performed for the given
        ``degree`` (cf. for example [BC03]_). If ``groebner=True`` a
        Groebner basis is also computed for the result of that
        process.

        INPUT:

        - ``X`` - input variables

        - ``Y`` - output variables

        - ``degree`` - integer > 0 (default: ``2``)

        - ``groebner`` - calculate a reduced Groebner basis of the
          spanning polynomials to obtain more polynomials (default:
          ``False``)

        EXAMPLES::

            sage: S = mq.SBox(7,6,0,4,2,5,1,3)
            sage: P = S.ring()

        By default, this method returns an indirect representation::

            sage: S.polynomials()
            [x0*x2 + x1 + y1 + 1,
             x0*x1 + x1 + x2 + y0 + y1 + y2 + 1,
             x0*y1 + x0 + x2 + y0 + y2,
             x0*y0 + x0*y2 + x1 + x2 + y0 + y1 + y2 + 1,
             x1*x2 + x0 + x1 + x2 + y2 + 1,
             x0*y0 + x1*y0 + x0 + x2 + y1 + y2,
             x0*y0 + x1*y1 + x1 + y1 + 1,
             x1*y2 + x1 + x2 + y0 + y1 + y2 + 1,
             x0*y0 + x2*y0 + x1 + x2 + y1 + 1,
             x2*y1 + x0 + y1 + y2,
             x2*y2 + x1 + y1 + 1,
             y0*y1 + x0 + x2 + y0 + y1 + y2,
             y0*y2 + x1 + x2 + y0 + y1 + 1,
             y1*y2 + x2 + y0]

        We can get a direct representation by computing a
        lexicographical Groebner basis with respect to the right
        variable ordering, i.e. a variable ordering where the output
        bits are greater than the input bits::

            sage: P.<y0,y1,y2,x0,x1,x2> = PolynomialRing(GF(2),6,order='lex')
            sage: S.polynomials([x0,x1,x2],[y0,y1,y2], groebner=True)
            [y0 + x0*x1 + x0*x2 + x0 + x1*x2 + x1 + 1,
             y1 + x0*x2 + x1 + 1,
             y2 + x0 + x1*x2 + x1 + x2 + 1]

        REFERENCES:

        .. [BC03] \A. Biryukov and C. D. Canniere *Block Ciphers and
          Systems of Quadratic Equations*; in Proceedings of Fast
          Software Encryption 2003; LNCS 2887; pp. 274-289,
          Springer-Verlag 2003.
        """
        def nterms(nvars, deg):
            """
            Return the number of monomials possible up to a given
            degree.

            INPUT:

            - ``nvars`` - number of variables

            - ``deg`` - degree

            TESTS::

                sage: S = mq.SBox(7,6,0,4,2,5,1,3)
                sage: F = S.polynomials(degree=3) # indirect doctest
            """
            total = 1
            divisor = 1
            var_choices = 1

            for d in range(1, deg+1):
                var_choices *= (nvars - d + 1)
                divisor *= d
                total += var_choices/divisor
            return total

        m = self.m
        n = self.n
        F = self._F

        if X is None and Y is None:
            P = self.ring()
            X = P.gens()[:m]
            Y = P.gens()[m:]
        else:
            P = X[0].parent()

        gens = X+Y

        bits = []
        for i in range(1<<m):
            bits.append( self.to_bits(i,m) + self(self.to_bits(i,m)) )

        ncols = (1<<m)+1

        A = Matrix(P, nterms(m+n, degree), ncols)

        exponents = []
        for d in range(degree+1):
            exponents += IntegerVectors(d, max_length=m+n, min_length=m+n, min_part=0, max_part=1).list()

        row = 0
        for exponent in exponents:
            A[row,ncols-1] = mul([gens[i]**exponent[i] for i in range(len(exponent))])
            for col in range(1<<m):
                A[row,col] = mul([bits[col][i] for i in range(len(exponent)) if exponent[i]])
            row +=1

        for c in range(ncols):
            A[0,c] = 1

        RR = A.echelon_form(algorithm='row_reduction')

        # extract spanning stet
        gens = (RR.column(ncols-1)[1<<m:]).list()

        if not groebner:
            return gens

        FI = set(FieldIdeal(P).gens())
        I = Ideal(gens + list(FI))
        gb = I.groebner_basis()

        gens = []
        for f in gb:
            if f not in FI: # filter out field equations
                gens.append(f)
        return gens
예제 #20
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)