Example #1
0
def solve_SAT(expr, num_solutions=None):
    """
    Returns a iterator of {var: truth value} assignments which satisfy the given
    expression.

    Expressions should not include a variable named ``TRUE_``, since those
    are used in the internals of this function as stand-ins for truth literals.
    """
    expr = convert_to_conjunctive_normal_form(expr)
    Assignment = get_assignment_class(expr)

    # Hack to include a True literal (not directly supported by pycosat API).
    # We add a trivial constraint to the list of constraints, forcing this
    # variables to be True in any solutions. Note that this is still conjunctive
    # normal form, since T and F are literals.
    T = Var('TRUE_')
    expr = expr & T

    vars = list(get_free_variables(expr))

    # 1-index, since pycosat expects nonzero integers.
    var2pycosat_index = {v: i + 1 for i, v in enumerate(vars)}

    def get_pycosat_index(literal):
        # pycosat accepts input as a list of CNF subclauses (disjunctions of variables
        # or negated variables).
        if isinstance(literal, Not):
            return -get_pycosat_index(literal.children[0])
        elif isinstance(literal, Var):
            return var2pycosat_index[literal]
        elif isinstance(literal, ExpressionNode):  # pragma: no cover
            raise TypeError('Unhandled literal type %r' % literal)
        else:
            # Here we assume this is some other python object, so we consider it
            # a boolean.
            return var2pycosat_index[T] if literal else -var2pycosat_index[T]

    constraints = [
        map(get_pycosat_index,
            # Child is one of a literal or a disjunction of literals.
            (child.children if isinstance(child, Or) else [child]))
        for child in expr.children
    ]

    solutions = (
        pycosat.itersolve(constraints)
        if num_solutions is None else pycosat.itersolve(constraints, num_solutions))
    for solution in solutions:
        namespace = {}
        for i, var_assignment in enumerate(solution):
            # pycosat returns the solution as a list of positive or negative
            # 1-indexed variable numbers. Positive indices correspond to assignments
            # to True, and negative corresponds to False.
            as_bool = var_assignment > 0
            var = vars[i]
            if var == T:
                assert as_bool, 'Bug: Solution has an invalid solution to the T literal.'
            else:
                namespace[var.name] = as_bool
        yield Assignment(**namespace)
Example #2
0
def sat(clauses):
    """
    Calculate a SAT solution for `clauses`.

    Returned is the list of those solutions.  When the clauses are
    unsatisfiable, an empty list is returned.

    """
    try:
        import pycosat
    except ImportError:
        sys.exit('Error: could not import pycosat (required for dependency '
                 'resolving)')

    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))

    solution = pycosat.solve(clauses)
    if solution == "UNSAT" or solution == "UNKNOWN": # wtf https://github.com/ContinuumIO/pycosat/issues/14
        return []
    # XXX: If solution == [] (i.e., clauses == []), the result will have
    # boolean value of False even though the clauses are not unsatisfiable)
    return solution
Example #3
0
def main():
    # A requires B
    r1 = [-1, 2]

    # A requires C
    r2 = [-1, 3]

    # B conflicts C
    r3 = [-2, -3]

    # A conflicts B
    r4 = [-1, -2]

    # (-A|B) & (-A|C) & (-B|-C)
    cnf1 = [r1, r2, r3]

    # (-A|B) & (-A|-B)
    cnf2 = [r1, r4]

    print("Case 1:")
    for sol in pycosat.itersolve(cnf1):
        interpret(sol)
        print("\t----")

    print("Case 2:")
    for sol in pycosat.itersolve(cnf2):
        interpret(sol)
        print("\t----")
Example #4
0
 def test_shuffle_clauses(self):
     ref_sols = set(tuple(sol) for sol in itersolve(clauses1))
     for _ in range(10):
         cnf = copy.deepcopy(clauses1)
         # shuffling the clauses does not change the solutions
         random.shuffle(cnf)
         self.assertEqual(set(tuple(sol) for sol in itersolve(cnf)),
                          ref_sols)
