/// <summary> /// Add a rule node into the appropriate chains within the graph. /// </summary> /// <remarks> /// The node is prepended to the watch chains for each of the two literals it /// watches. /// Assertions are skipped because they only require on a single package and /// have no alternative literal that could be true, so there is no need to /// watch changes in any literals. /// </remarks> /// <param name="node">The rule node to be inserted into the graph.</param> public void Add(RuleWatchNode node) { if (node.GetRule().IsAssertion) { return; } foreach (var literal in new[] { node.Watch1, node.Watch2 }) { if (!watchChains.TryGetValue(literal, out LinkedList <RuleWatchNode> watchChainNode)) { watchChains[literal] = watchChainNode = new LinkedList <RuleWatchNode>(); } watchChainNode.AddFirst(node); } }
/// <summary> /// Set propagate learn. /// </summary> /// <remarks> /// Add free decision (a positive literal) to decision queue /// increase level and propagate decision return if no conflict. /// in conflict case, analyze conflict rule, add resulting /// rule to learnt rule set, make decision from learnt /// rule (always unit) and re-propagate. /// </remarks> /// <returns>returns the new solver level or 0 if unsolvable.</returns> private int SetPropagateLearn(int level, int literal, Rule rule) { level++; decisions.Decide(literal, level, rule); while (true) { rule = Propagate(level); if (rule == null) { // return if no conflict. break; } if (level == 1) { return(AnalyzeUnsolvable(rule)); } // conflict var(learnLiteral, newLevel, newRule, why) = Analyze(level, rule); if (newLevel <= 0 || newLevel >= level) { throw new SolverBugException( $"Trying to revert to invalid level {newLevel} from level {level}."); } else if (newRule == null) { throw new SolverBugException( $"No rule was learned from analyzing {rule} at level {level}."); } level = newLevel; Revert(level); rules.Add(newRule, RuleType.Learned); learnedWhy[newRule.ObjectId] = why; var ruleNode = new RuleWatchNode(newRule); ruleNode.Watch2OnHighest(decisions); watchGraph.Add(ruleNode); decisions.Decide(learnLiteral, level, newRule); } return(level); }