Example #1
0
def buchberger_improved(F):
    """
    An improved version of Buchberger's algorithm as presented in
    [BW93]_, page 232.

    This variant uses the Gebauer-Moeller Installation to apply
    Buchberger's first and second criterion to avoid useless pairs.

    INPUT:
    
    - ``F`` - an ideal in a multivariate polynomial ring

    OUTPUT:

        a Groebner basis for F

    .. note:: 

       The verbosity of this function may be controlled with a
       ``set_verbose()`` call. Any value ``>=1`` will result in this
       function printing intermediate Groebner bases.

    EXAMPLES::

        sage: from sage.rings.polynomial.toy_buchberger import buchberger_improved
        sage: R.<x,y,z> = PolynomialRing(QQ,3)
        sage: set_verbose(0)
        sage: buchberger_improved(R.ideal([x^4-y-z,x*y*z-1]))
        [x*y*z - 1, x^3 - y^2*z - y*z^2, y^3*z^2 + y^2*z^3 - x^2]
    """
    F = inter_reduction(F.gens())

    G = set()
    B = set()

    if get_verbose() >=1:
        reductions_to_zero = 0

    while F != set():
        f = min(F)
        F.remove(f)
        G,B = update(G,B,f)
    
    while B != set():

        g1,g2 = select(B)
        B.remove((g1,g2))
        h = spol(g1,g2).reduce(G)
        if h!=0: G,B = update(G,B,h)

        if get_verbose() >= 1:
            print "(%s, %s) => %s"%(g1,g2,h)
            print "G: %s\n"%(G)
            if h==0:
                reductions_to_zero +=1
        
    if get_verbose() >= 1:
        print "%d reductions to zero."%(reductions_to_zero)
        
    return Sequence(inter_reduction(G))
Example #2
0
def buchberger_improved(F):
    """
    An improved version of Buchberger's algorithm as presented in
    [BW93]_, page 232.

    This variant uses the Gebauer-Moeller Installation to apply
    Buchberger's first and second criterion to avoid useless pairs.

    INPUT:

    - ``F`` - an ideal in a multivariate polynomial ring

    OUTPUT:

        a Groebner basis for F

    .. note::

       The verbosity of this function may be controlled with a
       ``set_verbose()`` call. Any value ``>=1`` will result in this
       function printing intermediate Groebner bases.

    EXAMPLES::

        sage: from sage.rings.polynomial.toy_buchberger import buchberger_improved
        sage: R.<x,y,z> = PolynomialRing(QQ,3)
        sage: set_verbose(0)
        sage: buchberger_improved(R.ideal([x^4-y-z,x*y*z-1]))
        [x*y*z - 1, x^3 - y^2*z - y*z^2, y^3*z^2 + y^2*z^3 - x^2]
    """
    F = inter_reduction(F.gens())

    G = set()
    B = set()

    if get_verbose() >= 1:
        reductions_to_zero = 0

    while F != set():
        f = min(F)
        F.remove(f)
        G, B = update(G, B, f)

    while B != set():

        g1, g2 = select(B)
        B.remove((g1, g2))
        h = spol(g1, g2).reduce(G)
        if h != 0: G, B = update(G, B, h)

        if get_verbose() >= 1:
            print "(%s, %s) => %s" % (g1, g2, h)
            print "G: %s\n" % (G)
            if h == 0:
                reductions_to_zero += 1

    if get_verbose() >= 1:
        print "%d reductions to zero." % (reductions_to_zero)

    return Sequence(inter_reduction(G))