Example #5
0
    def test_cnf1(self):
        for sol in itersolve(clauses1, nvars1):
            #sys.stderr.write('%r\n' % repr(sol))
            self.assertTrue(evaluate(clauses1, sol))

        sols = list(itersolve(clauses1, vars=nvars1))
        self.assertEqual(len(sols), 18)
        # ensure solutions are unique
        self.assertEqual(len(set(tuple(sol) for sol in sols)), 18)
Example #6
0
def min_sat(clauses, max_n=1000, N=None, alg='iterate'):
    """
    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.

    """
    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))
        for sol in islice(pycosat.itersolve(clauses), 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)
        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')
Example #7
0
 def solve(self):
     """
     Produces an iterator for schedule possibilities that have no conflicts.
     
     Solves the constraints using a SAT solving algorithm and processes the results.
     """
     return ([self.index_mapping[y] for y in x if y > 0] for x in pycosat.itersolve(self.constraints))
Example #8
0
def min_sat(clauses, max_n=1000):
    """
    Calculate the SAT solutions for the `clauses` for which the number of
    true literals is minimal.  Returned is the list of those solutions.
    When the clauses are unsatisfiable, an empty list is returned.

    This function could be implemented using a Pseudo-Boolean SAT solver,
    which would avoid looping over the SAT solutions, and would therefore
    be much more efficient.  However, for our purpose the current
    implementation is good enough.
    """
    try:
        import pycosat
    except ImportError:
        sys.exit('Error: could not import pycosat (required for dependency '
                 'resolving)')

    min_tl, solutions = sys.maxsize, []
    for sol in islice(pycosat.itersolve(clauses), max_n):
        tl = sum(lit > 0 for lit in sol) # number of true literals
        if tl < min_tl:
            min_tl, solutions = tl, [sol]
        elif tl == min_tl:
            solutions.append(sol)

    return solutions
Example #9
0
def solve(n):
	y =[]
	#rows
	for i in range (1,(n*n)+1,n):
		y += vertical(range(i,i+n,1),True)

	#columns
	for i in range (1,n+1):
		y+= vertical(range(i,(n*n)-n+1+i,n),True)
		
	#diagonals 
	y+=diagonal(1,n)
	
	#results
	result = []
	for sol in pycosat.itersolve(y):
		result.append(sol)

	#replace numbers with something more meaningful
	result = changeFormat(result,n)
	#return a boolean list indicating which solutions are unique 
	isValid = returnWithoutRotations(result)
	#figure out how many unique solutions there are
	NValidSol = 0
	for i in range(0,len(result)): 
		if isValid[i] :
			NValidSol += 1
	#print out all the unique solutions
	for i in range(0,len(result)):
		if(isValid[i]):
			printSol(result[i])

	print("There are " , NValidSol ,  " unique solutions with rotations and reflections")
Example #10
0
def solve():
    clauses = queens_clauses()
    # solve the SAT problem
    for sol in pycosat.itersolve(clauses):
        sol = set(sol)
        for i in range(N):
            print(''.join('Q' if v(i, j) in sol else '.' for j in range(N)))
        print('')
Example #11
0
    def solutions(self):
        """
        Yield each solution to the current set of constraints.
        """
        solution_found = False
        for solution in pycosat.itersolve(self.clauses):
            yield self.remap_solution(solution)
            solution_found = True

        if not solution_found:
            # Only present to raise a descriptive exception.
            self.solution
Example #12
0
    def minimal_solutions(self):
        # this is a bit of a strawman.  the idea is, we need to enumerate all of the SAT
        # solutions to know which is the smallest!  the containment thing in the old version (below)
        # seems sketchy to me, due to nonmonotonicity.  return to this later.
        solns = []
        for soln in pycosat.itersolve(self.satformula):
            solns.append(frozenset(map(self.vars.lookupNum, filter(lambda x: x > 0, soln))))

        def getKey(item):
            return len(item)

        for soln in sorted(solns, key=getKey):
            yield soln
