public void AddClause(IClause clause) { if (clause == null) { return; } _satisfiedLiterals.Clear(); if (clause.Head != null && clause.Head.Negated && clause.Body.Count > 0) { var newClause = new Clause(new Literal(clause.Head.NegatedValue())); foreach (var literal in clause.Body) { newClause.Body.Add(new Literal(literal.NegatedValue())); } AddClause(newClause); return; } var headNode = clause.Head != null ? (_graph.GetNode(clause.Head.Value) ?? _graph.AddNode(clause.Head.Negated ? (ILogicNode) new ClauseNode(clause.Head.Value) : new LiteralNode(clause.Head.Value)).GetNode(clause.Head.Value)) : null; if (clause.Body.Count < 1) { if (headNode == null) { throw new NullReferenceException("Clause Head is null"); } headNode.Fact = true; } else if (clause.Body.Count == 1) { if (clause.Head == null) { throw new NullReferenceException("Clause Head is null"); } var literal = clause.Body.First(); if (clause.Head.Value != literal.Value) { var node = _graph.GetNode(literal.Value) ?? _graph.AddNode(literal.Negated ? (ILogicNode) new ClauseNode(literal.Value) : new LiteralNode(literal.Value)).GetNode(literal.Value); if (_graph.GetEdge(headNode, node) == null) { _graph.AddEdge(new DirectedEdge <ILogicNode> (headNode, node)); } } } else if (clause.Body.Count > 1) { if (clause.Head != null) { var literals = clause.Body.Where(literal => clause.Head.Value != literal.Value).ToList(); if (literals.Count > 0) { var clauseKey = ClauseKey(literals); var clauseNode = _graph.GetNode(clauseKey) ?? _graph.AddNode(new ClauseNode(clauseKey)).GetNode(clauseKey); if (_graph.GetEdge(headNode, clauseNode) == null) { _graph.AddEdge(new DirectedEdge <ILogicNode> (headNode, clauseNode)); } foreach (var literalNode in literals.Select(literal => _graph.GetNode(literal.Value) ?? _graph.AddNode(literal.Negated ? (ILogicNode) new ClauseNode(literal.Value) : new LiteralNode(literal.Value)).GetNode(literal.Value)).Where(literalNode => _graph.GetEdge(clauseNode, literalNode) == null)) { _graph.AddEdge(new WeightedDirectedEdge <ILogicNode> (clauseNode, literalNode, 1)); } } } else { var disjointLiteralKey = DisjointLiteralKey(clause.Body); var disjointLiteral = _graph.GetNode(disjointLiteralKey) ?? _graph.AddNode(new LiteralNode(disjointLiteralKey)).GetNode(disjointLiteralKey); foreach (var literalNode in clause.Body.Select(literal => _graph.GetNode(literal.Value) ?? _graph.AddNode(literal.Negated ? (ILogicNode) new ClauseNode(literal.Value) : new LiteralNode(literal.Value)).GetNode(literal.Value)).Where(literalNode => _graph.GetEdge(disjointLiteral, literalNode) == null)) { _graph.AddEdge(new DirectedEdge <ILogicNode>(disjointLiteral, literalNode)); } } } var negated = clause.Head != null ? new Clause(new Literal(clause.Head.NegatedValue())) : new Clause(); foreach (var dependency in clause.Body) { negated.Body.Add(new Literal(dependency.NegatedValue())); } AddNegatedClause(negated); if (headNode != null && negated.Head != null) { var negatedHeadNode = _graph.GetNode(negated.Head.Value); if (negatedHeadNode != null) { if (headNode.Fact && negatedHeadNode.Fact) { throw new Exception("KB is inconsistent, " + headNode.Id + " and " + negatedHeadNode.Id + " are both facts!"); } if (clause.Body.Count > 0) { var nodesA = clause.Body.Select(literal => _graph.GetNode(literal.Value)); var nodesB = clause.Body.Select(literal => _graph.GetNode(literal.NegatedValue())); if (SharedAncestor(nodesA, nodesB)) { Console.WriteLine("Adding " + clause.ToProperString() + " will cause conflict skipping clause..."); RemoveClause(clause); } } } } if (headNode != null && headNode.Fact) { FactFlow(headNode); } if (clause.Body.Count > 0) { foreach (var node in clause.Body.Select(literal => _graph.GetNode(literal.Value)).Where(node => node.Fact)) { FactFlow(node); } foreach (var node in clause.Body.Select(literal => _graph.GetNode(literal.NegatedValue())).Where(node => node.Fact)) { FactFlow(node); } } }