bool Solver::addClause(vec<Lit>& ps) { assert(decisionLevel() == 0); if (!ok) return false; else{ // Check if clause is satisfied and remove false/duplicate literals: sort(ps); Lit p; int i, j; for (i = j = 0, p = lit_Undef; i < ps.size(); i++) if (value(ps[i]) == l_True || ps[i] == ~p) return true; else if (value(ps[i]) != l_False && ps[i] != p) ps[j++] = p = ps[i]; ps.shrink(i - j); } if (ps.size() == 0) return ok = false; else if (ps.size() == 1){ assert(value(ps[0]) == l_Undef); uncheckedEnqueue(ps[0]); return ok = (propagate() == NULL); }else{ Clause* c = Clause_new(ps, false); clauses.push(c); attachClause(*c); } return true; }
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; }
/*_________________________________________________________________________________________________ | | propagate : [void] -> [Clause*] | | Description: | Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned, | otherwise NULL. | | Post-conditions: | * the propagation queue is empty, even if there was a conflict. |________________________________________________________________________________________________@*/ Clause* Solver::propagate() { Clause* confl = NULL; int num_props = 0; while (qhead < trail.size()){ Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. vec<Clause*>& ws = watches[toInt(p)]; Clause **i, **j, **end; num_props++; for (i = j = (Clause**)ws, end = i + ws.size(); i != end;){ Clause& c = **i++; // Make sure the false literal is data[1]: Lit false_lit = ~p; if (c[0] == false_lit) c[0] = c[1], c[1] = false_lit; assert(c[1] == false_lit); // If 0th watch is true, then clause is already satisfied. Lit first = c[0]; if (value(first) == l_True){ *j++ = &c; }else{ // Look for new watch: for (int k = 2; k < c.size(); k++) if (value(c[k]) != l_False){ c[1] = c[k]; c[k] = false_lit; watches[toInt(~c[1])].push(&c); goto FoundWatch; } // Did not find watch -- clause is unit under assignment: *j++ = &c; if (value(first) == l_False){ confl = &c; qhead = trail.size(); // Copy the remaining watches: while (i < end) *j++ = *i++; }else uncheckedEnqueue(first, &c); } FoundWatch:; } ws.shrink(i - j); } propagations += num_props; simpDB_props -= num_props; return confl; }
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; }
/*_________________________________________________________________________________________________ | | 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); } } }
/*_________________________________________________________________________________________________ | | propagate : [void] -> [Clause*] | | Description: | Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned, | otherwise NULL. | | Post-conditions: | * the propagation queue is empty, even if there was a conflict. |________________________________________________________________________________________________@*/ Clause* Solver::propagate() { Clause* confl = NULL; int num_props = 0; while (qhead < trail.size()){ const Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. vec<Watched>& ws = watches[toInt(p)]; Watched *i, *j, *end; num_props++; #ifdef RESTORE printf("Propagating lit "); printLit(p); printf(" number: %d\n", toInt(p)); #endif const vec<Binaire> & wbin = watchesBin[toInt(p)]; bogoProps += wbin.size(); for(int k = 0;k<wbin.size();k++) { Lit imp = wbin[k].implied; if(value(imp) == l_False) { if (handleConflict(*wbin[k].clause, num_props)) return wbin[k].clause; } if(value(imp) == l_Undef) { uncheckedEnqueue(imp,wbin[k].clause); } } if (backup.running && watchBackup.flags[toInt(p)] == false ) { watchBackup.ws[toInt(p)] = watches[toInt(p)]; watchBackup.flags[toInt(p)] = true; watchBackup.changed.push(toInt(p)); } bogoProps += ws.size(); for (i = j = (Watched*)ws, end = i + ws.size(); i != end;){ if(value(i->blocked)==l_True) { // Clause is sat *j++ = *i++; continue; } Lit bl = i->blocked; Clause& c = *(i->wcl); i++; bogoProps += 5; if (backup.running && backup.touchedClauses.find(&c) == backup.touchedClauses.end() ) { backup.touchedClauses.insert(&c); c.saveLiterals(); } // Make sure the false literal is data[1]: Lit false_lit = ~p; if (c[0] == false_lit) c[0] = c[1], c[1] = false_lit; assert(c[1] == false_lit); // If 0th watch is true, then clause is already satisfied. Lit first = c[0]; if (value(first) == l_True){ j->wcl = &c; j->blocked = first; j++; }else{ // Look for new watch: for (int k = 2; k < c.size(); k++) if (value(c[k]) != l_False){ c[1] = c[k]; c[k] = false_lit; const int wsNum = toInt(~c[1]); //Save ws before changing it if (backup.running && watchBackup.flags[wsNum] == false ) { watchBackup.ws[wsNum] = watches[wsNum]; watchBackup.flags[wsNum] = true; watchBackup.changed.push(wsNum); } watches[wsNum].push(); watches[wsNum].last().wcl = &c; watches[wsNum].last().blocked = c[0]; goto FoundWatch; } // Did not find watch -- clause is unit under assignment: j->wcl = &c; j->blocked = bl; j++; if (value(first) == l_False){ if (handleConflict(c, num_props)) { confl = &c; qhead = trail.size(); // Copy the remaining watches: while (i < end) *j++ = *i++; } else { goto FoundWatch; } } else { uncheckedEnqueue(first, &c); #ifdef DYNAMICNBLEVEL if(backup.stage == 0 && c.learnt() && c.activity()>2 ) { MYFLAG++; int nblevels =0; for(int i=0;i<c.size();i++) { int l = level[var(c[i])]; if (permDiff[l] != MYFLAG) { permDiff[l] = MYFLAG; nblevels++; } } if(nblevels+1<c.activity()) { c.setActivity(nblevels); } } #endif } } FoundWatch:; } ws.shrink(i - j); } propagations+=num_props; simpDB_props-=num_props; return confl; }
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); } } }
/*_________________________________________________________________________________________________ | | propagate : [void] -> [Clause*] | | Description: | Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned, | otherwise NULL. | | Post-conditions: | * the propagation queue is empty, even if there was a conflict. |________________________________________________________________________________________________@*/ Clause* MiniSATP::propagate(const bool deduce) { Clause* confl = NULL; int num_props = 0; while (qhead < trail.size()){ Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. vec<Clause*>& ws = watches[toInt(p)]; Clause **i, **j, **end; num_props++; for (i = j = (Clause**)ws, end = i + ws.size(); i != end;){ Clause& c = **i++; // Make sure the false literal is data[1]: Lit false_lit = ~p; if (c[0] == false_lit) c[0] = c[1], c[1] = false_lit; assert(c[1] == false_lit); // If 0th watch is true, then clause is already satisfied. Lit first = c[0]; if (value(first) == l_True){ *j++ = &c; }else{ // Look for new watch: for (int k = 2; k < c.size(); k++) if (value(c[k]) != l_False){ c[1] = c[k]; c[k] = false_lit; watches[toInt(~c[1])].push(&c); goto FoundWatch; } // Did not find watch -- clause is unit under assignment: *j++ = &c; if (value(first) == l_False){ confl = &c; qhead = trail.size(); // Copy the remaining watches: while (i < end) *j++ = *i++; } else { uncheckedEnqueue(first, &c); //================================================================================================= // Added Code assert( (int)var_to_enode.size( ) > var( first ) ); if ( deduce && var_to_enode[ var( first ) ] != NULL ) { Enode * e = var_to_enode[ var( first ) ]; if ( !e->hasPolarity( ) && !e->isDeduced( ) ) { e->setDeduced( sign( first ), solver_id ); deductions.push_back( e ); } } // Added Code //================================================================================================= } } FoundWatch:; } ws.shrink(i - j); } propagations += num_props; simpDB_props -= num_props; return confl; }
// Modified line // bool MiniSATP::addClause(vec<Lit>& ps, Enode * e) bool MiniSATP::addClause(vec<Lit>& psin, Enode * e) { assert( decisionLevel() == 0 ); assert( ok ); // Added Lines vec< Lit > ps; psin.copyTo( ps ); if (!ok) return false; // Check if clause is satisfied and remove false/duplicate literals: sort(ps); Lit p; int i, j; for (i = j = 0, p = lit_Undef; i < ps.size(); i++) { if (value(ps[i]) == l_True || ps[i] == ~p) return true; else if (value(ps[i]) != l_False && ps[i] != p) ps[j++] = p = ps[i]; } ps.shrink(i - j); //================================================================================================= // Modified Code assert( psin.size( ) == 1 || ps.size() > 0 ); // // This case happens only when deductions are enabled // if (ps.size() == 0) { Clause * confl = Clause_new( psin ); if ( confl == NULL ) return ok = true; initExpDup( ); explanation.push_back( e ); storeExpDup( e ); fillExplanation( confl ); doneExpDup( ); assert( !explanation.empty( ) ); return ok = false; } if (ps.size() == 1) { assert(value(ps[0]) == l_Undef); uncheckedEnqueue(ps[0]); /* const Var v = var(ps[0]); if ( var_to_enode.size( ) <= v ) var_to_enode.resize( v + 1, NULL ); var_to_enode[ v ] = e; */ /* if ( e != NULL && seen_in_conflict.insert( e->getId( ) ).second ) explanation.push_back( e ); */ // undo_stack_oper.push_back( NEWUNIT ); // undo_stack_elem.push_back( (void *)v ); #define LAZY_PROPAGATION 0 #if LAZY_PROPAGATION #else // Modified Line // return ok = (propagate() == NULL); #if LIMIT_DEDUCTIONS deductions_done_in_call = 0; #endif Clause * confl = propagate( theory_prop ); if ( confl == NULL ) return ok = true; initExpDup( ); fillExplanation( confl ); doneExpDup( ); assert( !explanation.empty( ) ); return ok = false; #endif // Modified Code //================================================================================================= } else { Clause* c = Clause_new(ps, false); clauses.push(c); attachClause(*c); // Added Lines undo_stack_oper.push_back( NEWCLAUSE ); undo_stack_elem.push_back( (void *)c ); } return true; }
// NOTE: enqueue does not set the ok flag! (only public methods do) inline bool Solver::enqueue(Lit p, CRef from) { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), 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(); 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); } } }
/*_________________________________________________________________________________________________ | | propagate : [void] -> [Clause*] | | Description: | Propagates all enqueued facts. If a conflict arises, the conflicting clause is returned, | otherwise NULL. | | Post-conditions: | * the propagation queue is empty, even if there was a conflict. |________________________________________________________________________________________________@*/ Clause* Solver::propagate() { Clause* confl = NULL; int num_props = 0; while (qhead < trail.size()){ Lit p = trail[qhead++]; // 'p' is enqueued fact to propagate. vec<Watched>& ws = watches[toInt(p)]; Watched *i, *j, *end; num_props++; vec<Binaire> & wbin = watchesBin[toInt(p)]; for(int k = 0;k<wbin.size();k++) { Lit imp = wbin[k].implied; if(value(imp) == l_False) { return wbin[k].clause; } if(value(imp) == l_Undef) { uncheckedEnqueue(imp,wbin[k].clause); } } for (i = j = (Watched*)ws, end = i + ws.size(); i != end;){ if(value(i->blocked)==l_True) { // Clause is sat *j++ = *i++; continue; } Lit bl = i->blocked; Clause& c = *(i->wcl); i++; // Make sure the false literal is data[1]: Lit false_lit = ~p; if (c[0] == false_lit) c[0] = c[1], c[1] = false_lit; assert(c[1] == false_lit); // If 0th watch is true, then clause is already satisfied. Lit first = c[0]; if (value(first) == l_True){ j->wcl = &c; j->blocked = first; j++; }else{ // Look for new watch: for (int k = 2; k < c.size(); k++) if (value(c[k]) != l_False){ c[1] = c[k]; c[k] = false_lit; watches[toInt(~c[1])].push(); watches[toInt(~c[1])].last().wcl = &c; watches[toInt(~c[1])].last().blocked = c[0]; goto FoundWatch; } // Did not find watch -- clause is unit under assignment: j->wcl = &c; j->blocked = bl; j++; if (value(first) == l_False){ confl = &c; qhead = trail.size(); // Copy the remaining watches: while (i < end) *j++ = *i++; }else { uncheckedEnqueue(first, &c); #ifdef DYNAMICNBLEVEL if(c.learnt() && c.activity()>2) { // GA MYFLAG++; int nblevels =0; for(int i=0;i<c.size();i++) { int l = level[var(c[i])]; if (permDiff[l] != MYFLAG) { permDiff[l] = MYFLAG; nblevels++; } } if(nblevels+1<c.activity()) { c.setActivity(nblevels); } else { } } #endif } } FoundWatch:; } ws.shrink(i - j); } propagations += num_props; simpDB_props -= num_props; return confl; }
bool Solver::addClause(vec<Lit>& ps) { #ifdef __PRINT for (int i = 0; i < ps.size(); i++) { if (_literal_count.find(ps[i]) == _literal_count.end()) _literal_count[ps[i]] = 1; else _literal_count[ps[i]]++; } #endif if (!ok) return false; // Check if clause is satisfied and remove false/duplicate literals: // Special attention is put on single and double literal clauses if (ps.size() == 1 || (ps.size() == 2 && ps[0] == ps[1])) { // Unary or Binary with a duplicate literal if (value(ps[0]) == l_True) { #ifdef __PRINT printf("---satisfied---\n"); #endif return true; } else if (value(ps[0]) == l_False) { #ifdef __PRINT printf("Clause empty after simplification\n"); #endif return ok = false; } else { uncheckedEnqueue(ps[0]); return ok = (propagate() == NULL); } } else if (ps.size() == 2) { // Real Binary clauses if (value(ps[0]) == l_True || value(ps[1]) == l_True || ps[0] == ~ps[1]) { #ifdef __PRINT printf("---satisfied---\n"); #endif return true; } else if (value(ps[0]) == l_False) { if (value(ps[1]) == l_False) { #ifdef __PRINT printf("Clause empty after simplification\n"); #endif return ok = false; } else { uncheckedEnqueue(ps[1]); return ok = (propagate() == NULL); } } else { if (value(ps[1]) == l_False) { uncheckedEnqueue(ps[0]); return ok = (propagate() == NULL); } else { Clause* c = Clause::Clause_new(ps, false); clauses.push(c); attachClause(*c); } } } else { sort(ps); Lit p; int i, j; for (i = j = 0, p = lit_Undef; i < ps.size(); i++) if (value(ps[i]) == l_True || ps[i] == ~p) { #ifdef __PRINT printf("---satisfied---\n"); #endif return true; } else if (value(ps[i]) != l_False && ps[i] != p) ps[j++] = p = ps[i]; ps.shrink(i - j); if (ps.size() == 0) { #ifdef __PRINT printf("Clause empty after simplification\n"); #endif return ok = false; } else if (ps.size() == 1){ uncheckedEnqueue(ps[0]); return ok = (propagate() == NULL); }else{ Clause* c = Clause::Clause_new(ps, false); clauses.push(c); attachClause(*c); #ifdef __PRINT // printf("Simplified: "); // printClause(*c); // printf("\n"); #endif } } return 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) { 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(); } }