def buchberger(F):
    """
    The original version of Buchberger's algorithm as presented in
    [BW93]_, page 214.

    INPUT:

    - ``F`` - an ideal in a multivariate polynomial ring

    OUTPUT:

        a Groebner basis for F

    .. note::

       The verbosity of this function may be controlled with a
       ``set_verbose()`` call. Any value >=1 will result in this
       function printing intermediate bases.

    EXAMPLES::

        sage: from sage.rings.polynomial.toy_buchberger import buchberger
        sage: R.<x,y,z> = PolynomialRing(QQ,3)
        sage: set_verbose(0)
        sage: buchberger(R.ideal([x^2 - z - 1, z^2 - y - 1, x*y^2 - x - 1]))
        [-y^3 + x*z - x + y, y^2*z + y^2 - x - z - 1, x*y^2 - x - 1, x^2 - z - 1, z^2 - y - 1]

    """
    G = set(F.gens())
    B = set(filter(lambda x_y: x_y[0] != x_y[1],
                   [(g1, g2) for g1 in G for g2 in G]))

    if get_verbose() >= 1:
        reductions_to_zero = 0

    while B!=set():
        g1,g2 = select(B)
        B.remove( (g1,g2) )

        h = spol(g1,g2).reduce(G)
        if h != 0:
            B = B.union( [(g,h) for g in G] )
            G.add( h )

        if get_verbose() >= 1:
            print "(%s, %s) => %s"%(g1, g2, h)
            print "G: %s\n"%(G)
            if h==0:
                reductions_to_zero +=1

    if get_verbose() >= 1:
        print "%d reductions to zero."%(reductions_to_zero)

    return Sequence(G)
Example #4
0
def buchberger(F):
    """
    Compute a Groebner basis using the original version of Buchberger's
    algorithm as presented in [BW1993]_, page 214.

    INPUT:

    - ``F`` -- an ideal in a multivariate polynomial ring

    OUTPUT: a Groebner basis for F

    .. NOTE::

       The verbosity of this function may be controlled with a
       ``set_verbose()`` call. Any value >=1 will result in this
       function printing intermediate bases.

    EXAMPLES::

        sage: from sage.rings.polynomial.toy_buchberger import buchberger
        sage: R.<x,y,z> = PolynomialRing(QQ)
        sage: I = R.ideal([x^2 - z - 1, z^2 - y - 1, x*y^2 - x - 1])
        sage: set_verbose(0)
        sage: gb = buchberger(I)
        sage: gb.is_groebner()
        True
        sage: gb.ideal() == I
        True
    """
    G = set(F.gens())
    B = set((g1, g2) for g1 in G for g2 in G if g1 != g2)

    if get_verbose() >= 1:
        reductions_to_zero = 0

    while B:
        g1, g2 = select(B)
        B.remove((g1, g2))

        h = spol(g1, g2).reduce(G)
        if h != 0:
            B = B.union((g, h) for g in G)
            G.add(h)

        if get_verbose() >= 1:
            print("(%s, %s) => %s" % (g1, g2, h))
            print("G: %s\n" % G)
            if h == 0:
                reductions_to_zero += 1

    if get_verbose() >= 1:
        print("%d reductions to zero." % reductions_to_zero)

    return Sequence(G)
Example #5
0
    def __call__(self, assumptions=None):
        """
        Run 'command' and collect output.

        INPUT:

        - ``assumptions`` - ignored, accepted for compatibility with
          other solvers (default: ``None``)

        TESTS:

        This class is not meant to be called directly::

            sage: from sage.sat.solvers.dimacs import DIMACS
            sage: fn = tmp_filename()
            sage: solver = DIMACS(filename=fn)
            sage: solver.add_clause( (1, -2 , 3) )
            sage: solver()
            Traceback (most recent call last):
            ...
            ValueError: No SAT solver command selected.
        """
        if assumptions is not None:
            raise NotImplementedError("Assumptions are not supported for DIMACS based solvers.")

        self.write()

        output_filename = None
        self._output = []

        command = self._command.strip()

        if not command:
            raise ValueError("No SAT solver command selected.")


        if "{output}" in command:
            output_filename = tmp_filename()
        command = command.format(input=self._headname, output=output_filename)

        args = shlex.split(command)

        try:
            process = subprocess.Popen(args, stdout=subprocess.PIPE)
        except OSError:
            raise OSError("Could run '%s', perhaps you need to add your SAT solver to $PATH?"%(" ".join(args)))

        try:
            while process.poll() is None:
                for line in iter(process.stdout.readline,''):
                    if get_verbose() or self._verbosity:
                        print line,
                        sys.stdout.flush()
                    self._output.append(line)
                sleep(0.1)
            if output_filename:
                self._output.extend(open(output_filename).readlines())
        except KeyboardInterrupt:
            process.kill()
            raise KeyboardInterrupt
