public void testContrapositives() { List<Chain> conts; Literal p = new Literal(new Predicate("P", new List<Term>())); Literal notq = new Literal(new Predicate("Q", new List<Term>()), true); Literal notr = new Literal(new Predicate("R", new List<Term>()), true); Chain c = new Chain(); conts = c.getContrapositives(); Assert.AreEqual(0, conts.Count); c.addLiteral(p); conts = c.getContrapositives(); Assert.AreEqual(0, conts.Count); c.addLiteral(notq); conts = c.getContrapositives(); Assert.AreEqual(1, conts.Count); Assert.AreEqual("<~Q(),P()>", conts[0].ToString()); c.addLiteral(notr); conts = c.getContrapositives(); Assert.AreEqual(2, conts.Count); Assert.AreEqual("<~Q(),P(),~R()>", conts[0].ToString()); Assert.AreEqual("<~R(),P(),~Q()>", conts[1].ToString()); }
public ProofStepChainContrapositive(Chain contrapositive, Chain contrapositiveOf) { this.contrapositive = contrapositive; this.contrapositiveOf = contrapositiveOf; this.predecessors.Add(contrapositiveOf.getProofStep()); }
public ProofStepChainCancellation(Chain cancellation, Chain cancellationOf, Dictionary<Variable, Term> subst) { this.cancellation = cancellation; this.cancellationOf = cancellationOf; this.subst = subst; this.predecessors.Add(cancellationOf.getProofStep()); }
public static int standardizeApart(Chain c, int saIdx) { List<Variable> variables = new List<Variable>(); foreach (Literal l in c.getLiterals()) { collectAllVariables(l.getAtomicSentence(), variables); } return standardizeApart(variables, c, saIdx); }
public ProofStepChainReduction(Chain reduction, Chain nearParent, Chain farParent, Dictionary<Variable, Term> subst) { this.reduction = reduction; this.nearParent = nearParent; this.farParent = farParent; this.subst = subst; this.predecessors.Add(farParent.getProofStep()); this.predecessors.Add(nearParent.getProofStep()); }
public List<Variable> collectAllVariables(Chain aChain) { List<Variable> variables = new List<Variable>(); foreach (Literal l in aChain.getLiterals()) { l.getAtomicSentence().accept(this, variables); } return variables; }
public void testIsEmpty() { Chain c = new Chain(); Assert.IsTrue(c.isEmpty()); c.addLiteral(new Literal(new Predicate("P", new List<Term>()))); Assert.IsFalse(c.isEmpty()); List<Literal> lits = new List<Literal>(); lits.Add(new Literal(new Predicate("P", new List<Term>()))); c = new Chain(lits); Assert.IsFalse(c.isEmpty()); }
public void resetNumberFarParentsTo(Chain farParent, int toSize) { Literal head = farParent.getHead(); Dictionary<String, List<Chain>> heads = null; if (head.isPositiveLiteral()) { heads = posHeads; } else { heads = negHeads; } String key = head.getAtomicSentence().getSymbolicName(); List<Chain> farParents = heads[key]; while (farParents.Count > toSize) { farParents.RemoveAt(farParents.Count - 1); } }
public int getNumberFarParents(Chain farParent) { Literal head = farParent.getHead(); Dictionary<String, List<Chain>> heads = null; if (head.isPositiveLiteral()) { heads = posHeads; } else { heads = negHeads; } String headKey = head.getAtomicSentence().getSymbolicName(); List<Chain> farParents = heads[headKey]; if (null != farParents) { return farParents.Count; } return 0; }
public bool isAnswer(Chain nearParent) { bool isAns = false; if (answerChain.isEmpty()) { if (nearParent.isEmpty()) { proofs.Add(new ProofFinal(nearParent.getProofStep(), new Dictionary<Variable, Term>())); complete = true; isAns = true; } } else { if (nearParent.isEmpty()) { // This should not happen // as added an answer literal to sos, which // implies the database (i.e. premises) are // unsatisfiable to begin with. throw new ApplicationException( "Generated an empty chain while looking for an answer, implies original KB is unsatisfiable"); } if (1 == nearParent.getNumberLiterals() && nearParent.getHead().getAtomicSentence() .getSymbolicName().Equals( answerChain.getHead() .getAtomicSentence() .getSymbolicName())) { Dictionary<Variable, Term> answerBindings = new Dictionary<Variable, Term>(); List<FOLNode> answerTerms = nearParent.getHead() .getAtomicSentence().getArgs(); int idx = 0; foreach (Variable v in answerLiteralVariables) { answerBindings.Add(v, (Term) answerTerms[idx]); idx++; } bool addNewAnswer = true; foreach (Proof.Proof p in proofs) { if (p.getAnswerBindings().Equals(answerBindings)) { addNewAnswer = false; break; } } if (addNewAnswer) { proofs.Add(new ProofFinal(nearParent.getProofStep(), answerBindings)); } isAns = true; } } if (DateTime.Now.Ticks > finishTime) { complete = true; // Indicate that I have run out of query time timedOut = true; } return isAns; }
// Returns c if no dropping occurred private Chain tryDropping(Chain c) { Literal head = c.getHead(); if (null != head && (head is ReducedLiteral)) { Chain dropped = new Chain(c.getTail()); dropped.setProofStep(new ProofStepChainDropped(dropped, c)); return dropped; } return c; }
// Returns c if no cancellation occurred private Chain tryCancellation(Chain c) { Literal head = c.getHead(); if (null != head && !(head is ReducedLiteral)) { foreach (Literal l in c.getTail()) { if (l is ReducedLiteral) { // if they can be resolved if (head.isNegativeLiteral() != l.isNegativeLiteral()) { Dictionary<Variable, Term> subst = unifier.unify(head .getAtomicSentence(), l.getAtomicSentence()); if (null != subst) { // I have a cancellation // Need to apply subst to all of the // literals in the cancellation List<Literal> cancLits = new List<Literal>(); foreach (Literal lfc in c.getTail()) { AtomicSentence a = (AtomicSentence)substVisitor .subst(subst, lfc.getAtomicSentence()); cancLits.Add(lfc.newInstance(a)); } Chain cancellation = new Chain(cancLits); cancellation .setProofStep(new ProofStepChainCancellation( cancellation, c, subst)); return cancellation; } } } } } return c; }
public ProofStepChainFromClause(Chain chain, Clause fromClause) { this.chain = chain; this.fromClause = fromClause; this.predecessors.Add(fromClause.getProofStep()); }
public Chain addToIndex(Chain c) { Chain added = null; Literal head = c.getHead(); if (null != head) { Dictionary<String, List<Chain>> toAddTo = null; if (head.isPositiveLiteral()) { toAddTo = posHeads; } else { toAddTo = negHeads; } String key = head.getAtomicSentence().getSymbolicName(); List<Chain> farParents = toAddTo[key]; if (null == farParents) { farParents = new List<Chain>(); toAddTo.Add(key, farParents); } added = c; farParents.Add(added); } return added; }
public int getNumberCandidateFarParents(Chain nearParent) { Literal nearestHead = nearParent.getHead(); Dictionary<String, List<Chain>> candidateHeads = null; if (nearestHead.isPositiveLiteral()) { candidateHeads = negHeads; } else { candidateHeads = posHeads; } String nearestKey = nearestHead.getAtomicSentence().getSymbolicName(); List<Chain> farParents = candidateHeads[nearestKey]; if (null != farParents) { return farParents.Count; } return 0; }
public Chain standardizeApart(Chain chain, StandardizeApartIndexical standardizeApartIndexical) { List<Variable> toRename = variableCollector.collectAllVariables(chain); Dictionary<Variable, Term> renameSubstitution = new Dictionary<Variable, Term>(); foreach (Variable var in toRename) { Variable v = null; do { v = new Variable(standardizeApartIndexical.getPrefix() + standardizeApartIndexical.getNextIndex()); // Ensure the new variable name is not already // accidentally used in the sentence } while (toRename.Contains(v)); renameSubstitution.Add(var, v); } if (renameSubstitution.Count > 0) { List<Literal> lits = new List<Literal>(); foreach (Literal l in chain.getLiterals()) { AtomicSentence atom = (AtomicSentence)substVisitor.subst( renameSubstitution, l.getAtomicSentence()); lits.Add(l.newInstance(atom)); } Chain renamed = new Chain(lits); renamed.setProofStep(new ProofStepRenaming(renamed, chain .getProofStep())); return renamed; } return chain; }
public ProofStepChainDropped(Chain dropped, Chain droppedOff) { this.dropped = dropped; this.droppedOff = droppedOff; this.predecessors.Add(droppedOff.getProofStep()); }
public Chain attemptReduction(Chain nearParent, int farParentIndex) { Chain nnpc = null; Literal nearLiteral = nearParent.getHead(); Dictionary<String, List<Chain>> candidateHeads = null; if (nearLiteral.isPositiveLiteral()) { candidateHeads = negHeads; } else { candidateHeads = posHeads; } AtomicSentence nearAtom = nearLiteral.getAtomicSentence(); String nearestKey = nearAtom.getSymbolicName(); List<Chain> farParents = candidateHeads[nearestKey]; if (null != farParents) { Chain farParent = farParents[farParentIndex]; standardizeApart(farParent); Literal farLiteral = farParent.getHead(); AtomicSentence farAtom = farLiteral.getAtomicSentence(); Dictionary<Variable, Term> subst = unifier.unify(nearAtom, farAtom); // If I was able to unify with one // of the far heads if (null != subst) { // Want to always apply reduction uniformly Chain topChain = farParent; Literal botLit = nearLiteral; Chain botChain = nearParent; // Need to apply subst to all of the // literals in the reduction List<Literal> reduction = new List<Literal>(); foreach (Literal l in topChain.getTail()) { AtomicSentence atom = (AtomicSentence)substVisitor.subst( subst, l.getAtomicSentence()); reduction.Add(l.newInstance(atom)); } reduction.Add(new ReducedLiteral((AtomicSentence)substVisitor .subst(subst, botLit.getAtomicSentence()), botLit .isNegativeLiteral())); foreach (Literal l in botChain.getTail()) { AtomicSentence atom = (AtomicSentence)substVisitor.subst( subst, l.getAtomicSentence()); reduction.Add(l.newInstance(atom)); } nnpc = new Chain(reduction); nnpc.setProofStep(new ProofStepChainReduction(nnpc, nearParent, farParent, subst)); } } return nnpc; }
public Chain standardizeApart(Chain aChain) { return _standardizeApart.standardizeApart(aChain, variableIndexical); }
public void standardizeApart(Chain c) { saIdx = StandardizeApartInPlace.standardizeApart(c, saIdx); }
// END-InferenceProcedure // // // PRIVATE METHODS // public List<Chain> createChainsFromClauses(List<Clause> clauses) { List<Chain> chains = new List<Chain>(); foreach (Clause c in clauses) { Chain chn = new Chain(c.getLiterals()); chn.setProofStep(new ProofStepChainFromClause(chn, c)); chains.Add(chn); chains.AddRange(chn.getContrapositives()); } return chains; }
// Recursive Depth Limited Search private void recursiveDLS(int maxDepth, int currentDepth, Chain nearParent, IndexedFarParents indexedFarParents, AnswerHandler ansHandler) { // Keep track of the maximum depth reached. ansHandler.updateMaxDepthReached(currentDepth); if (currentDepth == maxDepth) { return; } int noCandidateFarParents = indexedFarParents .getNumberCandidateFarParents(nearParent); if (null != tracer) { tracer.increment(currentDepth, noCandidateFarParents); } indexedFarParents.standardizeApart(nearParent); for (int farParentIdx = 0; farParentIdx < noCandidateFarParents; farParentIdx++) { // If have a complete answer, don't keep // checking candidate far parents if (ansHandler.isComplete()) { break; } // Reduction Chain nextNearParent = indexedFarParents.attemptReduction( nearParent, farParentIdx); if (null == nextNearParent) { // Unable to remove the head via reduction continue; } // Handle Canceling and Dropping bool cancelled = false; bool dropped = false; do { cancelled = false; Chain nextParent = null; while (nextNearParent != (nextParent = tryCancellation(nextNearParent))) { nextNearParent = nextParent; cancelled = true; } dropped = false; while (nextNearParent != (nextParent = tryDropping(nextNearParent))) { nextNearParent = nextParent; dropped = true; } } while (dropped || cancelled); // Check if have answer before // going to the next level if (!ansHandler.isAnswer(nextNearParent)) { // Keep track of the current # of // far parents that are possible for the next near parent. int noNextFarParents = indexedFarParents .getNumberFarParents(nextNearParent); // Add to indexed far parents nextNearParent = indexedFarParents.addToIndex(nextNearParent); // Check the next level recursiveDLS(maxDepth, currentDepth + 1, nextNearParent, indexedFarParents, ansHandler); // Reset the number of far parents possible // when recursing back up. indexedFarParents.resetNumberFarParentsTo(nextNearParent, noNextFarParents); } } }
/** * A contrapositive of a chain is a permutation in which a different literal * is placed at the front. The contrapositives of a chain are logically * equivalent to the original chain. * * @return a list of contrapositives for this chain. */ public List<Chain> getContrapositives() { List<Chain> contrapositives = new List<Chain>(); List<Literal> lits = new List<Literal>(); for (int i = 1; i < literals.Count; i++) { lits.Clear(); lits.Add(literals[i]); lits.AddRange(literals.Take(i)); lits.AddRange(literals.GetRange(i + 1, literals.Count)); Chain cont = new Chain(lits); cont.setProofStep(new ProofStepChainContrapositive(cont, this)); contrapositives.Add(cont); } return contrapositives; }