Example #13
0
    def Nminimal_solutions(self):
        solns = []        
        done = []
        for soln in pycosat.itersolve(self.satformula):
            solns.append(frozenset(map(self.vars.lookupNum, filter(lambda x: x > 0, soln))))
        
        def getKey(item):
            return len(item)

        for soln in sorted(solns, key=getKey):
            #if not done.has_key(soln):
            #    yield soln
            if self.contained_in_none(done, soln):
                yield soln
            done.append(soln)
Example #14
0
def main(req_use):
    if req_use.strip() == '':
        return [[]]
    # REQUIRED_USE variable value for which the combinations
    # are being generated

    # If flags aren't provided, match words from REQUIRED_USE
    flags = re.findall(r'\w+', req_use)

    # Remove duplicates
    flags = list(set(flags))
    # sort reverse to length (so that they can be replaced in
    # this order by numbers later)
    flags = sorted(flags, key=len)
    flags.reverse()

    i = 1
    dict = {}
    rev_dict = {}
    # Assign a number to each keyword (to send to pycosat as
    # it accepts cnf in form of numbers )
    for k in flags:
        dict[k] = i
        rev_dict[i] = k
        i += 1

    # Generate the needed boolean expression
    cnf_out = solve(req_use)

    # str(object) gives a string in CNF form
    cnf_str = str(cnf_out)

    # Replace all flags with numerical equivalent
    for key in flags:
        cnf_str = cnf_str.replace(key, str(dict[key]))

    # Convert to form needed by pycosat
    cnf_str = cnf_str[1:-1]
    cnf_lst = cnf_str.split(') & (')
    for i in range(len(cnf_lst)):
        cnf_lst[i] = [int(k) for k in cnf_lst[i].split(' | ')]

    # Generate all possible solutions to the equation
    k = (list(pycosat.itersolve(cnf_lst)))
    for soln in k:
        for i in range(0, len(soln)):
            soln[i] = ( "-" if soln[i] < 0 else "" ) + rev_dict[abs(soln[i])]
    return k
Example #15
0
File: logic.py Project: ARF1/conda
def sat(clauses, iterator=False):
    """
    Calculate a SAT solution for `clauses`.

    Returned is the list of those solutions.  When the clauses are
    unsatisfiable, an empty list is returned.

    """
    if pycosat_prep:
        clauses = list(map(list,clauses))
    if iterator:
        return pycosat.itersolve(clauses)
    solution = pycosat.solve(clauses)
    if solution == "UNSAT" or solution == "UNKNOWN":
        return None
    return solution
Example #16
0
def process_cnf_file(path):
    sys.stdout.write('%30s:  ' % basename(path))
    sys.stdout.flush()

    clauses, n_vars = read_cnf(path)
    sys.stdout.write('vars: %6d   cls: %6d   ' % (n_vars, len(clauses)))
    sys.stdout.flush()
    n_sol = 0
    for sol in itersolve(clauses, n_vars):
        sys.stdout.write('.')
        sys.stdout.flush()
        assert evaluate(clauses, sol)
        n_sol += 1
    sys.stdout.write("%d\n" % n_sol)
    sys.stdout.flush()
    return n_sol
