void ClauseCleaner::cleanClauses(vec<Clause*>& cs, ClauseSetType type, const uint32_t limit) { assert(solver.decisionLevel() == 0); assert(solver.qhead == solver.trail.size()); if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num()) return; #ifdef VERBOSE_DEBUG std::cout << "Cleaning " << (type==binaryClauses ? "binaryClauses" : "normal clauses" ) << std::endl; #endif //VERBOSE_DEBUG Clause **s, **ss, **end; for (s = ss = cs.getData(), end = s + cs.size(); s != end; s++) { if (s+1 != end) __builtin_prefetch(*(s+1)); if (cleanClause(*s)) { solver.clauseAllocator.clauseFree(*s); } else { *ss++ = *s; } } cs.shrink(s-ss); lastNumUnitaryClean[type] = solver.get_unitary_learnts_num(); #ifdef VERBOSE_DEBUG cout << "cleanClauses(Clause) useful ?? Removed: " << s-ss << endl; #endif }
void ClauseCleaner::cleanClausesBewareNULL(vec<ClauseSimp>& cs, ClauseCleaner::ClauseSetType type, Subsumer& subs, const unsigned limit) { assert(solver.decisionLevel() == 0); assert(solver.qhead == solver.trail.size()); if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num()) return; ClauseSimp* s, *end; for (s = cs.getData(), end = s + cs.size(); s != end; s++) { if (s + 1 != end) __builtin_prefetch((s + 1)->clause, 1, 0); if (s->clause == NULL) continue; if (cleanClauseBewareNULL(*s, subs)) { continue; } else if (s->clause->size() == 2) solver.becameBinary++; } lastNumUnitaryClean[type] = solver.get_unitary_learnts_num(); }
void ClauseAllocator::updatePointers(vec<T*>& toUpdate, const map<Clause*, Clause*>& oldToNewPointer) { for (T **it = toUpdate.getData(), **end = toUpdate.getDataEnd(); it != end; it++) { if (!(*it)->wasBin()) { //assert(oldToNewPointer.find((TT*)*it) != oldToNewPointer.end()); map<Clause*, Clause*>::const_iterator it2 = oldToNewPointer.find((Clause*)*it); *it = (T*)it2->second; } } }
bool PartHandler::checkOnlyThisPart(const vec<T*>& cs, const uint32_t part, const PartFinder& partFinder) const { for(T * const*it = cs.getData(), * const*end = it + cs.size(); it != end; it++) { const T& c = **it; for(const Lit *l = c.getData(), *end2 = l + c.size(); l != end2; l++) { if (partFinder.getVarPart(l->var()) != part) return false; } } return true; }
void RestartTypeChooser::addDegrees(const vec<T*>& cs, vector<uint32_t>& degrees) const { for (T * const*c = cs.getData(), * const*end = c + cs.size(); c != end; c++) { T& cl = **c; if (cl.learnt()) continue; for (const Lit *l = cl.getData(), *end2 = l + cl.size(); l != end2; l++) { degrees[l->var()]++; } } }
void PartFinder::calcIn(const vec<T*>& cs, vector<uint>& numClauseInPart, vector<uint>& sumLitsInPart) { for (T*const* c = cs.getData(), *const*end = c + cs.size(); c != end; c++) { if ((*c)->learnt()) continue; T& x = **c; const uint part = table[x[0].var()]; assert(part < part_no); //for stats numClauseInPart[part]++; sumLitsInPart[part] += x.size(); } }
void XorSubsumer::addFromSolver(vec<XorClause*>& cs) { clauseID = 0; clauses.clear(); XorClause **i = cs.getData(); for (XorClause **end = i + cs.size(); i != end; i++) { if (i+1 != end) __builtin_prefetch(*(i+1)); linkInClause(**i); } cs.clear(); cs.push(NULL); //HACK --to force xor-propagation }
/** @brief Replaces vars in xorclauses */ bool VarReplacer::replace_set(vec<XorClause*>& cs) { XorClause **a = cs.getData(); XorClause **r = a; for (XorClause **end = a + cs.size(); r != end; r++) { XorClause& c = **r; bool changed = false; Var origVar1 = c[0].var(); Var origVar2 = c[1].var(); for (Lit *l = &c[0], *end2 = l + c.size(); l != end2; l++) { Lit newlit = table[l->var()]; if (newlit.var() != l->var()) { changed = true; *l = Lit(newlit.var(), false); c.invert(newlit.sign()); replacedLits++; } } if (changed && handleUpdatedClause(c, origVar1, origVar2)) { if (!solver.ok) { #ifdef VERBOSE_DEBUG cout << "contradiction while replacing lits in xor clause" << std::endl; #endif for(;r != end; r++) solver.clauseAllocator.clauseFree(*r); cs.shrink(r-a); return false; } //solver.clauseAllocator.clauseFree(&c); c.setRemoved(); solver.freeLater.push(&c); } else { #ifdef SILENT_DEBUG uint32_t numUndef = 0; for (uint32_t i = 0; i < c.size(); i++) { if (solver.value(c[i]) == l_Undef) numUndef++; } assert(numUndef >= 2 || numUndef == 0); #endif *a++ = *r; } } cs.shrink(r-a); return solver.ok; }
void XorSubsumer::addFromSolver(vec<XorClause*>& cs) { clauseID = 0; clauses.clear(); XorClause **i = cs.getData(); for (XorClause **end = i + cs.size(); i != end; i++) { if (i+1 != end) __builtin_prefetch(*(i+1), 1, 1); linkInClause(**i); if ((*i)->getVarChanged() || (*i)->getStrenghtened()) (*i)->calcXorAbstraction(); } cs.clear(); cs.push(NULL); //HACK --to force xor-propagation }
void ClauseCleaner::cleanClauses(vec<XorClause*>& cs, ClauseSetType type, const unsigned limit) { assert(solver.decisionLevel() == 0); assert(solver.qhead == solver.trail.size()); if (lastNumUnitaryClean[type] + limit >= solver.get_unitary_learnts_num()) return; XorClause** s, **ss, **end; for (s = ss = cs.getData(), end = s + cs.size(); s != end; s++) { if (s + 1 != end) __builtin_prefetch(*(s + 1), 1, 0); #ifdef DEBUG_ATTACH assert(find(solver.xorwatches[(**s)[0].var()], *s)); assert(find(solver.xorwatches[(**s)[1].var()], *s)); if (solver.assigns[(**s)[0].var()] != l_Undef || solver.assigns[(**s)[1].var()] != l_Undef) { satisfied(**s); } #endif // DEBUG_ATTACH if (cleanClause(**s)) { solver.freeLater.push(*s); (*s)->setRemoved(); } else { #ifdef DEBUG_ATTACH assert(find(solver.xorwatches[(**s)[0].var()], *s)); assert(find(solver.xorwatches[(**s)[1].var()], *s)); #endif // DEBUG_ATTACH *ss++ = *s; } } cs.shrink(s - ss); lastNumUnitaryClean[type] = solver.get_unitary_learnts_num(); #ifdef VERBOSE_DEBUG cout << "cleanClauses(XorClause) useful: ?? Removed: " << s - ss << endl; #endif }
/** @brief Initialises datastructures for 2-long xor finding by shortening longer xors */ void FailedLitSearcher::addFromSolver(const vec< XorClause* >& cs) { xorClauseSizes.clear(); xorClauseSizes.growTo(cs.size()); occur.resize(solver.nVars()); for (Var var = 0; var < solver.nVars(); var++) { occur[var].clear(); } uint32_t i = 0; for (XorClause * const*it = cs.getData(), * const*end = it + cs.size(); it != end; it++, i++) { if (it + 1 != end) __builtin_prefetch(*(it + 1)); const XorClause& cl = **it; xorClauseSizes[i] = cl.size(); for (const Lit *l = cl.getData(), *end2 = l + cl.size(); l != end2; l++) { occur[l->var()].push_back(i); } } }
void PartHandler::moveLearntClauses(vec<Clause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder) { Clause **i, **j, **end; for (i = j = cs.getData(), end = i + cs.size() ; i != end; i++) { if (!(**i).learnt()) { *j++ = *i; continue; } Clause& c = **i; assert(c.size() > 0); uint32_t clause_part = partFinder.getVarPart(c[0].var()); bool removed = false; for (const Lit* l = c.getData(), *end = l + c.size(); l != end; l++) { if (partFinder.getVarPart(l->var()) != clause_part) { #ifdef VERBOSE_DEBUG std::cout << "Learnt clause in both parts:"; c.plainPrint(); #endif removed = true; solver.removeClause(c); break; } } if (removed) continue; if (clause_part == part) { #ifdef VERBOSE_DEBUG //std::cout << "Learnt clause in this part:"; c.plainPrint(); #endif solver.detachClause(c); newSolver.addLearntClause(c, c.getGroup(), c.activity()); solver.clauseAllocator.clauseFree(&c); } else { #ifdef VERBOSE_DEBUG std::cout << "Learnt clause in other part:"; c.plainPrint(); #endif *j++ = *i; } } cs.shrink(i-j); }
const bool DataSync::syncBinFromOthers(const Lit lit, const vector<Lit>& bins, uint32_t& finished, vec<Watched>& ws) { assert(solver.varReplacer->getReplaceTable()[lit.var()].var() == lit.var()); assert(solver.subsumer->getVarElimed()[lit.var()] == false); assert(solver.xorSubsumer->getVarElimed()[lit.var()] == false); vec<Lit> addedToSeen; for (vec<Watched>::iterator it = ws.getData(), end = ws.getDataEnd(); it != end; it++) { if (it->isBinary()) { addedToSeen.push(it->getOtherLit()); seen[it->getOtherLit().toInt()] = true; } } vec<Lit> lits(2); for (uint32_t i = finished; i < bins.size(); i++) { if (!seen[bins[i].toInt()]) { Lit otherLit = bins[i]; otherLit = solver.varReplacer->getReplaceTable()[otherLit.var()] ^ otherLit.sign(); if (solver.subsumer->getVarElimed()[otherLit.var()] || solver.xorSubsumer->getVarElimed()[otherLit.var()] || solver.value(otherLit.var()) != l_Undef ) continue; recvBinData++; lits[0] = lit; lits[1] = otherLit; solver.addClauseInt(lits, 0, true, 2, 0, true); lits.clear(); lits.growTo(2); if (!solver.ok) goto end; } } finished = bins.size(); end: for (uint32_t i = 0; i < addedToSeen.size(); i++) seen[addedToSeen[i].toInt()] = false; return solver.ok; }
/** @brief Replaces variables in normal clauses */ const bool VarReplacer::replace_set(vec<Clause*>& cs, const bool binClauses) { Clause **a = cs.getData(); Clause **r = a; for (Clause **end = a + cs.size(); r != end; r++) { Clause& c = **r; bool changed = false; Lit origLit1 = c[0]; Lit origLit2 = c[1]; Lit origLit3 = (c.size() == 3) ? c[2] : lit_Undef; for (Lit *l = c.getData(), *end2 = l + c.size(); l != end2; l++) { if (table[l->var()].var() != l->var()) { changed = true; *l = table[l->var()] ^ l->sign(); replacedLits++; } } if (changed && handleUpdatedClause(c, origLit1, origLit2, origLit3)) { if (!solver.ok) { for(;r != end; r++) solver.clauseAllocator.clauseFree(*r); cs.shrink(r-a); return false; } } else { if (!binClauses && c.size() == 2) { solver.detachClause(c); Clause *c2 = solver.clauseAllocator.Clause_new(c); solver.clauseAllocator.clauseFree(&c); solver.attachClause(*c2); solver.becameBinary++; solver.binaryClauses.push(c2); } else *a++ = *r; } } cs.shrink(r-a); return solver.ok; }
void ClauseCleaner::removeSatisfied(vec<Clause*>& cs, ClauseSetType type, const uint limit) { #ifdef DEBUG_CLEAN assert(solver.decisionLevel() == 0); #endif if (lastNumUnitarySat[type] + limit >= solver.get_unitary_learnts_num()) return; Clause **i,**j, **end; for (i = j = cs.getData(), end = i + cs.size(); i != end; i++) { if (i+1 != end) __builtin_prefetch(*(i+1), 0, 0); if (satisfied(**i)) solver.removeClause(**i); else *j++ = *i; } cs.shrink(i - j); lastNumUnitarySat[type] = solver.get_unitary_learnts_num(); }
void PartHandler::moveClauses(vec<XorClause*>& cs, Solver& newSolver, const uint32_t part, PartFinder& partFinder) { XorClause **i, **j, **end; for (i = j = cs.getData(), end = i + cs.size(); i != end; i++) { if (partFinder.getVarPart((**i)[0].var()) != part) { *j++ = *i; continue; } solver.detachClause(**i); #ifdef VERBOSE_DEBUG std::cout << "xor clause in this part:"; (**i).plainPrint(); #endif XorClause& c = **i; vec<Lit> tmp(c.size()); std::copy(c.getData(), c.getDataEnd(), tmp.getData()); newSolver.addXorClause(tmp, c.xor_clause_inverted(), c.getGroup()); //NOTE: we need the CS because otherwise, the addXorClause could have changed **i, which we need to re-add later! xorClausesRemoved.push(*i); } cs.shrink(i-j); }
/** @brief Replaces vars in xorclauses */ const bool VarReplacer::replace_set(vec<XorClause*>& cs) { XorClause **a = cs.getData(); XorClause **r = a; for (XorClause **end = a + cs.size(); r != end; r++) { XorClause& c = **r; bool changed = false; Var origVar1 = c[0].var(); Var origVar2 = c[1].var(); for (Lit *l = &c[0], *end2 = l + c.size(); l != end2; l++) { Lit newlit = table[l->var()]; if (newlit.var() != l->var()) { changed = true; *l = Lit(newlit.var(), false); c.invert(newlit.sign()); replacedLits++; } } if (changed && handleUpdatedClause(c, origVar1, origVar2)) { if (!solver.ok) { for(;r != end; r++) solver.clauseAllocator.clauseFree(*r); cs.shrink(r-a); return false; } c.setRemoved(); solver.freeLater.push(&c); } else { *a++ = *r; } } cs.shrink(r-a); return solver.ok; }
void PartFinder::addToPart(const vec<T*>& cs) { set<uint> tomerge; vector<Var> newSet; for (T* const* c = cs.getData(), * const*end = c + cs.size(); c != end; c++) { if ((*c)->learnt()) continue; tomerge.clear(); newSet.clear(); for (const Lit *l = (*c)->getData(), *end2 = l + (*c)->size(); l != end2; l++) { if (table[l->var()] != std::numeric_limits<uint32_t>::max()) tomerge.insert(table[l->var()]); else newSet.push_back(l->var()); } if (tomerge.size() == 1) { //no trees to merge, only merge the clause into one tree const uint into = *tomerge.begin(); map<uint, vector<Var> >::iterator intoReverse = reverseTable.find(into); for (uint i = 0; i < newSet.size(); i++) { intoReverse->second.push_back(newSet[i]); table[newSet[i]] = into; } continue; } for (set<uint>::iterator it = tomerge.begin(); it != tomerge.end(); it++) { newSet.insert(newSet.end(), reverseTable[*it].begin(), reverseTable[*it].end()); reverseTable.erase(*it); } for (uint i = 0; i < newSet.size(); i++) table[newSet[i]] = part_no; reverseTable[part_no] = newSet; part_no++; } }
/** @brief Replaces variables in normal clauses */ bool VarReplacer::replace_set(vec<Clause*>& cs) { Clause **a = cs.getData(); Clause **r = a; for (Clause **end = a + cs.size(); r != end; r++) { Clause& c = **r; assert(c.size() > 2); bool changed = false; Lit origLit1 = c[0]; Lit origLit2 = c[1]; Lit origLit3 = (c.size() == 3) ? c[2] : lit_Undef; for (Lit *l = c.getData(), *end2 = l + c.size(); l != end2; l++) { if (table[l->var()].var() != l->var()) { changed = true; *l = table[l->var()] ^ l->sign(); replacedLits++; } } if (changed && handleUpdatedClause(c, origLit1, origLit2, origLit3)) { if (!solver.ok) { #ifdef VERBOSE_DEBUG cout << "contradiction while replacing lits in normal clause" << std::endl; #endif for(;r != end; r++) solver.clauseAllocator.clauseFree(*r); cs.shrink(r-a); return false; } } else { *a++ = *r; } } cs.shrink(r-a); return solver.ok; }
void XorSubsumer::removeWrong(vec<Clause*>& cs) { Clause **i = cs.getData(); Clause **j = i; for (Clause **end = i + cs.size(); i != end; i++) { Clause& c = **i; if (!c.learnt()) { *j++ = *i; continue; } bool remove = false; for (Lit *l = c.getData(), *end2 = l+c.size(); l != end2; l++) { if (var_elimed[l->var()]) { remove = true; solver.detachClause(c); solver.clauseAllocator.clauseFree(&c); break; } } if (!remove) *j++ = *i; } cs.shrink(i-j); }
bool ClauseVivifier::vivifyClauses2(vec<Clause*>& clauses) { assert(solver.ok); vec<char> seen; seen.growTo(solver.nVars()*2, 0); vec<char> seen_subs; seen_subs.growTo(solver.nVars()*2, 0); uint32_t litsRem = 0; uint32_t clShrinked = 0; uint64_t countTime = 0; uint64_t maxCountTime = 800 * 1000 * 1000; maxCountTime *= 6; if (solver.clauses_literals + solver.learnts_literals < 500000) maxCountTime *= 2; uint32_t clTried = 0; vec<Lit> lits; bool needToFinish = false; double myTime = cpuTime(); uint32_t subsumed_tri_num = 0; uint32_t subsumed_bin_num = 0; Clause** i = clauses.getData(); Clause** j = i; for (Clause** end = clauses.getDataEnd(); i != end; i++) { if (needToFinish) { *j++ = *i; continue; } if (countTime > maxCountTime) needToFinish = true; Clause& cl = **i; countTime += cl.size()*2; clTried++; bool subsumed = false; const bool learnt = cl.learnt(); for (uint32_t i2 = 0; i2 < cl.size(); i2++) { seen[cl[i2].toInt()] = 1; //for strengthening seen_subs[cl[i2].toInt()] = 1; //for subsumption } for (const Lit *l = cl.getData(), *end = cl.getDataEnd(); l != end; l++) { const Lit *l_other = l; l_other++; if (l_other != end) __builtin_prefetch(solver.watches[(~*l_other).toInt()].getData()); const vec<Watched>& ws = solver.watches[(~*l).toInt()]; countTime += ws.size()*2; for (vec<Watched>::const_iterator it = ws.getData(), end = ws.getDataEnd(); it != end; it++) { //Handle tri clause if (it->isTriClause() && cl.size() > 3) { if (learnt //we cannot decide if TRI is learnt or not && seen_subs[it->getOtherLit().toInt()] && seen_subs[it->getOtherLit2().toInt()] ) { subsumed_tri_num++; subsumed = true; } if (seen[l->toInt()]) { //we may have removed it already //one way if (seen[(it->getOtherLit2()).toInt()]) seen[(~it->getOtherLit()).toInt()] = 0; //other way if (seen[(it->getOtherLit()).toInt()]) seen[(~it->getOtherLit2()).toInt()] = 0; } } //Handle Binary clause if (it->isBinary()) { if (seen_subs[it->getOtherLit().toInt()]) { if (!learnt && it->getLearnt()) makeNonLearntBin(*l, it->getOtherLit(), it->getLearnt()); subsumed_bin_num++; subsumed = true; } if (seen[l->toInt()]) //we may have removed it already seen[(~it->getOtherLit()).toInt()] = 0; } } if (seen[l->toInt()] == 0) continue; countTime += solver.transOTFCache[l->toInt()].lits.size(); for (vector<Lit>::const_iterator it2 = solver.transOTFCache[l->toInt()].lits.begin() , end2 = solver.transOTFCache[l->toInt()].lits.end(); it2 != end2; it2++) { seen[(~(*it2)).toInt()] = 0; } } lits.clear(); for (const Lit *it2 = cl.getData(), *end2 = cl.getDataEnd(); it2 != end2; it2++) { if (seen[it2->toInt()]) lits.push(*it2); else litsRem++; seen[it2->toInt()] = 0; seen_subs[it2->toInt()] = 0; } if (subsumed) { solver.removeClause(cl); } else if (lits.size() < cl.size()) { solver.detachClause(cl); clShrinked++; Clause* c2 = solver.addClauseInt(lits, cl.learnt(), cl.getGlue(), cl.getMiniSatAct()); solver.clauseAllocator.clauseFree(&cl); if (c2 != NULL) *j++ = c2; if (!solver.ok) needToFinish = true; } else { *j++ = *i; } } clauses.shrink(i - j); if (solver.conf.verbosity >= 1) { std::cout << "c vivif2 -- " << " cl tried " << std::setw(8) << clTried << " cl rem " << std::setw(8) << (subsumed_bin_num + subsumed_tri_num) << " cl shrink " << std::setw(8) << clShrinked << " lits rem " << std::setw(10) << litsRem << " time: " << cpuTime() - myTime << std::endl; } return solver.ok; }