private static ClauseSet.ClauseOperationResult propagateUnitClauses(ClauseSet clauses, Variables variablesMap) { var unitClausuleRuleResult = ClauseSet.ClauseOperationResult.OperationNotUsed; while (true) { var toPropagateUnitClause = clauses.SelectUnitClause(variablesMap); if (toPropagateUnitClause == null) { break; } unitClausuleRuleResult = ClauseSet.ClauseOperationResult.OperationSuccess; var singleLiteral = toPropagateUnitClause.FirstLiteral; #if PROGRESS_TRACE Trace.WriteLine($"Trying unit propagation of the clause with literal: {singleLiteral}"); #endif variablesMap.SetToValue(singleLiteral.Name, singleLiteral.IsTrue); removeClausulesSatisfiedByLiteral(clauses, singleLiteral); clauses.AddClause(toPropagateUnitClause); var deleteLiteralResult = clauses.DeleteLiteralFromClauses(~singleLiteral); if (deleteLiteralResult == ClauseSet.ClauseOperationResult.MinOneEmptyClausuleFound) { return(deleteLiteralResult); } } return(unitClausuleRuleResult); }
private static Literal?chooseNewLiteral(ClauseSet clauses, Variables variablesMap) { var selectedLiteral = clauses.SelectUnusedLiteral(variablesMap); return(selectedLiteral); }
public SolverState(ClauseSet clauses, Variables variablesMap, int depth, bool literalAdded) { Clauses = clauses; VariablesMap = variablesMap; Depth = depth; LiteralAdded = literalAdded; }
private static void removeClausulesSatisfiedByLiteral(ClauseSet clausules, Literal literal) { #if PROGRESS_TRACE Trace.WriteLine($"Deleting clausules with literal: {literal}"); #endif clausules.DeleteClausesWithLiteral(literal); #if PROGRESS_TRACE Trace.WriteLine($"Remaining ClausulesSet: {clausules.ClausesCount}"); #endif }
public bool IsModelFor(ClauseSet clauseSet) { foreach (var literals in clauseSet.Clauses.Select(clause => clause.Literals)) { var isClauseSatisfied = literals.Any(literal => ModelValues.Single(val => val.Name == literal.Name) == literal); if (!isClauseSatisfied) { return(false); } } return(true); }
private static IEnumerable <ModelValue> generateModelValues(ClauseSet clausesSet, Variables variablesMap) { var modelValues = clausesSet.Clauses.Select(clause => { var literal = clause.FirstLiteral; return(new ModelValue(literal.Name, literal.IsTrue)); }).Distinct().ToArray(); var retModelValues = modelValues.Concat(variablesMap .VariableNames().Where(varName => !modelValues.Any(modelValue => modelValue .Name.Equals(varName))) .Select(varName => new ModelValue(varName, true))).ToArray(); return(retModelValues); }
public static Model?Solve(ClauseSet clauseSet, Variables variablesMap) { var models = generateModels(variablesMap, clauseSet); #if DUMP_MODELS foreach (var model in models) { if (model.IsModelFor(clauseSet)) { Console.WriteLine("Found model (dump)..."); Console.WriteLine(model); } } #endif return(models.FirstOrDefault(model => model.IsModelFor(clauseSet))); }
private static IEnumerable <Model> generateModels(Variables variablesMap, ClauseSet clauses) { const int VALUATIONS = 2; BigInteger ONE = 1; var variablesMapCount = variablesMap.VariablesCount; var singleLiterals = clauses.Clauses.Where(clause => clause.Literals.Count == 1) .Select(clause => clause.FirstLiteral) .ToDictionary(literal => literal.Name); var numberOfModels = (BigInteger)Math.Pow(VALUATIONS, variablesMapCount); for (BigInteger modelIndex = 0; modelIndex < numberOfModels; modelIndex++) { Console.WriteLine(modelIndex); var modelValues = new ModelValue[variablesMapCount]; var varIndex = 0; var haveModel = true; foreach (var varName in variablesMap.VariableNames()) { var isVarTrue = (modelIndex & (ONE << varIndex)) != 0; var modelValue = new ModelValue(varName, isVarTrue); modelValues[varIndex] = modelValue; if (singleLiterals.TryGetValue(modelValue.Name, out var literal)) { if (literal.IsTrue != modelValue.IsTrue) { Console.WriteLine($"Declined: {literal.Name}"); haveModel = false; break; } } varIndex++; } if (!haveModel) { continue; } var model = new Model(modelIndex, modelValues); Console.WriteLine("Evaluating..."); yield return(model); } }
private static bool handlePureLiterals(ClauseSet clauses, Variables variablesMap) { var pureLiteralsInClauses = clauses.GetPureLiterals(variablesMap); var hasPureLiterals = false; foreach (var pureLiteral in pureLiteralsInClauses) { #if PROGRESS_TRACE Trace.WriteLine($"Trying pure literal strategy: {pureLiteral}"); #endif variablesMap.SetToValue(pureLiteral.Name, pureLiteral.IsTrue); hasPureLiterals = true; removeClausulesSatisfiedByLiteral(clauses, pureLiteral); } return(hasPureLiterals); }
private static bool isConsistentSetOfLiterals(ClauseSet clauses) { return(clauses.IsConsistentSetOfLiterals()); }
private static bool hasEmptyClause(ClauseSet clauses) { return(clauses.HasEmptyClause()); }
public static Model?Solve(ClauseSet initialClauses, Variables variablesMap) { if (initialClauses == null) { throw new ArgumentNullException(nameof(initialClauses)); } if (variablesMap == null) { throw new ArgumentNullException(nameof(variablesMap)); } const int INITIAL_LEVEL = 0; var solverStack = ImmutableStack <SolverState> .Empty; var initialSolverState = new SolverState(initialClauses, variablesMap, INITIAL_LEVEL, true); solverStack = solverStack.Push(initialSolverState); while (!solverStack.IsEmpty) { solverStack = solverStack.Pop(out var currentState); #if PROGRESS_TRACE Trace.WriteLine($"Iteration depth: {currentState.Depth}"); #endif var clauses = currentState.Clauses; var variables = currentState.VariablesMap; if (isConsistentSetOfLiterals(clauses)) { #if PROGRESS_TRACE Trace.WriteLine("Found model..."); #endif return(new Model(0, generateModelValues(clauses, variables))); } if (hasEmptyClause(clauses)) { #if PROGRESS_TRACE Trace.WriteLine("Empty clause found. Backtracking..."); #endif continue; } var unitClauseRuleResult = propagateUnitClauses(clauses, variables); if (unitClauseRuleResult == ClauseSet.ClauseOperationResult.MinOneEmptyClausuleFound) { #if PROGRESS_TRACE Trace.WriteLine("Empty clause (after unit rule) found. Backtracking..."); #endif continue; } handlePureLiterals(clauses, variables); var chosenLiteral = chooseNewLiteral(clauses, variables); if (chosenLiteral == null) { if (hasEmptyClause(clauses)) { #if PROGRESS_TRACE Trace.WriteLine("Empty clause found. Backtracking..."); #endif continue; } #if PROGRESS_TRACE Trace.WriteLine("Found model..."); #endif return(new Model(0, generateModelValues(clauses, variables))); } #if PROGRESS_TRACE Trace.WriteLine($"Chosen literal {chosenLiteral.Name}"); #endif var newClauseNeg = clauses.CloneWithClause(new Clause(new List <Literal> { ~chosenLiteral })); var newClausePos = clauses.CloneWithClause(new Clause(new List <Literal> { chosenLiteral })); solverStack = solverStack.Push(new SolverState(newClauseNeg, variablesMap.Clone(), currentState.Depth + 1, true)); solverStack = solverStack.Push(new SolverState(newClausePos, variablesMap.Clone(), currentState.Depth + 1, true)); } return(null); }