/*_________________________________________________________________________________________________ | | 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); } } }
/*_________________________________________________________________________________________________ | | newClause : (ps : const vec<Lit>&) (learnt : bool) -> [void] | | Description: | Allocate and add a new clause to the SAT solvers clause database. If a conflict is detected, | the 'ok' flag is cleared and the solver is in an unusable state (must be disposed). | | Input: | ps - The new clause as a vector of literals. | learnt - Is the clause a learnt clause? For learnt clauses, 'ps[0]' is assumed to be the | asserting literal. An appropriate 'enqueue()' operation will be performed on this | literal. One of the watches will always be on this literal, the other will be set to | the literal with the highest decision level. | | Effect: | Activity heuristics are updated. |________________________________________________________________________________________________@*/ void Solver::newClause(const vec<Lit>& ps_, bool learnt) { if (!ok) return; vec<Lit> qs; if (!learnt){ assert(decisionLevel() == 0); ps_.copyTo(qs); // Make a copy of the input vector. // Remove duplicates: sortUnique(qs); // Check if clause is satisfied: for (int i = 0; i < qs.size()-1; i++){ if (qs[i] == ~qs[i+1]) return; } for (int i = 0; i < qs.size(); i++){ if (value(qs[i]) == l_True) return; } // Remove false literals: int i, j; for (i = j = 0; i < qs.size(); i++) if (value(qs[i]) != l_False) qs[j++] = qs[i]; qs.shrink(i - j); } const vec<Lit>& ps = learnt ? ps_ : qs; // 'ps' is now the (possibly) reduced vector of literals. if (ps.size() == 0){ ok = false; }else if (ps.size() == 1){ // NOTE: If enqueue takes place at root level, the assignment will be lost in incremental use (it doesn't seem to hurt much though). if (!enqueue(ps[0])) ok = false; }else if (ps.size() == 2){ // Create special binary clause watch: watches[index(~ps[0])].push(GClause_new(ps[1])); watches[index(~ps[1])].push(GClause_new(ps[0])); if (learnt){ check(enqueue(ps[0], GClause_new(~ps[1]))); stats.learnts_literals += ps.size(); }else stats.clauses_literals += ps.size(); n_bin_clauses++; }else{ // Allocate clause: Clause* c = Clause_new(learnt, ps); if (learnt){ // Put the second watch on the literal with highest decision level: int max_i = 1; int max = level[var(ps[1])]; for (int i = 2; i < ps.size(); i++) if (level[var(ps[i])] > max) max = level[var(ps[i])], max_i = i; (*c)[1] = ps[max_i]; (*c)[max_i] = ps[1]; // Bump, enqueue, store clause: claBumpActivity(c); // (newly learnt clauses should be considered active) check(enqueue((*c)[0], GClause_new(c))); learnts.push(c); stats.learnts_literals += c->size(); }else{ // Store clause: clauses.push(c); stats.clauses_literals += c->size(); } // Watch clause: watches[index(~(*c)[0])].push(GClause_new(c)); watches[index(~(*c)[1])].push(GClause_new(c)); } }
/*_________________________________________________________________________________________________ | | analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void] | | Description: | Analyze conflict and produce a reason clause. | | Pre-conditions: | * 'out_learnt' is assumed to be cleared. | * Current decision level must be greater than root level. | | Post-conditions: | * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'. | | Effect: | Will undo part of the trail, upto but not beyond the assumption of the current decision level. |________________________________________________________________________________________________@*/ void Solver::analyze(Clause* confl, vec<Lit>& out_learnt, int& out_btlevel) { int pathC = 0; Lit p = lit_Undef; // Generate conflict clause: // out_learnt.push(); // (leave room for the asserting literal) int index = trail.size() - 1; out_btlevel = 0; do{ assert(confl != NULL); // (otherwise should be UIP) Clause& c = *confl; if (c.learnt()) claBumpActivity(c); for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){ Lit q = c[j]; if (!seen[var(q)] && level[var(q)] > 0){ varBumpActivity(var(q)); seen[var(q)] = 1; if (level[var(q)] >= decisionLevel()) pathC++; else{ out_learnt.push(q); if (level[var(q)] > out_btlevel) out_btlevel = level[var(q)]; } } } // Select next clause to look at: while (!seen[var(trail[index--])]); p = trail[index+1]; confl = reason[var(p)]; seen[var(p)] = 0; pathC--; }while (pathC > 0); out_learnt[0] = ~p; // Simplify conflict clause: // int i, j; if (expensive_ccmin){ uint32_t abstract_level = 0; for (i = 1; i < out_learnt.size(); i++) abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict) out_learnt.copyTo(analyze_toclear); for (i = j = 1; i < out_learnt.size(); i++) if (reason[var(out_learnt[i])] == NULL || !litRedundant(out_learnt[i], abstract_level)) out_learnt[j++] = out_learnt[i]; }else{ out_learnt.copyTo(analyze_toclear); for (i = j = 1; i < out_learnt.size(); i++){ Clause& c = *reason[var(out_learnt[i])]; for (int k = 1; k < c.size(); k++) if (!seen[var(c[k])] && level[var(c[k])] > 0){ out_learnt[j++] = out_learnt[i]; break; } } } max_literals += out_learnt.size(); out_learnt.shrink(i - j); tot_literals += out_learnt.size(); // Find correct backtrack level: // if (out_learnt.size() == 1) out_btlevel = init_level; else{ int max_i = 1; for (int i = 2; i < out_learnt.size(); i++) if (level[var(out_learnt[i])] > level[var(out_learnt[max_i])]) max_i = i; Lit p = out_learnt[max_i]; out_learnt[max_i] = out_learnt[1]; out_learnt[1] = p; out_btlevel = level[var(p)]; } for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared) }
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); } } }
/*_________________________________________________________________________________________________ | | 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); } } }
/*_________________________________________________________________________________________________ | | analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void] | | Description: | Analyze conflict and produce a reason clause. | | Pre-conditions: | * 'out_learnt' is assumed to be cleared. | * Current decision level must be greater than root level. | | Post-conditions: | * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'. | | Effect: | Will undo part of the trail, upto but not beyond the assumption of the current decision level. |________________________________________________________________________________________________@*/ void Solver::analyze(Clause* confl, vec<Lit>& out_learnt, int& out_btlevel,int &nbl,int &mer) { int pathC = 0; Lit p = lit_Undef; out_learnt.push(); // (leave room for the asserting literal) int index = trail.size() - 1; out_btlevel = 0; do{ assert(confl != NULL); // (otherwise should be UIP) Clause& c = *confl; // The first one has to be SAT if( p != lit_Undef && c.size()==2 && value(c[0])==l_False) { assert(value(c[1])==l_True); Lit tmp = c[0]; c[0] = c[1], c[1] = tmp; } if (c.learnt()) claBumpActivity(c); for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){ Lit q = c[j]; if (!seen[var(q)] && level[var(q)] > 0){ varBumpActivity(var(q)); seen[var(q)] = 1; if (level[var(q)] >= decisionLevel()){ pathC++; #ifdef UPDATEVARACTIVITY if((reason[var(q)]!=NULL) && (reason[var(q)]->learnt())) lastDecisionLevel.push(q); #endif } else{ out_learnt.push(q); if (level[var(q)] > out_btlevel) out_btlevel = level[var(q)]; } } } // Select next clause to look at: while (!seen[var(trail[index--])]); p = trail[index+1]; confl = reason[var(p)]; seen[var(p)] = 0; pathC--; }while (pathC > 0); out_learnt[0] = ~p; // Simplify conflict clause: // int i, j; if (expensive_ccmin){ uint32_t abstract_level = 0; for (i = 1; i < out_learnt.size(); i++) abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict) out_learnt.copyTo(analyze_toclear); for (i = j = 1; i < out_learnt.size(); i++) if (reason[var(out_learnt[i])] == NULL || !litRedundant(out_learnt[i], abstract_level)) out_learnt[j++] = out_learnt[i]; }else{ out_learnt.copyTo(analyze_toclear); for (i = j = 1; i < out_learnt.size(); i++){ Clause& c = *reason[var(out_learnt[i])]; if(c.size()==2 && value(c[0])==l_False) { assert(value(c[1])==l_True); Lit tmp = c[0]; c[0] = c[1], c[1] = tmp; } for (int k = 1; k < c.size(); k++) if (!seen[var(c[k])] && level[var(c[k])] > 0){ out_learnt[j++] = out_learnt[i]; break; } } } max_literals += out_learnt.size(); out_learnt.shrink(i - j); tot_literals += out_learnt.size(); // Find correct backtrack level: // if (out_learnt.size() == 1) out_btlevel = 0; else{ int max_i = 1; for (int i = 2; i < out_learnt.size(); i++) if (level[var(out_learnt[i])] > level[var(out_learnt[max_i])]) max_i = i; Lit p = out_learnt[max_i]; out_learnt[max_i] = out_learnt[1]; out_learnt[1] = p; out_btlevel = level[var(p)]; } nbl = 0;mer = 0; MYFLAG++; for(int i=0;i<out_learnt.size();i++) { int l = level[var(out_learnt[i])]; if (permDiff[l] != MYFLAG) { permDiff[l] = MYFLAG; nbl++; mer +=nbPropagated(l); } } #ifdef UPDATEVARACTIVITY if(lastDecisionLevel.size()>0) { for(int i = 0;i<lastDecisionLevel.size();i++) { if(reason[var(lastDecisionLevel[i])]->activity()<nbl) varBumpActivity(var(lastDecisionLevel[i])); } lastDecisionLevel.clear(); } #endif for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared) }
/*_________________________________________________________________________________________________ | | analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void] | | Description: | Analyze conflict and produce a reason clause. | | Pre-conditions: | * 'out_learnt' is assumed to be cleared. | * Current decision level must be greater than root level. | | Post-conditions: | * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'. | | Effect: | Will undo part of the trail, upto but not beyond the assumption of the current decision level. |________________________________________________________________________________________________@*/ void Solver::analyze(Clause* _confl, vec<Lit>& out_learnt, int& out_btlevel) { GClause confl = GClause_new(_confl); vec<char>& seen = analyze_seen; int pathC = 0; Lit p = lit_Undef; // Generate conflict clause: // out_learnt.push(); // (leave room for the asserting literal) out_btlevel = 0; int index = trail.size()-1; do{ assert(confl != GClause_NULL); // (otherwise should be UIP) Clause& c = confl.isLit() ? ((*analyze_tmpbin)[1] = confl.lit(), *analyze_tmpbin) : *confl.clause(); if (c.learnt()) claBumpActivity(&c); for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){ Lit q = c[j]; if (!seen[var(q)] && level[var(q)] > 0){ varBumpActivity(q); seen[var(q)] = 1; if (level[var(q)] == decisionLevel()) pathC++; else{ out_learnt.push(q); out_btlevel = max(out_btlevel, level[var(q)]); } } } // Select next clause to look at: while (!seen[var(trail[index--])]); p = trail[index+1]; confl = reason[var(p)]; seen[var(p)] = 0; pathC--; }while (pathC > 0); out_learnt[0] = ~p; int i, j; if (expensive_ccmin){ // Simplify conflict clause (a lot): // unsigned int min_level = 0; for (i = 1; i < out_learnt.size(); i++) min_level |= 1 << (level[var(out_learnt[i])] & 31); // (maintain an abstraction of levels involved in conflict) out_learnt.copyTo(analyze_toclear); for (i = j = 1; i < out_learnt.size(); i++) if (reason[var(out_learnt[i])] == GClause_NULL || !analyze_removable(out_learnt[i], min_level)) out_learnt[j++] = out_learnt[i]; }else{ // Simplify conflict clause (a little): // out_learnt.copyTo(analyze_toclear); for (i = j = 1; i < out_learnt.size(); i++){ GClause r = reason[var(out_learnt[i])]; if (r == GClause_NULL) out_learnt[j++] = out_learnt[i]; else if (r.isLit()){ Lit q = r.lit(); if (!seen[var(q)] && level[var(q)] != 0) out_learnt[j++] = out_learnt[i]; }else{ Clause& c = *r.clause(); for (int k = 1; k < c.size(); k++) if (!seen[var(c[k])] && level[var(c[k])] != 0){ out_learnt[j++] = out_learnt[i]; break; } } } } stats.max_literals += out_learnt.size(); out_learnt.shrink(i - j); stats.tot_literals += out_learnt.size(); for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared) }
/*_________________________________________________________________________________________________ | | 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 } }
/*_________________________________________________________________________________________________ | | analyze : (confl : Clause*) (out_learnt : vec<Lit>&) (out_btlevel : int&) -> [void] | | Description: | Analyze conflict and produce a reason clause. | | Pre-conditions: | * 'out_learnt' is assumed to be cleared. | * Current decision level must be greater than root level. | | Post-conditions: | * 'out_learnt[0]' is the asserting literal at level 'out_btlevel'. | | Effect: | Will undo part of the trail, upto but not beyond the assumption of the current decision level. |________________________________________________________________________________________________@*/ void Solver::analyze(Clause* confl, vec<Lit>& out_learnt, int& out_btlevel) { int pathC = 0; Lit p = lit_Undef; // Generate conflict clause: // out_learnt.push(); // (leave room for the asserting literal) int index = trail.size() - 1; out_btlevel = 0; do{ Clause& c = *confl; #ifdef __PRINT printf("Explain: "); printClause(c); printf("\n"); #endif if (c.learnt()) claBumpActivity(c); for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){ Lit q = c[j]; if (!seen[var(q)] && level[var(q)] > 0){ #ifdef _MINISAT_DEFAULT_VSS varBumpActivity(var(q)); #endif seen[var(q)] = 1; if (level[var(q)] >= decisionLevel()) { pathC++; }else{ out_learnt.push(q); if (level[var(q)] > out_btlevel) out_btlevel = level[var(q)]; } } } // Select next clause to look at: while (!seen[var(trail[index--])]); p = trail[index+1]; confl = reason[var(p)]; seen[var(p)] = 0; pathC--; } while (pathC > 0); out_learnt[0] = ~p; // Simplify conflict clause: // int i, j; if (expensive_ccmin){ uint32_t abstract_level = 0; for (i = 1; i < out_learnt.size(); i++) abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict) out_learnt.copyTo(analyze_toclear); for (i = j = 1; i < out_learnt.size(); i++) if (reason[var(out_learnt[i])] == NULL || !litRedundant(out_learnt[i], abstract_level)) out_learnt[j++] = out_learnt[i]; }else{ out_learnt.copyTo(analyze_toclear); for (i = j = 1; i < out_learnt.size(); i++){ Clause& c = *reason[var(out_learnt[i])]; for (int k = 1; k < c.size(); k++) if (!seen[var(c[k])] && level[var(c[k])] > 0){ out_learnt[j++] = out_learnt[i]; break; } } } max_literals += out_learnt.size(); out_learnt.shrink(i - j); tot_literals += out_learnt.size(); // Find correct backtrack level: // if (out_learnt.size() == 1) out_btlevel = 0; else{ int max_i = 1; for (int i = 2; i < out_learnt.size(); i++) if (level[var(out_learnt[i])] > level[var(out_learnt[max_i])]) max_i = i; Lit p = out_learnt[max_i]; out_learnt[max_i] = out_learnt[1]; out_learnt[1] = p; out_btlevel = level[var(p)]; } #ifdef __PRINT printf("Learnt: "); for (int i = 0; i < out_learnt.size(); i++) { printf("%s%d ", sign(out_learnt[i]) ? "-" : "", var(out_learnt[i])); if (value(out_learnt[i]) != l_False) exit(1); } printf("\n"); #endif for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0; // ('seen[]' is now cleared) }
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(); } }