def gghlite_brief(l, kappa, **kwds):
    """
    Return parameter choics for a GGHLite-like graded encoding scheme
    instance with security level at least ‘λ‘ and multilinearity level ‘κ‘
    :param l:security parameter ‘λ‘
    :param kappa: multilinearity level ‘k‘
    :returns:parameter choices for a GGHLite-like graded-encoding scheme
    .. note:: ‘‘lambda‘‘ is a reserved key word in Python.
    """
    n = _sage_const_1024 
    while True:
        params = gghlite_params(n, kappa, target_lambda=l, **kwds)
        best = gghlite_attacks(params, rerand=kwds.get('rerand', False))
        current = OrderedDict()
        current[u"λ"] = l
        current[u"κ"] = kappa
        current["n"] = n
        current["q"] = params["q"]
        current["|enc|"] = params["|enc|"]
        current["|par|"] = params["|par|"]
        current[u"δ_0"]= best[u"δ_0"]
        current[u"bkz2"]= best[u"bkz2"]
        current[u"sieve"] = best[u"sieve"]
        current[u"k"] = best[u"k"]
        # if get_verbose() >= 1:
        #     print(params_str(current))
        if best["bkz2"] >= ZZ(_sage_const_2 )**l and best["sieve"] >= ZZ(_sage_const_2 )**l:
            break
        n = _sage_const_2 *n
    if get_verbose() >= _sage_const_1 :
        print(params_str(current))
    return current
def gghlite_brief(l, kappa, **kwds):
    """
    Return parameter choics for a GGHLite-like graded encoding scheme
    instance with security level at least ‘λ‘ and multilinearity level ‘κ‘
    :param l:security parameter ‘λ‘
    :param kappa: multilinearity level ‘k‘
    :returns:parameter choices for a GGHLite-like graded-encoding scheme
    .. note:: ‘‘lambda‘‘ is a reserved key word in Python.
    """
    n = _sage_const_1024
    while True:
        params = gghlite_params(n, kappa, target_lambda=l, **kwds)
        best = gghlite_attacks(params, rerand=kwds.get('rerand', False))
        current = OrderedDict()
        current[u"λ"] = l
        current[u"κ"] = kappa
        current["n"] = n
        current["q"] = params["q"]
        current["|enc|"] = params["|enc|"]
        current["|par|"] = params["|par|"]
        current[u"δ_0"] = best[u"δ_0"]
        current[u"bkz2"] = best[u"bkz2"]
        current[u"sieve"] = best[u"sieve"]
        current[u"k"] = best[u"k"]
        # if get_verbose() >= 1:
        #     print(params_str(current))
        if best["bkz2"] >= ZZ(_sage_const_2)**l and best["sieve"] >= ZZ(
                _sage_const_2)**l:
            break
        n = _sage_const_2 * n
    if get_verbose() >= _sage_const_1:
        print(params_str(current))
    return current
