private void calculateFactors(List <Clause> parentFactors) { nonTrivialFactors = new List <Clause>(); Dictionary <Variable, Term> theta = new Dictionary <Variable, Term>(); List <Literal> lits = new List <Literal>(); for (int i = 0; i < 2; i++) { lits.Clear(); if (i == 0) { // Look at the positive literals lits.AddRange(positiveLiterals); } else { // Look at the negative literals lits.AddRange(negativeLiterals); } for (int x = 0; x < lits.Count; x++) { for (int y = x + 1; y < lits.Count; y++) { Literal litX = lits[x]; Literal litY = lits[y]; theta.Clear(); Dictionary <Variable, Term> substitution = _unifier.unify(litX .getAtomicSentence(), litY.getAtomicSentence(), theta); if (null != substitution) { List <Literal> posLits = new List <Literal>(); List <Literal> negLits = new List <Literal>(); if (i == 0) { posLits .Add(_substVisitor .subst(substitution, litX)); } else { negLits .Add(_substVisitor .subst(substitution, litX)); } foreach (Literal pl in positiveLiterals) { if (pl == litX || pl == litY) { continue; } posLits.Add(_substVisitor.subst(substitution, pl)); } foreach (Literal nl in negativeLiterals) { if (nl == litX || nl == litY) { continue; } negLits.Add(_substVisitor.subst(substitution, nl)); } // Ensure the non trivial factor is standardized apart _standardizeApart.standardizeApart(posLits, negLits, _saIndexical); Clause c = new Clause(posLits, negLits); c.setProofStep(new ProofStepClauseFactor(c, this)); if (isImmutable()) { c.setImmutable(); } if (!isStandardizedApartCheckRequired()) { c.setStandardizedApartCheckNotRequired(); } if (null == parentFactors) { c.calculateFactors(nonTrivialFactors); nonTrivialFactors.AddRange(c.getFactors()); } else { if (!parentFactors.Contains(c)) { c.calculateFactors(nonTrivialFactors); nonTrivialFactors.AddRange(c.getFactors()); } } } } } } factors = new List <Clause>(); // Need to add self, even though a non-trivial // factor. See: slide 30 // http://logic.stanford.edu/classes/cs157/2008/lectures/lecture10.pdf // for example of incompleteness when // trivial factor not included. factors.Add(this); factors.AddRange(nonTrivialFactors); }
private bool checkSubsumes(Clause othC, Dictionary <String, List <Literal> > thisToTry, Dictionary <String, List <Literal> > othCToTry) { bool subsumes = false; List <Term> thisTerms = new List <Term>(); List <Term> othCTerms = new List <Term>(); // Want to track possible number of permuations List <int> radixs = new List <int>(); foreach (String literalName in thisToTry.Keys) { int sizeT = thisToTry[literalName].Count; int sizeO = othCToTry[literalName].Count; if (sizeO > 1) { // The following is being used to // track the number of permutations // that can be mapped from the // other clauses like literals to this // clauses like literals. // i.e. n!/(n-r)! // where n=sizeO and r =sizeT for (int i = 0; i < sizeT; i++) { int r = sizeO - i; if (r > 1) { radixs.Add(r); } } } // Track the terms for this clause foreach (Literal tl in thisToTry[literalName]) { List <FOLNode> folNodes = tl.getAtomicSentence().getArgs(); foreach (FOLNode n in folNodes) { thisTerms.Add((Term)n); } } } MixedRadixNumber permutation = null; long numPermutations = 1L; if (radixs.Count > 0) { permutation = new MixedRadixNumber(0, radixs); numPermutations = permutation.getMaxAllowedValue() + 1; } // Want to ensure none of the othCVariables are // part of the key set of a unification as // this indicates it is not a legal subsumption. List <Variable> othCVariables = _variableCollector .collectAllVariables(othC); Dictionary <Variable, Term> theta = new Dictionary <Variable, Term>(); List <Literal> literalPermuations = new List <Literal>(); for (long l = 0L; l < numPermutations; l++) { // Track the other clause's terms for this // permutation. othCTerms.Clear(); int radixIdx = 0; foreach (String literalName in thisToTry.Keys) { int sizeT = thisToTry[literalName].Count; literalPermuations.Clear(); literalPermuations.AddRange(othCToTry[literalName]); int sizeO = literalPermuations.Count; if (sizeO > 1) { for (int i = 0; i < sizeT; i++) { int r = sizeO - i; if (r > 1) { // If not a 1 to 1 mapping then you need // to use the correct permuation int numPos = permutation .getCurrentNumeralValue(radixIdx); Literal lit = literalPermuations[numPos]; literalPermuations.Remove(lit); foreach (FOLNode arg in lit.getAtomicSentence().getArgs()) { othCTerms.Add((Term)arg); } radixIdx++; } else { // is the last mapping, therefore // won't be on the radix foreach (FOLNode arg in literalPermuations[0].getAtomicSentence().getArgs()) { othCTerms.Add((Term)arg); } } } } else { // a 1 to 1 mapping foreach (FOLNode arg in literalPermuations[0].getAtomicSentence().getArgs()) { othCTerms.Add((Term)arg); } } } // Note: on unifier // unifier.unify(P(w, x), P(y, z)))={w=y, x=z} // unifier.unify(P(y, z), P(w, x)))={y=w, z=x} // Therefore want this clause to be the first // so can do the othCVariables check for an invalid // subsumes. theta.Clear(); List <FOLNode> termNodes = new List <FOLNode>(); foreach (Term t in thisTerms) { termNodes.Add((FOLNode)t); } List <FOLNode> othCNodes = new List <FOLNode>(); foreach (Term t in othCTerms) { othCNodes.Add((FOLNode)t); } if (null != _unifier.unify(termNodes, othCNodes, theta)) { bool containsAny = false; foreach (Variable v in theta.Keys) { if (othCVariables.Contains(v)) { containsAny = true; break; } } if (!containsAny) { subsumes = true; break; } } // If there is more than 1 mapping // keep track of where I am in the // possible number of mapping permutations. if (null != permutation) { permutation.increment(); } } return(subsumes); }
// Note: Applies binary resolution rule and factoring // Note: returns a set with an empty clause if both clauses // are empty, otherwise returns a set of binary resolvents. public List <Clause> binaryResolvents(Clause othC) { List <Clause> resolvents = new List <Clause>(); // Resolving two empty clauses // gives you an empty clause if (isEmpty() && othC.isEmpty()) { resolvents.Add(new Clause()); return(resolvents); } // Ensure Standardized Apart // Before attempting binary resolution othC = saIfRequired(othC); List <Literal> allPosLits = new List <Literal>(); List <Literal> allNegLits = new List <Literal>(); allPosLits.AddRange(this.positiveLiterals); allPosLits.AddRange(othC.positiveLiterals); allNegLits.AddRange(this.negativeLiterals); allNegLits.AddRange(othC.negativeLiterals); List <Literal> trPosLits = new List <Literal>(); List <Literal> trNegLits = new List <Literal>(); List <Literal> copyRPosLits = new List <Literal>(); List <Literal> copyRNegLits = new List <Literal>(); for (int i = 0; i < 2; i++) { trPosLits.Clear(); trNegLits.Clear(); if (i == 0) { // See if this clauses positives // unify with the other clauses // negatives trPosLits.AddRange(this.positiveLiterals); trNegLits.AddRange(othC.negativeLiterals); } else { // Try the other way round now trPosLits.AddRange(othC.positiveLiterals); trNegLits.AddRange(this.negativeLiterals); } // Now check to see if they resolve Dictionary <Variable, Term> copyRBindings = new Dictionary <Variable, Term>(); foreach (Literal pl in trPosLits) { foreach (Literal nl in trNegLits) { copyRBindings.Clear(); if (null != _unifier.unify(pl.getAtomicSentence(), nl .getAtomicSentence(), copyRBindings)) { copyRPosLits.Clear(); copyRNegLits.Clear(); bool found = false; foreach (Literal l in allPosLits) { if (!found && pl.Equals(l)) { found = true; continue; } copyRPosLits.Add(_substVisitor.subst(copyRBindings, l)); } found = false; foreach (Literal l in allNegLits) { if (!found && nl.Equals(l)) { found = true; continue; } copyRNegLits.Add(_substVisitor.subst(copyRBindings, l)); } // Ensure the resolvents are standardized apart Dictionary <Variable, Term> renameSubstitituon = _standardizeApart .standardizeApart(copyRPosLits, copyRNegLits, _saIndexical); Clause c = new Clause(copyRPosLits, copyRNegLits); c.setProofStep(new ProofStepClauseBinaryResolvent(c, this, othC, copyRBindings, renameSubstitituon)); if (isImmutable()) { c.setImmutable(); } if (!isStandardizedApartCheckRequired()) { c.setStandardizedApartCheckNotRequired(); } resolvents.Add(c); } } } } return(resolvents); }