Пример #1
0
        /// <summary>
        /// выбирает неназначенный литерал, добавляет его в присваивание и помечает как решающий.
        /// </summary>
        /// <param name="cnf"></param>
        public void Decide(CNF cnf)
        {
            var literal = cnf.Dlis();
            var addLit  = new Literal(literal.Var, false);

            addLit.SetValue(false);
            assigmentStack.Push(new AssignmentItem(addLit, true));//literal, true));
            decideCount++;
        }
Пример #2
0
        /// <summary>
        /// DPLL - работает используя полный перебор.
        /// Завершается sat - если удалось подобрать значения при которых нет ни одного ложного дизъюнкта.
        /// При обнаружении конфликта возвращаемся к хронологически последнему ветвлению.
        /// </summary>
        /// <param name="cnf">решаемый кнф</param>
        /// <returns>sat/unsat</returns>
        static public bool SolveDpll(CNF cnf)
        {
            var  assignment    = new Assignment();
            uint maxWhileCount = uint.MaxValue;
            uint l             = 0;

            //существует хотя бы один не назначенный литерал в cnf
            while (cnf.IsAnyUnknownLiteral())
            {
                //существует хотя бы один еденичный дизъюнкт
                while (cnf.IsAnyUnitClause())
                {
                    assignment.UnitPropagate(cnf);
                    while (cnf.IsUnsat())
                    {
                        //есть хоть один рещающий литерал, то откатываемся назад
                        if (assignment.IsAnyDecideLiteral())
                        {
                            assignment.BackjumpDpll(cnf);
                        }
                        else//правило Fail
                        {
                            return(false);
                        }
                    }
                }

                if (cnf.IsAnyUnknownLiteral())
                {
                    assignment.Decide(cnf);
                }
                else
                {
                    break;
                }

                if (l > maxWhileCount)
                {
                    throw new Exception("Превышена максимально допустимая глубина цикличности.");
                }
                l++;
            }

            Console.WriteLine("CNF");
            foreach (var cl in cnf.Clauses)
            {
                Console.WriteLine(cl.ToString());
            }
            Console.WriteLine(assignment.GetStatistics());
            Console.WriteLine("Variables");
            Console.WriteLine(cnf.VariablesValueToString());

            return(true);
        }
Пример #3
0
 /// <summary>
 /// единичный дизъюнкт с неназначенным литералом, верен если этот литерал верен
 /// </summary>
 /// <param name="cnf"></param>
 public void UnitPropagate(CNF cnf)
 {
     foreach (var cl in cnf.Clauses)
     {
         if (cl.TryGetUnit(out var lit))
         {
             lit.SetValue(true);
             var literal = new Literal(lit.Var, !lit.IsPositive);
             assigmentStack.Push(new AssignmentItem(literal, false));
             unitPropagateCount++;
             return;
         }
     }
 }
Пример #4
0
        /// <summary>
        /// Xронологический возврат
        /// </summary>
        public void BackjumpDpll(CNF cnf)
        {
            bool isFound = false;

            while (!isFound)
            {
                if (!assigmentStack.TryPop(out var popItem))
                {
                    break;                                        //вообще исключение следует генерить
                }
                if (popItem.IsDecide)
                {
                    var lit = new Literal(popItem.Literal.Var, true);//!popItem.Literal.isPositive);
                    lit.SetValue(false);
                    assigmentStack.Push(new AssignmentItem(lit, false));
                    isFound = true;
                }
                else
                {
                    popItem.Literal.SetValue(null);
                }
            }
            backjumpCount++;
        }