def _generate_schedules_sat_from_sections(sections, busy_times, preferences):
    clauses = []

    # Map from input domain to SAT domain
    # - input domain: course sections
    # - SAT domain: integers
    from_index, from_string, to_index = _build_section_index(sections)

    # Constraint: Must schedule one section for each core component
    core_clauses = collections.defaultdict(list)
    for core_section in sections:
        index = to_index[core_section.get('asString')]
        core_clauses[core_section.get('course') + core_section.get('component')].append(index)
    clauses += [v for k, v in core_clauses.iteritems()]

    # Constraint: Must not schedule conflicting sections together
    # Note: sections in the same component conflict
    # Note: recall (A' + B') == (AB)'
    conflict_clauses = []
    for a, b in _get_conflicts(sections, busy_times):
        if a.get('asString') != b.get('asString'):
            conflict_clauses.append([-1 * to_index[a.get('asString')],
                                     -1 * to_index[b.get('asString')]])
        else:
            conflict_clauses.append([-1 * to_index[a.get('asString')]])
    clauses += conflict_clauses

    # Solve the SAT problem and map back to input domain from SAT domain
    schedules = []
    for solution in pycosat.itersolve(clauses):
        sections = [from_index[i] for i in solution
                    if i > 0]
        schedules.append(Schedule(sections=sections,
                                  preferences=preferences))
        if len(schedules) > 100:
            break
    return schedules
Example #18
0
def mate(ind1, ind2, groups, model):
    # g = deepcopy(groups)
    # random.shuffle(g)
    # g = g[:int(len(g)*0.1)]
    # g = [item for i in g for item in i]
    # s1 = list(ind1)
    # s2 = list(ind2)
    # for i in range(len(s1)):
    #     if i in g:
    #         s1[i], s2[i] = s2[i], s1[i]
    # split_point = random.randint(0, len(s1))
    # ind1 = model.Individual(''.join(s1[:split_point]+s2[split_point:]))
    # ind2 = model.Individual(''.join(s2[:split_point]+s1[split_point:]))
    # pdb.set_trace()
    # return ind1, ind2

    diff = [i for i, (x, y) in enumerate(zip(ind1, ind2)) if x != y]
    # lock the irrelevant parts
    cnfs = []
    for i in range(len(ind1)):
        if random.random() < 0.1: continue
        if i not in diff:
            if ind1[i] == '1':
                cnfs += [[i+1]]
            else:
                cnfs += [[-i-1]]
    sat_engine = pycosat.itersolve(model.cnfs + cnfs)
    l = list(islice(sat_engine, 2))
    if len(l) == 0:
        return ind1, ind2
    if len(l) == 1:
        return model.Individual(pycosatSol2binstr(l[0])), ind2
    else:
        ind1 = model.Individual(pycosatSol2binstr(l[0]))
        ind2 = model.Individual(pycosatSol2binstr(l[1]))
        # pdb.set_trace()
        return ind1, ind2
Example #19
0
def grouping_dimacs_model_by_sat_solver(dimacs_model):
    # results start from 0
    appendix = list()
    model = dimacs_model
    inds = []
    i = 0
    cnfs = deepcopy(model.cnfs)
    groups = list()
    while True:
        sat_engine = pycosat.itersolve(cnfs)
        i = 0
        for sol in sat_engine:
            i += 1
            if i > 100: break
            inds.append(model.Individual(pycosatSol2binstr(sol)))
        tmp = map(list, zip(*inds))
        tmp = map(lambda x: len(set(x)), tmp)
        group1 = [i for i, j in enumerate(tmp) if j > 1]

        if len(group1) > 0:
            groups.append(group1)
        else:
            break

        addition = []
        for i, j in zip(group1, itemgetter(*group1)(inds[0])):
            if j == '0':
                addition.append([-i-1])
            else:
                addition.append([i+1])

        cnfs = cnfs + addition
        appendix.extend(inds)
        inds = []

    return groups, appendix
Example #20
0
 def test_cnf3_3vars(self):
     self.assertEqual(list(itersolve(clauses3, 3)),
                      [[-1, -2, -3], [-1, -2, 3]])
Example #21
0
 def test_many_clauses(self):
     ref_sols = set(tuple(sol) for sol in itersolve(clauses1))
     # repeating the clauses many times does not change the solutions
     cnf = 100 * copy.deepcopy(clauses1)
     self.assertEqual(set(tuple(sol) for sol in itersolve(cnf)),
                      ref_sols)