Example #8
0
    def eliminate_linear_variables(self, maxlength=3, skip=lambda lm,tail: False, return_reductors=False):
        """
        Return a new system where linear leading variables are
        eliminated if the tail of the polynomial has length at most
        ``maxlength``.

        INPUT:

        - ``maxlength`` - an optional upper bound on the number of
          monomials by which a variable is replaced.

        - ``skip`` - an optional callable to skip eliminations. It
          must accept two parameters and return either ``True`` or
          ``False``. The two parameters are the leading term and the
          tail of a polynomial (default: ``lambda lm,tail: False``).

        - ``return_reductors`` - if ``True`` the list of polynomials
          with linear leading terms which were used for reduction is
          also returned (default: ``False``).

        EXAMPLE::
        
            sage: B.<a,b,c,d> = BooleanPolynomialRing()
            sage: F = Sequence([c + d + b + 1, a + c + d, a*b + c, b*c*d + c])
            sage: F.eliminate_linear_variables() # everything vanishes
            []
            sage: F.eliminate_linear_variables(maxlength=2)
            [b + c + d + 1, b*c + b*d + c, b*c*d + c]
            sage: F.eliminate_linear_variables(skip=lambda lm,tail: str(lm)=='a')
            [a + c + d, a*c + a*d + a + c, c*d + c]

        The list of reductors can be requested by setting 'return_reductors' to ``True``::

            sage: B.<a,b,c,d> = BooleanPolynomialRing()
            sage: F = Sequence([a + b + d, a + b + c])
            sage: F,R = F.eliminate_linear_variables(return_reductors=True)
            sage: F
            [c + d]
            sage: R
            [a + b + d]

        .. note:: 
          
            This is called "massaging" in [CBJ07]_.

        """
        from polybori.ll import ll_encode
        from polybori.ll import ll_red_nf_redsb
        from sage.rings.polynomial.pbori import BooleanPolynomialRing
        from sage.misc.misc import get_verbose

        R = self.ring()

        if not isinstance(R, BooleanPolynomialRing):
            raise NotImplementedError("Only BooleanPolynomialRing's are supported.")

        F = self

        elim = []

        while True: 
            linear = []
            higher = []

            for f in F:
                if f.degree() == 1 and len(f) <= maxlength + 1:
                    flm = f.lex_lead()
                    if skip(flm, f-flm):
                        higher.append(f)
                        continue
                    lex_lead = map(lambda x: x.lex_lead(), linear)
                    if not flm in lex_lead:
                        linear.append(f)
                    else:
                        higher.append(f)
                else:
                    higher.append(f)

            if not linear:
                break
            if not higher:
                higher = linear
                break

            assert len(set(linear)) == len(linear)

            rb = ll_encode(linear)

            elim.extend(linear)

            F = []

            for f in linear:
                f = ll_red_nf_redsb(f, rb)
                if f:
                    F.append(f)

            for f in higher:
                f = ll_red_nf_redsb(f, rb)
                if f:
                    F.append(f)
            if get_verbose() > 0:
                print ".",
        if get_verbose() > 0:
            print

        ret = PolynomialSequence(R, higher)
        if return_reductors:
            return ret, PolynomialSequence(R, elim)
        else:
            return ret
Example #9
0
    def __call__(self, assumptions=None):
        """
        Run 'command' and collect output.

        INPUT:

        - ``assumptions`` - ignored, accepted for compatibility with
          other solvers (default: ``None``)

        TESTS:

        This class is not meant to be called directly::

            sage: from sage.sat.solvers.dimacs import DIMACS
            sage: fn = tmp_filename()
            sage: solver = DIMACS(filename=fn)
            sage: solver.add_clause( (1, -2 , 3) )
            sage: solver()
            Traceback (most recent call last):
            ...
            ValueError: No SAT solver command selected.
        """
        if assumptions is not None:
            raise NotImplementedError(
                "Assumptions are not supported for DIMACS based solvers.")

        self.write()

        output_filename = None
        self._output = []

        command = self._command.strip()

        if not command:
            raise ValueError("No SAT solver command selected.")

        if "{output}" in command:
            output_filename = tmp_filename()
        command = command.format(input=self._headname, output=output_filename)

        args = shlex.split(command)

        try:
            process = subprocess.Popen(args, stdout=subprocess.PIPE)
        except OSError:
            raise OSError(
                "Could run '%s', perhaps you need to add your SAT solver to $PATH?"
                % (" ".join(args)))

        try:
            while process.poll() is None:
                for line in iter(process.stdout.readline, ''):
                    if get_verbose() or self._verbosity:
                        print line,
                        sys.stdout.flush()
                    self._output.append(line)
                sleep(0.1)
            if output_filename:
                self._output.extend(open(output_filename).readlines())
        except KeyboardInterrupt:
            process.kill()
            raise KeyboardInterrupt
