Esempio n. 1
0
def min_sat(clauses, max_n=1000, N=None, alg='sorter', raise_on_max_n=False):
    """
    Calculate the SAT solutions for the `clauses` for which the number of true
    literals from 1 to N is minimal.  Returned is the list of those solutions.
    When the clauses are unsatisfiable, an empty list is returned.

    alg can be any algorithm supported by generate_constraints, or 'iterate",
    which iterates all solutions and finds the smallest.

    max_n is the maximum number of iterations the algorithm will run
    through. If raise_on_max_n=True, the function will raise
    MaximumIterationsError if max_n solutions were found. In other words, in
    this case, it is possible another minimal solution could be found if max_n
    were larger.

    """
    log.debug("min_sat using alg: %s" % alg)
    try:
        import pycosat
    except ImportError:
        sys.exit('Error: could not import pycosat (required for dependency '
                 'resolving)')

    if not clauses:
        return []
    m = max(map(abs, chain(*clauses)))
    if not N:
        N = m
    if alg == 'iterate':
        min_tl, solutions = sys.maxsize, []
        try:
            pycosat.itersolve({(1, )})
        except TypeError:
            # Old versions of pycosat require lists. This conversion can be
            # very slow, though, so only do it if we need to.
            clauses = list(map(list, clauses))
        i = -1
        for sol, i in zip(pycosat.itersolve(clauses), range(max_n)):
            tl = sum(lit > 0 for lit in sol[:N])  # number of true literals
            if tl < min_tl:
                min_tl, solutions = tl, [sol]
            elif tl == min_tl:
                solutions.append(sol)
        log.debug("Iterate ran %s times" % (i + 1))
        if i + 1 == max_n and raise_on_max_n:
            raise MaximumIterationsError("min_sat ran max_n times")
        return solutions
    else:
        solution = sat(clauses)
        if not solution:
            return []
        eq = [(1, i) for i in range(1, N + 1)]

        def func(lo, hi):
            return list(generate_constraints(eq, m, [lo, hi], alg=alg))

        evaluate_func = partial(evaluate_eq, eq)
        # Since we have a solution, might as well make use of that fact
        max_val = evaluate_func(solution)
        log.debug("Using max_val %s. N=%s" % (max_val, N))
        constraints = bisect_constraints(0,
                                         min(max_val, N),
                                         clauses,
                                         func,
                                         evaluate_func=evaluate_func,
                                         increment=1000)

        return min_sat(list(chain(clauses, constraints)),
                       max_n=max_n,
                       N=N,
                       alg='iterate')
Esempio n. 2
0
 def func(lo, hi):
     return list(generate_constraints([(1, i) for i in range(1, N+1)], m,
         [lo, hi], alg=alg))
Esempio n. 3
0
def min_sat(clauses, max_n=1000, N=None, alg='sorter', raise_on_max_n=False):
    """
    Calculate the SAT solutions for the `clauses` for which the number of true
    literals from 1 to N is minimal.  Returned is the list of those solutions.
    When the clauses are unsatisfiable, an empty list is returned.

    alg can be any algorithm supported by generate_constraints, or 'iterate',
    which iterates all solutions and finds the smallest.

    max_n is the maximum number of iterations the algorithm will run
    through. If raise_on_max_n=True, the function will raise
    MaximumIterationsError if max_n solutions were found. In other words, in
    this case, it is possible another minimal solution could be found if max_n
    were larger.

    """
    log.debug("min_sat using alg: %s" % alg)
    try:
        import pycosat
    except ImportError:
        sys.exit('Error: could not import pycosat (required for dependency '
                 'resolving)')

    if not clauses:
        return []
    m = max(map(abs, chain(*clauses)))
    if not N:
        N = m
    if alg == 'iterate':
        min_tl, solutions = sys.maxsize, []
        try:
            pycosat.itersolve({(1,)})
        except TypeError:
            # Old versions of pycosat require lists. This conversion can be
            # very slow, though, so only do it if we need to.
            clauses = list(map(list, clauses))
        i = -1
        for sol, i in zip(pycosat.itersolve(clauses), range(max_n)):
            tl = sum(lit > 0 for lit in sol[:N]) # number of true literals
            if tl < min_tl:
                min_tl, solutions = tl, [sol]
            elif tl == min_tl:
                solutions.append(sol)
        log.debug("Iterate ran %s times" % (i + 1))
        if i + 1 == max_n and raise_on_max_n:
            raise MaximumIterationsError("min_sat ran max_n times")
        return solutions
    else:
        solution = sat(clauses)
        if not solution:
            return []
        eq = [(1, i) for i in range(1, N+1)]
        def func(lo, hi):
            return list(generate_constraints(eq, m,
                [lo, hi], alg=alg))
        evaluate_func = partial(evaluate_eq, eq)
        # Since we have a solution, might as well make use of that fact
        max_val = evaluate_func(solution)
        log.debug("Using max_val %s. N=%s" % (max_val, N))
        constraints = bisect_constraints(0, min(max_val, N), clauses, func,
            evaluate_func=evaluate_func, increment=1000)

        return min_sat(list(chain(clauses, constraints)), max_n=max_n, N=N, alg='iterate')
Esempio n. 4
0
    if not N:
        N = m
    if alg == 'iterate':
        min_tl, solutions = sys.maxsize, []
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
        try:
            pycosat.itersolve({(1,)})
        except TypeError:
            # Old versions of pycosat require lists. This conversion can be
            # very slow, though, so only do it if we need to.
            clauses = list(map(list, clauses))
        i = -1
        for sol, i in zip(pycosat.itersolve(clauses), range(max_n)):
=======
        for sol in islice(pycosat.itersolve(clauses), max_n):
>>>>>>> conda/min_constraints
=======
        for sol in islice(pycosat.itersolve(clauses), max_n):
>>>>>>> origin/min_constraints
=======
        for sol in islice(pycosat.itersolve(clauses), max_n):
>>>>>>> princeofdarkness76/min_constraints
=======
        for sol in islice(pycosat.itersolve(clauses), max_n):
>>>>>>> origin/min_constraints
            tl = sum(lit > 0 for lit in sol[:N]) # number of true literals
            if tl < min_tl:
                min_tl, solutions = tl, [sol]