Example #22
0
=======
    m = max(chain(*clauses))
>>>>>>> princeofdarkness76/min_constraints
=======
    m = max(chain(*clauses))
>>>>>>> origin/min_constraints
    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
Example #23
0
 def test_gen_clauses(self):
     def gen_clauses():
         for clause in clauses1:
             yield clause
     self.assertTrue(all(evaluate(clauses1, sol) for sol in
                         itersolve(gen_clauses())))
Example #24
0
 def test_tuple_caluses(self):
     self.assertTrue(all(evaluate(clauses1, sol) for sol in
                         itersolve(tuple(clauses1))))
Example #25
0
 def test_no_clauses(self):
     for n in range(7):
         self.assertEqual(len(list(itersolve([], vars=n))), 2 ** n)
Example #26
0
# Ensure the given cells are shaded.
def fix_givens():
    clauses = []
    for row, col in GIVENS:
        clauses.append([shaded_vars[row, col].idx])

    return clauses

# Put together all the clauses, and then find the results.

all_clauses = (
    row_run_implies_shaded() +
    col_run_implies_shaded() +
    shaded_implies_row_run() +
    shaded_implies_col_run() +
    row_run_ordering() +
    col_run_ordering() +
    row_run_at_most_one_position() +
    col_run_at_most_one_position() +
    row_run_at_least_one_position() +
    col_run_at_least_one_position() +
    exclude_invalid_row_run_positions() +
    exclude_invalid_col_run_positions() +
    fix_givens()
)

for sol_idx, sol in enumerate(pycosat.itersolve(all_clauses)):
    pretty_print_solution(sol)

 def test_each_clause_tuples(self):
     self.assertTrue(
         all(
             evaluate(clauses1, sol)
             for sol in itersolve([tuple(clause) for clause in clauses1])))
 def test_each_clause_gen(self):
     self.assertTrue(
         all(
             evaluate(clauses1, sol)
             for sol in itersolve([(x for x in clause)
                                   for clause in clauses1])))
def itersolve(symbolic_cnf, include_neg=False):
    numbered_cnf, num2var = translate(symbolic_cnf)
    for solution in pycosat.itersolve(numbered_cnf):
        yield [num2var[n] for n in solution if include_neg or n > 0]
Example #30
0
    nz = len(C.clauses)
    if nz < len(eq):
        eq = [q for q in eq if q[0] <= rhs[1]]
        res = C.build_BDD(eq, rhs[0], rhs[1], polarity=True)
        if res is false:
            # Impossible to satisfy, so just stuff a contradiciton in there
            return [(m, ), (-m, )]
        elif res is true:
            return []
        else:
            C.clauses.append((res, ))
    return C.clauses


try:
    pycosat.itersolve({(1, )})
    pycosat_prep = False
except TypeError:
    pycosat_prep = True


def sat(clauses, iterator=False):
    """
    Calculate a SAT solution for `clauses`.

    Returned is the list of those solutions.  When the clauses are
    unsatisfiable, an empty list is returned.

    """
    if pycosat_prep:
        clauses = list(map(list, clauses))
 def test_cnf3_3vars(self):
     self.assertEqual(list(itersolve(clauses3, 3)),
                      [[-1, -2, -3], [-1, -2, 3]])
Example #32
0
def my_itersolve(iterable):
    """
    Work around https://github.com/ContinuumIO/pycosat/issues/13
    """
    iterable = [[i for i in j] for j in iterable]
    return pycosat.itersolve(iterable)