Example #10
0
    def eliminate_linear_variables(self,
                                   maxlength=3,
                                   skip=lambda lm, tail: False,
                                   return_reductors=False):
        """
        Return a new system where linear leading variables are
        eliminated if the tail of the polynomial has length at most
        ``maxlength``.

        INPUT:

        - ``maxlength`` - an optional upper bound on the number of
          monomials by which a variable is replaced.

        - ``skip`` - an optional callable to skip eliminations. It
          must accept two parameters and return either ``True`` or
          ``False``. The two parameters are the leading term and the
          tail of a polynomial (default: ``lambda lm,tail: False``).

        - ``return_reductors`` - if ``True`` the list of polynomials
          with linear leading terms which were used for reduction is
          also returned (default: ``False``).

        EXAMPLE::
        
            sage: B.<a,b,c,d> = BooleanPolynomialRing()
            sage: F = Sequence([c + d + b + 1, a + c + d, a*b + c, b*c*d + c])
            sage: F.eliminate_linear_variables() # everything vanishes
            []
            sage: F.eliminate_linear_variables(maxlength=2)
            [b + c + d + 1, b*c + b*d + c, b*c*d + c]
            sage: F.eliminate_linear_variables(skip=lambda lm,tail: str(lm)=='a')
            [a + c + d, a*c + a*d + a + c, c*d + c]

        The list of reductors can be requested by setting 'return_reductors' to ``True``::

            sage: B.<a,b,c,d> = BooleanPolynomialRing()
            sage: F = Sequence([a + b + d, a + b + c])
            sage: F,R = F.eliminate_linear_variables(return_reductors=True)
            sage: F
            [c + d]
            sage: R
            [a + b + d]

        .. note:: 
          
            This is called "massaging" in [CBJ07]_.

        """
        from polybori.ll import ll_encode
        from polybori.ll import ll_red_nf_redsb
        from sage.rings.polynomial.pbori import BooleanPolynomialRing
        from sage.misc.misc import get_verbose

        R = self.ring()

        if not isinstance(R, BooleanPolynomialRing):
            raise NotImplementedError(
                "Only BooleanPolynomialRing's are supported.")

        F = self

        elim = []

        while True:
            linear = []
            higher = []

            for f in F:
                if f.degree() == 1 and len(f) <= maxlength + 1:
                    flm = f.lex_lead()
                    if skip(flm, f - flm):
                        higher.append(f)
                        continue
                    lex_lead = map(lambda x: x.lex_lead(), linear)
                    if not flm in lex_lead:
                        linear.append(f)
                    else:
                        higher.append(f)
                else:
                    higher.append(f)

            if not linear:
                break
            if not higher:
                higher = linear
                break

            assert len(set(linear)) == len(linear)

            rb = ll_encode(linear)

            elim.extend(linear)

            F = []

            for f in linear:
                f = ll_red_nf_redsb(f, rb)
                if f:
                    F.append(f)

            for f in higher:
                f = ll_red_nf_redsb(f, rb)
                if f:
                    F.append(f)
            if get_verbose() > 0:
                print ".",
        if get_verbose() > 0:
            print

        ret = PolynomialSequence(R, higher)
        if return_reductors:
            return ret, PolynomialSequence(R, elim)
        else:
            return ret