bool BothCache::tryBoth() { vec<bool> seen(solver.nVars(), 0); vec<bool> val(solver.nVars(), 0); vec<Lit> tmp; uint32_t bProp = 0; uint32_t bXProp = 0; double myTime = cpuTime(); uint32_t backupTrailSize = solver.trail.size(); for (Var var = 0; var < solver.nVars(); var++) { if (solver.value(var) != l_Undef || (solver.subsumer && solver.subsumer->getVarElimed()[var]) || solver.xorSubsumer->getVarElimed()[var] || solver.varReplacer->getReplaceTable()[var].var() != var) continue; Lit lit = Lit(var, false); vector<Lit> const* cache1; vector<Lit> const* cache2; bool startWithTrue; if (solver.transOTFCache[lit.toInt()].lits.size() < solver.transOTFCache[(~lit).toInt()].lits.size()) { cache1 = &solver.transOTFCache[lit.toInt()].lits; cache2 = &solver.transOTFCache[(~lit).toInt()].lits; startWithTrue = false; } else { cache1 = &solver.transOTFCache[(~lit).toInt()].lits; cache2 = &solver.transOTFCache[lit.toInt()].lits; startWithTrue = true; } if (cache1->size() == 0) continue; for (vector<Lit>::const_iterator it = cache1->begin(), end = cache1->end(); it != end; it++) { seen[it->var()] = true; val[it->var()] = it->sign(); } for (vector<Lit>::const_iterator it = cache2->begin(), end = cache2->end(); it != end; it++) { if (seen[it->var()]) { Var var2 = it->var(); if ((solver.subsumer && solver.subsumer->getVarElimed()[var2]) || solver.xorSubsumer->getVarElimed()[var2] || solver.varReplacer->getReplaceTable()[var2].var() != var2) continue; if (val[it->var()] == it->sign()) { tmp.clear(); tmp.push(*it); solver.addClauseInt(tmp, true); if (!solver.ok) goto end; bProp++; } else { tmp.clear(); tmp.push(Lit(var, false)); tmp.push(Lit(it->var(), false)); bool sign = true ^ startWithTrue ^ it->sign(); solver.addXorClauseInt(tmp, sign); if (!solver.ok) goto end; bXProp++; } } } for (vector<Lit>::const_iterator it = cache1->begin(), end = cache1->end(); it != end; it++) { seen[it->var()] = false; } } end: if (solver.conf.verbosity >= 1) { std::cout << "c Cache " << " BProp: " << bProp << " Set: " << (solver.trail.size() - backupTrailSize) << " BXProp: " << bXProp << " T: " << (cpuTime() - myTime) << std::endl; } return solver.ok; }
Lit HyperEngine::propagate_bfs(const uint64_t timeout) { timedOutPropagateFull = false; propStats.otfHyperPropCalled++; #ifdef VERBOSE_DEBUG_FULLPROP cout << "Prop full BFS started" << endl; #endif PropBy confl; //Assert startup: only 1 enqueued, uselessBin is empty assert(uselessBin.empty()); //assert(decisionLevel() == 1); //The toplevel decision has to be set specifically //If we came here as part of a backtrack to decision level 1, then //this is already set, and there is no need to set it if (trail.size() - trail_lim.back() == 1) { //Set up root node Lit root = trail[qhead]; varData[root.var()].reason = PropBy(~lit_Undef, false, false, false); } uint32_t nlBinQHead = qhead; uint32_t lBinQHead = qhead; needToAddBinClause.clear(); PropResult ret = PROP_NOTHING; start: //Early-abort if too much time was used (from prober) if (propStats.otfHyperTime + propStats.bogoProps > timeout) { timedOutPropagateFull = true; return lit_Undef; } //Propagate binary irred while (nlBinQHead < trail.size()) { const Lit p = trail[nlBinQHead++]; watch_subarray_const ws = watches[~p]; propStats.bogoProps += 1; for(const Watched *k = ws.begin(), *end = ws.end() ; k != end ; k++ ) { //If something other than irred binary, skip if (!k->isBin() || k->red()) continue; ret = prop_bin_with_ancestor_info(p, k, confl); if (ret == PROP_FAIL) return analyzeFail(confl); } propStats.bogoProps += ws.size()*4; } //Propagate binary redundant ret = PROP_NOTHING; while (lBinQHead < trail.size()) { const Lit p = trail[lBinQHead]; watch_subarray_const ws = watches[~p]; propStats.bogoProps += 1; size_t done = 0; for(const Watched *k = ws.begin(), *end = ws.end(); k != end; k++, done++) { //If something other than redundant binary, skip if (!k->isBin() || !k->red()) continue; ret = prop_bin_with_ancestor_info(p, k, confl); if (ret == PROP_FAIL) { return analyzeFail(confl); } else if (ret == PROP_SOMETHING) { propStats.bogoProps += done*4; goto start; } else { assert(ret == PROP_NOTHING); } } lBinQHead++; propStats.bogoProps += done*4; } ret = PROP_NOTHING; while (qhead < trail.size()) { const Lit p = trail[qhead]; watch_subarray ws = watches[~p]; propStats.bogoProps += 1; Watched* i = ws.begin(); Watched* j = ws.begin(); Watched* end = ws.end(); for(; i != end; i++) { if (i->isBin()) { *j++ = *i; continue; } if (i->isTri()) { *j++ = *i; ret = prop_tri_clause_with_acestor_info(i, p, confl); if (ret == PROP_SOMETHING || ret == PROP_FAIL) { i++; break; } else { assert(ret == PROP_NOTHING); continue; } } if (i->isClause()) { ret = prop_normal_cl_with_ancestor_info(i, j, p, confl); if (ret == PROP_SOMETHING || ret == PROP_FAIL) { i++; break; } else { assert(ret == PROP_NOTHING); continue; } } } propStats.bogoProps += ws.size()*4; while(i != end) *j++ = *i++; ws.shrink_(end-j); if (ret == PROP_FAIL) { return analyzeFail(confl); } else if (ret == PROP_SOMETHING) { propStats.bogoProps += ws.size()*4; goto start; } qhead++; propStats.bogoProps += ws.size()*4; } return lit_Undef; }
/** We can try both ways: either binary clause can be removed. Try to remove one, then the other Return which one is to be removed */ Lit HyperEngine::remove_which_bin_due_to_trans_red( Lit conflict , Lit thisAncestor , bool thisStepRed ) { propStats.otfHyperTime += 1; const PropBy& data = varData[conflict.var()].reason; bool onlyIrred = !data.isRedStep(); Lit lookingForAncestor = data.getAncestor(); if (thisAncestor == lit_Undef || lookingForAncestor == lit_Undef) return lit_Undef; propStats.otfHyperTime += 1; bool second_is_deeper = false; bool ambivalent = true; if (use_depth_trick) { ambivalent = depth[thisAncestor.var()] == depth[lookingForAncestor.var()]; if (depth[thisAncestor.var()] < depth[lookingForAncestor.var()]) { second_is_deeper = true; } } #ifdef DEBUG_DEPTH cout << "1st: " << std::setw(6) << thisAncestor << " depth: " << std::setw(4) << depth[thisAncestor.var()] << " 2nd: " << std::setw(6) << lookingForAncestor << " depth: " << std::setw(4) << depth[lookingForAncestor.var()] ; #endif if ((ambivalent || !second_is_deeper) && is_ancestor_of( conflict , thisAncestor , thisStepRed , onlyIrred , lookingForAncestor ) ) { #ifdef DEBUG_DEPTH cout << " -- OK" << endl; #endif //assert(ambivalent || !second_is_deeper); return thisAncestor; } onlyIrred = !thisStepRed; thisStepRed = data.isRedStep(); std::swap(lookingForAncestor, thisAncestor); if ((ambivalent || second_is_deeper) && is_ancestor_of( conflict , thisAncestor , thisStepRed , onlyIrred , lookingForAncestor ) ) { #ifdef DEBUG_DEPTH cout << " -- OK" << endl; #endif //assert(ambivalent || second_is_deeper); return thisAncestor; } #ifdef DEBUG_DEPTH cout << " -- NOTK" << endl; #endif return lit_Undef; }
const bool MatrixFinder::findMatrixes() { table.clear(); table.resize(solver.nVars(), var_Undef); reverseTable.clear(); matrix_no = 0; double myTime = cpuTime(); if (solver.xorclauses.size() < MIN_GAUSS_XOR_CLAUSES || solver.gaussconfig.decision_until <= 0 || solver.xorclauses.size() > MAX_GAUSS_XOR_CLAUSES ) return true; solver.clauseCleaner->cleanClauses(solver.xorclauses, ClauseCleaner::xorclauses); if (!solver.ok) return false; if (solver.gaussconfig.noMatrixFind) { if (solver.verbosity >=1) cout << "c Matrix finding disabled through switch. Putting all xors into matrix." << endl; vector<XorClause*> xorclauses; xorclauses.reserve(solver.xorclauses.size()); for (uint32_t i = 0; i < solver.xorclauses.size(); i++) xorclauses.push_back(solver.xorclauses[i]); solver.gauss_matrixes.push_back(new Gaussian(solver, solver.gaussconfig, 0, xorclauses)); return true; } for (XorClause** c = solver.xorclauses.getData(), **end = c + solver.xorclauses.size(); c != end; c++) { set<uint32_t> tomerge; vector<Var> newSet; for (Lit *l = &(**c)[0], *end2 = l + (**c).size(); l != end2; l++) { if (table[l->var()] != var_Undef) tomerge.insert(table[l->var()]); else newSet.push_back(l->var()); } if (tomerge.size() == 1) { const uint32_t into = *tomerge.begin(); map<uint32_t, vector<Var> >::iterator intoReverse = reverseTable.find(into); for (uint32_t i = 0; i < newSet.size(); i++) { intoReverse->second.push_back(newSet[i]); table[newSet[i]] = into; } continue; } for (set<uint32_t>::iterator it = tomerge.begin(); it != tomerge.end(); it++) { newSet.insert(newSet.end(), reverseTable[*it].begin(), reverseTable[*it].end()); reverseTable.erase(*it); } for (uint32_t i = 0; i < newSet.size(); i++) table[newSet[i]] = matrix_no; reverseTable[matrix_no] = newSet; matrix_no++; } #ifdef VERBOSE_DEBUG for (map<uint32_t, vector<Var> >::iterator it = reverseTable.begin(), end = reverseTable.end(); it != end; it++) { cout << "-- set begin --" << endl; for (vector<Var>::iterator it2 = it->second.begin(), end2 = it->second.end(); it2 != end2; it2++) { cout << *it2 << ", "; } cout << "-------" << endl; } #endif uint32_t numMatrixes = setMatrixes(); if (solver.verbosity >=1) std::cout << "c Finding matrixes : " << cpuTime() - myTime << " s (found " << numMatrixes << ")" << endl; for (vector<Gaussian*>::iterator gauss = solver.gauss_matrixes.begin(), end = solver.gauss_matrixes.end(); gauss != end; gauss++) { if (!(*gauss)->full_init()) return false; } return true; }
void BVA::fill_potential(const Lit lit) { for(const OccurClause& c: m_cls) { if (*simplifier->limit_to_decrease < 0) break; const Lit l_min = least_occurring_except(c); if (l_min == lit_Undef) continue; solver->watches.prefetch(l_min.toInt()); m_lits_this_cl = m_lits; *simplifier->limit_to_decrease -= m_lits_this_cl.size(); for(const lit_pair lits: m_lits_this_cl) { seen2[lits.hash(seen2.size())] = 1; } if (solver->conf.verbosity >= 6 || bva_verbosity) { cout << "c [occ-bva] Examining clause for addition to 'potential':" << solver->watched_to_string(c.lit, c.ws) << " -- Least occurring in this CL: " << l_min << endl; } *simplifier->limit_to_decrease -= (long)solver->watches[l_min].size()*3; for(const Watched& d_ws: solver->watches[l_min]) { if (*simplifier->limit_to_decrease < 0) goto end; OccurClause d(l_min, d_ws); const size_t sz_c = solver->cl_size(c.ws); const size_t sz_d = solver->cl_size(d.ws); if (c.ws != d.ws && (sz_c == sz_d || (sz_c+1 == sz_d && solver->conf.bva_also_twolit_diff && (long)solver->sumConflicts() >= solver->conf.bva_extra_lit_and_red_start ) ) && !solver->redundant(d.ws) && lit_diff_watches(c, d) == lit ) { const lit_pair diff = lit_diff_watches(d, c); if (seen2[diff.hash(seen2.size())] == 0) { *simplifier->limit_to_decrease -= 3; potential.push_back(PotentialClause(diff, c)); m_lits_this_cl.push_back(diff); seen2[diff.hash(seen2.size())] = 1; if (solver->conf.verbosity >= 6 || bva_verbosity) { cout << "c [occ-bva] Added to P: " << potential.back().to_string(solver) << endl; } } } } end: for(const lit_pair lits: m_lits_this_cl) { seen2[lits.hash(seen2.size())] = 0; } } }
/** @brief If needed, compacts stacks, removing unused clauses Firstly, the algorithm determines if the number of useless slots is large or small compared to the problem size. If it is small, it does nothing. If it is large, then it allocates new stacks, copies the non-freed clauses to these new stacks, updates all pointers and offsets, and frees the original stacks. */ void ClauseAllocator::consolidate( Solver* solver , const bool force , bool lower_verb ) { //If re-allocation is not really neccessary, don't do it //Neccesities: //1) There is too much memory allocated. Re-allocation will save space // Avoiding segfault (max is 16 outerOffsets, more than 10 is near) //2) There is too much empty, unused space (>30%) if (!force && (float_div(currentlyUsedSize, size) > 0.8 || currentlyUsedSize < (100ULL*1000ULL)) ) { if (solver->conf.verbosity >= 3 || (lower_verb && solver->conf.verbosity) ) { cout << "c Not consolidating memory." << endl; } return; } const double myTime = cpuTime(); //Pointers that will be moved along BASE_DATA_TYPE * const newDataStart = (BASE_DATA_TYPE*)malloc(currentlyUsedSize*sizeof(BASE_DATA_TYPE)); BASE_DATA_TYPE * new_ptr = newDataStart; assert(sizeof(BASE_DATA_TYPE) % sizeof(Lit) == 0); vector<bool> visited(solver->watches.size(), 0); Heap<Solver::VarOrderLt> &order_heap = solver->VSIDS ? solver->order_heap_vsids : solver->order_heap_maple; if (solver->conf.static_mem_consolidate_order) { for(auto& ws: solver->watches) { move_one_watchlist(ws, newDataStart, new_ptr); } } else { for(uint32_t i = 0; i < order_heap.size(); i++) { for(uint32_t i2 = 0; i2 < 2; i2++) { Lit lit = Lit(order_heap[i], i2); assert(lit.toInt() < solver->watches.size()); move_one_watchlist(solver->watches[lit], newDataStart, new_ptr); visited[lit.toInt()] = 1; } } for(uint32_t i = 0; i < solver->watches.size(); i++) { Lit lit = Lit::toLit(i); watch_subarray ws = solver->watches[lit]; if (!visited[lit.toInt()]) { move_one_watchlist(ws, newDataStart, new_ptr); visited[lit.toInt()] = 1; } } } #ifdef USE_GAUSS for (EGaussian* gauss : solver->gmatrixes) { if (gauss == NULL) { continue; } for(auto& gcl: gauss->clauses_toclear) { Clause* old = ptr(gcl.first); if (old->reloced) { ClOffset new_offset = (*old)[0].toInt(); #ifdef LARGE_OFFSETS new_offset += ((uint64_t)(*old)[1].toInt())<<32; #endif gcl.first = new_offset; } else { ClOffset new_offset = move_cl(newDataStart, new_ptr, old); gcl.first = new_offset; } assert(!old->freed()); } } #endif //USE_GAUSS update_offsets(solver->longIrredCls); for(auto& lredcls: solver->longRedCls) { update_offsets(lredcls); } //Fix up propBy for (size_t i = 0; i < solver->nVars(); i++) { VarData& vdata = solver->varData[i]; if (vdata.reason.isClause()) { if (vdata.removed == Removed::none && solver->decisionLevel() >= vdata.level && vdata.level != 0 && solver->value(i) != l_Undef ) { Clause* old = ptr(vdata.reason.get_offset()); assert(!old->freed()); ClOffset new_offset = (*old)[0].toInt(); #ifdef LARGE_OFFSETS new_offset += ((uint64_t)(*old)[1].toInt())<<32; #endif vdata.reason = PropBy(new_offset); } else { vdata.reason = PropBy(); } } } //Update sizes const uint64_t old_size = size; size = new_ptr-newDataStart; capacity = currentlyUsedSize; currentlyUsedSize = size; free(dataStart); dataStart = newDataStart; const double time_used = cpuTime() - myTime; if (solver->conf.verbosity >= 2 || (lower_verb && solver->conf.verbosity) ) { size_t log_2_size = 0; if (size > 0) { //yes, it can be 0 (only binary clauses, for example) std::log2(size); } cout << "c [mem] consolidate "; cout << " old-sz: "; print_value_kilo_mega(old_size*sizeof(BASE_DATA_TYPE)); cout << " new-sz: "; print_value_kilo_mega(size*sizeof(BASE_DATA_TYPE)); cout << " new bits offs: " << std::fixed << std::setprecision(2) << log_2_size; cout << solver->conf.print_times(time_used) << endl; } if (solver->sqlStats) { solver->sqlStats->time_passed_min( solver , "consolidate" , time_used ); } }
inline Lit comp(const Lit x) { return x.comp(); }
void SubsumeImplicit::subsume_implicit(const bool check_stats) { assert(solver->okay()); const double myTime = cpuTime(); timeAvailable = 1900LL*1000LL*1000LL; const bool doStamp = solver->conf.doStamp; runStats.clear(); //Randomize starting point const size_t rnd_start = solver->mtrand.randInt(solver->watches.size()-1); size_t numDone = 0; for (;numDone < solver->watches.size() && timeAvailable > 0 ;numDone++ ) { const size_t at = (rnd_start + numDone) % solver->watches.size(); runStats.numWatchesLooked++; const Lit lit = Lit::toLit(at); watch_subarray ws = solver->watches[lit.toInt()]; //We can't do much when there is nothing, or only one if (ws.size() < 2) continue; if (ws.size() > 1) { timeAvailable -= ws.size()*std::ceil(std::log((double)ws.size())) + 20; std::sort(ws.begin(), ws.end(), WatchSorter()); } /*cout << "---> Before" << endl; printWatchlist(ws, lit);*/ Watched* i = ws.begin(); Watched* j = i; clear(); for (Watched* end = ws.end(); i != end; i++) { if (timeAvailable < 0) { *j++ = *i; continue; } switch(i->getType()) { case CMSat::watch_clause_t: *j++ = *i; break; case CMSat::watch_tertiary_t: try_subsume_tri(lit, i, j, doStamp); break; case CMSat::watch_binary_t: try_subsume_bin(lit, i, j); break; default: assert(false); break; } } ws.shrink(i-j); } if (check_stats) { solver->checkStats(); } runStats.numCalled++; runStats.time_used += cpuTime() - myTime; runStats.time_out += (timeAvailable <= 0); if (solver->conf.verbosity >= 1) { runStats.printShort(); } globalStats += runStats; }
void SubsumeImplicit::subsume_implicit(const bool check_stats) { assert(solver->okay()); const double myTime = cpuTime(); const uint64_t orig_timeAvailable = 1000LL*1000LL*solver->conf.subsume_implicit_time_limitM *solver->conf.global_timeout_multiplier; timeAvailable = orig_timeAvailable; const bool doStamp = solver->conf.doStamp; runStats.clear(); //For randomization, we must have at least 1 if (solver->watches.size() == 0) { return; } //Randomize starting point const size_t rnd_start = solver->mtrand.randInt(solver->watches.size()-1); size_t numDone = 0; for (;numDone < solver->watches.size() && timeAvailable > 0 && !solver->must_interrupt_asap() ;numDone++ ) { const size_t at = (rnd_start + numDone) % solver->watches.size(); runStats.numWatchesLooked++; const Lit lit = Lit::toLit(at); watch_subarray ws = solver->watches[lit.toInt()]; //We can't do much when there is nothing, or only one if (ws.size() < 2) continue; if (ws.size() > 1) { timeAvailable -= ws.size()*std::ceil(std::log((double)ws.size())) + 20; std::sort(ws.begin(), ws.end(), WatchSorterBinTriLong()); } /*cout << "---> Before" << endl; print_watch_list(ws, lit);*/ Watched* i = ws.begin(); Watched* j = i; clear(); for (Watched* end = ws.end(); i != end; i++) { if (timeAvailable < 0) { *j++ = *i; continue; } switch(i->getType()) { case CMSat::watch_clause_t: *j++ = *i; break; case CMSat::watch_tertiary_t: try_subsume_tri(lit, i, j, doStamp); break; case CMSat::watch_binary_t: try_subsume_bin(lit, i, j); break; default: assert(false); break; } } ws.shrink(i-j); } const double time_used = cpuTime() - myTime; const bool time_out = (timeAvailable <= 0); const double time_remain = float_div(timeAvailable, orig_timeAvailable); runStats.numCalled++; runStats.time_used += time_used; runStats.time_out += time_out; if (solver->conf.verbosity >= 1) { runStats.print_short(solver); } if (solver->sqlStats) { solver->sqlStats->time_passed( solver , "subsume implicit" , time_used , time_out , time_remain ); } if (check_stats) { #ifdef DEBUG_IMPLICIT_STATS solver->check_stats(); #endif } globalStats += runStats; }
bool Prober::probe() { assert(solver->decisionLevel() == 0); assert(solver->nVars() > 0); uint64_t numPropsTodo = 2000L*1000L*1000L; solver->testAllClauseAttach(); const double myTime = cpuTime(); const size_t origTrailSize = solver->trail.size(); solver->clauseCleaner->removeAndCleanAll(); //Stats extraTime = 0; solver->propStats.clear(); runStats.clear(); runStats.origNumFreeVars = solver->getNumFreeVars(); runStats.origNumBins = solver->binTri.redBins + solver->binTri.irredBins; numCalls++; //State visitedAlready.clear(); visitedAlready.resize(solver->nVars()*2, 0); propagatedBitSet.clear(); propagated.resize(solver->nVars(), 0); propValue.resize(solver->nVars(), 0); //If failed var searching is going good, do successively more and more of it if ((double)lastTimeZeroDepthAssings > (double)solver->getNumFreeVars() * 0.10) numPropsMultiplier = std::max(numPropsMultiplier*1.3, 1.6); else numPropsMultiplier = 1.0; numPropsTodo = (uint64_t) ((double)numPropsTodo * numPropsMultiplier * solver->conf.probeMultiplier); numPropsTodo = (double)numPropsTodo * std::pow(numCalls, 0.2); //Use candidates sortAndResetCandidates(); candidates.clear(); //Calculate the set of possible variables for branching on randomly vector<Var> possCh; for(size_t i = 0; i < solver->nVars(); i++) { if (solver->value(i) == l_Undef && solver->decisionVar[i] ) { possCh.push_back(i); } } //Random swap for (size_t i = 0 //Seems redundant, but '-1' on unsigned wraps around ; i < possCh.size() && i < possCh.size()-1 ; i++ ) { std::swap( possCh[i] , possCh[i+solver->mtrand.randInt(possCh.size()-1-i)] ); } //For fast black-listing, O(1)-time lookup vector<size_t> lookup(solver->nVars(), std::numeric_limits<size_t>::max()); for (size_t i = 0; i < possCh.size(); i++) { lookup[possCh[i]] = i; } const uint64_t origBogoProps = solver->propStats.bogoProps; for(size_t i = 0 ; i < possCh.size() && solver->propStats.bogoProps + extraTime < origBogoProps + numPropsTodo ; i++ ) { runStats.numLoopIters++; const Var var = possCh[i]; //Check if already blacklisted if (var == std::numeric_limits<Var>::max()) continue; Lit lit = Lit(var, false); extraTime += 200; //Check if var is set already if (solver->value(lit.var()) != l_Undef || !solver->decisionVar[lit.var()] || visitedAlready[lit.toInt()] ) { continue; } //If this lit is reachable from somewhere else, then reach it from there if (solver->timestamp[lit.toInt()].dominator[STAMP_IRRED] != lit_Undef) { const Lit betterlit = solver->timestamp[lit.toInt()].dominator[STAMP_IRRED]; if (solver->value(betterlit.var()) == l_Undef && solver->decisionVar[betterlit.var()] ) { //Update lit lit = betterlit; //Blacklist new lit possCh[lookup[lit.var()]] = std::numeric_limits<Var>::max(); //Must not have visited it already, otherwise the stamp dominator would be incorrect assert(!visitedAlready[lit.toInt()]); } } //Update stats runStats.numVarProbed++; //Try it if (!tryThis(lit, true)) goto end; //If we are still unset, do the opposite, too //this lets us carry out BothProp if (solver->value(lit) == l_Undef && !tryThis((~lit), false) ) { goto end; } } end: runStats.zeroDepthAssigns = solver->trail.size() - origTrailSize; if (solver->ok && runStats.zeroDepthAssigns) { double time = cpuTime(); bool advancedCleanup = false; //If more than 10% were set, detach&reattach. It's faster if ((double)runStats.origNumFreeVars - (double)solver->getNumFreeVars() > (double)runStats.origNumFreeVars/10.0 && solver->getNumLongClauses() > 200000 ) { //Advanced cleanup if (solver->conf.verbosity >= 5) cout << "c Advanced cleanup after probing" << endl; advancedCleanup = true; CompleteDetachReatacher reattacher(solver); reattacher.detachNonBinsNonTris(); const bool ret = reattacher.reattachLongs(); release_assert(ret == true); } else { //Standard cleanup if (solver->conf.verbosity >= 5) cout << "c Standard cleanup after probing" << endl; solver->clauseCleaner->removeAndCleanAll(); } //Tell me about the speed of cleanup if (solver->conf.verbosity >= 1 && (runStats.zeroDepthAssigns > 100 || advancedCleanup) ) { cout << "c Cleaning up after probing: " << std::setw(8) << std::fixed << std::setprecision(2) << cpuTime() - time << " s " << endl; } } //Update stats for(size_t i = 0; i < visitedAlready.size(); i++) { if (visitedAlready[i]) runStats.numVisited++; } lastTimeZeroDepthAssings = runStats.zeroDepthAssigns; runStats.cpu_time = cpuTime() - myTime; runStats.propStats = solver->propStats; globalStats += runStats; //Print & update stats if (solver->conf.verbosity >= 1) { if (solver->conf.verbosity >= 3) runStats.print(solver->nVars()); else runStats.printShort(); } solver->testAllClauseAttach(); return solver->ok; }
bool Prober::tryThis(const Lit lit, const bool first) { //Clean state if this is the 1st of two if (first) { propagated.removeThese(propagatedBitSet); propagatedBitSet.clear(); bothSame.clear(); } //Start-up cleaning runStats.numProbed++; //Test removal of non-learnt binary clauses #ifdef DEBUG_REMOVE_USELESS_BIN fillTestUselessBinRemoval(lit); #endif solver->newDecisionLevel(); solver->enqueue(lit); solver->varData[lit.var()].depth = 0; if (solver->conf.verbosity >= 6) cout << "c Probing lit " << lit << endl; Lit failed = lit_Undef; if (solver->mtrand.randInt(1) == 0) { const StampType stampType = solver->mtrand.randInt(1) ? STAMP_IRRED : STAMP_RED; failed = solver->propagateFullDFS(stampType); } else { failed = solver->propagateFullBFS(); } if (failed != lit_Undef) { if (solver->conf.verbosity >= 6) { cout << "c Failed on lit " << lit << endl; } solver->cancelZeroLight(); //Update conflict stats runStats.numFailed++; runStats.conflStats.update(solver->lastConflictCausedBy); runStats.conflStats.numConflicts++; runStats.addedBin += solver->hyperBinResAll(); std::pair<size_t, size_t> tmp = solver->removeUselessBins(); runStats.removedIrredBin += tmp.first; runStats.removedRedBin += tmp.second; vector<Lit> lits; lits.push_back(~failed); solver->addClauseInt(lits, true); return solver->ok; } //Fill bothprop, cache assert(solver->decisionLevel() > 0); size_t numElemsSet = solver->trail.size() - solver->trail_lim[0]; for (int64_t c = solver->trail.size()-1; c != (int64_t)solver->trail_lim[0] - 1; c--) { const Lit thisLit = solver->trail[c]; const Var var = thisLit.var(); //If this is the first, set what is propagated if (first) { //Visited this var, needs clear later on propagatedBitSet.push_back(var); //Set prop has been done propagated.setBit(var); //Set propValue if (solver->assigns[var].getBool()) propValue.setBit(var); else propValue.clearBit(var); } else if (propagated[var]) { if (propValue[var] == solver->value(var).getBool()) { //they both imply the same bothSame.push_back(Lit(var, !propValue[var])); } } visitedAlready[thisLit.toInt()] = 1; //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; extraTime += solver->implCache[(~ancestor).toInt()].lits.size()/100; extraTime += solver->implCache[(~thisLit).toInt()].lits.size()/100; const bool learntStep = solver->varData[thisLit.var()].reason.getLearntStep(); //Update the cache now assert(ancestor != lit_Undef); solver->implCache[(~ancestor).toInt()].merge( solver->implCache[(~thisLit).toInt()].lits , thisLit , learntStep , ancestor , solver->seen ); #ifdef VERBOSE_DEBUG_FULLPROP cout << "The impl cache of " << (~ancestor) << " is now: "; cout << solver->implCache[(~ancestor).toInt()] << endl; #endif } } solver->cancelZeroLight(); runStats.addedBin += solver->hyperBinResAll(); std::pair<size_t, size_t> tmp = solver->removeUselessBins(); runStats.removedIrredBin += tmp.first; runStats.removedRedBin += tmp.second; #ifdef DEBUG_REMOVE_USELESS_BIN testBinRemoval(lit); #endif if (!first) { //Add bothsame for(size_t i = 0; i < bothSame.size(); i++) { extraTime += 3; solver->enqueue(bothSame[i]); } runStats.bothSameAdded += bothSame.size(); } assert(solver->ok); solver->ok = solver->propagate().isNULL(); return solver->ok; }
inline Pass::Pass(const Lit x) { pa = std::map<Var, bool>(); pa[x.var()] = x.val(); }
bool Prober::try_this(const Lit lit, const bool first) { //Clean state if this is the 1st of two if (first) { clear_up_before_first_set(); } toEnqueue.clear(); runStats.numProbed++; solver->new_decision_level(); solver->enqueue(lit); solver->depth[lit.var()] = 0; if (solver->conf.verbosity >= 6) { cout << "c Probing lit " << lit << endl; } Lit failed = lit_Undef; if (!propagate(failed)) { return solver->okay(); } if (failed == lit_Undef) { if (solver->conf.verbosity >= 6) cout << "c Did not fail on lit " << lit << endl; //Fill bothprop, cache assert(solver->decisionLevel() > 0); size_t numElemsSet = solver->trail_size() - solver->trail_lim[0]; 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]; const uint32_t var = thisLit.var(); if (solver->conf.doBothProp) { check_and_set_both_prop(var, first); } visitedAlready[thisLit.toInt()] = 1; if (solver->conf.otfHyperbin) { update_cache(thisLit, lit, numElemsSet); } } if (!solver->conf.otfHyperbin && solver->conf.doCache ) { add_rest_of_lits_to_cache(lit); } } solver->cancelUntil<false>(0); solver->add_otf_subsume_long_clauses(); solver->add_otf_subsume_implicit_clause(); runStats.addedBin += solver->hyper_bin_res_all(); std::pair<size_t, size_t> tmp = solver->remove_useless_bins(); runStats.removedIrredBin += tmp.first; runStats.removedRedBin += tmp.second; if (failed != lit_Undef) { if (solver->conf.verbosity >= 6) { cout << "c Failed while enq + prop " << lit << " Lit that got propagated to both values: " << failed << endl; } runStats.numFailed++; #ifdef STATS_NEEDED runStats.conflStats.update(solver->lastConflictCausedBy); #endif runStats.conflStats.numConflicts++; vector<Lit> lits; lits.push_back(~failed); solver->add_clause_int(lits, true); clear_up_before_first_set(); return solver->ok; } else { assert(solver->ok); runStats.bothSameAdded += toEnqueue.size(); extraTime += 3*toEnqueue.size(); return solver->fully_enqueue_these(toEnqueue); } }
bool Prober::probe(vector<uint32_t>* probe_order) { assert(solver->decisionLevel() == 0); assert(solver->nVars() > 0); solver->test_all_clause_attached(); clean_clauses_before_probe(); reset_stats_and_state(); uint64_t numPropsTodo = calc_numpropstodo(); const double myTime = cpuTime(); const size_t origTrailSize = solver->trail_size(); numPropsTodo = update_numpropstodo_based_on_prev_performance(numPropsTodo); if (probe_order == NULL) { randomize_possible_choices(); } else { vars_to_probe = *probe_order; } if (solver->conf.verbosity >= 10) { cout << "Order of probe:"; for(auto x: vars_to_probe) { cout << x+1 << ", "; } cout << endl; } assert(solver->propStats.bogoProps == 0); assert(solver->propStats.otfHyperTime == 0); single_prop_tout = (double)numPropsTodo *solver->conf.single_probe_time_limit_perc; for(size_t i = 0 ; i < vars_to_probe.size() && limit_used() < numPropsTodo && !solver->must_interrupt_asap() ; i++ ) { if ((i & 0xff) == 0xff && cpuTime() >= solver->conf.maxTime ) { break; } extraTime += 20; runStats.numLoopIters++; const uint32_t var = vars_to_probe[i]; //Probe 'false' first --> this is not critical Lit lit = Lit(var, false); //Check if var is set already if (solver->value(lit.var()) != l_Undef || solver->varData[lit.var()].removed != Removed::none || visitedAlready[lit.toInt()] ) { continue; } runStats.numVarProbed++; extraTime += 20; if (!try_this(lit, true)) goto end; if (solver->value(lit) == l_Undef && !try_this(~lit, false) ) { goto end; } } end: if (solver->conf.verbosity >= 10) { cout << "c main loop for " << __PRETTY_FUNCTION__ << " finished: " << " must_interrupt? " << solver->must_interrupt_asap() << " limit_used? " << (limit_used() >= numPropsTodo) << endl; } //Delete any remaining binaries to add or remove //next time, variables will be renumbered/etc. so it will be wrong //to add/remove them solver->needToAddBinClause.clear(); solver->uselessBin.clear(); runStats.zeroDepthAssigns = solver->trail_size() - origTrailSize; if (solver->ok && runStats.zeroDepthAssigns) { clean_clauses_after_probe(); } update_and_print_stats(myTime, numPropsTodo); check_if_must_disable_otf_hyperbin_and_tred(numPropsTodo); check_if_must_disable_cache_update(); solver->test_all_clause_attached(); return solver->ok; }
Base* Ran::mutating_canonicalize() { Base* ret = this; switch (m_subs.size()) { case 2: { auto it = begin(m_subs); Lit* subA = dynamic_cast<Lit*>(*it); it++; Lit* subB = dynamic_cast<Lit*>(*it); // TODO: Generalize to n bytes and reuse auto_set_detected_pmatch() if (subA and subB) { // if both literals const auto nbytes = subA->bitsize().get() / 8; if ((subA->bitsize() == 8 and subB->bitsize() == 8 and subA->get_byte() == 0 and (~subB->get_byte()) == 0) or (subA->bitsize() == 16 and subB->bitsize() == 16 and subA->get_i16ne() == 0 and (~subB->get_i16ne()) == 0) or (subA->bitsize() == 32 and subB->bitsize() == 32 and subA->get_i32ne() == 0 and (~subB->get_i32ne()) == 0) or (subA->bitsize() == 64 and subB->bitsize() == 64 and subA->get_i64ne() == 0 and (~subB->get_i64ne()) == 0)) { ret = mutate_to(anybytes(nbytes)); // mutate \p this to \c Any } } break; } default: { break; } } return ret; }
void SubsumeImplicit::try_subsume_tri( const Lit lit , Watched*& i , Watched*& j , const bool doStamp ) { //Only treat one of the TRI's instances if (lit > i->lit2()) { *j++ = *i; return; } bool remove = false; //Subsumed by bin if (lastLit2 == i->lit2() && lastLit3 == lit_Undef ) { if (lastRed && !i->red()) { assert(lastBin->isBin()); assert(lastBin->red()); assert(lastBin->lit2() == lastLit2); lastBin->setRed(false); timeAvailable -= 20; timeAvailable -= solver->watches[lastLit2.toInt()].size(); findWatchedOfBin(solver->watches, lastLit2, lit, true).setRed(false); solver->binTri.redBins--; solver->binTri.irredBins++; lastRed = false; } remove = true; } //Subsumed by Tri if (!remove && lastLit2 == i->lit2() && lastLit3 == i->lit3() ) { //The sorting algorithm prefers irred to red, so it is //impossible to have irred before red assert(!(i->red() == false && lastRed == true)); remove = true; } tmplits.clear(); tmplits.push_back(lit); tmplits.push_back(i->lit2()); tmplits.push_back(i->lit3()); //Subsumed by stamp if (doStamp && !remove && (solver->conf.otfHyperbin || !solver->drup->enabled()) ) { timeAvailable -= 15; remove = solver->stamp.stampBasedClRem(tmplits); runStats.stampTriRem += remove; } //Subsumed by cache if (!remove && solver->conf.doCache && (solver->conf.otfHyperbin || !solver->drup->enabled()) ) { for(size_t at = 0; at < tmplits.size() && !remove; at++) { timeAvailable -= (int64_t)solver->implCache[lit.toInt()].lits.size(); for (vector<LitExtra>::const_iterator it2 = solver->implCache[tmplits[at].toInt()].lits.begin() , end2 = solver->implCache[tmplits[at].toInt()].lits.end() ; it2 != end2 ; it2++ ) { if (( it2->getLit() == tmplits[0] || it2->getLit() == tmplits[1] || it2->getLit() == tmplits[2] ) && it2->getOnlyIrredBin() ) { remove = true; runStats.cacheTriRem++; break; } } } } if (remove) { timeAvailable -= 30; solver->remove_tri_but_lit1(lit, i->lit2(), i->lit3(), i->red(), timeAvailable); runStats.remTris++; (*solver->drup) << del << lit << i->lit2() << i->lit3() << fin; return; } //Don't remove lastLit2 = i->lit2(); lastLit3 = i->lit3(); lastRed = i->red(); *j++ = *i; return; }
bool DataSync::shareUnitData() { uint32_t thisGotUnitData = 0; uint32_t thisSentUnitData = 0; SharedData& shared = *sharedData; if (shared.value.size() < solver->nVarsOutside()) { shared.value.resize(solver->nVarsOutside(), l_Undef); } for (uint32_t var = 0; var < solver->nVarsOutside(); var++) { Lit thisLit = Lit(var, false); thisLit = solver->map_to_with_bva(thisLit); thisLit = solver->varReplacer->get_lit_replaced_with_outer(thisLit); thisLit = solver->map_outer_to_inter(thisLit); 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->varData[litToEnqueue.var()].removed != Removed::none) { continue; } solver->enqueue(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) ) { cout << "c [sync] got units " << thisGotUnitData << " sent units " << thisSentUnitData << endl; } stats.recvUnitData += thisGotUnitData; stats.sentUnitData += thisSentUnitData; return true; }
bool ImplCache::clean(Solver* solver, bool* setSomething) { assert(solver->ok); assert(solver->decisionLevel() == 0); vector<Lit> toEnqueue; double myTime = cpuTime(); uint64_t numUpdated = 0; uint64_t numCleaned = 0; uint64_t numFreed = 0; //Merge in & free memory for (Var var = 0; var < solver->nVars(); var++) { //If replaced, merge it into the one that replaced it if (solver->varData[var].removed == Removed::replaced) { for(int i = 0; i < 2; i++) { const Lit litOrig = Lit(var, i); if (implCache[litOrig.toInt()].lits.empty()) continue; const Lit lit = solver->varReplacer->getLitReplacedWith(litOrig); //Updated literal must be normal, otherwise, biig problems e.g //implCache is not even large enough, etc. if (solver->varData[lit.var()].removed == Removed::none) { bool taut = implCache.at(lit.toInt()).merge( implCache[litOrig.toInt()].lits , lit_Undef //nothing to add , false //replaced, so 'irred' , lit.var() //exclude the literal itself , solver->seen ); if (taut) { toEnqueue.push_back(lit); (*solver->drup) << lit << fin; } } } } //Free it if (solver->value(var) != l_Undef || solver->varData[var].removed == Removed::elimed || solver->varData[var].removed == Removed::replaced || solver->varData[var].removed == Removed::decomposed ) { vector<LitExtra> tmp1; numFreed += implCache[Lit(var, false).toInt()].lits.capacity(); implCache[Lit(var, false).toInt()].lits.swap(tmp1); vector<LitExtra> tmp2; numFreed += implCache[Lit(var, true).toInt()].lits.capacity(); implCache[Lit(var, true).toInt()].lits.swap(tmp2); } } vector<uint16_t>& inside = solver->seen; vector<uint16_t>& irred = solver->seen2; size_t wsLit = 0; for(vector<TransCache>::iterator trans = implCache.begin(), transEnd = implCache.end() ; trans != transEnd ; trans++, wsLit++ ) { //Stats size_t origSize = trans->lits.size(); size_t newSize = 0; //Update to replaced vars, remove vars already set or eliminated Lit vertLit = Lit::toLit(wsLit); vector<LitExtra>::iterator it = trans->lits.begin(); vector<LitExtra>::iterator it2 = it; for (vector<LitExtra>::iterator end = trans->lits.end(); it != end; it++) { Lit lit = it->getLit(); assert(lit.var() != vertLit.var()); //Remove if value is set if (solver->value(lit.var()) != l_Undef) continue; //Update to its replaced version if (solver->varData[lit.var()].removed == Removed::replaced || solver->varData[lit.var()].removed == Removed::queued_replacer ) { lit = solver->varReplacer->getLitReplacedWith(lit); //This would be tautological (and incorrect), so skip if (lit.var() == vertLit.var()) continue; numUpdated++; } //Yes, it's possible that the child was not set, but the parent is set //This is because there is a delay between replacement and cache cleaning if (solver->value(lit.var()) != l_Undef) continue; //If updated version is eliminated/decomposed, skip if (solver->varData[lit.var()].removed != Removed::none) continue; //Mark irred irred[lit.toInt()] |= (char)it->getOnlyIrredBin(); //If we have already visited this var, just skip over, but update irred if (inside[lit.toInt()]) { continue; } inside[lit.toInt()] = true; *it2++ = LitExtra(lit, it->getOnlyIrredBin()); newSize++; } trans->lits.resize(newSize); //Now that we have gone through the list, go through once more to: //1) set irred right (above we might have it set later) //2) clear 'inside' //3) clear 'irred' for (vector<LitExtra>::iterator it = trans->lits.begin(), end = trans->lits.end(); it != end; it++) { Lit lit = it->getLit(); //Clear 'inside' inside[lit.toInt()] = false; //Clear 'irred' const bool nRed = irred[lit.toInt()]; irred[lit.toInt()] = false; //Set non-leartness correctly *it = LitExtra(lit, nRed); assert(solver->varData[it->getLit().var()].removed == Removed::none); assert(solver->value(it->getLit()) == l_Undef); } numCleaned += origSize-trans->lits.size(); } size_t origTrailDepth = solver->trail.size(); solver->enqueueThese(toEnqueue); if (setSomething) { *setSomething = (solver->trail.size() != origTrailDepth); } if (solver->conf.verbosity >= 1) { cout << "c Cache cleaned." << " Updated: " << std::setw(7) << numUpdated/1000 << " K" << " Cleaned: " << std::setw(7) << numCleaned/1000 << " K" << " Freed: " << std::setw(7) << numFreed/1000 << " K" << " T: " << std::setprecision(2) << std::fixed << (cpuTime()-myTime) << endl; } return solver->okay(); }
// Propagating a literal. Type of literal and the (learned clause's)/(propagating clause's)/(etc) group must be given. Updates the proof graph and the statistics. note: the meaning of the variable 'group' depends on the type void Logger::propagation(const Lit lit, Clause* c) { first_begin(); assert(!(proof == NULL && proof_graph_on)); uint group; prop_type type; if (c == NULL) { if (S->decisionLevel() == 0) type = add_clause_type; else type = guess_type; group = std::numeric_limits<uint>::max(); } else { type = simple_propagation_type; group = c->getGroup(); } //graph if (proof_graph_on && (!mini_proof || type == guess_type)) { uniqueid++; fprintf(proof,"node%d [shape=box, label=\"",uniqueid);; if (lit.sign()) fprintf(proof,"-"); if (varnames[lit.var()] != "Noname") fprintf(proof,"%s\"];\n",varnames[lit.var()].c_str()); else fprintf(proof,"Var: %d\"];\n",lit.var()); fprintf(proof,"node%d -> node%d [label=\"",history[history.size()-1],uniqueid); switch (type) { case simple_propagation_type: fprintf(proof,"%s\"];\n", groupnames[group].c_str()); break; case add_clause_type: fprintf(proof,"red. from clause\"];\n"); break; case guess_type: fprintf(proof,"guess\",style=bold];\n"); break; } history.push_back(uniqueid); } if (statistics_on) { switch (type) { case simple_propagation_type: depths_of_propagations_for_group[group].sum += S->decisionLevel(); depths_of_propagations_for_group[group].num ++; if (S->decisionLevel() == 0) depths_of_propagations_unit[group] = true; times_group_caused_propagation[group]++; case add_clause_type: no_propagations++; times_var_propagated[lit.var()]++; depths_of_assigns_for_var[lit.var()].sum += S->decisionLevel(); depths_of_assigns_for_var[lit.var()].num ++; if (S->decisionLevel() == 0) depths_of_assigns_unit[lit.var()] = true; break; case guess_type: no_decisions++; times_var_guessed[lit.var()]++; depths_of_assigns_for_var[lit.var()].sum += S->decisionLevel(); depths_of_assigns_for_var[lit.var()].num ++; break; } } }
void ImplCache::tryVar( Solver* solver , Var var ) { //Sanity check assert(solver->ok); assert(solver->decisionLevel() == 0); //Convenience vector<uint16_t>& seen = solver->seen; vector<uint16_t>& val = solver->seen2; Lit lit = Lit(var, false); const vector<LitExtra>& cache1 = implCache[lit.toInt()].lits; assert(solver->watches.size() > (lit.toInt())); watch_subarray_const ws1 = solver->watches[lit.toInt()]; const vector<LitExtra>& cache2 = implCache[(~lit).toInt()].lits; watch_subarray_const ws2 = solver->watches[(~lit).toInt()]; //Fill 'seen' and 'val' from cache for (vector<LitExtra>::const_iterator it = cache1.begin(), end = cache1.end() ; it != end ; it++ ) { const Var var2 = it->getLit().var(); //A variable that has been really eliminated, skip if (solver->varData[var2].removed != Removed::none && solver->varData[var2].removed != Removed::queued_replacer ) { continue; } seen[it->getLit().var()] = 1; val[it->getLit().var()] = it->getLit().sign(); } //Fill 'seen' and 'val' from watch for (watch_subarray::const_iterator it = ws1.begin(), end = ws1.end() ; it != end ; it++ ) { if (!it->isBinary()) continue; const Lit otherLit = it->lit2(); if (!seen[otherLit.var()]) { seen[otherLit.var()] = 1; val[otherLit.var()] = otherLit.sign(); } else if (val[otherLit.var()] != otherLit.sign()) { //(a->b, a->-b) -> so 'a' delayedClausesToAddNorm.push_back(lit); } } //Okay, filled //Try to see if we propagate the same or opposite from the other end //Using cache for (vector<LitExtra>::const_iterator it = cache2.begin(), end = cache2.end() ; it != end ; it++ ) { assert(it->getLit().var() != var); const Var var2 = it->getLit().var(); //Only if the other one also contained it if (!seen[var2]) continue; //If var has been removed, skip if (solver->varData[var2].removed != Removed::none && solver->varData[var2].removed != Removed::queued_replacer ) continue; handleNewData(val, var, it->getLit()); } //Try to see if we propagate the same or opposite from the other end //Using binary clauses for (watch_subarray::const_iterator it = ws2.begin(), end = ws2.end(); it != end; it++) { if (!it->isBinary()) continue; assert(it->lit2().var() != var); const Var var2 = it->lit2().var(); assert(var2 < solver->nVars()); //Only if the other one also contained it if (!seen[var2]) continue; handleNewData(val, var, it->lit2()); } //Clear 'seen' and 'val' for (vector<LitExtra>::const_iterator it = cache1.begin(), end = cache1.end(); it != end; it++) { seen[it->getLit().var()] = false; val[it->getLit().var()] = false; } for (watch_subarray::const_iterator it = ws1.begin(), end = ws1.end(); it != end; it++) { if (!it->isBinary()) continue; seen[it->lit2().var()] = false; val[it->lit2().var()] = false; } }
inline Var var(const Lit x) { return x.var(); }
void PropEngine::enqueue(const Lit p, const PropBy from) { #ifdef DEBUG_ENQUEUE_LEVEL0 #ifndef VERBOSE_DEBUG if (decisionLevel() == 0) #endif //VERBOSE_DEBUG cout << "enqueue var " << p.var()+1 << " to val " << !p.sign() << " level: " << decisionLevel() << " sublevel: " << trail.size() << " by: " << from << endl; #endif //DEBUG_ENQUEUE_LEVEL0 #ifdef ENQUEUE_DEBUG //assert(trail.size() <= nVarsOuter()); //assert(decisionLevel() == 0 || varData[p.var()].removed == Removed::none); #endif const Var v = p.var(); assert(value(v) == l_Undef); if (!watches[(~p).toInt()].empty()) { watches.prefetch((~p).toInt()); } const bool sign = p.sign(); assigns[v] = boolToLBool(!sign); #ifdef STATS_NEEDED_EXTRA varData[v].stats.trailLevelHist.push(trail.size()); varData[v].stats.decLevelHist.push(decisionLevel()); #endif varData[v].reason = from; varData[v].level = decisionLevel(); trail.push_back(p); propStats.propagations++; if (update_bogoprops) { propStats.bogoProps += 1; } if (sign) { #ifdef STATS_NEEDED_EXTRA varData[v].stats.negPolarSet++; #endif #ifdef STATS_NEEDED propStats.varSetNeg++; #endif } else { #ifdef STATS_NEEDED_EXTRA varData[v].stats.posPolarSet++; #endif #ifdef STATS_NEEDED propStats.varSetPos++; #endif } if (varData[v].polarity != sign) { #ifdef UPDATE_AGILITY agility.update(true); #endif #ifdef STATS_NEEDED_EXTRA varData[v].stats.flippedPolarity++; #endif #ifdef STATS_NEEDED propStats.varFlipped++; #endif } else { #ifdef UPDATE_AGILITY agility.update(false); #endif } //Only update non-decision: this way, flipped decisions don't get saved if (update_polarity_and_activity && from != PropBy() ) { varData[v].polarity = !sign; } #ifdef ANIMATE3D std::cerr << "s " << v << " " << p.sign() << endl; #endif }
bool BVA::bounded_var_addition() { bounded_var_elim_time_limit = solver->conf.bva_time_limitM*2ULL*400LL *1000LL *solver->conf.global_timeout_multiplier; bva_verbosity = false; assert(solver->ok); if (!solver->conf.do_bva) return solver->okay(); if (solver->conf.verbosity >= 3 || bva_verbosity) { cout << "c [occ-bva] Running BVA" << endl; } if (!solver->propagate_occur()) return false; simplifier->limit_to_decrease = &bounded_var_elim_time_limit; int64_t limit_orig = *simplifier->limit_to_decrease; solver->clauseCleaner->clean_implicit_clauses(); if (solver->conf.doStrSubImplicit) { solver->subsumeImplicit->subsume_implicit(false); } bva_worked = 0; bva_simp_size = 0; var_bva_order.clear(); calc_watch_irred_sizes(); for(size_t i = 0; i < solver->nVars()*2; i++) { const Lit lit = Lit::toLit(i); if (solver->value(lit) != l_Undef || solver->varData[lit.var()].removed != Removed::none ) { continue; } var_bva_order.insert(lit.toInt()); } double my_time = cpuTime(); while(!var_bva_order.empty()) { if (*simplifier->limit_to_decrease < 0 || bva_worked >= solver->conf.bva_limit_per_call || solver->must_interrupt_asap() ) { break; } const Lit lit = Lit::toLit(var_bva_order.removeMin()); if (solver->conf.verbosity >= 5 || bva_verbosity) { cout << "c [occ-bva] trying lit " << lit << endl; } bool ok = try_bva_on_lit(lit); if (!ok) break; } solver->bva_changed(); bool time_out = *simplifier->limit_to_decrease <= 0; const double time_used = cpuTime() - my_time; double time_remain = float_div(*simplifier->limit_to_decrease ,limit_orig); if (solver->conf.verbosity >= 2) { cout << "c [occ-bva] added: " << bva_worked << " simp: " << bva_simp_size << " 2lit: " << ((solver->conf.bva_also_twolit_diff && (long)solver->sumConflicts() >= solver->conf.bva_extra_lit_and_red_start) ? "Y" : "N") << solver->conf.print_times(time_used, time_out, time_remain) << endl; } if (solver->sqlStats) { solver->sqlStats->time_passed( solver , "bva" , time_used , time_out , time_remain ); } return solver->okay(); }
void CompHandler::moveClausesLong( vector<ClOffset>& cs , SATSolver* newSolver , const uint32_t comp ) { vector<Lit> tmp; vector<ClOffset>::iterator i, j, end; for (i = j = cs.begin(), end = cs.end() ; i != end ; ++i ) { Clause& cl = *solver->cl_alloc.ptr(*i); //Irred, different comp if (!cl.red()) { if (compFinder->getVarComp(cl[0].var()) != comp) { //different comp, move along *j++ = *i; continue; } } if (cl.red()) { //Check which comp(s) it belongs to bool thisComp = false; bool otherComp = false; for (Lit* l = cl.begin(), *end2 = cl.end(); l != end2; ++l) { if (compFinder->getVarComp(l->var()) == comp) thisComp = true; if (compFinder->getVarComp(l->var()) != comp) otherComp = true; } //In both comps, remove it if (thisComp && otherComp) { solver->detachClause(cl); solver->cl_alloc.clauseFree(&cl); continue; } //In one comp, but not this one if (!thisComp) { //different comp, move along *j++ = *i; continue; } assert(thisComp && !otherComp); } //Let's move it to the other solver! #ifdef VERBOSE_DEBUG cout << "clause in this comp:" << cl << endl; #endif //Create temporary space 'tmp' and copy to backup tmp.resize(cl.size()); for (size_t i2 = 0; i2 < cl.size(); ++i2) { tmp[i2] = upd_bigsolver_to_smallsolver(cl[i2]); } //Add 'tmp' to the new solver if (cl.red()) { #ifdef STATS_NEEDED cl.stats.introduced_at_conflict = 0; #endif //newSolver->addRedClause(tmp, cl.stats); } else { saveClause(cl); newSolver->add_clause(tmp); } //Remove from here solver->detachClause(cl); solver->cl_alloc.clauseFree(&cl); } cs.resize(cs.size() - (i-j)); }
Lit HyperEngine::prop_irred_bin_dfs( StampType stampType , PropBy& confl , const Lit //root , bool& restart ) { const Lit p = toPropBin.top(); watch_subarray_const ws = watches[~p]; size_t done = 0; for(const Watched *k = ws.begin(), *end = ws.end() ; k != end ; k++, done++ ) { propStats.bogoProps += 1; //Pre-fetch long clause if (k->isClause()) { if (value(k->getBlockedLit()) != l_True) { const ClOffset offset = k->get_offset(); __builtin_prefetch(cl_alloc.ptr(offset)); } continue; } //end CLAUSE //If something other than binary, skip if (!k->isBin()) continue; //If stamping only irred, go over red binaries if (stampType == STAMP_IRRED && k->red() ) { continue; } PropResult ret = prop_bin_with_ancestor_info(p, k, confl); switch(ret) { case PROP_FAIL: close_all_timestamps(stampType); return analyzeFail(confl); case PROP_SOMETHING: propStats.bogoProps += 8; stamp.stampingTime++; stamp.tstamp[trail.back().toInt()].start[stampType] = stamp.stampingTime; #ifdef DEBUG_STAMPING cout << "From " << p << " enqueued " << trail.back() << " for stamp.stampingTime " << stamp.stampingTime << endl; #endif toPropNorm.push(trail.back()); toPropBin.push(trail.back()); if (stampType == STAMP_IRRED) toPropRedBin.push(trail.back()); propStats.bogoProps += done*4; restart = true; return lit_Undef; case PROP_NOTHING: break; default: assert(false); break; } } //Finished with this literal propStats.bogoProps += ws.size()*4; toPropBin.pop(); stamp.stampingTime++; stamp.tstamp[p.toInt()].end[stampType] = stamp.stampingTime; #ifdef DEBUG_STAMPING cout << "End time for " << p << " is " << stamp.stampingTime << endl; #endif return lit_Undef; }
void CompHandler::move_tri_clause( SATSolver* newSolver , const uint32_t comp , Watched *i , const Lit lit ) { const Lit lit2 = i->lit2(); const Lit lit3 = i->lit3(); //Unless redundant, cannot be in 2 comps at once assert((compFinder->getVarComp(lit.var()) == comp && compFinder->getVarComp(lit2.var()) == comp && compFinder->getVarComp(lit3.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 || compFinder->getVarComp(lit3.var()) != comp ) { assert(i->red()); //The way we go through this, it's definitely going to be //either lit2 or lit3, not lit, that's in the other comp assert(compFinder->getVarComp(lit2.var()) != comp || compFinder->getVarComp(lit3.var()) != comp ); remove_tri_except_for_lit1(lit, lit2, lit3); return; } //don't add the same clause twice if (lit < lit2 && lit2 < lit3 ) { //Add clause tmp_lits = {upd_bigsolver_to_smallsolver(lit) , upd_bigsolver_to_smallsolver(lit2) , upd_bigsolver_to_smallsolver(lit3) }; assert(compFinder->getVarComp(lit.var()) == comp); assert(compFinder->getVarComp(lit2.var()) == comp); assert(compFinder->getVarComp(lit3.var()) == comp); //Add new clause if (i->red()) { //newSolver->addRedClause(tmp_lits); numRemovedThirdRed++; } else { //Save backup saveClause(vector<Lit>{lit, lit2, lit3}); newSolver->add_clause(tmp_lits); numRemovedThirdIrred++; } } else { //Just remove, already added above if (i->red()) { numRemovedThirdRed++; } else { numRemovedThirdIrred++; } } }
Lit HyperEngine::propagate_dfs( const StampType stampType , const uint64_t timeout ) { timedOutPropagateFull = false; propStats.otfHyperPropCalled++; #ifdef VERBOSE_DEBUG_FULLPROP cout << "Prop full started" << endl; #endif PropBy confl; //Assert startup: only 1 enqueued, uselessBin is empty assert(uselessBin.empty()); assert(decisionLevel() == 1); //The toplevel decision has to be set specifically //If we came here as part of a backtrack to decision level 1, then //this is already set, and there is no need to set it if (trail.size() - trail_lim.back() == 1) { //Set up root node Lit root = trail[qhead]; varData[root.var()].reason = PropBy(~lit_Undef, false, false, false); } //Set up stacks toPropBin.clear(); toPropRedBin.clear(); toPropNorm.clear(); Lit root = trail.back(); toPropBin.push(root); toPropNorm.push(root); if (stampType == STAMP_RED) toPropRedBin.push(root); //Setup needToAddBinClause.clear(); stamp.stampingTime++; stamp.tstamp[root.toInt()].start[stampType] = stamp.stampingTime; #ifdef DEBUG_STAMPING cout << "Top-enqueued << " << trail.back() << " for stamp.stampingTime " << stamp.stampingTime << endl; #endif while(true) { propStats.bogoProps += 3; if (need_early_abort_dfs(stampType, timeout)) return lit_Undef; //Propagate binary irred bool restart = false; while (!toPropBin.empty()) { Lit ret = prop_irred_bin_dfs(stampType, confl, root, restart); if (ret != lit_Undef) return ret; if (restart) break; } if (restart) continue; if (stampType == STAMP_IRRED) { while (!toPropRedBin.empty()) { Lit ret = prop_red_bin_dfs(stampType, confl, root, restart); if (ret != lit_Undef) return ret; if (restart) break; } } if (restart) continue; while (!toPropNorm.empty()) { Lit ret = prop_larger_than_bin_cl_dfs(stampType, confl, root, restart); if (ret != lit_Undef) return ret; if (restart) break; qhead++; } if (restart) continue; //Nothing more to propagate break; } return lit_Undef; }
void CompHandler::moveClausesImplicit( SATSolver* newSolver , const uint32_t comp , const vector<Var>& vars ) { numRemovedHalfIrred = 0; numRemovedHalfRed = 0; numRemovedThirdIrred = 0; numRemovedThirdRed = 0; for(const Var var: vars) { for(unsigned sign = 0; sign < 2; ++sign) { const Lit lit = Lit(var, sign); watch_subarray ws = solver->watches[lit.toInt()]; //If empty, nothing to to, skip if (ws.empty()) { continue; } Watched *i = ws.begin(); Watched *j = i; for (Watched *end2 = ws.end() ; i != end2 ; ++i ) { //At least one variable inside comp if (i->isBinary() && (compFinder->getVarComp(lit.var()) == comp || compFinder->getVarComp(i->lit2().var()) == comp ) ) { move_binary_clause(newSolver, comp, i, lit); continue; } if (i->isTri() && (compFinder->getVarComp(lit.var()) == comp || compFinder->getVarComp(i->lit2().var()) == comp || compFinder->getVarComp(i->lit3().var()) == comp ) ) { move_tri_clause(newSolver, comp, i, lit); continue; } *j++ = *i; } ws.shrink_(i-j); }} assert(numRemovedHalfIrred % 2 == 0); solver->binTri.irredBins -= numRemovedHalfIrred/2; assert(numRemovedThirdIrred % 3 == 0); solver->binTri.irredTris -= numRemovedThirdIrred/3; assert(numRemovedHalfRed % 2 == 0); solver->binTri.redBins -= numRemovedHalfRed/2; assert(numRemovedThirdRed % 3 == 0); solver->binTri.redTris -= numRemovedThirdRed/3; }
/** hop backwards from thisAncestor until: 1) we reach ancestor of 'conflict' -- at this point, we return TRUE 2) we reach an invalid point. Either root, or an invalid hop. We return FALSE. */ bool HyperEngine::is_ancestor_of( const Lit conflict , Lit thisAncestor , const bool thisStepRed , const bool onlyIrred , const Lit lookingForAncestor ) { propStats.otfHyperTime += 1; #ifdef VERBOSE_DEBUG_FULLPROP cout << "is_ancestor_of." << "conflict: " << conflict << " thisAncestor: " << thisAncestor << " thisStepRed: " << thisStepRed << " onlyIrred: " << onlyIrred << " lookingForAncestor: " << lookingForAncestor << endl; #endif //Was propagated at level 0 -- clauseCleaner will remove the clause if (lookingForAncestor == lit_Undef) return false; if (lookingForAncestor == thisAncestor) { #ifdef VERBOSE_DEBUG_FULLPROP cout << "Last position inside prop queue is not saved during propFull" << endl << "This may be the same exact binary clause -- not removing" << endl; #endif return false; } #ifdef VERBOSE_DEBUG_FULLPROP cout << "Looking for ancestor of " << conflict << " : " << lookingForAncestor << endl; cout << "This step based on redundant cl? " << (thisStepRed ? "yes" : "false") << endl; cout << "Only irred is acceptable?" << (onlyIrred ? "yes" : "no") << endl; cout << "This step would be based on redundant cl?" << (thisStepRed ? "yes" : "no") << endl; #endif if (onlyIrred && thisStepRed) { #ifdef VERBOSE_DEBUG_FULLPROP cout << "This step doesn't work -- is redundant but needs irred" << endl; #endif return false; } //This is as low as we should search -- we cannot find what we are searchig for lower than this const size_t bottom = depth[lookingForAncestor.var()]; while(thisAncestor != lit_Undef && (!use_depth_trick || bottom <= depth[thisAncestor.var()]) ) { #ifdef VERBOSE_DEBUG_FULLPROP cout << "Current acestor: " << thisAncestor << " redundant step? " << varData[thisAncestor.var()].reason.isRedStep() << endl; #endif if (thisAncestor == conflict) { #ifdef VERBOSE_DEBUG_FULLPROP cout << "We are trying to step over the conflict." << " That would create a loop." << endl; #endif return false; } if (thisAncestor == lookingForAncestor) { #ifdef VERBOSE_DEBUG_FULLPROP cout << "Ancestor found" << endl; #endif return true; } const PropBy& data = varData[thisAncestor.var()].reason; if ((onlyIrred && data.isRedStep()) || data.getHyperbinNotAdded() ) { #ifdef VERBOSE_DEBUG_FULLPROP cout << "Wrong kind of hop would be needed" << endl; #endif return false; //reached would-be redundant hop (but this is irred) } thisAncestor = data.getAncestor(); propStats.otfHyperTime += 1; } #ifdef VERBOSE_DEBUG_FULLPROP cout << "Exit, reached root" << endl; #endif return false; }
Lit CNF_Manager::translateExprRec(const Expr& e, CNF_Formula& cnf, const Theorem& thmIn) { if (e.isFalse()) return Lit::getFalse(); if (e.isTrue()) return Lit::getTrue(); if (e.isNot()) return !translateExprRec(e[0], cnf, thmIn); ExprHashMap<Var>::iterator iMap = d_cnfVars.find(e); if (e.isTranslated()) { DebugAssert(iMap != d_cnfVars.end(), "Translated expr should be in map"); return Lit((*iMap).second); } else e.setTranslated(d_bottomScope); Var v(int(d_varInfo.size())); bool translateOnly = false; if (iMap != d_cnfVars.end()) { v = (*iMap).second; translateOnly = true; d_varInfo[v].fanouts.clear(); } else { d_varInfo.resize(v+1); d_varInfo.back().expr = e; d_cnfVars[e] = v; } Expr::iterator i, iend; bool isAnd = false; switch (e.getKind()) { case AND: isAnd = true; case OR: { vector<Lit> lits; unsigned idx; for (i = e.begin(), iend = e.end(); i != iend; ++i) { lits.push_back(translateExprRec(*i, cnf, thmIn)); } // DebugAssert(concreteExpr(e,Lit(v)) == e,"why here"); for (idx = 0; idx < lits.size(); ++idx) { cnf.newClause(); cnf.addLiteral(Lit(v),isAnd); cnf.addLiteral(lits[idx], !isAnd); // DebugAssert(concreteExpr(e[idx],lits[idx]) == e[idx], "why here"); std::string reasonStr = (isAnd ? "and_mid" : "or_mid"); Expr after = e[idx] ; cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, after, reasonStr, idx)); // by yeting } cnf.newClause(); cnf.addLiteral(Lit(v),!isAnd); for (idx = 0; idx < lits.size(); ++idx) { cnf.addLiteral(lits[idx], isAnd); } std::string reasonStr = (isAnd ? "and_final" : "or_final") ; Expr after = e ; cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, after, reasonStr, 0)); // by yeting break; } case IMPLIES: { Lit arg0 = translateExprRec(e[0], cnf, thmIn); Lit arg1 = translateExprRec(e[1], cnf, thmIn); // DebugAssert(concreteExpr(e, Lit(v)) == e, "why here"); // DebugAssert(concreteExpr(e[0], arg0) == e[0], "why here"); // DebugAssert(concreteExpr(e[1], arg1) == e[1], "why here"); cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0); cnf.getCurrentClause().setClauseTheorem( d_rules->CNFtranslate(e, e, "imp", 0)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg1,true); cnf.getCurrentClause().setClauseTheorem( d_rules->CNFtranslate(e, e, "imp", 1)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1); cnf.getCurrentClause().setClauseTheorem( d_rules->CNFtranslate(e, e, "imp", 2)); // by yeting break; } case IFF: { Lit arg0 = translateExprRec(e[0], cnf, thmIn); Lit arg1 = translateExprRec(e[1], cnf, thmIn); // DebugAssert(concreteExpr(e, Lit(v)) == e, "why here"); // DebugAssert(concreteExpr(e[0], arg0) == e[0], "why here"); // DebugAssert(concreteExpr(e[1], arg1) == e[1], "why here"); cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0); cnf.addLiteral(arg1); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 0)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 1)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 2)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0); cnf.addLiteral(arg1,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "iff", 3)); // by yeting break; } case XOR: { Lit arg0 = translateExprRec(e[0], cnf, thmIn); Lit arg1 = translateExprRec(e[1], cnf, thmIn); // DebugAssert(concreteExpr(e, Lit(v)) == e, "why here"); // DebugAssert(concreteExpr(e[0], arg0) == e[0], "why here"); // DebugAssert(concreteExpr(e[1], arg1) == e[1], "why here"); cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0); cnf.addLiteral(arg1); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 0)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 1)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 2)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0); cnf.addLiteral(arg1,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFtranslate(e, e, "xor", 3)); // by yeting break; } case ITE: { Lit arg0 = translateExprRec(e[0], cnf, thmIn); Lit arg1 = translateExprRec(e[1], cnf, thmIn); Lit arg2 = translateExprRec(e[2], cnf, thmIn); Expr aftere0 = concreteExpr(e[0], arg0); Expr aftere1 = concreteExpr(e[1], arg1); Expr aftere2 = concreteExpr(e[2], arg2); vector<Expr> after ; after.push_back(aftere0); after.push_back(aftere1); after.push_back(aftere2); Theorem e0thm; Theorem e1thm; Theorem e2thm; { e0thm = d_iteMap[e[0]]; if (e0thm.isNull()) e0thm = d_commonRules->reflexivityRule(e[0]); e1thm = d_iteMap[e[1]]; if (e1thm.isNull()) e1thm = d_commonRules->reflexivityRule(e[1]); e2thm = d_iteMap[e[2]]; if (e2thm.isNull()) e2thm = d_commonRules->reflexivityRule(e[2]); } vector<Theorem> thms ; thms.push_back(e0thm); thms.push_back(e1thm); thms.push_back(e2thm); cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0); cnf.addLiteral(arg2); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 1)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0); cnf.addLiteral(arg2,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 2)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 3)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg0,true); cnf.addLiteral(arg1); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 4)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v)); cnf.addLiteral(arg1,true); cnf.addLiteral(arg2,true); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 5)); // by yeting cnf.newClause(); cnf.addLiteral(Lit(v),true); cnf.addLiteral(arg1); cnf.addLiteral(arg2); cnf.getCurrentClause().setClauseTheorem(d_rules->CNFITEtranslate(e, after,thms, 6)); // by yeting break; } default: { DebugAssert(!e.isAbsAtomicFormula() || d_varInfo[v].expr == e, "Corrupted Varinfo"); if (e.isAbsAtomicFormula()) { registerAtom(e, thmIn); return Lit(v); } Theorem thm = replaceITErec(e, v, translateOnly); const Expr& e2 = thm.getRHS(); DebugAssert(e2.isAbsAtomicFormula(), "Expected AbsAtomicFormula"); if (e2.isTranslated()) { // Ugly corner case: we happen to create an expression that has been // created before. We remove the current variable and fix up the // translation stack. if (translateOnly) { DebugAssert(v == d_cnfVars[e2], "Expected literal match"); } else { d_varInfo.resize(v); while (!d_translateQueueVars.empty() && d_translateQueueVars.back() == v) { d_translateQueueVars.pop_back(); } DebugAssert(d_cnfVars.find(e2) != d_cnfVars.end(), "Expected existing literal"); v = d_cnfVars[e2]; d_cnfVars[e] = v; while (d_translateQueueVars.size() < d_translateQueueThms.size()) { d_translateQueueVars.push_back(v); } } } else { e2.setTranslated(d_bottomScope); // Corner case: don't register reflexive equality if (!e2.isEq() || e2[0] != e2[1]) registerAtom(e2, thmIn); if (!translateOnly) { if (d_cnfVars.find(e2) == d_cnfVars.end()) { d_varInfo[v].expr = e2; d_cnfVars[e2] = v; } else { // Same corner case in an untranslated expr d_varInfo.resize(v); while (!d_translateQueueVars.empty() && d_translateQueueVars.back() == v) { d_translateQueueVars.pop_back(); } v = d_cnfVars[e2]; d_cnfVars[e] = v; while (d_translateQueueVars.size() < d_translateQueueThms.size()) { d_translateQueueVars.push_back(v); } } } } return Lit(v); } } // Record fanins / fanouts Lit l; for (i = e.begin(), iend = e.end(); i != iend; ++i) { l = getCNFLit(*i); DebugAssert(!l.isNull(), "Expected non-null literal"); if (!translateOnly) d_varInfo[v].fanins.push_back(l); if (l.isVar()) d_varInfo[l.getVar()].fanouts.push_back(v); } return Lit(v); }