Example #33
0
def readDMACS():
	global clauseFile, clauseFileLines, clauseSet
	clauseFile = open('days.txt', "r")
	clauseFileLines = clauseFile.readlines()
	clauseSet = list()
	clauseSet.append(list())
	maxvar = 0
	for line in clauseFileLines:
		tokens = line.split()
		if len(tokens) != 0 and tokens[0] not in ("p", "c"):
			for tok in tokens:
				lit = int(tok)
				maxvar = max(maxvar, abs(lit))
				if lit == 0:
					clauseSet.append(list())
				else:
					clauseSet[-1].append(lit)
	assert len(clauseSet[-1]) == 0
	clauseSet.pop()
	print(clauseSet)
	print(maxvar)

if __name__ == "__main__":
	print "Welcome!"
	readDMACS()
	print "The clause set after calling the parser function is:"
	print clauseSet
	print "This is the solution"
	for sol in pycosat.itersolve(clauseSet):
		print sol
Example #34
0
    def setup(self, m, limit=0, **kwargs):
        from pycosat import itersolve

        # NOTE: The iterative solving isn't actually used here, we just call
        #       itersolve to separate setup from the actual run.
        return itersolve(self._clauses.as_list(), vars=m, prop_limit=limit)
Example #35
0
    def get_valid_variants(self, size):
        """
        A function to compute the valid variants of a model.

        Args:
            constraint_list (list): All constrains provided for the model.
            size (int): The desired number of variants for the model.

        Returns:
            A numpy matrix with variants, which satisfy the provided constrains. Each row represents one variant.
        """
        new_c = self.constraints.copy()
        perm_method = self.perm_method
        assert (perm_method in ["complete", "clauses", "no_permutation"]), (
            "Options for Permutation_Method are: complete, clauses, no_permutation"
        )
        assert (self.sampling_method in [
            "random", "feature-wise", "pair-wise", "neg-feature-wise",
            "neg-pair-wise"
        ]), (
            "Options for Sampling_Method are: random, feature-wise, neg-feature-wise, pair-wise, neg-pair-wise"
        )
        sampling = {
            'feature-wise': lambda x, i, j: x.append([i]),
            'pair-wise': lambda x, i, j: x.extend([[i], [j]]),
            'neg-feature-wise': lambda x, i, j: x.append([-(i)]),
            'neg-pair-wise': lambda x, i, j: x.extend([[-i], [-j]])
        }.get(self.sampling_method)
        sol_collection = list()
        # substract root feature
        largest_dimacs_literal = len(self.feature_influences)  #- 1
        if not np.any([
                largest_dimacs_literal in sub_list
                for sub_list in self.constraints
        ]):
            dummy_constraint = [
                largest_dimacs_literal, -1 * largest_dimacs_literal
            ]
            new_c.append(dummy_constraint)
        if perm_method == "no_permutation" and self.sampling_method == "random":
            solutions = list(itertools.islice(pycosat.itersolve(new_c), size))
            for elem in solutions:
                solution = Vm.transform2binary(elem)
                sol_collection.append(solution)
        else:
            for i in range(0, size):
                if perm_method == "clauses" or perm_method == "complete":
                    shuffle(new_c)  # shuffle the constraints
                    if perm_method == "complete":
                        for constraint in new_c:  # shuffle feature assignment in constraints
                            shuffle(constraint)
                c_copy = list(new_c)
                if self.sampling_method != "random":
                    sampling(c_copy, i + 1, (i + 1) % (size) + 1)

                solution = pycosat.solve(c_copy)
                if solution != "UNSAT":
                    new_c.append([j * -1 for j in solution])
                    solution = Vm.transform2binary(solution)
                    sol_collection.append(solution)
        m_sol_list = np.asmatrix(sol_collection)
        return m_sol_list
 def test_tuple_caluses(self):
     self.assertTrue(
         all(evaluate(clauses1, sol) for sol in itersolve(tuple(clauses1))))
Example #37
0
 def test_iter_clauses(self):
     self.assertTrue(all(evaluate(clauses1, sol) for sol in
                         itersolve(iter(clauses1))))
