Exemplo n.º 1
0
def learn(F, converter=None, solver=None, max_learnt_length=3, interreduction=False, **kwds):
    """
    Learn new polynomials by running SAT-solver ``solver`` on
    SAT-instance produced by ``converter`` from ``F``.

    INPUT:

    - ``F`` - a sequence of Boolean polynomials

    - ``converter`` - an ANF to CNF converter class or object.  If ``converter`` is ``None`` then
      :class:`sage.sat.converters.polybori.CNFEncoder` is used to construct a new
      converter. (default: ``None``)

    - ``solver`` - a SAT-solver class or object. If ``solver`` is ``None`` then
      :class:`sage.sat.solvers.cryptominisat.CryptoMiniSat` is used to construct a new converter.
      (default: ``None``)

    - ``max_learnt_length`` - only clauses of length <= ``max_length_learnt`` are considered and
      converted to polynomials. (default: ``3``)

    - ``interreduction`` - inter-reduce the resulting polynomials (default: ``False``)

    .. NOTE::

       More parameters can be passed to the converter and the solver by prefixing them with ``c_`` and
       ``s_`` respectively. For example, to increase CryptoMiniSat's verbosity level, pass
       ``s_verbosity=1``.

    OUTPUT:

        A sequence of Boolean polynomials.

    EXAMPLES::

       sage: from sage.sat.boolean_polynomials import learn as learn_sat # optional - cryptominisat

    We construct a simple system and solve it::

       sage: set_random_seed(2300)                      # optional - cryptominisat
       sage: sr = mq.SR(1,2,2,4,gf2=True,polybori=True) # optional - cryptominisat
       sage: F,s = sr.polynomial_system()               # optional - cryptominisat
       sage: H = learn_sat(F)                           # optional - cryptominisat
       sage: H[-1]                                      # optional - cryptominisat
       k033 + 1
    """
    try:
        len(F)
    except AttributeError:
        F = F.gens()
        len(F)

    P = next(iter(F)).parent()
    K = P.base_ring()

    # instantiate the SAT solver

    if solver is None:
        from sage.sat.solvers.cryptominisat import CryptoMiniSat as solver

    solver_kwds = {}
    for k, v in six.iteritems(kwds):
        if k.startswith("s_"):
            solver_kwds[k[2:]] = v

    solver = solver(**solver_kwds)

    # instantiate the ANF to CNF converter

    if converter is None:
        from sage.sat.converters.polybori import CNFEncoder as converter

    converter_kwds = {}
    for k, v in six.iteritems(kwds):
        if k.startswith("c_"):
            converter_kwds[k[2:]] = v

    converter = converter(solver, P, **converter_kwds)

    phi = converter(F)
    rho = dict((phi[i], i) for i in range(len(phi)))

    s = solver()

    if s:
        learnt = [x + K(s[rho[x]]) for x in P.gens()]
    else:
        learnt = []
        try:
            lc = solver.learnt_clauses()
        except (AttributeError, NotImplementedError):
        # solver does not support recovering learnt clauses
            lc = []
        for c in lc:
            if len(c) <= max_learnt_length:
                try:
                    learnt.append(converter.to_polynomial(c))
                except (ValueError, NotImplementedError, AttributeError):
                    # the solver might have learnt clauses that contain CNF
                    # variables which have no correspondence to variables in our
                    # polynomial ring (XOR chaining variables for example)
                    pass

    learnt = PolynomialSequence(P, learnt)

    if interreduction:
        learnt = learnt.ideal().interreduced_basis()
    return learnt
