void DataSync::signalNewBinClause(Lit lit1, Lit lit2) { if (!enabled()) { return; } if (must_rebuild_bva_map) { outer_to_without_bva_map = solver->build_outer_to_without_bva_map(); must_rebuild_bva_map = false; } if (solver->varData[lit1.var()].is_bva) return; if (solver->varData[lit2.var()].is_bva) return; lit1 = solver->map_inter_to_outer(lit1); lit1 = map_outside_without_bva(lit1); lit2 = solver->map_inter_to_outer(lit2); lit2 = map_outside_without_bva(lit2); if (lit1.toInt() > lit2.toInt()) { std::swap(lit1, lit2); } newBinClauses.push_back(std::make_pair(lit1, lit2)); }
void XorSubsumer::removeWrongBins() { uint32_t numRemovedHalfLearnt = 0; uint32_t wsLit = 0; for (vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) { Lit lit = ~Lit::toLit(wsLit); vec<Watched>& ws = *it; vec<Watched>::iterator i = ws.getData(); vec<Watched>::iterator j = i; for (vec<Watched>::iterator end2 = ws.getDataEnd(); i != end2; i++) { if (i->isBinary() && i->getLearnt() && (var_elimed[lit.var()] || var_elimed[i->getOtherLit().var()]) ) { numRemovedHalfLearnt++; } else { assert(!i->isBinary() || (!var_elimed[lit.var()] && !var_elimed[i->getOtherLit().var()])); *j++ = *i; } } ws.shrink_(i - j); } assert(numRemovedHalfLearnt % 2 == 0); solver.learnts_literals -= numRemovedHalfLearnt; solver.numBins -= numRemovedHalfLearnt/2; }
void HyperEngine::add_hyper_bin(const Lit lit1, const Lit lit2, const Lit lit3) { assert(value(lit1.var()) == l_Undef); #ifdef VERBOSE_DEBUG_FULLPROP print_trail(); cout << "Enqueing " << lit1 << " with ancestor 3-long clause: " << lit1 << " , " << lit2 << " (lev:" << varData[lit2.var()].level << ") " << lit3 << " (lev:" << varData[lit3.var()].level << ") " << endl; #endif assert(value(lit2) == l_False); assert(value(lit3) == l_False); currAncestors.clear(); if (varData[lit2.var()].level != 0) { currAncestors.push_back(~lit2); } if (varData[lit3.var()].level != 0) currAncestors.push_back(~lit3); add_hyper_bin(lit1); }
bool TransCache::merge( const vector<Lit>& otherLits //Lits to add , const Lit extraLit //Add this, too to the list of lits , const bool red //The step was a redundant-dependent step? , const Var leaveOut //Leave this literal out , vector<uint16_t>& seen ) { //Mark every literal that is to be added in 'seen' for (size_t i = 0, size = otherLits.size(); i < size; i++) { const Lit lit = otherLits[i]; seen[lit.toInt()] = 1; } bool taut = mergeHelper(extraLit, red, seen); //Whatever rests needs to be added for (size_t i = 0 ,size = otherLits.size(); i < size; i++) { const Lit lit = otherLits[i]; if (seen[lit.toInt()]) { if (lit.var() != leaveOut) lits.push_back(LitExtra(lit, false)); seen[lit.toInt()] = 0; } } //Handle extra lit if (extraLit != lit_Undef && seen[extraLit.toInt()]) { if (extraLit.var() != leaveOut) lits.push_back(LitExtra(extraLit, !red)); seen[extraLit.toInt()] = 0; } return taut; }
void SolutionExtender::addClause(const vector<Lit>& lits, const Lit blockedOn) { const uint32_t blocked_on_inter = solver->map_outer_to_inter(blockedOn.var()); assert(solver->varData[blocked_on_inter].removed == Removed::elimed); assert(contains_lit(lits, blockedOn)); if (satisfied(lits)) return; #ifdef VERBOSE_DEBUG_SOLUTIONEXTENDER for(Lit lit: lits) { Lit lit_inter = solver->map_outer_to_inter(lit); cout << lit << ": " << solver->model_value(lit) << "(elim: " << removed_type_to_string(solver->varData[lit_inter.var()].removed) << ")" << ", "; } cout << "blocked on: " << blockedOn << endl; #endif if (solver->model_value(blockedOn) != l_Undef) { cout << "ERROR: Model value for var " << blockedOn.unsign() << " is " << solver->model_value(blockedOn) << " but that doesn't satisfy a v-elim clause on the stack!" << endl; } assert(solver->model_value(blockedOn) == l_Undef); solver->model[blockedOn.var()] = blockedOn.sign() ? l_False : l_True; if (solver->conf.verbosity >= 10) { cout << "Extending VELIM cls. -- setting model for var " << blockedOn.unsign() << " to " << solver->model[blockedOn.var()] << endl; } assert(satisfied(lits)); solver->varReplacer->extend_model(blockedOn.var()); }
/** @brief Returns if we already know that var = lit Also checks if var = ~lit, in which it sets solver.ok = false */ bool VarReplacer::alreadyIn(const Var var, const Lit lit) { Lit lit2 = table[var]; if (lit2.var() == lit.var()) { if (lit2.sign() != lit.sign()) { #ifdef VERBOSE_DEBUG cout << "Inverted cycle in var-replacement -> UNSAT" << endl; #endif solver.ok = false; } return true; } lit2 = table[lit.var()]; if (lit2.var() == var) { if (lit2.sign() != lit.sign()) { #ifdef VERBOSE_DEBUG cout << "Inverted cycle in var-replacement -> UNSAT" << endl; #endif solver.ok = false; } return true; } return false; }
void SolutionExtender::addClause(const vector<Lit>& lits, const Lit blockedOn) { const Var blocked_on_inter = solver->map_outer_to_inter(blockedOn.var()); assert(solver->varData[blocked_on_inter].removed == Removed::elimed); assert(contains_lit(lits, blockedOn)); if (satisfied(lits)) return; #ifdef VERBOSE_DEBUG_SOLUTIONEXTENDER for(Lit lit: lits) { Lit lit_inter = solver->map_outer_to_inter(lit); cout << lit << ": " << solver->model_value(lit) << "(elim: " << removed_type_to_string(solver->varData[lit_inter.var()].removed) << ")" << ", "; } cout << "blocked on: " << blockedOn << endl; #endif assert(solver->model_value(blockedOn) == l_Undef); solver->model[blockedOn.var()] = blockedOn.sign() ? l_False : l_True; assert(satisfied(lits)); solver->varReplacer->extend_model(blockedOn.var()); }
bool SolutionExtender::propagateCl( const Clause* cl , const Lit blockedOn ) { size_t numUndef = 0; Lit lastUndef = lit_Undef; for (const Lit *it = cl->begin(), *end = cl->end() ; it != end ; ++it ) { if (value(*it) == l_True) return true; if (value(*it) == l_False) continue; assert(value(*it) == l_Undef); numUndef++; //Doesn't propagate anything if (numUndef > 1) break; lastUndef = *it; } //Must set this one value if (numUndef == 1) { #ifdef VERBOSE_DEBUG_RECONSTRUCT cout << "c Due to cl " << *cl << " propagate enqueueing " << lastUndef << endl; #endif enqueue(lastUndef); } if (numUndef >= 1) return true; //Must flip #ifdef VERBOSE_DEBUG_RECONSTRUCT cout << "Flipping lit " << blockedOn << " due to clause " << *cl << endl; #endif assert(blockedOn != lit_Undef); if (solver->varData[blockedOn.var()].level == 0) { cout << "!! Flip 0-level var:" << solver->map_inter_to_outer(blockedOn.var()) + 1 << endl; } assert( (solver->varData[blockedOn.var()].level != 0 //|| solver->varData[blockedOn.var()].removed == Removed::decomposed ) && "We cannot flip 0-level vars" ); enqueue(blockedOn); replaceSet(blockedOn); return true; }
void CalcDefPolars::add_vote(const Lit lit, const double value) { if (lit.sign()) { votes[lit.var()] -= value; } else { votes[lit.var()] += value; } }
void SolutionExtender::enqueue(const Lit lit) { assigns[lit.var()] = boolToLBool(!lit.sign()); trail.push_back(lit); #ifdef VERBOSE_DEBUG_RECONSTRUCT cout << "c Enqueueing lit " << lit << " during solution reconstruction" << endl; #endif solver->varData[lit.var()].level = std::numeric_limits< uint32_t >::max(); }
const bool DataSync::shareUnitData() { uint32_t thisGotUnitData = 0; uint32_t thisSentUnitData = 0; SharedData& shared = *sharedData; shared.value.growTo(solver.nVars(), l_Undef); for (uint32_t var = 0; var < solver.nVars(); var++) { Lit thisLit = Lit(var, false); thisLit = solver.varReplacer->getReplaceTable()[thisLit.var()] ^ thisLit.sign(); const lbool thisVal = solver.value(thisLit); const lbool otherVal = shared.value[var]; if (thisVal == l_Undef && otherVal == l_Undef) continue; if (thisVal != l_Undef && otherVal != l_Undef) { if (thisVal != otherVal) { solver.ok = false; return false; } else { continue; } } if (otherVal != l_Undef) { assert(thisVal == l_Undef); Lit litToEnqueue = thisLit ^ (otherVal == l_False); if (solver.subsumer->getVarElimed()[litToEnqueue.var()] || solver.xorSubsumer->getVarElimed()[litToEnqueue.var()] ) continue; solver.uncheckedEnqueue(litToEnqueue); solver.ok = solver.propagate<false>().isNULL(); if (!solver.ok) return false; thisGotUnitData++; continue; } if (thisVal != l_Undef) { assert(otherVal == l_Undef); shared.value[var] = thisVal; thisSentUnitData++; continue; } } if (solver.conf.verbosity >= 3 && (thisGotUnitData > 0 || thisSentUnitData > 0)) { std::cout << "c got units " << std::setw(8) << thisGotUnitData << " sent units " << std::setw(8) << thisSentUnitData << std::endl; } recvUnitData += thisGotUnitData; sentUnitData += thisSentUnitData; return true; }
//Analyze why did we fail at decision level 1 Lit HyperEngine::analyzeFail(const PropBy propBy) { //Clear out the datastructs we will be usin currAncestors.clear(); //First, we set the ancestors, based on the clause //Each literal in the clause is an ancestor. So just 'push' them inside the //'currAncestors' variable switch(propBy.getType()) { case tertiary_t : { const Lit lit = ~propBy.lit3(); if (varData[lit.var()].level != 0) currAncestors.push_back(lit); //intentionally falling through here //i.e. there is no 'break' here for a reason } case binary_t: { const Lit lit = ~propBy.lit2(); if (varData[lit.var()].level != 0) currAncestors.push_back(lit); if (varData[failBinLit.var()].level != 0) currAncestors.push_back(~failBinLit); break; } case clause_t: { const uint32_t offset = propBy.get_offset(); const Clause& cl = *cl_alloc.ptr(offset); for(size_t i = 0; i < cl.size(); i++) { if (varData[cl[i].var()].level != 0) currAncestors.push_back(~cl[i]); } break; } case xor_t: { //in the future, we'll have XOR clauses. Not yet. assert(false); exit(-1); break; } case null_clause_t: assert(false); break; } Lit foundLit = deepest_common_ancestor(); return foundLit; }
bool DataSync::syncBinFromOthers( const Lit lit , const vector<Lit>& bins , uint32_t& finished , watch_subarray ws ) { assert(solver->varReplacer->get_lit_replaced_with(lit) == lit); assert(solver->varData[lit.var()].removed == Removed::none); assert(toClear.empty()); for (const Watched& w: ws) { if (w.isBin()) { toClear.push_back(w.lit2()); assert(seen.size() > w.lit2().toInt()); seen[w.lit2().toInt()] = true; } } vector<Lit> lits(2); for (uint32_t i = finished; i < bins.size(); i++) { Lit otherLit = bins[i]; otherLit = solver->map_to_with_bva(otherLit); otherLit = solver->varReplacer->get_lit_replaced_with_outer(otherLit); otherLit = solver->map_outer_to_inter(otherLit); if (solver->varData[otherLit.var()].removed != Removed::none || solver->value(otherLit) != l_Undef ) { continue; } assert(seen.size() > otherLit.toInt()); if (!seen[otherLit.toInt()]) { stats.recvBinData++; lits[0] = lit; lits[1] = otherLit; //Don't add DRUP: it would add to the thread data, too solver->add_clause_int(lits, true, ClauseStats(), true, NULL, false); if (!solver->ok) { goto end; } } } finished = bins.size(); end: for (const Lit l: toClear) { seen[l.toInt()] = false; } toClear.clear(); return solver->ok; }
/** @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 VarReplacer::print_equivalent_literals(std::ostream *os) const { vector<Lit> tmpCl; for (Var var = 0; var < table.size(); var++) { const Lit lit = table[var]; if (lit.var() == var) continue; tmpCl.clear(); tmpCl.push_back(~lit); tmpCl.push_back(Lit(var, false)); std::sort(tmpCl.begin(), tmpCl.end()); *os << tmpCl[0] << " " << tmpCl[1] << " 0\n"; tmpCl[0] ^= true; tmpCl[1] ^= true; *os << tmpCl[0] << " " << tmpCl[1] << " 0\n"; } }
/** @brief Changes internal graph to set everything that pointed to var to point to lit */ void VarReplacer::setAllThatPointsHereTo(const Var var, const Lit lit) { map<Var, vector<Var> >::iterator it = reverseTable.find(var); if (it != reverseTable.end()) { for(const Var var2: it->second) { assert(table[var2].var() == var); if (lit.var() != var2) { table[var2] = lit ^ table[var2].sign(); reverseTable[lit.var()].push_back(var2); } } reverseTable.erase(it); } table[var] = lit; reverseTable[lit.var()].push_back(var); }
void Prober::add_rest_of_lits_to_cache(Lit lit) { tmp_lits.clear(); for (int64_t c = solver->trail_size()-1 ; c != (int64_t)solver->trail_lim[0] - 1 ; c-- ) { extraTime += 2; const Lit thisLit = solver->trail[c]; tmp_lits.push_back(thisLit); } bool taut = solver->implCache[~lit].merge( tmp_lits , lit_Undef , true //Red step -- we don't know, so we assume , lit.var() , solver->seen ); //If tautology according to cache we can //enqueue ~lit at toplevel since both //~lit V OTHER, and ~lit V ~OTHER are technically in if (taut) { toEnqueue.push_back(~lit); (*solver->drat) << ~lit << fin; } }
void Prober::sortAndResetCandidates() { candidates.clear(); candidates.resize(solver->nVars()); for(size_t i = 0; i < solver->nVars(); i++) { Lit lit = Lit(i, false); candidates[i].var = lit.var(); //Calculate approx number of literals propagated for positive polarity //TODO stamping -- replace '0' size_t posPolar = std::max<size_t>( solver->watches[(~lit).toInt()].size() , 0//solver->implCache[(~lit).toInt()].lits.size() ); //Calculate approx number of literals propagated for negative polarity //TODO stamping -- replace '0' size_t negPolar = std::max<size_t>( solver->watches[lit.toInt()].size() , 0 //solver->implCache[lit.toInt()].lits.size() ); //Minimim of the two polarities candidates[i].minOfPolarities = std::min(posPolar, negPolar); //cout << "candidate size: " << candidates[i].minOfPolarities << endl; } //Sort candidates from MAX to MIN of 'minOfPolarities' std::sort(candidates.begin(), candidates.end()); }
void SubsumeImplicit::try_subsume_bin( const Lit lit , Watched*& i , Watched*& j ) { //Subsume bin with bin if (i->lit2() == lastLit2 && lastLit3 == lit_Undef ) { //The sorting algorithm prefers irred to red, so it is //impossible to have irred before red assert(!(i->red() == false && lastRed == true)); runStats.remBins++; assert(i->lit2().var() != lit.var()); timeAvailable -= 30; timeAvailable -= solver->watches[i->lit2().toInt()].size(); removeWBin(solver->watches, i->lit2(), lit, i->red()); if (i->red()) { solver->binTri.redBins--; } else { solver->binTri.irredBins--; } (*solver->drup) << del << lit << i->lit2() << fin; return; } else { lastBin = j; lastLit2 = i->lit2(); lastLit3 = lit_Undef; lastRed = i->red(); *j++ = *i; } }
bool UselessBinRemover::fillBinImpliesMinusLast(const Lit& origLit, const Lit& lit, vec<Lit>& wrong) { solver.newDecisionLevel(); solver.uncheckedEnqueueLight(lit); //if it's a cycle, it doesn't work, so don't propagate origLit failed = !onlyNonLearntBins.propagateBinExcept(origLit); if (failed) return false; assert(solver.decisionLevel() > 0); int c; extraTime += (solver.trail.size() - solver.trail_lim[0]) / EXTRATIME_DIVIDER; for (c = solver.trail.size()-1; c > (int)solver.trail_lim[0]; c--) { Lit x = solver.trail[c]; if (toDeleteSet[x.toInt()]) { wrong.push(x); toDeleteSet[x.toInt()] = false; }; solver.assigns[x.var()] = l_Undef; } solver.assigns[solver.trail[c].var()] = l_Undef; solver.qhead = solver.trail_lim[0]; solver.trail.shrink_(solver.trail.size() - solver.trail_lim[0]); solver.trail_lim.clear(); //solver.cancelUntil(0); return true; }
void ImplCache::printStatsSort(const Solver* solver) const { size_t numHasElems = 0; size_t totalElems = 0; size_t activeLits = 0; for(size_t i = 0; i < implCache.size(); i++) { Lit lit = Lit::toLit(i); if (solver->varData[lit.var()].is_decision) { activeLits++; totalElems += implCache[i].lits.size(); numHasElems += !implCache[i].lits.empty(); } } printStatsLine( "c lits having cache" , stats_line_percent(numHasElems, activeLits) , "% of decision lits" ); printStatsLine( "c num elems in cache/lit" , stats_line_percent(totalElems, numHasElems) , "extralits" ); }
//Add binary clause to deepest common ancestor void HyperEngine::add_hyper_bin(const Lit p) { propStats.otfHyperTime += 2; Lit deepestAncestor = lit_Undef; bool hyperBinNotAdded = true; if (currAncestors.size() > 1) { deepestAncestor = deepest_common_ancestor(); #ifdef VERBOSE_DEBUG_FULLPROP cout << "Adding hyper-bin clause: " << p << " , " << ~deepestAncestor << endl; #endif needToAddBinClause.insert(BinaryClause(p, ~deepestAncestor, true)); *drat << p << (~deepestAncestor) << fin; hyperBinNotAdded = false; } else { //0-level propagation is NEVER made by propFull assert(currAncestors.size() > 0); #ifdef VERBOSE_DEBUG_FULLPROP cout << "Not adding hyper-bin because only ONE lit is not set at" << "level 0 in long clause, but that long clause needs to be cleaned" << endl; #endif deepestAncestor = currAncestors[0]; hyperBinNotAdded = true; } enqueue_with_acestor_info(p, deepestAncestor, true); varData[p.var()].reason.setHyperbin(true); varData[p.var()].reason.setHyperbinNotAdded(hyperBinNotAdded); }
void XorSubsumer::fillCannotEliminate() { std::fill(cannot_eliminate.getData(), cannot_eliminate.getDataEnd(), false); for (uint32_t i = 0; i < solver.clauses.size(); i++) addToCannotEliminate(solver.clauses[i]); uint32_t wsLit = 0; for (const vec<Watched> *it = solver.watches.getData(), *end = solver.watches.getDataEnd(); it != end; it++, wsLit++) { Lit lit = ~Lit::toLit(wsLit); const vec<Watched>& ws = *it; for (vec<Watched>::const_iterator it2 = ws.getData(), end2 = ws.getDataEnd(); it2 != end2; it2++) { if (it2->isBinary() && !it2->getLearnt()) { cannot_eliminate[lit.var()] = true; cannot_eliminate[it2->getOtherLit().var()] = true; } } } for (Var var = 0; var < solver.nVars(); var++) { cannot_eliminate[var] |= solver.varReplacer->cannot_eliminate[var]; } #ifdef VERBOSE_DEBUG uint32_t tmpNum = 0; for (uint32_t i = 0; i < cannot_eliminate.size(); i++) if (cannot_eliminate[i]) tmpNum++; std::cout << "Cannot eliminate num:" << tmpNum << std::endl; #endif }
void HyperEngine::add_hyper_bin(const Lit p, const Clause& cl) { assert(value(p.var()) == l_Undef); #ifdef VERBOSE_DEBUG_FULLPROP cout << "Enqueing " << p << " with ancestor clause: " << cl << endl; #endif currAncestors.clear(); size_t i = 0; for (Clause::const_iterator it = cl.begin(), end = cl.end() ; it != end ; ++it, i++ ) { if (*it != p) { assert(value(*it) == l_False); if (varData[it->var()].level != 0) currAncestors.push_back(~*it); } } add_hyper_bin(p); }
/** @brief Changes internal graph to set everything that pointed to var to point to lit */ void VarReplacer::setAllThatPointsHereTo(const Var var, const Lit lit) { map<Var, vector<Var> >::iterator it = reverseTable.find(var); if (it != reverseTable.end()) { for(vector<Var>::const_iterator it2 = it->second.begin(), end = it->second.end(); it2 != end; it2++) { assert(table[*it2].var() == var); if (lit.var() != *it2) { table[*it2] = lit ^ table[*it2].sign(); reverseTable[lit.var()].push_back(*it2); } } reverseTable.erase(it); } table[var] = lit; reverseTable[lit.var()].push_back(var); }
void CalcDefPolars::tallyVotesBinTri(const vector<vec<Watched> >& watches) { size_t wsLit = 0; for (vector<vec<Watched> >::const_iterator it = watches.begin(), end = watches.end() ; it != end ; it++, wsLit++ ) { Lit lit = Lit::toLit(wsLit); const vec<Watched>& ws = *it; for (vec<Watched>::const_iterator it2 = ws.begin(), end2 = ws.end(); it2 != end2; it2++) { //Only count bins once if (it2->isBinary() && lit < it2->lit2() && !it2->learnt() ) { if (lit.sign()) votes[lit.var()] += 0.5; else votes[lit.var()] -= 0.5; Lit lit2 = it2->lit2(); if (lit2.sign()) votes[lit2.var()] += 0.5; else votes[lit2.var()] -= 0.5; } //Only count TRI-s once if (it2->isTri() && lit < it2->lit2() && it2->lit2() < it2->lit3() && it2->learnt() ) { if (lit.sign()) votes[lit.var()] += 0.3; else votes[lit.var()] -= 0.3; Lit lit2 = it2->lit2(); if (lit2.sign()) votes[lit2.var()] += 0.3; else votes[lit2.var()] -= 0.3; Lit lit3 = it2->lit3(); if (lit3.sign()) votes[lit3.var()] += 0.3; else votes[lit3.var()] -= 0.3; } } } }
Lit Prober::update_lit_for_dominator( Lit lit ) { if (solver->conf.doCache) { if (solver->litReachable[lit.toInt()].lit != lit_Undef) { const Lit betterlit = solver->litReachable[lit.toInt()].lit; if (solver->value(betterlit.var()) == l_Undef && solver->varData[betterlit.var()].removed == Removed::none ) { //Update lit lit = betterlit; } } } return lit; }
bool BVA::try_bva_on_lit(const Lit lit) { assert(solver->value(lit) == l_Undef); assert(solver->varData[lit.var()].removed == Removed::none); m_cls.clear(); m_lits.clear(); m_lits.push_back(lit); *simplifier->limit_to_decrease -= solver->watches[lit].size(); for(const Watched w: solver->watches[lit]) { if (!solver->redundant(w)) { m_cls.push_back(OccurClause(lit, w)); if (solver->conf.verbosity >= 6 || bva_verbosity) { cout << "1st adding to m_cls " << solver->watched_to_string(lit, w) << endl; } } } remove_duplicates_from_m_cls(); while(true) { potential.clear(); fill_potential(lit); if (*simplifier->limit_to_decrease < 0) { return solver->okay(); } size_t num_occur; const lit_pair l_max = most_occuring_lit_in_potential(num_occur); if (simplifies_system(num_occur)) { m_lits.push_back(l_max); m_cls.clear(); *simplifier->limit_to_decrease -= potential.size()*3; for(const PotentialClause pot: potential) { if (pot.lits == l_max) { m_cls.push_back(pot.occur_cl); if (solver->conf.verbosity >= 6 || bva_verbosity) { cout << "-- max is : (" << l_max.lit1 << ", " << l_max.lit2 << "), adding to m_cls " << solver->watched_to_string(pot.occur_cl.lit, pot.occur_cl.ws) << endl; } assert(pot.occur_cl.lit == lit); } } } else { break; } } const int simp_size = simplification_size(m_lits.size(), m_cls.size()); if (simp_size <= 0) { return solver->okay(); } const bool ok = bva_simplify_system(); return ok; }
void CompHandler::move_binary_clause( SATSolver* newSolver , const uint32_t comp , Watched *i , const Lit lit ) { const Lit lit2 = i->lit2(); //Unless redundant, cannot be in 2 comps at once assert((compFinder->getVarComp(lit.var()) == comp && compFinder->getVarComp(lit2.var()) == comp ) || i->red() ); //If it's redundant and the lits are in different comps, remove it. if (compFinder->getVarComp(lit.var()) != comp || compFinder->getVarComp(lit2.var()) != comp ) { //Can only be redundant, otherwise it would be in the same //component assert(i->red()); //The way we go through this, it's definitely going to be //lit2 that's in the other component assert(compFinder->getVarComp(lit2.var()) != comp); remove_bin_except_for_lit1(lit, lit2); return; } //don't add the same clause twice if (lit < lit2) { //Add clause tmp_lits = {upd_bigsolver_to_smallsolver(lit), upd_bigsolver_to_smallsolver(lit2)}; assert(compFinder->getVarComp(lit.var()) == comp); assert(compFinder->getVarComp(lit2.var()) == comp); //Add new clause if (i->red()) { //newSolver->addRedClause(tmp_lits); numRemovedHalfRed++; } else { //Save backup saveClause(vector<Lit>{lit, lit2}); newSolver->add_clause(tmp_lits); numRemovedHalfIrred++; } } else { //Just remove, already added above if (i->red()) { numRemovedHalfRed++; } else { numRemovedHalfIrred++; } } }
void Prober::update_cache(Lit thisLit, Lit lit, size_t numElemsSet) { //Update cache, if the trail was within limits (cacheUpdateCutoff) const Lit ancestor = solver->varData[thisLit.var()].reason.getAncestor(); if (solver->conf.doCache && thisLit != lit && numElemsSet <= solver->conf.cacheUpdateCutoff //&& cacheUpdated[(~ancestor).toInt()] == 0 ) { //Update stats/markings //cacheUpdated[(~ancestor).toInt()]++; extraTime += 1; extraTimeCache += solver->implCache[~ancestor].lits.size()/30; extraTimeCache += solver->implCache[~thisLit].lits.size()/30; const bool redStep = solver->varData[thisLit.var()].reason.isRedStep(); //Update the cache now assert(ancestor != lit_Undef); bool taut = solver->implCache[~ancestor].merge( solver->implCache[~thisLit].lits , thisLit , redStep , ancestor.var() , solver->seen ); //If tautology according to cache we can //enqueue ~ancestor at toplevel since both //~ancestor V OTHER, and ~ancestor V ~OTHER are technically in if (taut && solver->varData[ancestor.var()].removed == Removed::none ) { toEnqueue.push_back(~ancestor); if (solver->conf.verbosity >= 10) cout << "c Tautology from cache indicated we can enqueue " << (~ancestor) << endl; } #ifdef VERBOSE_DEBUG_FULLPROP cout << "The impl cache of " << (~ancestor) << " is now: "; cout << solver->implCache[(~ancestor).toInt()] << endl; #endif } }