Example #38
0
    def FillInSequence(self, boundaryCondition=BoundaryCondition.ALL_DEAD):
        sequence = self.game.tilings
        if len(sequence) <= 1:
            raise Exception('A sequence needs at least 2 elements!')
        for tiling in sequence:
            assert isinstance(tiling, LifeTiling)
            assert tiling.height == sequence[0].height and tiling.width == sequence[0].width, \
                'Cannot compare tilings with different dimensions.'
        height = sequence[0].height
        width = sequence[0].width
        oldToNewVariables = dict()
        offsets = [-1, 0, 1]

        inputWires = []
        if DEBUG:
            print('Initiating building of circuit graph.')
            t0 = time.time()
        for index in reversed(range(1, len(sequence))):
            A = sequence[index - 1]
            B = sequence[index]
            for row in range(A.height):
                for col in range(A.width):
                    inputWires.append(A[row][col].wire)
                    prevNodes = []
                    for i in offsets:
                        for j in offsets:
                            if boundaryCondition == BoundaryCondition.TOROIDAL:
                                adjustedRow = (row + i) % A.height
                                adjustedCol = (col + j) % A.width
                                prevNodes.append(
                                    A[adjustedRow][adjustedCol].wire)
                            elif boundaryCondition == BoundaryCondition.ALL_DEAD:
                                adjustedRow = row + i
                                adjustedCol = col + j
                                # Out of bounds cells count as dead
                                if adjustedRow not in range(
                                        A.height) or adjustedCol not in range(
                                            A.width):
                                    prevNodes.append(Wire(constant=False))
                                else:
                                    prevNodes.append(
                                        A[adjustedRow][adjustedCol].wire)
                            elif boundaryCondition == BoundaryCondition.ALL_ALIVE:
                                adjustedRow = row + i
                                adjustedCol = col + j
                                # Out of bounds cells count as alive
                                if adjustedRow not in range(
                                        A.height) or adjustedCol not in range(
                                            A.width):
                                    prevNodes.append(Wire(constant=True))
                                else:
                                    prevNodes.append(
                                        A[adjustedRow][adjustedCol].wire)
                            else:
                                raise Exception('Unknown boundary condition')
                    tilePrecedingLogic = GateCustom()
                    tilePrecedingLogic.LIFE_nextState(prev9tiles=prevNodes,
                                                      output=B[row][col].wire)
        if DEBUG:
            total = time.time() - t0
            print('Building of circuit graph completed. (' + str(total) +
                  ' seconds)')
        layerFormula = LogicFormula(inputWires)
        cnfFormula = sorted(layerFormula.cnfForm.rawCNF(),
                            key=lambda x: [len(x), [abs(y) for y in x]])

        # Add extra assertion that no triple along an edge has all 3 variables true.
        for tiling in sequence:
            if tiling.time == len(sequence) - 1:
                pass
            for row in range(height):
                for col in range(width):
                    if (row == 0 or row
                            == height - 1) and (col != 0 and col != width - 1):
                        cnfFormula.append([
                            -tiling[row][col - 1].variable,
                            -tiling[row][col].variable,
                            -tiling[row][col + 1].variable
                        ])
                    if (col == 0 or col
                            == width - 1) and (row != 0 and row != height - 1):
                        cnfFormula.append([
                            -tiling[row - 1][col].variable,
                            -tiling[row][col].variable,
                            -tiling[row + 1][col].variable
                        ])

        cnt = 0
        for tiling in sequence:
            for row in range(tiling.height):
                for col in range(tiling.width):
                    oldToNewVariables[tiling[row][col].variable] = tiling[row][
                        col].wire.variable

        self.createSolutionDir()
        if DEBUG:
            print('Starting to find solutions.')
            t0 = time.time()
        for solution in pycosat.itersolve(cnfFormula):
            if DEBUG and cnt == 0:
                total = time.time() - t0
                print('First solution found in ' + str(total) + ' seconds.')
            if self.solutionCap is not None and self.solutionCap <= cnt:
                break
            # print('--------------------')
            # print(solution)
            updatedSequence = []
            for tiling in sequence:
                newTilingA = LifeTiling(tiling.height, tiling.width,
                                        tiling.time)

                for row in range(tiling.height):
                    for col in range(tiling.width):
                        if oldToNewVariables[tiling[row]
                                             [col].variable] in solution:
                            if tiling[row][
                                    col].state == LifeState.ALIVE or tiling[
                                        row][col].state == LifeState.DONTCARE:
                                # This means that we either forced the cell to be alive or we derived a possible value
                                newTilingA[row][col].state = LifeState.ALIVE
                                pass
                            else:
                                raise Exception(
                                    "Computed state is incompatible with original state"
                                )
                        elif -oldToNewVariables[tiling[row]
                                                [col].variable] in solution:
                            if tiling[row][
                                    col].state == LifeState.DEAD or tiling[
                                        row][col].state == LifeState.DONTCARE:
                                # This means that we either forced the cell to be dead or we derived a possible value
                                newTilingA[row][col].state = LifeState.DEAD
                                pass
                            else:
                                raise Exception(
                                    "Computed state is incompatible with original state"
                                )
                        else:
                            raise Exception(
                                "Input wasn't even in the solution! Something is clearly wrong here."
                            )
                updatedSequence.append(newTilingA)
                # print('After A:')
                # print(newTilingA)
                # print('After B:')
                # print(B)
            gameSolution = LifeGameInstance(
                boundaryCondition=boundaryCondition)
            gameSolution.SetFrames(updatedSequence)
            print(gameSolution)
            self.addSolution(gameSolution)
            cnt += 1
        if DEBUG:
            total = time.time() - t0
            print('All solutions found or solution limit reached. (' +
                  str(total) + ' seconds)')
