bool SimpSMTSolver::asymm(Var v, Clause& c) { assert(decisionLevel() == 0); if (c.mark() || satisfied(c)) return true; trail_lim.push(trail.size()); Lit l = lit_Undef; for (int i = 0; i < c.size(); i++) if (var(c[i]) != v && value(c[i]) != l_False) { uncheckedEnqueue(~c[i]); } else l = c[i]; if (propagate() != NULL){ cancelUntil(0); asymm_lits++; if (!strengthenClause(c, l)) return false; }else cancelUntil(0); return true; }
bool SimpSolver::implied(const vec<Lit>& c) { assert(decisionLevel() == 0); trail_lim.push(trail.size()); for (int i = 0; i < c.size(); i++) if (value(c[i]) == l_True){ cancelUntil(0); return false; }else if (value(c[i]) != l_False){ assert(value(c[i]) == l_Undef); uncheckedEnqueue(~c[i]); } bool result = propagate() != NULL; cancelUntil(0); return result; }
bool Solver::solve(const vec<Lit>& assumps) { model.clear(); conflict.clear(); allMinVarsAssigned = false; if (!ok) return false; assumps.copyTo(assumptions); double nof_conflicts = restart_first; double nof_learnts = nClauses() * learntsize_factor; lbool status = l_Undef; if (verbosity >= 1){ reportf("============================[ Search Statistics ]==============================\n"); reportf("| Conflicts | ORIGINAL | LEARNT | Progress |\n"); reportf("| | Vars Clauses Literals | Limit Clauses Lit/Cl | |\n"); reportf("===============================================================================\n"); } // Search: while (status == l_Undef){ if (verbosity >= 1) reportf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n", (int)conflicts, order_heap.size(), nClauses(), (int)clauses_literals, (int)nof_learnts, nLearnts(), (double)learnts_literals/nLearnts(), progress_estimate*100), fflush(stdout); status = search((int)nof_conflicts, (int)nof_learnts); nof_conflicts *= restart_inc; nof_learnts *= learntsize_inc; } if (verbosity >= 1) reportf("===============================================================================\n"); if (status == l_True){ // Extend & copy model: model.growTo(nVars()); for (int i = 0; i < nVars(); i++) model[i] = value(i); #ifndef NDEBUG verifyModel(); #endif }else{ assert(status == l_False); if (conflict.size() == 0) ok = false; } cancelUntil(0); return status == l_True; }
//bool Solver::solve(const vec<Lit>& assumps) bool Solver::solve() { simplifyDB(); if (!ok) return false; SearchParams params(0.95, 0.999, 0.02); double nof_conflicts = 100; double nof_learnts = nConstrs() / 3; lbool status = l_Undef; // for (int i = 0; i < assumps.size(); i++) // if (!assume(assumps[i]) || propagate() != NULL){ // propQ.clear(); // cancelUntil(0); // return false; } root_level = decisionLevel; if (verbosity >= 1){ printf("==================================[MINISAT]===================================\n"); printf("| Conflicts | ORIGINAL | LEARNT | Progress |\n"); printf("| | Clauses Literals | Limit Clauses Literals Lit/Cl | |\n"); printf("==============================================================================\n"); } while (status == l_Undef){ if (verbosity >= 1){ printf("| %9d | %7d %8d | %7d %7d %8d %7.1f | %6.3f %% |\n", (int)stats.conflicts, nConstrs(), (int)stats.clauses_literals, (int)nof_learnts, nLearnts(), (int)stats.learnts_literals, (double)stats.learnts_literals/nLearnts(), progress_estimate*100); fflush(stdout); } status = search((int)nof_conflicts, (int)nof_learnts, params); nof_conflicts *= 1.5; nof_learnts *= 1.1; } if (verbosity >= 1) printf("==============================================================================\n"); cancelUntil(0); return status == l_True; }
/*_________________________________________________________________________________________________ | | search : (nof_conflicts : int) (nof_learnts : int) (params : const SearchParams&) -> [lbool] | | Description: | Search for a model the specified number of conflicts, keeping the number of learnt clauses | below the provided limit. NOTE! Use negative value for 'nof_conflicts' or 'nof_learnts' to | indicate infinity. | | Output: | 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If | all variables are decision variables, this means that the clause set is satisfiable. 'l_False' | if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached. |________________________________________________________________________________________________@*/ lbool Solver::search(int nof_conflicts, int nof_learnts, const SearchParams& params) { if (!ok) return l_False; // GUARD (public method) assert(root_level == decisionLevel); stats.starts++; int conflictC = 0; var_decay = 1 / params.var_decay; cla_decay = 1 / params.clause_decay; model.clear(); for (;;){ Constr* confl = propagate(); if (confl != NULL){ // CONFLICT //if (verbosity >= 2) printf(L_IND"**CONFLICT**\n", L_ind); stats.conflicts++; conflictC++; vec<Lit> learnt_clause; int backtrack_level; if (decisionLevel == root_level) { if (doDeriv) { analyzeFinalDeriv(confl); } return l_False; } Deriv* deriv = new Deriv(); derivs.push_back(deriv); analyze(confl, learnt_clause, backtrack_level, deriv); cancelUntil(max(backtrack_level, root_level)); record(learnt_clause, deriv); varDecayActivity(); claDecayActivity(); }else{ // NO CONFLICT if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ // Reached bound on number of conflicts: progress_estimate = progressEstimate(); propQ.clear(); cancelUntil(root_level); return l_Undef; } if (decisionLevel == 0) // Simplify the set of problem clauses: simplifyDB(), assert(ok); if (nof_learnts >= 0 && learnts.size()-nAssigns() >= nof_learnts) // Reduce the set of learnt clauses: reduceDB(); // New variable decision: stats.decisions++; Var next = order.select(params.random_var_freq); if (next == var_Undef){ // Model found: model.growTo(nVars); for (int i = 0; i < nVars; i++) model[i] = (value(i) == l_True); cancelUntil(root_level); return l_True; } // VERY important for the Y-variables to try positive polarity first // - follows the value ordering heuristic of aiming for solutions (as opposed to fail-first var order) check(assume(Lit(next))); //check(assume(~Lit(next))); } } }
/*_________________________________________________________________________________________________ | | search : (nof_conflicts : int) (nof_learnts : int) (params : const SearchParams&) -> [lbool] | | Description: | Search for a model the specified number of conflicts, keeping the number of learnt clauses | below the provided limit. NOTE! Use negative value for 'nof_conflicts' or 'nof_learnts' to | indicate infinity. | | Output: | 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If | all variables are decision variables, this means that the clause set is satisfiable. 'l_False' | if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached. |________________________________________________________________________________________________@*/ lbool Solver::search(int nof_conflicts, int nof_learnts) { assert(ok); int backtrack_level; int conflictC = 0; vec<Lit> learnt_clause; starts++; for (;;){ #ifdef _DEBUGSEARCH for(int k=0; k<decisionLevel(); ++k) std::cout << " "; std::cout << "propagate" << std::endl; #endif Clause* confl = propagate(); if (confl != NULL){ // CONFLICT conflicts++; conflictC++; if (decisionLevel() <= init_level) { #ifdef _DEBUGSEARCH std::cout << "infeasible" << std::endl; #endif return l_False; } learnt_clause.clear(); analyze(confl, learnt_clause, backtrack_level); cancelUntil(backtrack_level); #ifdef _DEBUGSEARCH for(int k=0; k<decisionLevel(); ++k) std::cout << " "; std::cout << "backtrack to " << decisionLevel() << std::endl; #endif assert(value(learnt_clause[0]) == l_Undef); if (learnt_clause.size() == 1){ uncheckedEnqueue(learnt_clause[0]); #ifdef _DEBUGSEARCH for(int k=0; k<decisionLevel(); ++k) std::cout << " "; std::cout << "deduce " ; printLit(learnt_clause[0]); std::cout << std::endl; #endif }else{ Clause* c = Clause_new(learnt_clause, true); #ifdef _DEBUGSEARCH for(int k=0; k<decisionLevel(); ++k) std::cout << " "; std::cout << "deduce "; printClause(*c); std::cout << std::endl; #endif learnts.push(c); attachClause(*c); claBumpActivity(*c); uncheckedEnqueue(learnt_clause[0], c); } varDecayActivity(); claDecayActivity(); }else{ // NO CONFLICT if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ // Reached bound on number of conflicts: progress_estimate = progressEstimate(); cancelUntil(0); return l_Undef; } // Simplify the set of problem clauses: if (decisionLevel() == 0 && !simplify()) return l_False; if (nof_learnts >= 0 && learnts.size()-nAssigns() >= nof_learnts) // Reduce the set of learnt clauses: reduceDB(); Lit next = lit_Undef; while (decisionLevel() < assumptions.size()){ // Perform user provided assumption: Lit p = assumptions[decisionLevel()]; if (value(p) == l_True){ // Dummy decision level: newDecisionLevel(); }else if (value(p) == l_False){ analyzeFinal(~p, conflict); return l_False; }else{ next = p; break; } } if (next == lit_Undef){ // New variable decision: decisions++; next = pickBranchLit(polarity_mode, random_var_freq); if (next == lit_Undef) // Model found: return l_True; } #ifdef _DEBUGSEARCH for(int k=0; k<decisionLevel(); ++k) std::cout << " "; std::cout << "branch on " ; printLit(next); std::cout << std::endl; #endif // Increase decision level and enqueue 'next' assert(value(next) == l_Undef); newDecisionLevel(); uncheckedEnqueue(next); } } }
bool Solver::solve(const vec<Lit>& assumps) { model.clear(); conflict.clear(); nbDecisionLevelHistory.initSize(100); totalSumOfDecisionLevel = 0; if (!ok) return false; assumps.copyTo(assumptions); double nof_conflicts = restart_first; nof_learnts = nClauses() * learntsize_factor; if(nof_learnts <nbclausesbeforereduce) { nbclausesbeforereduce = (nof_learnts/2 < 5000) ? 5000 : nof_learnts/2; } lbool status = l_Undef; if (verbosity >= 1){ reportf("============================[ Search Statistics ]==============================\n"); reportf("| Conflicts | ORIGINAL | LEARNT | Progress |\n"); reportf("| | Vars Clauses Literals | Limit Clauses Lit/Cl | |\n"); reportf("===============================================================================\n"); } // Search: while (status == l_Undef){ if (verbosity >= 1) reportf("| %9d | %7d %8d %8d | %8d %8d %6.0f | %6.3f %% |\n", (int)conflicts, order_heap.size(), nClauses(), (int)clauses_literals, (int)nof_learnts, nLearnts(), (double)learnts_literals/nLearnts(), progress_estimate*100), fflush(stdout); status = search((int)nof_conflicts, (int)nof_learnts); nof_conflicts *= restart_inc; //LS mis dans reduceDB lui meme nof_learnts *= learntsize_inc; } if (verbosity >= 1) reportf("===============================================================================\n"); if (status == l_True){ // Extend & copy model: model.growTo(nVars()); for (int i = 0; i < nVars(); i++) model[i] = value(i); #ifndef NDEBUG verifyModel(); #endif }else{ assert(status == l_False); if (conflict.size() == 0) ok = false; } #ifdef LS_STATS_NBBUMP for(int i=0;i<learnts.size();i++) printf("## %d %d %d\n",learnts[i]->size(),learnts[i]->activity(),(unsigned int)learnts[i]->nbBump()); #endif cancelUntil(0); return status == l_True; }
lbool Solver::search(int nof_conflicts, int nof_learnts) { assert(ok); int backtrack_level; int conflictsC = 0; vec<Lit> learnt_clause; int nblevels=0,nbCC=0,merged=0; starts++; bool first = true; for (;;){ Clause* confl = propagate(); //Conflict at a later stage. if (backup.running && confl != NULL && backup.stage == 1 ) { #ifdef RESTORE_FULL printf("Somebody else (maybe bin clause) did the conflict -- stage is one, going 2\n"); #endif fullCancelUntil(backup.level, backup.sublevel); backup.stage = 2; continue; } if (confl != NULL){ assert(backup.stage == 0); // CONFLICT conflicts++; conflictsC++;cons++;nbCC++; if (decisionLevel() == 0) return l_False; first = false; learnt_clause.clear(); analyze(confl, learnt_clause, backtrack_level,nblevels,merged); conf4Stats++; nbDecisionLevelHistory.push(nblevels); totalSumOfDecisionLevel += nblevels; cancelUntil(backtrack_level); assert(value(learnt_clause[0]) == l_Undef); if (learnt_clause.size() == 1){ assert(decisionLevel() == 0); uncheckedEnqueue(learnt_clause[0]); nbUn++; }else{ Clause* c = Clause_new(learnt_clause, clIndex++, conflicts, true); dumpFile << "INSERT INTO clausedata(runID, idx, timeofcreation, size) VALUES(" << runID << "," << c->getIndex() << "," << c->getTimeOfCreation() << "," << c->size() << ");" << std::endl; learnts.push(c); c->setActivity(nblevels); // LS if(nblevels<=2) nbDL2++; if(c->size()==2) nbBin++; attachClause(*c); uncheckedEnqueue(learnt_clause[0], c); if (backup.running && backup.stage == 0 ) { saveState(); #ifdef RESTORE printf("Saving state after conflict at dec level: %d, sublevel: %d\n", decisionLevel(), trail.size()); #endif } } varDecayActivity(); }else{ if (backup.stage == 0 && nbDecisionLevelHistory.isvalid() && ((nbDecisionLevelHistory.getavg()*0.7) > (totalSumOfDecisionLevel / conf4Stats)) ) { nbDecisionLevelHistory.fastclear(); progress_estimate = progressEstimate(); cancelUntil(0); return l_Undef; } // Simplify the set of problem clauses: if (backup.stage == 0 && decisionLevel() == 0 && !simplify() ) { return l_False; } Lit next = lit_Undef; if (backup.stage == 0 && ((cons-curRestart * nbclausesbeforereduce) >=0) ) { curRestart = (conflicts/ nbclausesbeforereduce)+1; reduceDB(); nbclausesbeforereduce += 500; } if (next == lit_Undef){ // New variable decision: decisions++; next = pickBranchLit(polarity_mode, random_var_freq); if (next == lit_Undef) // Model found: return l_True; } // Increase decision level and enqueue 'next' assert(value(next) == l_Undef); newDecisionLevel(); uncheckedEnqueue(next); if (backup.running && backup.stage == 0 ) { saveState(); #ifdef RESTORE printf("Saving state after pickbranch at dec level: %d, sublevel: %d\n", decisionLevel(), trail.size()); printf("sublevel: %d, level: %d, qhead:%d\n", trail.size(), decisionLevel(), qhead); #endif } } } }
/*_________________________________________________________________________________________________ | | search : (nof_conflicts : int) (nof_learnts : int) (params : const SearchParams&) -> [lbool] | | Description: | Search for a model the specified number of conflicts, keeping the number of learnt clauses | below the provided limit. NOTE! Use negative value for 'nof_conflicts' or 'nof_learnts' to | indicate infinity. | | Output: | 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If | all variables are decision variables, this means that the clause set is satisfiable. 'l_False' | if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached. |________________________________________________________________________________________________@*/ lbool MiniSATP::search(int nof_conflicts, int nof_learnts) { assert(ok); int backtrack_level; int conflictC = 0; vec<Lit> learnt_clause; starts++; bool first = true; for (;;){ Clause* confl = propagate(); if (confl != NULL){ // CONFLICT conflicts++; conflictC++; if (decisionLevel() == 0) { // Added Lines fillExplanation(confl); return l_False; } first = false; learnt_clause.clear(); analyze(confl, learnt_clause, backtrack_level); cancelUntil(backtrack_level); assert(value(learnt_clause[0]) == l_Undef); if (learnt_clause.size() == 1){ uncheckedEnqueue(learnt_clause[0]); }else{ Clause* c = Clause_new(learnt_clause, true); learnts.push(c); attachClause(*c); claBumpActivity(*c); uncheckedEnqueue(learnt_clause[0], c); } varDecayActivity(); claDecayActivity(); }else{ // NO CONFLICT if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ // Reached bound on number of conflicts: progress_estimate = progressEstimate(); cancelUntil(0); return l_Undef; } // Simplify the set of problem clauses: if (decisionLevel() == 0 && !simplify()) { return l_False; } if (nof_learnts >= 0 && learnts.size()-nAssigns() >= nof_learnts) // Reduce the set of learnt clauses: reduceDB(); Lit next = lit_Undef; while (decisionLevel() < assumptions.size()){ // Perform user provided assumption: Lit p = assumptions[decisionLevel()]; if (value(p) == l_True){ // Dummy decision level: newDecisionLevel(); }else if (value(p) == l_False){ analyzeFinal(~p, conflict); return l_False; }else{ next = p; break; } } if (next == lit_Undef){ // New variable decision: decisions++; next = pickBranchLit(polarity_mode, random_var_freq); if (next == lit_Undef) { // Added Line // Clear explanation vector if satisfiable explanation.clear( ); // Model found: return l_True; } } // Increase decision level and enqueue 'next' assert(value(next) == l_Undef); newDecisionLevel(); uncheckedEnqueue(next); } } }
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 ); }
lbool Solver::search(int nof_conflicts, int nof_learnts) { assert(ok); int backtrack_level; int conflictsC = 0; vec<Lit> learnt_clause; int nblevels=0,nbCC=0,merged=0; starts++; bool first = true; for (;;){ Clause* confl = propagate(); if (confl != NULL){ // CONFLICT conflicts++; conflictsC++;cons++;nbCC++; if (decisionLevel() == 0) return l_False; first = false; learnt_clause.clear(); analyze(confl, learnt_clause, backtrack_level,nblevels,merged); conf4Stats++; nbDecisionLevelHistory.push(nblevels); totalSumOfDecisionLevel += nblevels; cancelUntil(backtrack_level); assert(value(learnt_clause[0]) == l_Undef); if (learnt_clause.size() == 1){ uncheckedEnqueue(learnt_clause[0]); nbUn++; }else{ Clause* c = Clause_new(learnt_clause, true); learnts.push(c); c->setActivity(nblevels); // LS if(nblevels<=2) nbDL2++; if(c->size()==2) nbBin++; attachClause(*c); claBumpActivity(*c); uncheckedEnqueue(learnt_clause[0], c); } varDecayActivity(); claDecayActivity(); }else{ if ( ( nbDecisionLevelHistory.isvalid() && ((nbDecisionLevelHistory.getavg()*0.7) > (totalSumOfDecisionLevel / conf4Stats)))) { nbDecisionLevelHistory.fastclear(); progress_estimate = progressEstimate(); cancelUntil(0); return l_Undef; } // Simplify the set of problem clauses: if (decisionLevel() == 0 && !simplify()) return l_False; // Lit next = lit_Undef; if(cons-curRestart* nbclausesbeforereduce>=0) { curRestart = (conflicts/ nbclausesbeforereduce)+1; reduceDB(); nbclausesbeforereduce += 500; } if (next == lit_Undef){ // New variable decision: decisions++; next = pickBranchLit(polarity_mode, random_var_freq); if (next == lit_Undef) // Model found: return l_True; } // Increase decision level and enqueue 'next' assert(value(next) == l_Undef); newDecisionLevel(); uncheckedEnqueue(next); } } }
/*_________________________________________________________________________________________________ | | solve : (assumps : const vec<Lit>&) -> [bool] | | Description: | Top-level solve. If using assumptions (non-empty 'assumps' vector), you must call | 'simplifyDB()' first to see that no top-level conflict is present (which would put the solver | in an undefined state). |________________________________________________________________________________________________@*/ bool Solver::solve(const vec<Lit>& assumps) { simplifyDB(); if (!ok) return false; SearchParams params(default_params); double nof_conflicts = 100; double nof_learnts = nClauses() / 3; lbool status = l_Undef; // Perform assumptions: root_level = assumps.size(); for (int i = 0; i < assumps.size(); i++){ Lit p = assumps[i]; assert(var(p) < nVars()); if (!assume(p)){ GClause r = reason[var(p)]; if (r != GClause_NULL){ Clause* confl; if (r.isLit()){ confl = propagate_tmpbin; (*confl)[1] = ~p; (*confl)[0] = r.lit(); }else confl = r.clause(); analyzeFinal(confl, true); conflict.push(~p); }else conflict.clear(), conflict.push(~p); cancelUntil(0); return false; } Clause* confl = propagate(); if (confl != NULL){ analyzeFinal(confl), assert(conflict.size() > 0); cancelUntil(0); return false; } } assert(root_level == decisionLevel()); // Search: if (verbosity >= 1){ reportf("==================================[MINISAT]===================================\n", NULL); reportf("| Conflicts | ORIGINAL | LEARNT | Progress |\n", NULL); reportf("| | Clauses Literals | Limit Clauses Literals Lit/Cl | |\n", NULL); reportf("==============================================================================\n", NULL); } while (status == l_Undef){ if (verbosity >= 1) reportf("| %9d | %7d %8d | %7d %7d %8d %7.1f | %6.3f %% |\n", (int)stats.conflicts, nClauses(), (int)stats.clauses_literals, (int)nof_learnts, nLearnts(), (int)stats.learnts_literals, (double)stats.learnts_literals/nLearnts(), progress_estimate*100); status = search((int)nof_conflicts, (int)nof_learnts, params); nof_conflicts *= 1.5; nof_learnts *= 1.1; } if (verbosity >= 1) reportf("==============================================================================\n", NULL); cancelUntil(0); return status == l_True; }
/*_________________________________________________________________________________________________ | | search : (nof_conflicts : int) (nof_learnts : int) (params : const SearchParams&) -> [lbool] | | Description: | Search for a model the specified number of conflicts, keeping the number of learnt clauses | below the provided limit. NOTE! Use negative value for 'nof_conflicts' or 'nof_learnts' to | indicate infinity. | | Output: | 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If | all variables are decision variables, this means that the clause set is satisfiable. 'l_False' | if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached. |________________________________________________________________________________________________@*/ lbool Solver::search(int nof_conflicts, int nof_learnts, const SearchParams& params) { if (!ok) return l_False; // GUARD (public method) assert(root_level == decisionLevel()); stats.starts++; int conflictC = 0; var_decay = 1 / params.var_decay; cla_decay = 1 / params.clause_decay; model.clear(); for (;;){ Clause* confl = propagate(); if (confl != NULL){ // CONFLICT stats.conflicts++; conflictC++; vec<Lit> learnt_clause; int backtrack_level; if (decisionLevel() == root_level){ // Contradiction found: analyzeFinal(confl); return l_False; } analyze(confl, learnt_clause, backtrack_level); cancelUntil(max(backtrack_level, root_level)); newClause(learnt_clause, true); if (learnt_clause.size() == 1) level[var(learnt_clause[0])] = 0; // (this is ugly (but needed for 'analyzeFinal()') -- in future versions, we will backtrack past the 'root_level' and redo the assumptions) varDecayActivity(); claDecayActivity(); }else{ // NO CONFLICT if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ // Reached bound on number of conflicts: progress_estimate = progressEstimate(); cancelUntil(root_level); return l_Undef; } if (decisionLevel() == 0) // Simplify the set of problem clauses: simplifyDB(), assert(ok); if (nof_learnts >= 0 && learnts.size()-nAssigns() >= nof_learnts) // Reduce the set of learnt clauses: reduceDB(); // New variable decision: stats.decisions++; Var next = order.select(params.random_var_freq); if (next == var_Undef){ // Model found: model.growTo(nVars()); for (int i = 0; i < nVars(); i++) model[i] = value(i); cancelUntil(root_level); return l_True; } check(assume(~Lit(next))); } } }
/*_________________________________________________________________________________________________ | | search : (nof_conflicts : int) (nof_learnts : int) (params : const SearchParams&) -> [lbool] | | Description: | Search for a model the specified number of conflicts, keeping the number of learnt clauses | below the provided limit. NOTE! Use negative value for 'nof_conflicts' or 'nof_learnts' to | indicate infinity. | | Output: | 'l_True' if a partial assigment that is consistent with respect to the clauseset is found. If | all variables are decision variables, this means that the clause set is satisfiable. 'l_False' | if the clause set is unsatisfiable. 'l_Undef' if the bound on number of conflicts is reached. |________________________________________________________________________________________________@*/ lbool Solver::search(int nof_conflicts, int nof_learnts) { int backtrack_level; int conflictC = 0; vec<Lit> learnt_clause; starts++; // bool first = true; for (;;){ Clause* confl = propagate(); if (confl != NULL){ // CONFLICT conflicts++; conflictC++; if (decisionLevel() == 0) return l_False; // first = false; learnt_clause.clear(); analyze(confl, learnt_clause, backtrack_level); cancelUntil(backtrack_level); #ifdef __PRINT char c1 = sign(learnt_clause[0]) ? '-' : '+'; char c2 = polarity[var(learnt_clause[0])] == 0 ? '-' : '+'; if (decisionLevel() < minDecisionLevel && original_activity[var(learnt_clause[0])] > 0) { printf("Conflict record: "); printLit(learnt_clause[0]); printf(" .%d.\t.%d. %c .%c .%g\n", decisionLevel(), trail.size(), c1, c2, original_activity[var(learnt_clause[0])]); if (decisionLevel() == 0) { minDecisionLevel = (unsigned)(-1); } else { minDecisionLevel = decisionLevel(); } } #endif if (learnt_clause.size() == 1){ uncheckedEnqueue(learnt_clause[0]); }else{ Clause* c = Clause::Clause_new(learnt_clause, true); learnts.push(c); attachClause(*c); claBumpActivity(*c); uncheckedEnqueue(learnt_clause[0], c); } #ifdef _MINISAT_DEFAULT_VSS varDecayActivity(); #endif claDecayActivity(); }else{ // NO CONFLICT if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ // Reached bound on number of conflicts: progress_estimate = progressEstimate(); // cancelUntil(0); return l_Undef; } // Simplify the set of problem clauses: if (decisionLevel() == 0 && !simplify()) return l_False; if (nof_learnts >= 0 && learnts.size()-nAssigns() >= nof_learnts) // Reduce the set of learnt clauses: reduceDB(); Lit next = lit_Undef; while (decisionLevel() < assumptions.size()){ // Perform user provided assumption: Lit p = assumptions[decisionLevel()]; if (value(p) == l_True){ // Dummy decision level: newDecisionLevel(); }else if (value(p) == l_False){ analyzeFinal(~p, conflict); return l_False; }else{ next = p; break; } } if (next == lit_Undef){ // New variable decision: decisions++; next = pickBranchLit(polarity_mode, random_var_freq); if (next == lit_Undef) // Model found: return l_True; #ifdef __PRINT printf("Decision: "); printLit(next); printf("\t.%f.\t.%d.\t.%d.", activity[var(next)], decisionLevel(), trail.size()); printf("\n"); #endif } // Increase decision level and enqueue 'next' newDecisionLevel(); uncheckedEnqueue(next); } //#ifdef __PRINT // printTrail(); //#endif } }
void Solver::addConflictingClause(vec<Lit>& lits) { if (lits.size() == 1) { if (value(lits[0]) == l_True) return; if (value(lits[0]) == l_False) { if (level[var(lits[0])] == 0) { ok = false; return; } cancelUntil(level[var(lits[0])] - 1); } uncheckedEnqueue(~lits[0]); } else { vec<Lit> learnt_clause; int backtrack_level; for (int i = 1; i < lits.size(); i++) { if (value(lits[0]) == l_False) { if (value(lits[i]) != l_False){ Lit tmp = lits[0]; lits[0] = lits[i]; lits[i] = tmp; } } else if (value(lits[1]) == l_False) { if (value(lits[i]) != l_False){ Lit tmp = lits[1]; lits[1] = lits[i]; lits[i] = tmp; break; } } } if (value(lits[0]) == l_False) { for (int i = 1; i < lits.size(); i++) { if (level[var(lits[i])] > level[var(lits[0])]) { Lit tmp = lits[0]; lits[0] = lits[i]; lits[i] = tmp; } } } if (value(lits[1]) == l_False) { for (int i = 2; i < lits.size(); i++) { if (level[var(lits[i])] > level[var(lits[1])]) { Lit tmp = lits[1]; lits[1] = lits[i]; lits[i] = tmp; } } } Clause* confl = Clause::Clause_new(lits, true); clauses.push(confl); attachClause(*confl); if (value(lits[0]) != l_False) { if (value(lits[1]) == l_False) { uncheckedEnqueue(lits[0], confl); } return; } int maxLevel = level[var(lits[0])]; cancelUntil(maxLevel); if (maxLevel == 0) { ok = false; return; } learnt_clause.clear(); analyze(confl, learnt_clause, backtrack_level); cancelUntil(backtrack_level); if (learnt_clause.size() == 1){ uncheckedEnqueue(learnt_clause[0]); } else { Clause* c = Clause::Clause_new(learnt_clause, true); learnts.push(c); attachClause(*c); claBumpActivity(*c); uncheckedEnqueue(learnt_clause[0], c); } #ifdef _MINISAT_DEFAULT_VSS varDecayActivity(); #endif claDecayActivity(); } }