Exemplo n.º 2
0
def learn(F,
          converter=None,
          solver=None,
          max_learnt_length=3,
          interreduction=False,
          **kwds):
    """
    Learn new polynomials by running SAT-solver ``solver`` on
    SAT-instance produced by ``converter`` from ``F``.

    INPUT:

    - ``F`` - a sequence of Boolean polynomials

    - ``converter`` - an ANF to CNF converter class or object.  If ``converter`` is ``None`` then
      :class:`sage.sat.converters.polybori.CNFEncoder` is used to construct a new
      converter. (default: ``None``)

    - ``solver`` - a SAT-solver class or object. If ``solver`` is ``None`` then
      :class:`sage.sat.solvers.cryptominisat.CryptoMiniSat` is used to construct a new converter.
      (default: ``None``)

    - ``max_learnt_length`` - only clauses of length <= ``max_length_learnt`` are considered and
      converted to polynomials. (default: ``3``)

    - ``interreduction`` - inter-reduce the resulting polynomials (default: ``False``)

    .. NOTE::

       More parameters can be passed to the converter and the solver by prefixing them with ``c_`` and
       ``s_`` respectively. For example, to increase CryptoMiniSat's verbosity level, pass
       ``s_verbosity=1``.

    OUTPUT:

        A sequence of Boolean polynomials.

    EXAMPLE::

       sage: from sage.sat.boolean_polynomials import learn as learn_sat # optional - cryptominisat

    We construct a simple system and solve it::

       sage: set_random_seed(2300)                      # optional - cryptominisat
       sage: sr = mq.SR(1,2,2,4,gf2=True,polybori=True) # optional - cryptominisat
       sage: F,s = sr.polynomial_system()               # optional - cryptominisat
       sage: H = learn_sat(F)                           # optional - cryptominisat
       sage: H[-1]                                      # optional - cryptominisat
       k033 + 1

    We construct a slightly larger equation system and recover some
    equations after 20 restarts::

       sage: set_random_seed(2303)                        # optional - cryptominisat
       sage: sr = mq.SR(1,4,4,4,gf2=True,polybori=True)   # optional - cryptominisat
       sage: F,s = sr.polynomial_system()                 # optional - cryptominisat
       sage: from sage.sat.boolean_polynomials import learn as learn_sat # optional - cryptominisat
       sage: H = learn_sat(F, s_maxrestarts=20, interreduction=True)     # optional - cryptominisat
       sage: H[-1]                                        # optional - cryptominisat, output random
       k001200*s031*x011201 + k001200*x011201

    .. NOTE::

       This function is meant to be called with some parameter such
       that the SAT-solver is interrupted. For CryptoMiniSat this is
       max_restarts, so pass 'c_max_restarts' to limit the number of
       restarts CryptoMiniSat will attempt. If no such parameter is
       passed, then this function behaves essentially like
       :func:`solve` except that this function does not support
       ``n>1``.

    TESTS:

    We test that :trac:`17351` is fixed, by checking that the following doctest does not raise an
    error::

        sage: P.<a,b,c> = BooleanPolynomialRing()
        sage: F = [a*c + a + b*c + c + 1,  a*b + a*c + a + c + 1,  a*b + a*c + a + b*c + 1]
        sage: from sage.sat.boolean_polynomials import learn as learn_sat # optional - cryptominisat
        sage: learn_sat(F, s_maxrestarts=0, interreduction=True)      # optional - cryptominisat
        []
    """
    try:
        len(F)
    except AttributeError:
        F = F.gens()
        len(F)

    P = next(iter(F)).parent()
    K = P.base_ring()

    # instantiate the SAT solver

    if solver is None:
        from sage.sat.solvers.cryptominisat import CryptoMiniSat as solver

    solver_kwds = {}
    for k, v in kwds.iteritems():
        if k.startswith("s_"):
            solver_kwds[k[2:]] = v

    solver = solver(**solver_kwds)

    # instantiate the ANF to CNF converter

    if converter is None:
        from sage.sat.converters.polybori import CNFEncoder as converter

    converter_kwds = {}
    for k, v in kwds.iteritems():
        if k.startswith("c_"):
            converter_kwds[k[2:]] = v

    converter = converter(solver, P, **converter_kwds)

    phi = converter(F)
    rho = dict((phi[i], i) for i in range(len(phi)))

    s = solver()

    if s:
        learnt = [x + K(s[rho[x]]) for x in P.gens()]
    else:
        learnt = []
        for c in solver.learnt_clauses():
            if len(c) <= max_learnt_length:
                try:
                    learnt.append(converter.to_polynomial(c))
                except (ValueError, NotImplementedError, AttributeError):
                    # the solver might have learnt clauses that contain CNF
                    # variables which have no correspondence to variables in our
                    # polynomial ring (XOR chaining variables for example)
                    pass

    learnt = PolynomialSequence(P, learnt)

    if interreduction:
        learnt = learnt.ideal().interreduced_basis()
    return learnt