Example #39
0
 def test_each_clause_tuples(self):
     self.assertTrue(all(evaluate(clauses1, sol) for sol in
                         itersolve([tuple(clause) for clause in clauses1])))
 def test_iter_clauses(self):
     self.assertTrue(
         all(evaluate(clauses1, sol) for sol in itersolve(iter(clauses1))))
Example #41
0
 def test_each_clause_gen(self):
     self.assertTrue(all(evaluate(clauses1, sol) for sol in
                         itersolve([(x for x in clause) for clause in
                                    clauses1])))
 def test_cnf2(self):
     self.assertEqual(list(itersolve(clauses2, nvars2)), [])
Example #43
0
 def solve(self):
     """"""
     cnf = self.cnf2list()
     return ps.itersolve(cnf)
 def test_cnf1_prop_limit(self):
     self.assertEqual(list(itersolve(clauses1, prop_limit=2)), [])
Example #45
0
 def test_cnf2(self):
     self.assertEqual(list(itersolve(clauses2, nvars2)), [])
 def test_no_clauses(self):
     for n in range(7):
         self.assertEqual(len(list(itersolve([], vars=n))), 2**n)
Example #47
0
 def test_cnf1_prop_limit(self):
     self.assertEqual(list(itersolve(clauses1, prop_limit=2)), [])
Example #48
0
 def __init__(self, clauses):
     self.i = -1
     self.sol_iter = pycosat.itersolve(clauses)
     self.cache = []
 def test_many_clauses(self):
     ref_sols = set(tuple(sol) for sol in itersolve(clauses1))
     # repeating the clauses many times does not change the solutions
     cnf = 100 * copy.deepcopy(clauses1)
     self.assertEqual(set(tuple(sol) for sol in itersolve(cnf)), ref_sols)
Example #50
0
 def setup(self, clauses, m, limit=0):
     # NOTE: The iterative solving isn't actually used here, we just call
     #       itersolve to separate setup from the actual run.
     return pycosat.itersolve(clauses.as_list(), vars=m, prop_limit=limit)