void SAT::reduceDB() { int i, j; std::sort((Clause**) learnts, (Clause**) learnts + learnts.size(), activity_lt()); double minAct = learnts[0]->activity(); for(i = 0 ; i < receiveds.size() ; i++){ if(receiveds[i]->received && receiveds[i]->age != 0){ receiveds[i]->age--; } } for (i = j = 0; i < learnts.size()/2; i++) { if (!locked(*learnts[i])) removeClause(*learnts[i]); else learnts[j++] = learnts[i]; } for (; i < learnts.size(); i++) { learnts[j++] = learnts[i]; } learnts.resize(j); int nbLearntsRemoved = i-j; for(i = j = 0 ; i < receiveds.size() ; i++){ if(receiveds[i]->activity() <= minAct && !locked(*receiveds[i]) && receiveds[j]->age == 0){ removeClause(*receiveds[i]); } else receiveds[j++]=receiveds[i]; } receiveds.resize(j); if (so.verbosity >= 1) { fprintf(stderr, "Pruned %d learnt and %d received clauses\n", nbLearntsRemoved, i-j); fprintf(stderr, "Slave %d, received.size()=%d\n", so.thread_no, receiveds.size()); } }
void SAT::simplifyDB() { int i, j; for (i = j = 0; i < learnts.size(); i++) { if (simplify(*learnts[i])) removeClause(*learnts[i]); else learnts[j++] = learnts[i]; } learnts.resize(j); for (i = j = 0; i < receiveds.size(); i++) { if (simplify(*receiveds[i])) removeClause(*receiveds[i]); else receiveds[j++] = receiveds[i]; } receiveds.resize(j); next_simp_db = propagations + clauses_literals + learnts_literals; }
// Backward subsumption + backward subsumption resolution bool SimpSolver::backwardSubsumptionCheck(bool verbose) { int cnt = 0; int subsumed = 0; int deleted_literals = 0; assert(decisionLevel() == 0); while (subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()){ // Check top-level assignments by creating a dummy clause and placing it in the queue: if (subsumption_queue.size() == 0 && bwdsub_assigns < trail.size()){ Lit l = trail[bwdsub_assigns++]; (*bwdsub_tmpunit)[0] = l; bwdsub_tmpunit->calcAbstraction(); assert(bwdsub_tmpunit->mark() == 0); subsumption_queue.insert(bwdsub_tmpunit); } Clause& c = *subsumption_queue.peek(); subsumption_queue.pop(); if (c.mark()) continue; if (verbose && verbosity >= 2 && cnt++ % 1000 == 0) reportf("subsumption left: %10d (%10d subsumed, %10d deleted literals)\r", subsumption_queue.size(), subsumed, deleted_literals); assert(c.size() > 1 || value(c[0]) == l_True); // Unit-clauses should have been propagated before this point. // Find best variable to scan: Var best = var(c[0]); for (int i = 1; i < c.size(); i++) if (occurs[var(c[i])].size() < occurs[best].size()) best = var(c[i]); // Search all candidates: vec<Clause*>& _cs = getOccurs(best); Clause** cs = (Clause**)_cs; for (int j = 0; j < _cs.size(); j++) if (c.mark()) break; else if (!cs[j]->mark() && cs[j] != &c){ Lit l = c.subsumes(*cs[j]); if (l == lit_Undef) subsumed++, removeClause(*cs[j]); else if (l != lit_Error){ deleted_literals++; if (!strengthenClause(*cs[j], ~l)) return false; // Did current candidate get deleted from cs? Then check candidate at index j again: if (var(l) == best) j--; } } } return true; }
bool SimpSMTSolver::eliminateVar(Var v, bool fail) { if (!fail && asymm_mode && !asymmVar(v)) return false; const vec<Clause*>& cls = getOccurs(v); // if (value(v) != l_Undef || cls.size() == 0) return true; if (value(v) != l_Undef) return true; // Split the occurrences into positive and negative: vec<Clause*> pos, neg; for (int i = 0; i < cls.size(); i++) (find(*cls[i], Lit(v)) ? pos : neg).push(cls[i]); // Check if number of clauses decreases: int cnt = 0; for (int i = 0; i < pos.size(); i++) for (int j = 0; j < neg.size(); j++) if (merge(*pos[i], *neg[j], v) && ++cnt > cls.size() + grow) return true; #ifdef PEDANTIC_DEBUG cerr << "XXY gonna-remove" << endl; #endif // Delete and store old clauses: setDecisionVar(v, false); elimtable[v].order = elimorder++; assert(elimtable[v].eliminated.size() == 0); for (int i = 0; i < cls.size(); i++) { elimtable[v].eliminated.push(Clause_new(*cls[i])); removeClause(*cls[i]); } // Produce clauses in cross product: int top = clauses.size(); vec<Lit> resolvent; for (int i = 0; i < pos.size(); i++) for (int j = 0; j < neg.size(); j++) if (merge(*pos[i], *neg[j], v, resolvent) && !addClause(resolvent)) return false; // DEBUG: For checking that a clause set is saturated with respect to variable elimination. // If the clause set is expected to be saturated at this point, this constitutes an // error. if (fail){ reportf("eliminated var %d, %d <= %d\n", v+1, cnt, cls.size()); reportf("previous clauses:\n"); for (int i = 0; i < cls.size(); i++){ printClause(*cls[i]); reportf("\n"); } reportf("new clauses:\n"); for (int i = top; i < clauses.size(); i++){ printClause(*clauses[i]); reportf("\n"); } assert(0); } return backwardSubsumptionCheck(); }
void Solver::removeSatisfied(vec<Clause*>& cs) { int i,j; for (i = j = 0; i < cs.size(); i++){ if (satisfied(*cs[i])) removeClause(*cs[i]); else cs[j++] = cs[i]; } cs.shrink(i - j); }
void Solver::reduceDB() { int i, j; double extra_lim = cla_inc / learnts.size(); // Remove any clause below this activity sort(learnts, reduceDB_lt()); for (i = j = 0; i < learnts.size() / 2; i++){ if (learnts[i]->size() > 2 && !locked(*learnts[i])) removeClause(*learnts[i]); else learnts[j++] = learnts[i]; } for (; i < learnts.size(); i++){ if (learnts[i]->size() > 2 && !locked(*learnts[i]) && learnts[i]->activity() < extra_lim) removeClause(*learnts[i]); else learnts[j++] = learnts[i]; } learnts.shrink(i - j); }
void SAT::reduceDB() { int i, j; std::sort((Clause**) learnts, (Clause**) learnts + learnts.size(), activity_lt()); for (i = j = 0; i < learnts.size()/2; i++) { if (!locked(*learnts[i])) removeClause(*learnts[i]); else learnts[j++] = learnts[i]; } for (; i < learnts.size(); i++) { learnts[j++] = learnts[i]; } learnts.resize(j); if (so.verbosity >= 1) printf("Pruned %d learnt clauses\n", i-j); }
bool SimpSolver::strengthenClause(Clause& c, Lit l) { assert(decisionLevel() == 0); assert(c.mark() == 0); assert(!c.learnt()); assert(find(watches[toInt(~c[0])], &c)); assert(find(watches[toInt(~c[1])], &c)); // FIX: this is too inefficient but would be nice to have (properly implemented) // if (!find(subsumption_queue, &c)) subsumption_queue.insert(&c); // If l is watched, delete it from watcher list and watch a new literal if (c[0] == l || c[1] == l){ Lit other = c[0] == l ? c[1] : c[0]; if (c.size() == 2){ removeClause(c); c.strengthen(l); }else{ c.strengthen(l); remove(watches[toInt(~l)], &c); // Add a watch for the correct literal watches[toInt(~(c[1] == other ? c[0] : c[1]))].push(&c); // !! this version assumes that remove does not change the order !! //watches[toInt(~c[1])].push(&c); clauses_literals -= 1; } } else{ c.strengthen(l); clauses_literals -= 1; } // if subsumption-indexing is active perform the necessary updates if (use_simplification){ remove(occurs[var(l)], &c); n_occ[toInt(l)]--; updateElimHeap(var(l)); } return c.size() == 1 ? enqueue(c[0]) && propagate() == NULL : true; }
void Solver::reduceDB() { int i, j; nbReduceDB++; sort(learnts, reduceDB_lt()); for (i = j = 0; i < learnts.size() / RATIOREMOVECLAUSES; i++){ if (learnts[i]->size() > 2 && !locked(*learnts[i]) && learnts[i]->activity()>2){ removeClause(*learnts[i]); } else learnts[j++] = learnts[i]; } for (; i < learnts.size(); i++){ learnts[j++] = learnts[i]; } learnts.shrink(i - j); nof_learnts *= learntsize_inc; }
/* ----------- formula preprocessing --------------- */ void formule::preprocessing() { //la détection des clauses unitaires se fait via la function assignUniqueLitt() de deduce.cpp //élimination des doublons (vivants) et des clauses tautologiques (non satisfaites) vector<pair<int,int> > variables (v_var.size(), std::make_pair(0,0)); //vector contenant pour chaque variable une paire (nb_fois_vue_niée,nb_fois_vue_non_niée) bool isTauto; bool li_need_back; litt* li_prev; clause* cl_prev = nullptr; bool cl_need_back = false; for (clause* cl=this->f_ClauseUnsatisfied;cl != nullptr || cl_need_back;cl=cl->next_clause) { if (cl_need_back){ cl=cl_prev; cl_prev=nullptr; cl_need_back = false; } li_need_back = false; li_prev = nullptr; for (litt* li = cl->f_ElementAlive;li != nullptr || li_need_back;li = li->next_litt) { if (li_need_back){ li=li_prev; li_prev=nullptr; li_need_back = false; } if (li->neg){ if (variables[li->variable->id].first > 0){//si on a un doublon dans la clause, on l'élimine removeLitt(&cl->f_ElementAlive,&cl->l_ElementAlive,li,li_prev); delete li; if (li_prev != nullptr) li = li_prev;//On évite de casser la chaîne de parcours de la boucle for... else if (cl->f_ElementAlive != nullptr){ li = cl->f_ElementAlive; li_need_back = true; } else//there is nothing left break; } else { variables[li->variable->id].first++; } } else { if (variables[li->variable->id].second > 0){//si on a un doublon dans la clause, on l'élimine removeLitt(&cl->f_ElementAlive,&cl->l_ElementAlive,li,li_prev); delete li; if (li_prev != nullptr) li = li_prev;//On évite de casser la chaîne de parcours de la boucle for... else if (cl->f_ElementAlive != nullptr){ li = cl->f_ElementAlive; li_need_back = true; } else//there is nothing left break; } else { variables[li->variable->id].second++; } } li_prev = li; } isTauto = false; for (auto& v:variables){ if (v.first != 0 and v.second != 0){//la clause est tautologique isTauto = true; } v.first = 0; v.second = 0; } if (isTauto) { removeClause(&this->f_ClauseUnsatisfied,&this->l_ClauseUnsatisfied,cl,cl_prev); for (litt* li = cl->f_ElementAlive;li != nullptr;li = li->next_litt){//supprimer la clause cl des clauseInto li->variable->clauseInto.erase(std::remove(li->variable->clauseInto.begin(), li->variable->clauseInto.end(), cl), li->variable->clauseInto.end()); } cl->free_clause(); if (cl_prev != nullptr) cl = cl_prev;//On évite de casser la chaîne de parcours de la boucle for... else if (this->f_ClauseUnsatisfied != nullptr){ cl = this->f_ClauseUnsatisfied; cl_need_back = true; } else//there is nothing left break; } cl_prev = cl; } //supprimer les doublons de clauseInto for (auto& v:v_var){ if (v != nullptr){ sort(v->clauseInto.begin(), v->clauseInto.end()); v->clauseInto.erase(std::unique(v->clauseInto.begin(), v->clauseInto.end()), v->clauseInto.end()); } } }
void MiniSATP::popBacktrackPoint ( ) { // // Force restart, but retain assumptions // cancelUntil(0); // // Shrink back trail // int new_trail_size = undo_trail_size.back( ); undo_trail_size.pop_back( ); for ( int i = trail.size( ) - 1 ; i >= new_trail_size ; i -- ) { Var x = var(trail[i]); assigns[x] = toInt(l_Undef); reason [x] = NULL; insertVarOrder(x); } trail.shrink(trail.size( ) - new_trail_size); assert( trail_lim.size( ) == 0 ); qhead = trail.size( ); // // Undo operations // size_t new_stack_size = undo_stack_size.back( ); undo_stack_size.pop_back( ); while ( undo_stack_oper.size( ) > new_stack_size ) { const oper_t op = undo_stack_oper.back( ); if ( op == NEWVAR ) { #ifdef BUILD_64 long xl = reinterpret_cast< long >( undo_stack_elem.back( ) ); const Var x = static_cast< Var >( xl ); #else const Var x = reinterpret_cast< int >( undo_stack_elem.back( ) ); #endif // Undoes insertVarOrder( ) assert( order_heap.inHeap(x) ); order_heap .remove(x); // Undoes decision_var ... watches decision_var.pop(); polarity .pop(); seen .pop(); activity .pop(); level .pop(); assigns .pop(); reason .pop(); watches .pop(); watches .pop(); } else if ( op == NEWUNIT ) { } else if ( op == NEWCLAUSE ) { Clause * c = (Clause *)undo_stack_elem.back( ); assert( clauses.last( ) == c ); // assert( c->id + 1 == (int)clause_id_to_enode.size( ) ); clauses.pop( ); removeClause( *c ); // clause_id_to_enode.pop_back( ); } else { opensmt_error2( "unknown undo operation in BitBlaster", op ); } undo_stack_oper.pop_back( ); undo_stack_elem.pop_back( ); } while( learnts.size( ) > 0 ) { Clause * c = learnts.last( ); learnts.pop( ); removeClause( *c ); } while( removed.size( ) > 0 ) { Clause * c = removed.last( ); removed.pop( ); free( c ); } assert( undo_stack_elem.size( ) == undo_stack_oper.size( ) ); assert( learnts.size( ) == 0 ); assert( removed.size( ) == 0 ); }