| 
									
										
										
										
											2009-11-11 10:56:37 +00:00
										 |  |  | /****************************************************************************************[Solver.C]
 | 
					
						
							|  |  |  | MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and | 
					
						
							|  |  |  | associated documentation files (the "Software"), to deal in the Software without restriction, | 
					
						
							|  |  |  | including without limitation the rights to use, copy, modify, merge, publish, distribute, | 
					
						
							|  |  |  | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is | 
					
						
							|  |  |  | furnished to do so, subject to the following conditions: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The above copyright notice and this permission notice shall be included in all copies or | 
					
						
							|  |  |  | substantial portions of the Software. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT | 
					
						
							|  |  |  | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 
					
						
							|  |  |  | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | 
					
						
							|  |  |  | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT | 
					
						
							|  |  |  | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 
					
						
							|  |  |  | **************************************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Solver.h"
 | 
					
						
							|  |  |  | #include "Sort.h"
 | 
					
						
							|  |  |  | #include <cmath>
 | 
					
						
							|  |  |  | #include <iostream>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //=================================================================================================
 | 
					
						
							|  |  |  | // Constructor/Destructor:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Solver::Solver() : | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Parameters: (formerly in 'SearchParams')
 | 
					
						
							|  |  |  |     var_decay(1 / 0.95), clause_decay(1 / 0.999), random_var_freq(0.02) | 
					
						
							|  |  |  |   , restart_first(100), restart_inc(1.5), learntsize_factor((double)1/(double)3), learntsize_inc(1.1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // More parameters:
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |   , expensive_ccmin  (true) | 
					
						
							|  |  |  |   , polarity_mode    (polarity_false) | 
					
						
							|  |  |  |   , verbosity        (0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Statistics: (formerly in 'SolverStats')
 | 
					
						
							|  |  |  |     //
 | 
					
						
							|  |  |  |   , starts(0), decisions(0), rnd_decisions(0), propagations(0), conflicts(0) | 
					
						
							|  |  |  |   , clauses_literals(0), learnts_literals(0), max_literals(0), tot_literals(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   //***************
 | 
					
						
							|  |  |  |   , allMinVarsAssigned(false) | 
					
						
							|  |  |  |   //***************
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   , ok               (true) | 
					
						
							|  |  |  |   , cla_inc          (1) | 
					
						
							|  |  |  |   , var_inc          (1) | 
					
						
							|  |  |  |   , qhead            (0) | 
					
						
							|  |  |  |   , simpDB_assigns   (-1) | 
					
						
							|  |  |  |   , simpDB_props     (0) | 
					
						
							|  |  |  |   , order_heap       (VarOrderLt(activity)) | 
					
						
							|  |  |  |   , random_seed      (91648253) | 
					
						
							|  |  |  |   , progress_estimate(0) | 
					
						
							|  |  |  |   , remove_satisfied (true) | 
					
						
							|  |  |  | {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Solver::~Solver() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     for (int i = 0; i < learnts.size(); i++) free(learnts[i]); | 
					
						
							|  |  |  |     for (int i = 0; i < clauses.size(); i++) free(clauses[i]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //=================================================================================================
 | 
					
						
							|  |  |  | // Minor methods:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Creates a new SAT variable in the solver. If 'decision_var' is cleared, variable will not be
 | 
					
						
							|  |  |  | // used as a decision variable (NOTE! This has effects on the meaning of a SATISFIABLE result).
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | Var Solver::newVar(bool sign, bool dvar) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int v = nVars(); | 
					
						
							|  |  |  |     watches   .push();          // (list for positive literal)
 | 
					
						
							|  |  |  |     watches   .push();          // (list for negative literal)
 | 
					
						
							|  |  |  |     reason    .push(NULL); | 
					
						
							|  |  |  |     assigns   .push(toInt(l_Undef)); | 
					
						
							|  |  |  |     level     .push(-1); | 
					
						
							|  |  |  |     activity  .push(0); | 
					
						
							|  |  |  |     seen      .push(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     polarity    .push((char)sign); | 
					
						
							|  |  |  |     decision_var.push((char)dvar); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     insertVarOrder(v); | 
					
						
							|  |  |  |     return v; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 Solver::setminVars(vec<Lit>& ps) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    minVars.clear(); | 
					
						
							|  |  |  |    for (int i=0; i < ps.size(); i++){ | 
					
						
							|  |  |  |      minVars.push(ps[i]); | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  |    allMinVarsAssigned = false; | 
					
						
							|  |  |  |     | 
					
						
							|  |  |  |    return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | //****************
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Solver::attachClause(Clause& c) { | 
					
						
							|  |  |  |     assert(c.size() > 1); | 
					
						
							|  |  |  |     watches[toInt(~c[0])].push(&c); | 
					
						
							|  |  |  |     watches[toInt(~c[1])].push(&c); | 
					
						
							|  |  |  |     if (c.learnt()) learnts_literals += c.size(); | 
					
						
							|  |  |  |     else            clauses_literals += c.size(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Solver::detachClause(Clause& c) { | 
					
						
							|  |  |  |     assert(c.size() > 1); | 
					
						
							|  |  |  |     assert(find(watches[toInt(~c[0])], &c)); | 
					
						
							|  |  |  |     assert(find(watches[toInt(~c[1])], &c)); | 
					
						
							|  |  |  |     remove(watches[toInt(~c[0])], &c); | 
					
						
							|  |  |  |     remove(watches[toInt(~c[1])], &c); | 
					
						
							|  |  |  |     if (c.learnt()) learnts_literals -= c.size(); | 
					
						
							|  |  |  |     else            clauses_literals -= c.size(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Solver::removeClause(Clause& c) { | 
					
						
							|  |  |  |     detachClause(c); | 
					
						
							|  |  |  |     free(&c); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Solver::satisfied(const Clause& c) const { | 
					
						
							|  |  |  |     for (int i = 0; i < c.size(); i++) | 
					
						
							|  |  |  |         if (value(c[i]) == l_True) | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |     return false; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Revert to the state at given level (keeping all assignment at 'level' but not beyond).
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | void Solver::cancelUntil(int level) { | 
					
						
							|  |  |  |     if (decisionLevel() > level){ | 
					
						
							|  |  |  |         for (int c = trail.size()-1; c >= trail_lim[level]; c--){ | 
					
						
							|  |  |  |             Var     x  = var(trail[c]); | 
					
						
							|  |  |  |             assigns[x] = toInt(l_Undef); | 
					
						
							|  |  |  |             insertVarOrder(x); } | 
					
						
							|  |  |  |         qhead = trail_lim[level]; | 
					
						
							|  |  |  |         trail.shrink(trail.size() - trail_lim[level]); | 
					
						
							|  |  |  |         trail_lim.shrink(trail_lim.size() - level); | 
					
						
							|  |  |  |     }  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //**************************
 | 
					
						
							|  |  |  |     if (lastMinVarDL > level){ | 
					
						
							|  |  |  |       allMinVarsAssigned = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     //**************************
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //=================================================================================================
 | 
					
						
							|  |  |  | // Major methods:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Lit Solver::pickBranchLit(int polarity_mode, double random_var_freq) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Var next = var_Undef; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Random decision:
 | 
					
						
							|  |  |  |     if (drand(random_seed) < random_var_freq && !order_heap.empty()){ | 
					
						
							|  |  |  |         next = order_heap[irand(random_seed,order_heap.size())]; | 
					
						
							|  |  |  |         if (toLbool(assigns[next]) == l_Undef && decision_var[next]) | 
					
						
							|  |  |  |             rnd_decisions++; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Activity based decision:
 | 
					
						
							|  |  |  |     while (next == var_Undef || toLbool(assigns[next]) != l_Undef || !decision_var[next]) | 
					
						
							|  |  |  |         if (order_heap.empty()){ | 
					
						
							|  |  |  |             next = var_Undef; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         }else | 
					
						
							|  |  |  |             next = order_heap.removeMin(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool sign = false; | 
					
						
							|  |  |  |     switch (polarity_mode){ | 
					
						
							|  |  |  |     case polarity_true:  sign = false; break; | 
					
						
							|  |  |  |     case polarity_false: sign = true;  break; | 
					
						
							|  |  |  |     case polarity_user:  sign = polarity[next]; break; | 
					
						
							|  |  |  |     case polarity_rnd:   sign = irand(random_seed, 2); break; | 
					
						
							|  |  |  |     default: assert(false); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return next == var_Undef ? lit_Undef : Lit(next, sign); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*_________________________________________________________________________________________________
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | |  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 = 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)]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0;    // ('seen[]' is now cleared)
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Check if 'p' can be removed. 'abstract_levels' is used to abort early if the algorithm is
 | 
					
						
							|  |  |  | // visiting literals at levels that cannot be removed later.
 | 
					
						
							|  |  |  | bool Solver::litRedundant(Lit p, uint32_t abstract_levels) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     analyze_stack.clear(); analyze_stack.push(p); | 
					
						
							|  |  |  |     int top = analyze_toclear.size(); | 
					
						
							|  |  |  |     while (analyze_stack.size() > 0){ | 
					
						
							|  |  |  |         assert(reason[var(analyze_stack.last())] != NULL); | 
					
						
							|  |  |  |         Clause& c = *reason[var(analyze_stack.last())]; analyze_stack.pop(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (int i = 1; i < c.size(); i++){ | 
					
						
							|  |  |  |             Lit p  = c[i]; | 
					
						
							|  |  |  |             if (!seen[var(p)] && level[var(p)] > 0){ | 
					
						
							|  |  |  |                 if (reason[var(p)] != NULL && (abstractLevel(var(p)) & abstract_levels) != 0){ | 
					
						
							|  |  |  |                     seen[var(p)] = 1; | 
					
						
							|  |  |  |                     analyze_stack.push(p); | 
					
						
							|  |  |  |                     analyze_toclear.push(p); | 
					
						
							|  |  |  |                 }else{ | 
					
						
							|  |  |  |                     for (int j = top; j < analyze_toclear.size(); j++) | 
					
						
							|  |  |  |                         seen[var(analyze_toclear[j])] = 0; | 
					
						
							|  |  |  |                     analyze_toclear.shrink(analyze_toclear.size() - top); | 
					
						
							|  |  |  |                     return false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*_________________________________________________________________________________________________
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | |  analyzeFinal : (p : Lit)  ->  [void] | 
					
						
							|  |  |  | |   | 
					
						
							|  |  |  | |  Description: | 
					
						
							|  |  |  | |    Specialized analysis procedure to express the final conflict in terms of assumptions. | 
					
						
							|  |  |  | |    Calculates the (possibly empty) set of assumptions that led to the assignment of 'p', and | 
					
						
							|  |  |  | |    stores the result in 'out_conflict'. | 
					
						
							|  |  |  | |________________________________________________________________________________________________@*/ | 
					
						
							|  |  |  | void Solver::analyzeFinal(Lit p, vec<Lit>& out_conflict) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     out_conflict.clear(); | 
					
						
							|  |  |  |     out_conflict.push(p); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (decisionLevel() == 0) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     seen[var(p)] = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int i = trail.size()-1; i >= trail_lim[0]; i--){ | 
					
						
							|  |  |  |         Var x = var(trail[i]); | 
					
						
							|  |  |  |         if (seen[x]){ | 
					
						
							|  |  |  |             if (reason[x] == NULL){ | 
					
						
							|  |  |  |                 assert(level[x] > 0); | 
					
						
							|  |  |  |                 out_conflict.push(~trail[i]); | 
					
						
							|  |  |  |             }else{ | 
					
						
							|  |  |  |                 Clause& c = *reason[x]; | 
					
						
							|  |  |  |                 for (int j = 1; j < c.size(); j++) | 
					
						
							|  |  |  |                     if (level[var(c[j])] > 0) | 
					
						
							|  |  |  |                         seen[var(c[j])] = 1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             seen[x] = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     seen[var(p)] = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Solver::uncheckedEnqueue(Lit p, Clause* from) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(value(p) == l_Undef); | 
					
						
							|  |  |  |     assigns [var(p)] = toInt(lbool(!sign(p)));  // <<== abstract but not uttermost effecient
 | 
					
						
							|  |  |  |     level   [var(p)] = decisionLevel(); | 
					
						
							|  |  |  |     reason  [var(p)] = from; | 
					
						
							|  |  |  |     trail.push(p); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*_________________________________________________________________________________________________
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | |  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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*_________________________________________________________________________________________________
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | |  reduceDB : ()  ->  [void] | 
					
						
							|  |  |  | |   | 
					
						
							|  |  |  | |  Description: | 
					
						
							|  |  |  | |    Remove half of the learnt clauses, minus the clauses locked by the current assignment. Locked | 
					
						
							|  |  |  | |    clauses are clauses that are reason to some assignment. Binary clauses are never removed. | 
					
						
							|  |  |  | |________________________________________________________________________________________________@*/ | 
					
						
							|  |  |  | struct reduceDB_lt { bool operator () (Clause* x, Clause* y) { return x->size() > 2 && (y->size() == 2 || x->activity() < y->activity()); } }; | 
					
						
							|  |  |  | void Solver::reduceDB() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int     i, j; | 
					
						
							|  |  |  |     double  extra_lim = cla_inc / learnts.size();    // Remove any clause below this activity
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     sort(learnts, reduceDB_lt()); | 
					
						
							|  |  |  |     for (i = j = 0; i < learnts.size() / 2; i++){ | 
					
						
							|  |  |  |         if (learnts[i]->size() > 2 && !locked(*learnts[i])) | 
					
						
							|  |  |  |             removeClause(*learnts[i]); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             learnts[j++] = learnts[i]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (; i < learnts.size(); i++){ | 
					
						
							|  |  |  |         if (learnts[i]->size() > 2 && !locked(*learnts[i]) && learnts[i]->activity() < extra_lim) | 
					
						
							|  |  |  |             removeClause(*learnts[i]); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             learnts[j++] = learnts[i]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     learnts.shrink(i - j); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Solver::removeSatisfied(vec<Clause*>& cs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int i,j; | 
					
						
							|  |  |  |     for (i = j = 0; i < cs.size(); i++){ | 
					
						
							|  |  |  |         if (satisfied(*cs[i])) | 
					
						
							|  |  |  |             removeClause(*cs[i]); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             cs[j++] = cs[i]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     cs.shrink(i - j); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*_________________________________________________________________________________________________
 | 
					
						
							|  |  |  | | | 
					
						
							|  |  |  | |  simplify : [void]  ->  [bool] | 
					
						
							|  |  |  | |   | 
					
						
							|  |  |  | |  Description: | 
					
						
							|  |  |  | |    Simplify the clause database according to the current top-level assigment. Currently, the only | 
					
						
							|  |  |  | |    thing done here is the removal of satisfied clauses, but more things can be put here. | 
					
						
							|  |  |  | |________________________________________________________________________________________________@*/ | 
					
						
							|  |  |  | bool Solver::simplify() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(decisionLevel() == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!ok || propagate() != NULL) | 
					
						
							|  |  |  |         return ok = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (nAssigns() == simpDB_assigns || (simpDB_props > 0)) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Remove satisfied clauses:
 | 
					
						
							|  |  |  |     removeSatisfied(learnts); | 
					
						
							|  |  |  |     if (remove_satisfied)        // Can be turned off.
 | 
					
						
							|  |  |  |         removeSatisfied(clauses); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Remove fixed variables from the variable heap:
 | 
					
						
							|  |  |  |     order_heap.filter(VarFilter(*this)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     simpDB_assigns = nAssigns(); | 
					
						
							|  |  |  |     simpDB_props   = clauses_literals + learnts_literals;   // (shouldn't depend on stats really, but it will do for now)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(ok); | 
					
						
							|  |  |  |     int         backtrack_level; | 
					
						
							|  |  |  |     int         conflictC = 0; | 
					
						
							|  |  |  |     vec<Lit>    learnt_clause; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     starts++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-25 16:42:35 +00:00
										 |  |  |     // bool first = true;
 | 
					
						
							| 
									
										
										
										
											2009-11-11 10:56:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for (;;){ | 
					
						
							|  |  |  |         Clause* confl = propagate(); | 
					
						
							|  |  |  |         if (confl != NULL){ | 
					
						
							|  |  |  |             // CONFLICT
 | 
					
						
							|  |  |  |             conflicts++; conflictC++; | 
					
						
							|  |  |  |             if (decisionLevel() == 0) return l_False; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-25 16:42:35 +00:00
										 |  |  | 	    //            first = false;
 | 
					
						
							| 
									
										
										
										
											2009-11-11 10:56:37 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             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++; | 
					
						
							|  |  |  | 	       | 
					
						
							|  |  |  | 	      if (!allMinVarsAssigned){ | 
					
						
							|  |  |  | 	    	for (int i=0; i<minVars.size(); i++){ | 
					
						
							|  |  |  | 	    	  if (value(minVars[i])==l_Undef){ | 
					
						
							|  |  |  | 	    	    next = minVars[i]; | 
					
						
							|  |  |  | 	    	    break; | 
					
						
							|  |  |  | 	    	  } | 
					
						
							|  |  |  | 	    	} | 
					
						
							|  |  |  | 	    	if (next == lit_Undef){ | 
					
						
							|  |  |  | 	    	  allMinVarsAssigned = true; | 
					
						
							|  |  |  | 	    	  lastMinVarDL = decisionLevel(); | 
					
						
							|  |  |  | 	    	} | 
					
						
							|  |  |  | 	      } | 
					
						
							|  |  |  | 	    } | 
					
						
							|  |  |  | 	    //***************************
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             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); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | double Solver::progressEstimate() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     double  progress = 0; | 
					
						
							|  |  |  |     double  F = 1.0 / nVars(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int i = 0; i <= decisionLevel(); i++){ | 
					
						
							|  |  |  |         int beg = i == 0 ? 0 : trail_lim[i - 1]; | 
					
						
							|  |  |  |         int end = i == decisionLevel() ? trail.size() : trail_lim[i]; | 
					
						
							|  |  |  |         progress += pow(F, i) * (end - beg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return progress / nVars(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Solver::verifyModel() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bool failed = false; | 
					
						
							|  |  |  |     for (int i = 0; i < clauses.size(); i++){ | 
					
						
							|  |  |  |         assert(clauses[i]->mark() == 0); | 
					
						
							|  |  |  |         Clause& c = *clauses[i]; | 
					
						
							|  |  |  |         for (int j = 0; j < c.size(); j++) | 
					
						
							|  |  |  |             if (modelValue(c[j]) == l_True) | 
					
						
							|  |  |  |                 goto next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         reportf("unsatisfied clause: "); | 
					
						
							|  |  |  |         printClause(*clauses[i]); | 
					
						
							|  |  |  |         reportf("\n"); | 
					
						
							|  |  |  |         failed = true; | 
					
						
							|  |  |  |     next:; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(!failed); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //    reportf("Verified %d original clauses.\n", clauses.size());
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Solver::checkLiteralCount() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Check that sizes are calculated correctly:
 | 
					
						
							|  |  |  |     int cnt = 0; | 
					
						
							|  |  |  |     for (int i = 0; i < clauses.size(); i++) | 
					
						
							|  |  |  |         if (clauses[i]->mark() == 0) | 
					
						
							|  |  |  |             cnt += clauses[i]->size(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((int)clauses_literals != cnt){ | 
					
						
							|  |  |  |         fprintf(stderr, "literal count: %d, real value = %d\n", (int)clauses_literals, cnt); | 
					
						
							|  |  |  |         assert((int)clauses_literals == cnt); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |