// dump any new clause void dumpnewclause(const Clause &cl1, const Clause &cl2, const Clause &newcl) { cout << "((p1,l1), (p2,l2)) = (("; cout << cl1.getNumber() << "," << cl1.getTotalMembers() << "),("; cout << cl2.getNumber() << "," << cl2.getTotalMembers() << ")) = "; cout << newcl << endl; return; }
int subsumes(const Clause &cl1, const Clause &cl2, Substitutions &s) { // clear substitution list s.clear(); // make sure the clauses are not the same one. // this check works since the index in literals // are never reassigned. // if (cl1 == cl2) { return(NOMATCH); } // check that every class in clause 1 exists in clause 2. if (subset(cl1, cl2) != OK) { return(NOMATCH); } // now start the actual subsumption algorithm. Substitutions subs; Clause clause2(cl2); if (groundSubstitutions(clause2, subs) != OK) { ERROR("groundSubstitutions failed.", errno); return(NOTOK); } // convert second clause to a ground clause if (subs.applyTo(clause2) != OK) { ERROR("applyTo failed.", errno); return(NOTOK); } // copy clauses to arrays Array<Literal> clarray1(1, cl1.getTotalMembers()); ClauseIterator cl1Iter(cl1); for (int i=1; !cl1Iter.done(); i++, cl1Iter++) { clarray1[i] = cl1Iter(); } Array<Literal> clarray2(1, cl2.getTotalMembers()); ClauseIterator cl2Iter(clause2); #ifdef SC42 for (i=1; !cl2Iter.done(); i++, cl2Iter++) #else for (int i=1; !cl2Iter.done(); i++, cl2Iter++) #endif { clarray2[i] = cl2Iter(); } // use Stillman's algorithm statistics[AttemptedStillmanSubsumptionTests] += 1; totalstatistics[TotalAttemptedStillmanSubsumptionTests] += 1; int status = ST(clarray1, clarray2, 1, 1, s); if (status == OK && verbose) { cout << endl; cout << "clause1 subsumes clause2 ..." << endl; cout << "clause1: " << cl1 << endl; cout << "clause2: " << cl2 << endl; } return(status); }
// check if a clause is a subset of another. only compares // equivalent sets. // int subset(const Clause &cl1, const Clause &cl2) { // verify smaller clause subsumes larger clause if (cl1.getTotalMembers() > cl2.getTotalMembers()) { return(NOMATCH); } // certain types of clauses cannot subsume others, // p = positive, n = negative, m = mixed. // // clause 1 clause 2 can // type type subsume? // ------------------------------------------- // P P yes // P N no // P M yes // N P no // N N yes // N M yes // M P yes // M N yes // M M yes // if (((cl1.getType() == Clause::Positive) && (cl2.getType() == Clause::Negative)) || ((cl1.getType() == Clause::Negative) && (cl2.getType() == Clause::Positive))) { return(NOMATCH); } // start checking every literal equivalent class. every equivalent // class in clause 1 should be in clause2. absolute equality // is checked with unification. // ClauseIterator cl1Iter(cl1); ClauseIterator cl2Iter(cl2); for ( ; !cl1Iter.done(); cl1Iter++) { // search for literal in clause 2 int found = 0; while (!cl2Iter.done() && !found) { if (cl2Iter().lt(cl1Iter())) { cl2Iter++; } else if (cl2Iter().gt(cl1Iter())) { return(NOMATCH); } else { found = 1; } } if (!found) { return(NOMATCH); } } // all done return(OK); }
// resolve two clauses, if possible. int resolveClauses(Array<BinaryTree_AVL<Clause> > &clausesArray, Clause &cl1, Clause &cl2, int &clausesAdded, unsigned int currentDepth) { // check if any of the clauses are empty statistics[ResolutionsAttempted] += 1; totalstatistics[TotalResolutionsAttempted] += 1; if (cl1.isEmpty() || cl2.isEmpty()) { return(VALID); } // check if clauses can be resolved if (!cl1.getSOS() && !cl2.getSOS()) { // one clause must be in the set-of-support return(NOMATCH); } if ((cl1.getType() == Clause::Negative && cl2.getType() == Clause::Negative) || (cl1.getType() == Clause::Positive && cl2.getType() == Clause::Positive)) { // two positive clauses or two negative clauses // can not be resolved. return(NOMATCH); } // attempt to resolve two clauses. use A-ordering resolution, // try to resolve maximal literals. // Literal maxlit1; if (cl1.getMaximalLiteral(maxlit1) != OK) { ERROR("getMaximalLiteral failed.", errno); return(NOTOK); } Literal maxlit2; if (cl2.getMaximalLiteral(maxlit2) != OK) { ERROR("getMaximalLiteral failed.", errno); return(NOTOK); } if ((cl1.getTotalMembers() > maxliterals) || (cl2.getTotalMembers() > maxliterals)) { statistics[MaximumLiteralsClausesRejected] += 1; totalstatistics[TotalMaximumLiteralsClausesRejected] += 1; return(NOMATCH); } if (maxlit1.unify_ne(~maxlit2)) { return(NOMATCH); } // factor clauses Substitutions subs; if (factor(maxlit1, cl1, subs) == NOTOK) { ERROR("factor failed.", errno); return(NOTOK); } if (factor(maxlit2, cl2, subs) == NOTOK) { ERROR("factor failed.", errno); return(NOTOK); } // attempt to unify the clauses subs.clear(); int status = unify(maxlit1, ~maxlit2, subs); switch (status) { case OK: if (verbose) { cout << endl; Literal ml1(maxlit1); cout << "max literal 1 (before subs): " << ml1 << endl; subs.applyTo(ml1); cout << "max literal 1 (after subs): " << ml1 << endl; Literal ml2(maxlit2); cout << "max literal 2 (before subs): " << ml2 << endl; subs.applyTo(ml2); cout << "max literal 2 (after subs): " << ml2 << endl; MustBeTrue(equal(ml1, ~ml2)); } break; case NOMATCH: return(NOMATCH); default: ERROR("unify failed.", errno); return(status); } // can resolve, remove literals from clauses Clause newcl1(cl1); if (newcl1.remove(maxlit1) != OK) { ERROR("remove failed.", errno); return(NOTOK); } if (subs.applyTo(newcl1) != OK) { ERROR("applyTo failed.", errno); return(NOTOK); } Clause newcl2(cl2); if (newcl2.remove(maxlit2) != OK) { ERROR("remove failed.", errno); return(NOTOK); } if (subs.applyTo(newcl2) != OK) { ERROR("applyTo failed.", errno); return(NOTOK); } // store new clause and update flag Clause newcl = newcl1+newcl2; if (newcl.renameVariables() != OK) { ERROR("renameVariables failed.", errno); return(NOTOK); } newcl.setDepth(currentDepth+1); newcl.setNumber(nextClause++); if (clausesArray[currentDepth+1].insert(newcl) != OK) { ERROR("insert failed.", errno); return(NOTOK); } clausesAdded = 1; // indicate the clauses that were resolved statistics[ClausesGenerated] += 1; totalstatistics[TotalClausesGenerated] += 1; dumpnewclause(cl1, cl2, newcl); // check if we found an empty clause if (newcl.isEmpty()) { return(VALID); } else { return(OK); } }