Exemplo n.º 3
0
def learn(F,
          converter=None,
          solver=None,
          max_learnt_length=3,
          interreduction=False,
          **kwds):
    """
    Learn new polynomials by running SAT-solver ``solver`` on
    SAT-instance produced by ``converter`` from ``F``.

    INPUT:

    - ``F`` - a sequence of Boolean polynomials

    - ``converter`` - an ANF to CNF converter class or object.  If ``converter`` is ``None`` then
      :class:`sage.sat.converters.polybori.CNFEncoder` is used to construct a new
      converter. (default: ``None``)

    - ``solver`` - a SAT-solver class or object. If ``solver`` is ``None`` then
      :class:`sage.sat.solvers.cryptominisat.CryptoMiniSat` is used to construct a new converter.
      (default: ``None``)

    - ``max_learnt_length`` - only clauses of length <= ``max_length_learnt`` are considered and
      converted to polynomials. (default: ``3``)

    - ``interreduction`` - inter-reduce the resulting polynomials (default: ``False``)

    .. NOTE::

       More parameters can be passed to the converter and the solver by prefixing them with ``c_`` and
       ``s_`` respectively. For example, to increase CryptoMiniSat's verbosity level, pass
       ``s_verbosity=1``.

    OUTPUT:

        A sequence of Boolean polynomials.

    EXAMPLES::

       sage: from sage.sat.boolean_polynomials import learn as learn_sat # optional - cryptominisat

    We construct a simple system and solve it::

       sage: set_random_seed(2300)                      # optional - cryptominisat
       sage: sr = mq.SR(1,2,2,4,gf2=True,polybori=True) # optional - cryptominisat
       sage: F,s = sr.polynomial_system()               # optional - cryptominisat
       sage: H = learn_sat(F)                           # optional - cryptominisat
       sage: H[-1]                                      # optional - cryptominisat
       k033 + 1
    """
    try:
        len(F)
    except AttributeError:
        F = F.gens()
        len(F)

    P = next(iter(F)).parent()
    K = P.base_ring()

    # instantiate the SAT solver

    if solver is None:
        from sage.sat.solvers.cryptominisat import CryptoMiniSat as solver

    solver_kwds = {}
    for k, v in kwds.items():
        if k.startswith("s_"):
            solver_kwds[k[2:]] = v

    solver = solver(**solver_kwds)

    # instantiate the ANF to CNF converter

    if converter is None:
        from sage.sat.converters.polybori import CNFEncoder as converter

    converter_kwds = {}
    for k, v in kwds.items():
        if k.startswith("c_"):
            converter_kwds[k[2:]] = v

    converter = converter(solver, P, **converter_kwds)

    phi = converter(F)
    rho = dict((phi[i], i) for i in range(len(phi)))

    s = solver()

    if s:
        learnt = [x + K(s[rho[x]]) for x in P.gens()]
    else:
        learnt = []
        try:
            lc = solver.learnt_clauses()
        except (AttributeError, NotImplementedError):
            # solver does not support recovering learnt clauses
            lc = []
        for c in lc:
            if len(c) <= max_learnt_length:
                try:
                    learnt.append(converter.to_polynomial(c))
                except (ValueError, NotImplementedError, AttributeError):
                    # the solver might have learnt clauses that contain CNF
                    # variables which have no correspondence to variables in our
                    # polynomial ring (XOR chaining variables for example)
                    pass

    learnt = PolynomialSequence(P, learnt)

    if interreduction:
        learnt = learnt.ideal().interreduced_basis()
    return learnt
