예제 #1
0
        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);
        }
예제 #2
0
        private static Literal?chooseNewLiteral(ClauseSet clauses,
                                                Variables variablesMap)
        {
            var selectedLiteral = clauses.SelectUnusedLiteral(variablesMap);

            return(selectedLiteral);
        }
예제 #3
0
 public SolverState(ClauseSet clauses,
                    Variables variablesMap,
                    int depth,
                    bool literalAdded)
 {
     Clauses      = clauses;
     VariablesMap = variablesMap;
     Depth        = depth;
     LiteralAdded = literalAdded;
 }
예제 #4
0
        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
        }
예제 #5
0
파일: Model.cs 프로젝트: renestein/SAT
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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)));
        }
예제 #8
0
        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);
            }
        }
예제 #9
0
        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);
        }
예제 #10
0
 private static bool isConsistentSetOfLiterals(ClauseSet clauses)
 {
     return(clauses.IsConsistentSetOfLiterals());
 }
예제 #11
0
 private static bool hasEmptyClause(ClauseSet clauses)
 {
     return(clauses.HasEmptyClause());
 }
예제 #12
0
        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);
        }