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 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 DistillerLongWithImpl::strengthen_clause_with_watch( const Lit lit , const Watched* wit ) { //Strengthening w/ bin if (wit->isBin() && seen[lit.toInt()] //We haven't yet removed it ) { if (seen[(~wit->lit2()).toInt()]) { thisRemLitBinTri++; seen[(~wit->lit2()).toInt()] = 0; } } //Strengthening w/ tri if (wit->isTri() && seen[lit.toInt()] //We haven't yet removed it ) { if (seen[(wit->lit2()).toInt()]) { if (seen[(~wit->lit3()).toInt()]) { thisRemLitBinTri++; seen[(~wit->lit3()).toInt()] = 0; } } else if (seen[wit->lit3().toInt()]) { if (seen[(~wit->lit2()).toInt()]) { thisRemLitBinTri++; seen[(~wit->lit2()).toInt()] = 0; } } } }
void GateFinder::set_seen2_tri( const OrGate& gate , const bool only_irred ) { assert(seen2Set.empty()); watch_subarray_const csOther = solver->watches[~(gate.lit2)]; *simplifier->limit_to_decrease -= csOther.size(); for (const Watched ws: csOther) { if (!ws.isTri()) continue; if (ws.red() && only_irred) continue; //We might be contracting 2 irred clauses based on a learnt gate //would lead to UNSAT->SAT if (!ws.red() && gate.red) continue; const Lit lits[2] = {ws.lit2(), ws.lit3()}; for (size_t i = 0; i < 2; i++) { const Lit lit = lits[i]; if (!seen2[lit.toInt()]) { seen2[lit.toInt()] = 1; seen2Set.push_back(lit.toInt()); } } } }
void OnlyNonLearntBins::removeBin(Lit lit1, Lit lit2) { uint32_t index0 = lit1.toInt(); uint32_t index1 = lit2.toInt(); if (index1 > index0) std::swap(index0, index1); uint64_t final = index0; final |= ((uint64_t)index1) << 32;
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; }
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.toInt()].size(); for(const Watched w: solver->watches[lit.toInt()]) { 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 DataSync::addOneBinToOthers(const Lit lit1, const Lit lit2) { assert(lit1.toInt() < lit2.toInt()); vector<Lit>& bins = sharedData->bins[(~lit1).toInt()]; for (vector<Lit>::const_iterator it = bins.begin(), end = bins.end(); it != end; it++) { if (*it == lit2) return; } bins.push_back(lit2); sentBinData++; }
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; }
void PropEngine::detach_bin_clause( const Lit lit1 , const Lit lit2 , const bool red , const bool allow_empty_watch ) { if (!(allow_empty_watch && watches[lit1.toInt()].empty())) { removeWBin(watches, lit1, lit2, red); } if (!(allow_empty_watch && watches[lit2.toInt()].empty())) { removeWBin(watches, lit2, lit1, red); } }
/** @brief Detaches a (potentially) modified clause The first two literals might have chaned through modification, so they are passed along as arguments -- they are needed to find the correct place where the clause is */ void PropEngine::detach_modified_clause( const Lit lit1 , const Lit lit2 , const uint32_t origSize , const Clause* address ) { assert(origSize > 3); if (address->red() && red_long_cls_is_reducedb(*address)) { num_red_cls_reducedb--; } ClOffset offset = cl_alloc.get_offset(address); removeWCl(watches[lit1.toInt()], offset); removeWCl(watches[lit2.toInt()], offset); }
void DataSync::addOneBinToOthers(Lit lit1, Lit lit2) { assert(lit1 < lit2); if (sharedData->bins[lit1.toInt()].data == NULL) { return; } vector<Lit>& bins = *sharedData->bins[lit1.toInt()].data; for (const Lit lit : bins) { if (lit == lit2) return; } bins.push_back(lit2); stats.sentBinData++; }
bool DistillerLongWithImpl::str_and_sub_clause_with_cache(const Lit lit, const bool alsoStrengthen) { if (solver->conf.doCache && seen[lit.toInt()] //We haven't yet removed this literal from the clause ) { timeAvailable -= (1+(int)alsoStrengthen)*(long)solver->implCache[lit].lits.size(); for (const LitExtra elit: solver->implCache[lit].lits) { if (alsoStrengthen && seen[(~(elit.getLit())).toInt()] ) { seen[(~(elit.getLit())).toInt()] = 0; thisRemLitCache++; } if (seen2[elit.getLit().toInt()] && elit.getOnlyIrredBin() ) { isSubsumed = true; cache_based_data.subCache++; return true; } } return false; } return false; }
bool TransCache::mergeHelper( const Lit extraLit //Add this, too to the list of lits , const bool red //The step was a redundant-dependent step? , vector<uint16_t>& seen ) { bool taut = false; //Handle extra lit if (extraLit != lit_Undef) seen[extraLit.toInt()] = 1 + (int)!red; //Everything that's already in the cache, set seen[] to zero //Also, if seen[] is 2, but it's marked redundant in the cache //mark it as irred for (size_t i = 0, size = lits.size(); i < size; i++) { if (!red && !lits[i].getOnlyIrredBin() && seen[lits[i].getLit().toInt()] == 2 ) { lits[i].setOnlyIrredBin(); } seen[lits[i].getLit().toInt()] = 0; //Both L and ~L are in, the ancestor is a tautology if (seen[(~(lits[i].getLit())).toInt()]) { taut = true; } } return taut; }
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()); }
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; }
void BVA::update_touched_lits_in_bva() { const vector<uint32_t>& touched_list = touched.getTouchedList(); for(const uint32_t lit_uint: touched_list) { const Lit lit = Lit::toLit(lit_uint); if (var_bva_order.in_heap(lit.toInt())) { watch_irred_sizes[lit.toInt()] = calc_watch_irred_size(lit); var_bva_order.update_if_inside(lit.toInt()); } if (var_bva_order.in_heap((~lit).toInt())) { watch_irred_sizes[(~lit).toInt()] = calc_watch_irred_size(~lit); var_bva_order.update_if_inside((~lit).toInt()); } } touched.clear(); }
void FeaturesCalc::for_all_clauses(Function func_each_cl, Function2 func_each_lit) const { for (size_t i = 0; i < solver->nVars() * 2; i++) { Lit lit = Lit::toLit(i); for (const Watched & w : solver->watches[lit.toInt()]) { for_one_clause(w, lit, func_each_cl, func_each_lit); } } }
void GateFinder::find_or_gates_in_sweep_mode(const Lit lit) { assert(toClear.empty()); watch_subarray_const ws = solver->watches[lit.toInt()]; *simplifier->limit_to_decrease -= ws.size(); for(const Watched w: ws) { if (w.isBinary() && !w.red()) { seen[(~w.lit2()).toInt()] = 1; toClear.push_back(~w.lit2()); } } if (solver->conf.doCache && solver->conf.otfHyperbin) { const vector<LitExtra>& cache = solver->implCache[lit.toInt()].lits; *simplifier->limit_to_decrease -= cache.size(); for(const LitExtra l: cache) { if (l.getOnlyIrredBin()) { seen[(~l.getLit()).toInt()] = 1; toClear.push_back(~l.getLit()); } } } watch_subarray_const ws2 = solver->watches[(~lit).toInt()]; *simplifier->limit_to_decrease -= ws2.size(); for(const Watched w: ws2) { if (w.isTri() && !w.red() && (seen[w.lit2().toInt()] || (solver->conf.doStamp && solver->conf.otfHyperbin && solver->find_with_stamp_a_or_b(~w.lit2(), lit))) && (seen[w.lit3().toInt()] || (solver->conf.doStamp && solver->conf.otfHyperbin && solver->find_with_stamp_a_or_b(~w.lit3(), lit))) ) { add_gate_if_not_already_inside(lit, w.lit2(), w.lit3()); } } *simplifier->limit_to_decrease -= toClear.size(); for(const Lit toclear: toClear) { seen[toclear.toInt()] = 0; } toClear.clear(); }
void PropEngine::attach_bin_clause( const Lit lit1 , const Lit lit2 , const bool red , const bool checkUnassignedFirst ) { #ifdef DEBUG_ATTACH assert(lit1.var() != lit2.var()); if (checkUnassignedFirst) { assert(value(lit1.var()) == l_Undef); assert(value(lit2) == l_Undef || value(lit2) == l_False); } assert(varData[lit1.var()].removed == Removed::none); assert(varData[lit2.var()].removed == Removed::none); #endif //DEBUG_ATTACH watches[lit1.toInt()].push(Watched(lit2, red)); watches[lit2.toInt()].push(Watched(lit1, red)); }
bool UselessBinRemover::removeUselessBinaries(const Lit& lit) { solver.newDecisionLevel(); solver.uncheckedEnqueueLight(lit); failed = !onlyNonLearntBins.propagateBinOneLevel(); if (failed) return false; bool ret = true; oneHopAway.clear(); assert(solver.decisionLevel() > 0); int c; if (solver.trail.size()-solver.trail_lim[0] == 0) { solver.cancelUntil(0); goto end; } 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]; toDeleteSet[x.toInt()] = true; oneHopAway.push(x); 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); wrong.clear(); for(uint32_t i = 0; i < oneHopAway.size(); i++) { //no need to visit it if it already queued for removal //basically, we check if it's in 'wrong' if (toDeleteSet[oneHopAway[i].toInt()]) { if (!fillBinImpliesMinusLast(lit, oneHopAway[i], wrong)) { ret = false; goto end; } } } for (uint32_t i = 0; i < wrong.size(); i++) { removeBin(~lit, wrong[i]); } end: for(uint32_t i = 0; i < oneHopAway.size(); i++) { toDeleteSet[oneHopAway[i].toInt()] = false; } return ret; }
void RestartTypeChooser::addDegreesBin(vector<uint32_t>& degrees) const { 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() && lit.toInt() < it2->getOtherLit().toInt()) { degrees[lit.var()]++; degrees[it2->getOtherLit().var()]++; } } } }
void VarReplacer::updateBin( watch_subarray::iterator& i , watch_subarray::iterator& j , const Lit origLit1 , const Lit origLit2 , Lit lit1 , Lit lit2 ) { bool remove = false; //Two lits are the same in BIN if (lit1 == lit2) { delayedEnqueue.push_back(lit2); (*solver->drup) << lit2 << fin; remove = true; } //Tautology if (lit1 == ~lit2) remove = true; if (remove) { impl_tmp_stats.remove(*i); //Drup -- Delete only once if (origLit1 < origLit2) { (*solver->drup) << del << origLit1 << origLit2 << fin; } return; } //Drup if (//Changed (lit1 != origLit1 || lit2 != origLit2) //Delete&attach only once && (origLit1 < origLit2) ) { (*solver->drup) << lit1 << lit2 << fin << del << origLit1 << origLit2 << fin; } if (lit1 != origLit1) { solver->watches[lit1.toInt()].push(*i); } else { *j++ = *i; } }
void PropEngine::attach_tri_clause( Lit lit1 , Lit lit2 , Lit lit3 , const bool red ) { #ifdef DEBUG_ATTACH assert(lit1.var() != lit2.var()); assert(value(lit1.var()) == l_Undef); assert(value(lit2) == l_Undef || value(lit2) == l_False); assert(varData[lit1.var()].removed == Removed::none); assert(varData[lit2.var()].removed == Removed::none); #endif //DEBUG_ATTACH //Order them orderLits(lit1, lit2, lit3); //And now they are attached, ordered watches[lit1.toInt()].push(Watched(lit2, lit3, red)); watches[lit2.toInt()].push(Watched(lit1, lit3, red)); watches[lit3.toInt()].push(Watched(lit1, lit2, red)); }
bool GateFinder::check_seen_and_gate_against_lit( const Lit lit , const OrGate& gate ) { //If some weird variable is inside, skip if ( lit.var() == gate.lit2.var() || lit.var() == gate.rhs.var() //A lit is inside this clause isn't inside the others || !seen2[lit.toInt()] ) { return false; } return true; }
size_t BVA::calc_watch_irred_size(const Lit lit) const { size_t num = 0; watch_subarray_const ws = solver->watches[lit.toInt()]; for(const Watched w: ws) { if (w.isBinary() || w.isTri()) { num += !w.red(); continue; } assert(w.isClause()); const Clause& cl = *solver->cl_alloc.ptr(w.get_offset()); num += !cl.red(); } return num; }
/** @brief Propagate recursively on non-learnt binaries */ bool OnlyNonLearntBins::propagate() { while (solver.qhead < solver.trail.size()) { Lit p = solver.trail[solver.qhead++]; vec<WatchedBin> & wbin = binwatches[p.toInt()]; solver.propagations += wbin.size()/2 + 2; for(WatchedBin *k = wbin.getData(), *end = wbin.getDataEnd(); k != end; k++) { lbool val = solver.value(k->impliedLit); if (val.isUndef()) { solver.uncheckedEnqueueLight(k->impliedLit); } else if (val == l_False) { return false; } } } return true; }
void PropEngine::printWatchList(const Lit lit) const { watch_subarray_const ws = watches[lit.toInt()]; for (watch_subarray_const::const_iterator it2 = ws.begin(), end2 = ws.end() ; it2 != end2 ; it2++ ) { if (it2->isBinary()) { cout << "bin: " << lit << " , " << it2->lit2() << " red : " << (it2->red()) << endl; } else if (it2->isTri()) { cout << "tri: " << lit << " , " << it2->lit2() << " , " << (it2->lit3()) << endl; } else if (it2->isClause()) { cout << "cla:" << it2->get_offset() << endl; } else { assert(false); } } }
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; }
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(watch_subarray::const_iterator 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; }