/// <summary> /// Gets all pure literals from Cnf /// </summary> /// <param name="cnf"></param> /// <returns>Returns a list containing all pure literals of Cnf</returns> private IEnumerable <Formula> PureLiterals(Cnf cnf) { var result = new List <Formula>(); foreach (var clause in cnf.Clauses) { foreach (var literal in clause.Literals) { if (PureLiteral(cnf, literal)) { result.Add(literal); } } } return(result); }
/// <summary> /// Determines whether a given literal is pure /// </summary> /// <param name="cnf"></param> /// <param name="literal"></param> /// <returns>True is literal is pure; false otherwise</returns> private bool PureLiteral(Cnf cnf, Formula literal) { var negation = NegateLiteral(literal); foreach (var clause in cnf.Clauses) { foreach (var l in clause.Literals) { if (clause.LiteralEquals(l, negation)) { return(false); } } } return(true); }
/// <summary> /// Splits the Cnf on a given literal /// </summary> /// <param name="cnf"></param> /// <param name="literal"></param> /// <returns>A tuple of Cnfs one for the left branch another for the right branch</returns> private Tuple <Cnf, Cnf> SplittingOnLiteral(Cnf cnf, Formula literal) { // List of clauses containing literal var @in = new List <Clause>(); // List of clauses containing Not(literal) var @inNegated = new List <Clause>(); // List of clauses not containing literal nor Not(literal) var @out = new List <Clause>(); var negated = NegateLiteral(literal); foreach (var clause in cnf.Clauses) { if (clause.Contains(literal)) { @in.Add(clause); } else if (clause.Contains(negated)) { @inNegated.Add(clause); } else { @out.Add(clause); } } var inCnf = new Cnf { Clauses = @in }; var outCnf = new Cnf { Clauses = @inNegated }; inCnf.Join(@out); outCnf.Join(@out); return(new Tuple <Cnf, Cnf>(inCnf, outCnf)); }
/// <summary> /// Applies the one literal rule i.e. finds all literals that are the single member of their clause. /// </summary> /// <param name="cnf"></param> /// <returns>Returns a tuple with the resulting Cnf after having removed clauses containing one literals or their negations and an integer which can be 0 (no clauses), 1 (continue dpll), -1 (empty clause)</returns> private Tuple <Cnf, int> OneLiteral(Cnf cnf) { var unitLiteral = UnitClause(cnf); if (unitLiteral == null) { return(new Tuple <Cnf, int>(cnf, 1)); } var newCnf = new Cnf(); while (unitLiteral != null) { var clausesToRemove = new List <int>(); var i = 0; // Finding clauses where the unit literal is, these clauses will be deleted foreach (var clause in cnf.Clauses) { if (clause.Literals.Any(literal => clause.LiteralEquals(literal, unitLiteral))) { clausesToRemove.Add(i); } i++; } // New Cnf after removing every clause where unit literal is newCnf = new Cnf(); // Leave clausules that do not include the unit literal for (var j = 0; j < cnf.Clauses.Count; j++) { if (!clausesToRemove.Contains(j)) { newCnf.Clauses.Add(cnf.Clauses[j]); } } // No clauses which implies SAT if (newCnf.Clauses.Count == 0) { return(new Tuple <Cnf, int>(newCnf, 0)); } // Remove negation of unit literal from remaining clauses var unitNegated = NegateLiteral(unitLiteral); var clausesNoLitNeg = new List <Clause>(); foreach (var clause in newCnf.Clauses) { var newClause = new Clause(); // Leaving every literal except the unit literal negated foreach (var literal in clause.Literals) { if (!clause.LiteralEquals(literal, unitNegated)) { newClause.Literals.Add(literal); } } clausesNoLitNeg.Add(newClause); } newCnf.Clauses = new List <Clause>(clausesNoLitNeg); // Resetting variables for next stage cnf = newCnf; unitLiteral = UnitClause(cnf); // Empty clause found if (cnf.Clauses.Any(c => c.Literals.Count == 0)) { return(new Tuple <Cnf, int>(newCnf, -1)); } } return(new Tuple <Cnf, int>(newCnf, 1)); }