def test_conversion_to_cnf(self): """ Tests the conversion of formulas that aren't in cnf form. """ formula = bf.Not(bf.Or([bf.Var("a"), bf.Var("b")])) result = bf.And([bf.Not(bf.Var("a")), bf.Not(bf.Var("b"))]) self.assertEqual(result, au.cnf_nnf(formula), "Invalid formula, expected the same as specified by result.") formula = bf.Or([bf.And([bf.Var("a"), bf.Var("b")]), bf.Var("c")]) result = bf.And([bf.Or([bf.Var("a"), bf.Var("c")]), bf.Or([bf.Var("b"), bf.Var("c")])]) self.assertEqual(result, au.cnf_nnf(formula), "Invalid formula, expected the same as specified by result.") formula = bf.And([bf.Var("a"), bf.Or([bf.Var("b"), bf.And([bf.Var("c"), bf.Var("d")])])]) result = bf.And([bf.Var("a"), bf.Or([bf.Var("c"), bf.Var("b")]), bf.Or([bf.Var("d"), bf.Var("b")])]) self.assertEqual(result, au.cnf_nnf(formula), "Invalid formula, expected the same as specified by result.")
def test_formulas_already_in_cnf(self): """ Tests the conversion of formulas that are already in cnf form. """ formula = bf.And([bf.Not(bf.Var("a")), bf.Or([bf.Var("b"), bf.Var("c")])]) self.assertEqual(formula, au.cnf_nnf(formula), "Invalid formula, expected the same as entered.") formula = bf.And([bf.Var("a"), bf.Var("b")]) self.assertEqual(formula, au.cnf_nnf(formula), "Invalid formula, expected the same as entered.") formula = bf.Or([bf.Var("a"), bf.Var("b")]) self.assertEqual(formula, au.cnf_nnf(formula), "Invalid formula, expected the same as entered.") formula = bf.And([bf.Or([bf.Var("a"), bf.Var("b")]), bf.Or([bf.Not(bf.Var("b")), bf.Var("c"), bf.Not(bf.Var("d"))]), bf.Or([bf.Var("d"), bf.Not(bf.Var("e"))])]) self.assertEqual(formula, au.cnf_nnf(formula), "Invalid formula, expected the same as entered.")
def DPLL(formula): """ Implementation of DPLL - argument is formula in CNF form. Returns False if formula is not in SAT or values of variables otherwise. """ CNF_formula = au.simplify(au.cnf_nnf(formula)) values = {} while True: if isinstance(CNF_formula, bf.Tru) or isinstance(CNF_formula, bf.Fls) or isinstance(CNF_formula, bf.Var) or isinstance(CNF_formula, bf.Not): # Formula is only True, False, Var or negated Var - no more pure vars / literals, we finished break temp_value = {} #Always check only for first clause in formula - sequence is F, T, Var, Not, And clause = CNF_formula.formulas[0] if isinstance(clause, bf.Var): #It is only literal - Var values[clause.name] = bf.Tru() temp_value[clause.name] = bf.Tru() elif isinstance(clause, bf.Not): # It is only literal - negated Var values[clause.formula.name] = bf.Fls() temp_value[clause.formula.name] = bf.Fls() if temp_value: #We found literal - replace formula with its value, simplify, put in cnf and look for literal again replaced_formula = CNF_formula.replace(temp_value) formula_simplified = au.simplify(replaced_formula) CNF_formula = au.cnf_nnf(formula_simplified) else: #finish, no more literals break #Check for pure variables pure_var_values = au.pure_variables(CNF_formula) replaced_formula = CNF_formula.replace(pure_var_values) formula_simplified = au.simplify(replaced_formula) CNF_formula = au.cnf_nnf(formula_simplified) #Solve the rest of formula by brute force values_brute_force = SAT_solver_brute_force(CNF_formula, {}) if values_brute_force is not None: # satisfiable problem return dict(values.items() + pure_var_values.items() + values_brute_force.items()) else: # unsatisfiable problem return False
# Or or1 = bf.Or([x1, x2, x3, x4]) or2 = bf.Or([x1, bf.Or([x1, x2, x3, x4]), x4, x3, x2]) # this is equivalent to bf.Or([x1, x1, x2, x3, x4, x4, x3, x2]) or3 = bf.Or([]) # bf.Or([]) is equivalent to bf.Fls() # Examples of using the nnf method print "NNF EXAMPLES:" print au.nnf(bf.Not(bf.Not(bf.Var("b")))) print au.nnf(bf.Or([bf.And([bf.Var("a"), bf.Var("b")]), bf.Var("c")])) print au.nnf(bf.Not(bf.Or([bf.Var("a"), bf.Var("b")]))) print au.nnf(bf.And([bf.Var("a"), bf.And([bf.Var("b"), bf.Var("a")]), bf.Or([bf.Var("c"), bf.Var("b")])])) print "-----------------------------------------------------------------------------------------------------------------\n" # Examples of using the cnf method print "CNF EXAMPLES:" print au.cnf_nnf(bf.Or([bf.Var("b"), bf.Var("c")])) print au.cnf_nnf(bf.And([bf.Not(bf.Var("a")), bf.Or([bf.Var("b"), bf.Var("c")])])) print au.cnf_nnf(bf.And([bf.Var("a"), bf.Or([bf.Var("b"), bf.And([bf.Var("c"), bf.Var("d")])])])) print au.cnf_nnf(bf.Not(bf.Or([bf.Var("a"), bf.Var("b"), bf.Not(bf.Fls())]))) print "-----------------------------------------------------------------------------------------------------------------\n" # Examples of using the simplify method print "SIMPLIFY EXAMPLES:" print au.simplify(bf.Not(bf.Or([bf.Var("b"), bf.Var("c")]))) print au.simplify(bf.And([bf.Not(bf.Var("a")), bf.Or([bf.Var("b"), bf.Var("c")])])) print au.simplify(bf.And([bf.Var("a"), bf.Or([bf.Var("b"), bf.Tru(), bf.And([bf.Fls(), bf.Var("c"), bf.Var("d")])])])) print au.simplify(bf.Not(bf.Or([bf.Var("a"), bf.Var("b"), bf.Not(bf.Fls())]))) print "-----------------------------------------------------------------------------------------------------------------\n"
def test_conversion_to_cnf_with_false_in_and(self): """ Tests the conversion of formula that isn't in cnf form and contains a False in a And formula. """ formula = bf.Not(bf.Or([bf.Var("a"), bf.Var("b"), bf.Not(bf.Fls())])) self.assertEqual(bf.Fls(), au.cnf_nnf(formula), "Invalid formula, expected Fls.")
def test_conversion_to_cnf_with_true_in_or(self): """ Tests the conversion of formula that isn't in cnf form and contains a True in a Or formula. """ formula = bf.Not(bf.And([bf.Var("a"), bf.Var("b"), bf.Not(bf.Tru())])) self.assertEqual(bf.Tru(), au.cnf_nnf(formula), "Invalid formula, expected Tru.")