Пример #1
0
        /// <summary>
        /// Propagates a decision on a literal to all rules watching the literal.
        /// </summary>
        /// <remarks>
        /// If a decision, e.g. +A has been made, then all rules containing -A, e.g.
        /// (-A|+B|+C) now need to satisfy at least one of the other literals, so
        /// that the rule as a whole becomes true, since with +A applied the rule
        /// is now (false|+B|+C) so essentially (+B|+C).
        /// This means that all rules watching the literal -A need to be updated to
        /// watch 2 other literals which can still be satisfied instead. So literals
        /// that conflict with previously made decisions are not an option.
        /// Alternatively it can occur that a unit clause results: e.g. if in the
        /// above example the rule was (-A|+B), then A turning true means that
        /// B must now be decided true as well.
        /// </remarks>
        /// <param name="decidedLiteral">The literal which was decided.</param>
        /// <param name="level">The level at which the decision took place and at which all resulting decisions should be made.</param>
        /// <param name="decisions">Used to check previous decisions and to register decisions resulting from propagation.</param>
        /// <returns>If a conflict is found the conflicting rule is returned.</returns>
        public Rule PropagateLiteral(int decidedLiteral, int level, Decisions decisions)
        {
            // we invert the decided literal here, example:
            // A was decided => (-A|B) now requires B to be true, so we look for
            // rules which are fulfilled by -A, rather than A.
            // This means finding out the conflicts or requires.
            var literal = -decidedLiteral;

            if (!watchChains.TryGetValue(literal, out LinkedList <RuleWatchNode> chain))
            {
                return(null);
            }

            foreach (var node in chain.ToArray())
            {
                var otherWatch = node.GetOtherWatch(literal);
                if (!node.GetRule().Enable || decisions.IsSatisfy(otherWatch))
                {
                    continue;
                }

                var ruleLiterals        = node.GetRule().GetLiterals();
                var alternativeLiterals = Arr.Filter(ruleLiterals, (ruleLiteral) =>
                {
                    // Guaranteed selection decision is not at the same time
                    // as Watch1 and Watch2, guaranteeing no conflict.
                    return(literal != ruleLiteral && otherWatch != ruleLiteral && !decisions.IsConflict(ruleLiteral));
                });

                if (alternativeLiterals.Length > 0)
                {
                    var toLiteral = alternativeLiterals[0];

                    if (!watchChains.TryGetValue(toLiteral, out LinkedList <RuleWatchNode> toChain))
                    {
                        watchChains[toLiteral] = toChain = new LinkedList <RuleWatchNode>();
                    }

                    node.MoveWatch(literal, toLiteral);
                    chain.Remove(node);
                    toChain.AddFirst(node);
                    continue;
                }

                if (decisions.IsConflict(otherWatch))
                {
                    return(node.GetRule());
                }

                decisions.Decide(otherWatch, level, node.GetRule());
            }

            return(null);
        }
Пример #2
0
        public void TestIsConflict()
        {
            decisions.Decide(1, 1, defaultRule);
            decisions.Decide(-2, 1, defaultRule);

            Assert.IsTrue(decisions.IsConflict(-1));
            Assert.IsFalse(decisions.IsConflict(1));
            Assert.IsTrue(decisions.IsConflict(2));
            Assert.IsFalse(decisions.IsConflict(-2));
            Assert.IsFalse(decisions.IsConflict(3));
        }