void Slave::splitJob() { vec<int> message; int num_splits; //fprintf(stderr, "%d: Split job called, assumptions.size()=%d, DL=%d!\n", thread_no, engine.assumptions.size(), engine.decisionLevel()); profile_start(); MPI_Recv(&num_splits, 1, MPI_INT, 0, STEAL_TAG, MPI_COMM_WORLD, &s); int max_splits = engine.decisionLevel() - engine.assumptions.size() - 1; if (num_splits > max_splits) num_splits = max_splits; if (num_splits < 0) num_splits = 0; if (FULL_DEBUG) fprintf(stderr, "%d: Splitting %d jobs\n", thread_no, num_splits); for (int i = 0; i < num_splits; i++) { engine.assumptions.push(toInt(sat.decLit(engine.assumptions.size()+1))); sat.incVarUse(engine.assumptions.last()/2); } assert(num_splits == 0 || engine.decisionLevel() > engine.assumptions.size()); vec<Lit> ps; for (int i = 0; i < engine.assumptions.size(); i++) ps.push(toLit(engine.assumptions[i])); Clause *c = Clause_new(ps); sat.convertToSClause(*c); free(c); message.push(num_splits); sat.temp_sc->pushInVec(message); MPI_Bsend((int*) message, message.size(), MPI_INT, 0, SPLIT_TAG, MPI_COMM_WORLD); profile_end("send split job", message.size()); if (FULL_DEBUG) fprintf(stderr, "%d: Sent %d split job to master\n", thread_no, message[0]); }
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 Master::createNewJob(int thread_no, bool random){ if(NULL == engine.opt_var) return false; int lb = engine.opt_var->getMin() + (engine.opt_type ? 1 : 0); int ub = engine.opt_var->getMax() - (engine.opt_type ? 1 : 0); // val must be in (lb, ub). int val; if(lb == ub) val = lb; else val = random? (lb + (rand() % (ub - lb))) : (lb + (ub - lb) * ((double) (thread_no+1) / (num_threads+1))); if(PAR_DEBUG) fprintf(stderr, "Creating new job for %d, bound=%d from (%d, %d)\n", thread_no, val, lb, ub); if(lb + 1 >= ub) return false; Lit l = engine.opt_type ? engine.opt_var->operator>=(val) : engine.opt_var->operator<=(val); vec<Lit> ls; ls.push(l); assert(sat.value(l) == l_Undef); Clause * c = Clause_new(ls, false); sat.convertToSClause(*c); job_queue.push(sat.temp_sc->copy()); return true; }
void Slave::exportBounds(){ int lb = engine.opt_var->getMin(); int ub = engine.opt_var->getMax(); Lit p = engine.opt_var->getLit(lb, 2); Lit p2 = engine.opt_var->getLit(ub, 3); vec<Lit> ps; ps.push(p); Clause *c = Clause_new(ps, true); shareClause(*c); ps.clear(); ps.push(p2); Clause *c2 = Clause_new(ps, true); shareClause(*c2); unitFound=true; free(c); free(c2); }
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 SAT::addClause(vec<Lit>& ps, bool one_watch) { int i, j; for (i = j = 0; i < ps.size(); i++) { if (value(ps[i]) == l_True) return; if (value(ps[i]) == l_Undef) ps[j++] = ps[i]; } ps.resize(j); if (ps.size() == 0) { assert(false); TL_FAIL(); } addClause(*Clause_new(ps), one_watch); }
void MIP::unboundedFailure() { // NOT_SUPPORTED; // if (MIP_DEBUG) // simplex.unboundedDebug(); assert(simplex.row[0] == 0); vec<Lit> ps; for (int i = 1; i < vars.size(); i++) { ps.push(simplex.shift[i] == 0 ? vars[i]->getMinLit() : vars[i]->getMaxLit()); } Clause *m_r = Clause_new(ps); m_r->temp_expl = 1; sat.rtrail.last().push(m_r); sat.confl = m_r; }
SimpSolver::SimpSolver() : Solver() , grow (0) , asymm_mode (false) , redundancy_check (false) , merges (0) , asymm_lits (0) , remembered_clauses (0) , elimorder (1) , use_simplification (true) , elim_heap (ElimLt(n_occ)) , bwdsub_assigns (0) { vec<Lit> dummy(1,lit_Undef); bwdsub_tmpunit = Clause_new(dummy); remove_satisfied = false; }
bool MIP::propagateBound(int i, long double s) { if (s > 4e9) return true; IntView<T> v(vars[i]); int64_t max = v.getMin() + (int64_t) floor(s); // fprintf(stderr, "%.3Lf %lld %lld %lld\n", s, v.getMin(), v.getMax(), max); if (v.setMaxNotR(max)) { Clause *m_r = NULL; if (so.lazy) { m_r = Clause_new(ps); (*m_r)[place[i]] = (*m_r)[0]; m_r->temp_expl = 1; sat.rtrail.last().push(m_r); } if (!v.setMax(max, m_r)) return false; } return true; }
// Record a clause and drive backtracking. 'clause[0]' must contain the asserting literal. // void Solver::record(const vec<Lit>& clause, Deriv* deriv) { assert(clause.size() != 0); Clause* c; check(Clause_new(*this, clause, true, c, 0, doDeriv, deriv)); check(ok); if (c != NULL) { learnts.push(c); check(enqueue(clause[0], c)); } else { assert(clause.size() == 1); if (doDeriv) { assert(var_deriv[var(clause[0])] == deriv); //var_deriv[var(clause[0])]->addDeriv(deriv); } } }
inline bool Engine::constrain() { best_sol = opt_var->getVal(); opt_time = wallClockTime() - start_time - init_time; sat.btToLevel(0); if (so.parallel) { Lit p = opt_type ? opt_var->getLit(best_sol+1, 2) : opt_var->getLit(best_sol-1, 3); vec<Lit> ps; ps.push(p); Clause *c = Clause_new(ps, true); slave.shareClause(*c); free(c); } // printf("opt_var = %d, opt_type = %d, best_sol = %d\n", opt_var->var_id, opt_type, best_sol); // printf("%% opt_var min = %d, opt_var max = %d\n", opt_var->getMin(), opt_var->getMax()); if (so.mip) mip->setObjective(best_sol); return (opt_type ? opt_var->setMin(best_sol+1) : opt_var->setMax(best_sol-1)); }
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 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 SimpSMTSolver::addClause( vec<Lit> & ps #ifdef PRODUCE_PROOF , const ipartitions_t & in #endif ) { //================================================================================================= // Added code if ( !use_simplification ) #ifdef PRODUCE_PROOF return CoreSMTSolver::addClause( ps, in ); #else return CoreSMTSolver::addClause( ps ); #endif // Added code //================================================================================================= for (int i = 0; i < ps.size(); i++) if (isEliminated(var(ps[i]))) remember(var(ps[i])); int nclauses = clauses.size(); if (redundancy_check && implied(ps)) return true; //================================================================================================= // Added code // // Hack to consider clauses of size 1 that // wouldn't otherwise be considered by // MiniSAT // if ( config.sat_preprocess_theory != 0 && ps.size( ) == 1 // Consider unit clauses && var(ps[0]) >= 2 ) // Don't consider true/false { Var v = var( ps[0] ); Enode * e = theory_handler->varToEnode( v ); if ( e->isTAtom( ) ) { Clause * uc = Clause_new(ps, false); unary_to_remove.push_back( uc ); Clause &c = *(unary_to_remove.back( )); Enode * x, * y; getDLVars( e, sign(ps[0]), &x, &y ); assert( x->isVar( ) ); assert( y->isVar( ) ); t_pos[ x->getId( ) ].push_back( &c ); t_neg[ y->getId( ) ].push_back( &c ); t_var[ x ].insert( y->getId( ) ); t_var[ y ].insert( x->getId( ) ); } } // Added code //================================================================================================= if (!CoreSMTSolver::addClause(ps)) return false; if (use_simplification && clauses.size() == nclauses + 1) { Clause& c = *clauses.last(); subsumption_queue.insert(&c); for (int i = 0; i < c.size(); i++) { assert(occurs.size() > var(c[i])); assert(!find(occurs[var(c[i])], &c)); occurs[var(c[i])].push(&c); n_occ[toInt(c[i])]++; touched[var(c[i])] = 1; assert(elimtable[var(c[i])].order == 0); if (elim_heap.inHeap(var(c[i]))) elim_heap.increase_(var(c[i])); } } return 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 } } } }
/*_________________________________________________________________________________________________ | | 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)); } }
// 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; }
/*_________________________________________________________________________________________________ | | 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); } } }