Exemplo n.º 4
0
def learn(F, converter=None, solver=None, max_learnt_length=3, interreduction=False, **kwds):
    """
    Learn new polynomials by running SAT-solver ``solver`` on
    SAT-instance produced by ``converter`` from ``F``.

    INPUT:

    - ``F`` - a sequence of Boolean polynomials

    - ``converter`` - an ANF to CNF converter class or object.  If ``converter`` is ``None`` then
      :class:`sage.sat.converters.polybori.CNFEncoder` is used to construct a new
      converter. (default: ``None``)

    - ``solver`` - a SAT-solver class or object. If ``solver`` is ``None`` then
      :class:`sage.sat.solvers.cryptominisat.CryptoMiniSat` is used to construct a new converter.
      (default: ``None``)

    - ``max_learnt_length`` - only clauses of length <= ``max_length_learnt`` are considered and
      converted to polynomials. (default: ``3``)

    - ``interreduction`` - inter-reduce the resulting polynomials (default: ``False``)

    .. NOTE::

       More parameters can be passed to the converter and the solver by prefixing them with ``c_`` and
       ``s_`` respectively. For example, to increase CryptoMiniSat's verbosity level, pass
       ``s_verbosity=1``.

    OUTPUT:

        A sequence of Boolean polynomials.

    EXAMPLE::

       sage: from sage.sat.boolean_polynomials import learn as learn_sat # optional - cryptominisat

    We construct a simple system and solve it::

       sage: set_random_seed(2300)                      # optional - cryptominisat
       sage: sr = mq.SR(1,2,2,4,gf2=True,polybori=True) # optional - cryptominisat
       sage: F,s = sr.polynomial_system()               # optional - cryptominisat
       sage: H = learn_sat(F)                           # optional - cryptominisat
       sage: H[-1]                                      # optional - cryptominisat
       k033 + 1

    We construct a slightly larger equation system and recover some
    equations after 20 restarts::

       sage: set_random_seed(2303)                        # optional - cryptominisat
       sage: sr = mq.SR(1,4,4,4,gf2=True,polybori=True)   # optional - cryptominisat
       sage: F,s = sr.polynomial_system()                 # optional - cryptominisat
       sage: from sage.sat.boolean_polynomials import learn as learn_sat # optional - cryptominisat
       sage: H = learn_sat(F, s_maxrestarts=20, interreduction=True)     # optional - cryptominisat
       sage: H[-1]                                        # optional - cryptominisat, output random
       k001200*s031*x011201 + k001200*x011201

    .. NOTE::

       This function is meant to be called with some parameter such
       that the SAT-solver is interrupted. For CryptoMiniSat this is
       max_restarts, so pass 'c_max_restarts' to limit the number of
       restarts CryptoMiniSat will attempt. If no such parameter is
       passed, then this function behaves essentially like
       :func:`solve` except that this function does not support
       ``n>1``.

    TESTS:

    We test that :trac:`17351` is fixed, by checking that the following doctest does not raise an
    error::

        sage: P.<a,b,c> = BooleanPolynomialRing()
        sage: F = [a*c + a + b*c + c + 1,  a*b + a*c + a + c + 1,  a*b + a*c + a + b*c + 1]
        sage: from sage.sat.boolean_polynomials import learn as learn_sat # optional - cryptominisat
        sage: learn_sat(F, s_maxrestarts=0, interreduction=True)      # optional - cryptominisat
        []
    """
    try:
        len(F)
    except AttributeError:
        F = F.gens()
        len(F)

    P = next(iter(F)).parent()
    K = P.base_ring()

    # instantiate the SAT solver

    if solver is None:
        from sage.sat.solvers.cryptominisat import CryptoMiniSat as solver

    solver_kwds = {}
    for k, v in kwds.iteritems():
        if k.startswith("s_"):
            solver_kwds[k[2:]] = v

    solver = solver(**solver_kwds)

    # instantiate the ANF to CNF converter

    if converter is None:
        from sage.sat.converters.polybori import CNFEncoder as converter

    converter_kwds = {}
    for k, v in kwds.iteritems():
        if k.startswith("c_"):
            converter_kwds[k[2:]] = v

    converter = converter(solver, P, **converter_kwds)

    phi = converter(F)
    rho = dict((phi[i], i) for i in range(len(phi)))

    s = solver()

    if s:
        learnt = [x + K(s[rho[x]]) for x in P.gens()]
    else:
        learnt = []
        for c in solver.learnt_clauses():
            if len(c) <= max_learnt_length:
                try:
                    learnt.append(converter.to_polynomial(c))
                except (ValueError, NotImplementedError, AttributeError):
                    # the solver might have learnt clauses that contain CNF
                    # variables which have no correspondence to variables in our
                    # polynomial ring (XOR chaining variables for example)
                    pass

    learnt = PolynomialSequence(P, learnt)

    if interreduction:
        learnt = learnt.ideal().interreduced_basis()
    return learnt