def dpll(circ: Circuit, assigns: Assignment = {}) -> Solution: if len(circ) is 0: return True, assigns if any(len(clse) == 0 for clse in circ): return False, {} # do resolution unit_a, unit_circ = unit_clause_resolution(circ) pure_a, resolved_circ = pure_literal_elimination(unit_circ) assigns = {**assigns, **pure_a, **unit_a} # did resolution solve the problem if len(resolved_circ) is 0: return True, assigns v = Term(circ[0][0].variable) new_circ = rm_term(rm_clse(resolved_circ, v), -v) sat, pot_assign = dpll(new_circ, {**assigns, **{v.variable: True}}) if sat: return sat, pot_assign new_circ = rm_term(rm_clse(resolved_circ, -v), v) sat, pot_assign = dpll(new_circ, {**assigns, **{v.variable: False}}) if sat: return sat, pot_assign return False, {}
def random_circuit(n_vars: int, n_clause: int) -> Circuit: variables = [f"x_{i}" for i in range(n_vars)] circ = [] for i in range(n_clause): vs = rd.choices(variables, k=3) signs = rd.choices([1, -1], k=3) circ.append(tuple(s * Term(v) for v, s in zip(vs, signs))) return circ
def simple_dpll(circ: Circuit, assigns: Assignment = {}) -> Solution: if len(circ) is 0: return True, assigns if any(len(clse) is 0 for clse in circ): return False, {} v = Term(circ[0][0].variable) new_circ = rm_term(rm_clse(circ, v), -v) sat, pot_assign = simple_dpll(new_circ, {**assigns, **{v.variable: True}}) if sat: return sat, pot_assign new_circ = rm_term(rm_clse(circ, -v), v) sat, pot_assign = simple_dpll(new_circ, {**assigns, **{v.variable: False}}) if sat: return sat, pot_assign return False, {}
fmt = '|'.join(['%s' * n] * n) sep = '+'.join(['-' * n] * n) for i in range(n): for j in range(n): offset = (i * n + j) * n**2 print(fmt % tuple(sudoku[offset:offset+n**2])) if i != n - 1: print(sep) if __name__ == "__main__": circ = [] for point in points: circ += exactly_one_of([Term(point + value) for value in values]) for group in groups: for value in values: circ += exactly_one_of([Term(point + value) for point in group]) sudoku = '53..7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79' for p, s in zip(points, sudoku): if s is not ".": circ.append((Term(p + s), )) with open("sudoku/sudoku_circuit.txt", "w") as f: for c in circ: f.write(" ".join(map(str, c)) + "\n")
def make_circ(txt: str) -> Circuit: return [tuple(Term(t) for t in clse.split()) for clse in txt]