1 module satd.solvers.dpll; 2 3 import satd.cnf, satd.assignment; 4 import std.variant : Algebraic; 5 import std.typecons : Tuple; 6 7 alias Null = typeof(null); 8 alias SolverResult = Algebraic!(Assignment, Null); 9 10 alias unitPropagateResult = Tuple!(CNF, "F", Assignment, "assignment"); 11 12 SolverResult solve(CNF F) 13 { 14 auto res = dpll(F, Assignment(F.variableNum)); 15 if (res.peek!Assignment) 16 { 17 auto tmp = res.get!0; 18 tmp.fillUnassignedLiterals(); 19 res = tmp; 20 } 21 return res; 22 } 23 24 ulong k; 25 SolverResult dpll(CNF F, Assignment assignment) 26 { 27 k++; 28 auto uPRes = unitPropagate(F, assignment); 29 F = uPRes.F, assignment = uPRes.assignment; 30 31 // if there exists an empty clause 32 if (F.emptyClauses.length > 0) 33 return SolverResult(null); 34 // if there's no clauses left 35 if (F.allClauses.length == 0) 36 return SolverResult(assignment); 37 38 Literal l = assignment.getUnassignedLiteral(); 39 40 CNF F_l = CNF(F); 41 Assignment asgn1 = Assignment(assignment); 42 F_l.simplify(l); 43 asgn1.assign(l); 44 45 auto res1 = dpll(F_l, asgn1); 46 if (res1.peek!Assignment) 47 return SolverResult(res1); 48 49 CNF F_lnotl = CNF(F); 50 Assignment asgn2 = Assignment(assignment); 51 F_lnotl.simplify(-l); 52 asgn2.assign(-l); 53 54 return dpll(F_lnotl, asgn2); 55 } 56 57 unitPropagateResult unitPropagate(CNF F, Assignment assignment) 58 { 59 while (F.emptyClauses.length == 0 && F.unitClauses.length > 0) 60 { 61 auto k = F.unitClauses.keys[0], v = F.unitClauses[k]; 62 Literal x = v.unitLiteral; 63 64 F.simplify(x); 65 assignment.assign(x); 66 } 67 return unitPropagateResult(F, assignment); 68 }