CVC3

xchaff_solver.cpp

Go to the documentation of this file.
00001 /* =========FOR INTERNAL USE ONLY. NO DISTRIBUTION PLEASE ========== */
00002 
00003 /*********************************************************************
00004  Copyright 2000-2001, Princeton University.  All rights reserved. 
00005  By using this software the USER indicates that he or she has read, 
00006  understood and will comply with the following:
00007 
00008  --- Princeton University hereby grants USER nonexclusive permission 
00009  to use, copy and/or modify this software for internal, noncommercial,
00010  research purposes only. Any distribution, including commercial sale 
00011  or license, of this software, copies of the software, its associated 
00012  documentation and/or modifications of either is strictly prohibited 
00013  without the prior consent of Princeton University.  Title to copyright
00014  to this software and its associated documentation shall at all times 
00015  remain with Princeton University.  Appropriate copyright notice shall 
00016  be placed on all software copies, and a complete copy of this notice 
00017  shall be included in all copies of the associated documentation.  
00018  No right is  granted to use in advertising, publicity or otherwise 
00019  any trademark, service mark, or the name of Princeton University. 
00020 
00021 
00022  --- This software and any associated documentation is provided "as is" 
00023 
00024  PRINCETON UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS 
00025  OR IMPLIED, INCLUDING THOSE OF MERCHANTABILITY OR FITNESS FOR A 
00026  PARTICULAR PURPOSE, OR THAT  USE OF THE SOFTWARE, MODIFICATIONS, OR 
00027  ASSOCIATED DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, 
00028  TRADEMARKS OR OTHER INTELLECTUAL PROPERTY RIGHTS OF A THIRD PARTY.  
00029 
00030  Princeton University shall not be liable under any circumstances for 
00031  any direct, indirect, special, incidental, or consequential damages 
00032  with respect to any claim by USER or any third party on account of 
00033  or arising from the use, or inability to use, this software or its 
00034  associated documentation, even if Princeton University has been advised
00035  of the possibility of those damages.
00036 *********************************************************************/
00037 
00038 
00039 #include "xchaff_solver.h"
00040 #include <algorithm>
00041 
00042 
00043 CSolver::CSolver(void)    
00044 {
00045     dlevel()=0;
00046     _params.time_limit    = 3600 * 48;    //2 days
00047     _params.decision_strategy   = 0;
00048     _params.preprocess_strategy = 0;
00049     _params.allow_clause_deletion     = true ;
00050     _params.clause_deletion_interval    = 5000;
00051     _params.max_unrelevance     = 20;
00052     _params.min_num_clause_lits_for_delete  = 100;
00053     _params.max_conflict_clause_length    = 5000;
00054     _params.bubble_init_step  = 32;
00055 
00056     _params.randomness    = 0;
00057     _params.verbosity   = 0;
00058 
00059     _params.back_track_complete = true;
00060     _params.allow_multiple_conflict   = false;
00061     _params.allow_multiple_conflict_clause  = false;
00062 
00063     _params.allow_restart = true; 
00064     _params.next_restart_time = 50;   //this set the first restart time (in seconds)
00065     _params.restart_time_increment  = 0;
00066     _params.restart_time_incr_incr = 0;
00067 
00068     _params.next_restart_backtrack= 0;
00069     _params.restart_backtrack_incr= 40000;    
00070     _params.restart_backtrack_incr_incr = 100;
00071 
00072     _params.restart_randomness  = 0;  
00073     _params.base_randomness = 0;
00074     _params.randomness    = 0;
00075 
00076     _stats.is_solver_started  = false;
00077     _stats.outcome    = UNKNOWN;
00078     _stats.is_mem_out   = false;
00079     _stats.start_cpu_time = 0;      
00080     _stats.finish_cpu_time  = 0;
00081     _stats.last_cpu_time  = 0;      
00082 
00083     _stats.start_world_time = 0;
00084     _stats.finish_world_time  = 0;
00085 
00086     _stats.num_decisions  = 0;
00087     _stats.num_backtracks = 0;
00088     _stats.max_dlevel     = 0;
00089     _stats.num_implications     = 0;
00090 
00091     _num_marked     = 0;
00092     _dlevel     = 0;    
00093     _stats.total_bubble_move  = 0;
00094 
00095     _dlevel_hook = NULL;
00096     _decision_hook = NULL;
00097     _assignment_hook = NULL;
00098     _deduction_hook = NULL;
00099 }
00100 
00101 CSolver::~CSolver()
00102 {
00103   if (_stats.is_solver_started) {
00104     for (unsigned i=0; i<variables().size(); ++i)
00105   delete _assignment_stack[i];
00106   }
00107 }
00108 
00109 void CSolver::run_periodic_functions(void)
00110 {
00111     //a. clause deletion
00112     if ( _params.allow_clause_deletion &&
00113    _stats.num_backtracks % _params.clause_deletion_interval == 0)
00114         delete_unrelevant_clauses(); 
00115     //b. restart
00116     if (_params.allow_restart && _stats.num_backtracks > _params.next_restart_backtrack) {
00117   _params.next_restart_backtrack += _params.restart_backtrack_incr;
00118   _params.restart_backtrack_incr += _params.restart_backtrack_incr_incr;
00119     float current = current_cpu_time()/1000;
00120     if (current > _params.next_restart_time) {
00121         if (_params.verbosity > 1) cout << "restart..." << endl;
00122         _params.next_restart_time = current + _params.restart_time_increment;
00123       _params.restart_time_increment += _params.restart_time_incr_incr;
00124       _params.randomness = _params.restart_randomness;
00125       restart();
00126   }
00127     }    
00128     //c. update var stats for decision
00129     if ((_stats.num_decisions % 0xff)==0) 
00130       update_var_stats();
00131     //d. run hook functions
00132     for (unsigned i=0; i< _hooks.size(); ++i) {
00133   pair<int,pair<HookFunPtrT, int> > & hook = _hooks[i];
00134   if (_stats.num_decisions >= hook.first) {
00135       hook.first += hook.second.second;
00136       hook.second.first((void *) this);
00137   }
00138     }
00139 } 
00140 
00141 
00142 void CSolver::init(void)
00143 {
00144     CDatabase::init();
00145 
00146     _stats.is_solver_started  = true;
00147     _stats.start_cpu_time   = current_cpu_time();
00148     _stats.start_world_time = current_world_time();
00149     _stats.num_free_variables = num_variables();
00150     for (unsigned i=0; i<variables().size(); ++i)
00151   _assignment_stack.push_back(new vector<int>);
00152 
00153     _var_order.resize( num_variables());
00154     _last_var_lits_count[0].resize(variables().size());
00155     _last_var_lits_count[1].resize(variables().size());
00156     CHECK(dump());
00157 }
00158 
00159 
00160 int CSolver::add_variables(int new_vars)
00161 {
00162   int old_num_vars = variables().size();
00163   int num_vars = old_num_vars + new_vars;
00164   variables().resize(num_vars) ; 
00165   if (_stats.is_solver_started) {
00166     _stats.num_free_variables += new_vars;
00167 
00168     for (int i=old_num_vars; i<num_vars; ++i) {
00169       _assignment_stack.push_back(new vector<int>);
00170       _var_order.push_back(pair<int, int>(i,0));
00171     }
00172     _last_var_lits_count[0].resize(num_vars);
00173     _last_var_lits_count[1].resize(num_vars);
00174   }
00175   return old_num_vars;
00176 }
00177 
00178 
00179 ClauseIdx CSolver::add_clause(vector<long>& lits, bool addConflicts) {
00180     int new_cl;
00181     int n_lits = lits.size();
00182     //a. do we need to enlarge lits pool?
00183     while (lit_pool_free_space() <= n_lits + 1) { 
00184   if (enlarge_lit_pool()==false) 
00185       return -1; //mem out, can't enlarge lit pool, because 
00186                  //ClauseIdx can't be -1, so it shows error.
00187     } 
00188     //b. get a free cl index;
00189     if (_unused_clause_idx_queue.empty()) {
00190   new_cl = _clauses.size();
00191   _clauses.resize(new_cl + 1);
00192     }
00193     else {
00194   new_cl = _unused_clause_idx_queue.front();
00195   _unused_clause_idx_queue.pop();
00196     }
00197     //c. add the clause lits to lits pool
00198     clause(new_cl).init(lit_pool_end(), n_lits);
00199 
00200     //I want to verify added clauses are either all free or all 0
00201     bool satisfied = false, is_unit = false, is_conflict = false;
00202     int num_unknown = 0;
00203     for (int i=0; i< n_lits; ++i){
00204   int var_idx = lits[i]>>1;
00205   if ((unsigned)var_idx >= variables().size()) {
00206           assert(false);
00207         }
00208   int var_sign = lits[i]&0x1;
00209   lit_pool_push_back( ((var_idx<<1) + var_sign) << 2);
00210   ++variable(var_idx).lits_count(var_sign);
00211   int lit_value = literal_value(clause(new_cl).literal(i));
00212 
00213   if (lit_value == 1) {
00214     satisfied = true;
00215   }
00216   else if (lit_value != 0) {
00217     ++num_unknown;
00218   }
00219     }
00220     is_conflict = !satisfied && (num_unknown == 0);
00221     is_unit = !satisfied && (num_unknown == 1);
00222     assert(_stats.is_solver_started || num_unknown == n_lits);
00223     lit_pool_push_back(-new_cl); //push in the clause idx in the end
00224     //d. set the head/tail pointers
00225     if (clause(new_cl).num_lits() > 1) {
00226   //add the ht. note: ht must be the last free var
00227   int max_idx = -1, max_dl = -1;
00228   CClause & cl = clause(new_cl);
00229   int i, sz = cl.num_lits();
00230   int other_ht_idx;
00231   for (i=0; i< sz; ++i) {
00232       int v_idx = cl.literals()[i].var_index();
00233       if (variable(v_idx).value()==UNKNOWN) {
00234     int v_sign = cl.literals()[i].var_sign();
00235     variable(v_idx).ht_ptr(v_sign).push_back( & cl.literals()[i]);
00236     cl.literals()[i].set_ht(1);
00237     other_ht_idx = i;
00238     break;
00239       }
00240       else {
00241     if (variable(v_idx).dlevel() > max_dl) {
00242         max_dl = variable(v_idx).dlevel();
00243         max_idx = i;
00244     }
00245       }
00246   }
00247   if (i >= sz) {
00248       //no unknown literals. so use the max dl literal
00249       int v_idx = cl.literals()[max_idx].var_index();
00250       int v_sign = cl.literals()[max_idx].var_sign();
00251       variable(v_idx).ht_ptr(v_sign).push_back( & cl.literals()[max_idx]);
00252       cl.literals()[max_idx].set_ht(1);
00253       other_ht_idx = max_idx;
00254   }
00255   max_idx = -1; max_dl = -1;
00256   for (i=sz-1; i>=0; --i) {
00257       if (i==other_ht_idx ) continue;
00258       int v_idx = cl.literals()[i].var_index();
00259       if (variable(v_idx).value()==UNKNOWN) {
00260     int v_sign = cl.literals()[i].var_sign();
00261     variable(v_idx).ht_ptr(v_sign).push_back( & cl.literals()[i]);
00262     cl.literals()[i].set_ht(-1);
00263     break;
00264       }
00265       else {
00266     if (variable(v_idx).dlevel() > max_dl) {
00267         max_dl = variable(v_idx).dlevel();
00268         max_idx = i;
00269     }
00270       }
00271   }
00272   if (i < 0) {
00273       int v_idx = cl.literals()[max_idx].var_index();
00274       int v_sign = cl.literals()[max_idx].var_sign();
00275       CLitPoolElement * lit_ptr = & cl.literals()[max_idx];
00276       variable(v_idx).ht_ptr(v_sign).push_back(lit_ptr);
00277       cl.literals()[max_idx].set_ht(-1);
00278   }
00279     }
00280     //update some statistics
00281     ++CDatabase::_stats.num_added_clauses; 
00282     CDatabase::_stats.num_added_literals += n_lits;
00283     if (is_unit && _stats.is_solver_started) {
00284       if (n_lits == 1) _addedUnitClauses.push_back(new_cl);
00285       int lit = find_unit_literal(new_cl);
00286       assert(lit);
00287       queue_implication(lit, new_cl);
00288     }
00289     else if (addConflicts && is_conflict) {
00290       _conflicts.push_back(new_cl);
00291     }
00292     return new_cl;
00293 }
00294 
00295 
00296 void CSolver::set_var_value(int v, int value, ClauseIdx ante, int dl)
00297 {
00298     assert (value == 0 || value == 1);
00299     CHECK_FULL(dump());
00300     CHECK(verify_integrity());
00301     CHECK (cout << "Setting\t" << (value>0?"+":"-") << v 
00302      << " at " << dl << " because " << ante<< endl;);
00303     ++_stats.num_implications ;
00304     --num_free_variables();
00305     if (_assignment_hook) {
00306       (*_assignment_hook)(_assignment_hook_cookie, v, value);
00307     }
00308     CVariable & var = _variables[v];
00309     assert (var.value() == UNKNOWN);
00310     var.dlevel() = dl;
00311     var.value() = value;
00312     var.set_antecedence(ante);
00313     vector<CLitPoolElement *> & ht_ptrs = var.ht_ptr(value);
00314     if (dl == dlevel()) 
00315   set_var_value_with_current_dl(v, ht_ptrs);
00316     else 
00317   set_var_value_not_current_dl(v, ht_ptrs);
00318 }
00319 
00320 
00321 void CSolver::set_var_value_with_current_dl(int v, vector<CLitPoolElement *> & ht_ptrs)
00322 {
00323     ClauseIdx cl_idx;
00324     CLitPoolElement * ht_ptr, * other_ht_ptr = NULL, * ptr;
00325     int dir;
00326     for (vector <CLitPoolElement *>::iterator itr = ht_ptrs.begin(); itr != ht_ptrs.end(); ++itr) {
00327   ht_ptr = *itr;
00328   dir = ht_ptr->direction();
00329   ptr = ht_ptr;
00330   while(1) {
00331       ptr += dir;
00332       if (ptr->val() <= 0) {
00333     if (dir == 1) 
00334         cl_idx = - ptr->val();
00335     if (dir == ht_ptr->direction()) {
00336         ptr = ht_ptr;
00337         dir = -dir;
00338         continue;
00339     }
00340     int the_value = literal_value (*other_ht_ptr);
00341     if (the_value == 0) //a conflict
00342         _conflicts.push_back(cl_idx);
00343     else if ( the_value != 1) //e.g. unknown
00344         queue_implication (other_ht_ptr->s_var(), cl_idx);
00345     break;
00346       }
00347       if (ptr->is_ht()) {
00348     other_ht_ptr = ptr;
00349     continue;
00350       }
00351       if (literal_value(*ptr) == 0) 
00352     continue;
00353       //now it's value is either 1 or unknown
00354       int v1 = ptr->var_index();
00355       int sign = ptr->var_sign();
00356       variable(v1).ht_ptr(sign).push_back(ptr);
00357       ht_ptr->unset_ht();
00358       ptr->set_ht(dir);
00359 
00360       *itr = ht_ptrs.back();
00361       ht_ptrs.pop_back();
00362       --itr;
00363       break;
00364   }
00365     }
00366 }
00367 
00368 void CSolver::set_var_value_not_current_dl(int v, vector<CLitPoolElement *> & ht_ptrs)
00369 {
00370     ClauseIdx cl_idx;
00371     CLitPoolElement * ht_ptr, * other_ht_ptr = NULL, * ptr, * max_ptr = NULL;
00372     int dir,max_dl;
00373 
00374     for (vector <CLitPoolElement *>::iterator itr = ht_ptrs.begin(); 
00375    itr != ht_ptrs.end(); ++itr) {
00376   max_dl = -1;
00377   ht_ptr = *itr;
00378   dir = ht_ptr->direction();
00379   ptr = ht_ptr;
00380   while(1) {
00381       ptr += dir;
00382       if (ptr->val() <= 0) {
00383     if (dir == 1) 
00384         cl_idx = - ptr->val();
00385     if (dir == ht_ptr->direction()) {
00386         ptr = ht_ptr;
00387         dir = -dir;
00388         continue;
00389     }
00390     if (variable(ht_ptr->var_index()).dlevel() < max_dl) {
00391         int v1 = max_ptr->var_index();
00392         int sign = max_ptr->var_sign();
00393         variable(v1).ht_ptr(sign).push_back(max_ptr);
00394         ht_ptr->unset_ht();
00395         max_ptr->set_ht(dir);
00396         *itr = ht_ptrs.back();
00397         ht_ptrs.pop_back();
00398         --itr;
00399     }
00400     int the_value = literal_value (*other_ht_ptr);
00401     if (the_value == 0) //a conflict
00402         _conflicts.push_back(cl_idx);
00403     else if ( the_value != 1) //e.g. unknown
00404         queue_implication (other_ht_ptr->s_var(), cl_idx);
00405     break;
00406       }
00407       if (ptr->is_ht()) {
00408     other_ht_ptr = ptr;
00409     continue;
00410       }
00411       if (literal_value(*ptr) == 0) {
00412     if (variable(ptr->var_index()).dlevel() > max_dl) {
00413         max_dl = variable(ptr->var_index()).dlevel();
00414         max_ptr = ptr;
00415     }
00416     continue;
00417       }
00418       //now it's value is either 1 or unknown
00419       int v1 = ptr->var_index();
00420       int sign = ptr->var_sign();
00421       variable(v1).ht_ptr(sign).push_back(ptr);
00422       ht_ptr->unset_ht();
00423       ptr->set_ht(dir);
00424 
00425       *itr = ht_ptrs.back();
00426       ht_ptrs.pop_back();
00427       --itr;
00428       break;
00429   }
00430     }
00431 }
00432 
00433 void CSolver::unset_var_value(int v)
00434 {
00435     CHECK(cout <<"Unset var " << (variable(v).value()?"+":"-") << v << endl;);
00436     CVariable & var = variable(v);
00437     if (var.var_score_pos() < _max_score_pos)
00438   _max_score_pos = var.var_score_pos();
00439     var.value() = UNKNOWN;
00440     var.set_antecedence(NULL_CLAUSE);
00441     var.dlevel() = -1;
00442     if (_assignment_hook) {
00443       (*_assignment_hook)(_assignment_hook_cookie, v, -1);
00444     }
00445 }
00446 
00447 int CSolver::find_max_clause_dlevel(ClauseIdx cl)
00448 {
00449 //if cl has single literal, then dlevel should be 0 
00450     int max_level = 0;
00451     if (cl == NULL_CLAUSE || cl == FLIPPED) 
00452   return dlevel();
00453     for (int i=0, sz= clause(cl).num_lits(); i<sz;  ++i) {
00454   int var_idx =((clause(cl).literals())[i]).var_index();
00455   if (_variables[var_idx].value() != UNKNOWN) {
00456       if (max_level < _variables[var_idx].dlevel())
00457     max_level =  _variables[var_idx].dlevel();
00458   }
00459     }
00460     return max_level; 
00461 }
00462 
00463 void CSolver::dump_assignment_stack(ostream & os) {
00464     cout << "Assignment Stack:  ";
00465     for (int i=0; i<= dlevel(); ++i) {
00466   if ((*_assignment_stack[i]).size() > 0)
00467   if (variable( (*_assignment_stack[i])[0]>>1).get_antecedence()==FLIPPED)
00468       cout << "*" ;
00469   cout << "(" <<i << ":";
00470   for (unsigned j=0; j<(*_assignment_stack[i]).size(); ++j )
00471       cout << ((*_assignment_stack[i])[j]&0x1?"-":"+")
00472      << ((*_assignment_stack[i])[j] >> 1) << " ";
00473   cout << ") " << endl;
00474     }
00475     cout << endl;
00476 }
00477 
00478 
00479 bool CDatabase::is_conflict(ClauseIdx cl)
00480 {
00481     CLitPoolElement * lits = clause(cl).literals();
00482     for (int i=0, sz= clause(cl).num_lits(); i<sz;  ++i)
00483   if (literal_value(lits[i]) != 0)
00484     return false;
00485     return true;
00486 }
00487 
00488 bool CDatabase::is_satisfied(ClauseIdx cl)
00489 {
00490     CLitPoolElement * lits = clause(cl).literals();
00491     for (int i=0, sz= clause(cl).num_lits(); i<sz; ++i) 
00492   if (literal_value(lits[i]) == 1) 
00493       return true;
00494     return false;
00495 }
00496 
00497 int CDatabase::find_unit_literal(ClauseIdx cl) 
00498 {
00499 //if it's not unit, return 0.
00500     int unassigned = 0;
00501     for (int i=0, sz= clause(cl).num_lits(); i<sz;  ++i) {
00502   int var_idx =((clause(cl).literals())[i]).var_index();
00503   if (_variables[var_idx].value() == UNKNOWN) {
00504       if (unassigned == 0) 
00505     unassigned = clause(cl).literals()[i].s_var();
00506       else //more than one unassigned
00507     return 0;
00508   }
00509     }
00510     return unassigned;
00511 }
00512 
00513 void CSolver::delete_unrelevant_clauses(void) 
00514 {
00515     CHECK_FULL (dump());
00516     int original_num_deleted = num_deleted_clauses();
00517     if (CDatabase::_stats.mem_used_up) {
00518   CDatabase::_stats.mem_used_up = false;
00519   if (++CDatabase::_stats.mem_used_up_counts < 5) {
00520       _params.max_unrelevance = (int) (_params.max_unrelevance * 0.8);
00521       if (_params.max_unrelevance < 4)
00522     _params.max_unrelevance = 4;
00523       _params.min_num_clause_lits_for_delete = (int) (_params.min_num_clause_lits_for_delete* 0.8);
00524       if (_params.min_num_clause_lits_for_delete < 10)
00525     _params.min_num_clause_lits_for_delete = 10;
00526       _params.max_conflict_clause_length = (int) (_params.max_conflict_clause_length*0.8);
00527       if (_params.max_conflict_clause_length < 50 )
00528     _params.max_conflict_clause_length = 50;
00529       CHECK(
00530       cout << "Forced to reduce unrelevance in clause deletion. " << endl;
00531       cout <<"MaxUnrel: " << _params.max_unrelevance 
00532      << "  MinLenDel: " << _params.min_num_clause_lits_for_delete
00533      << "  MaxLenCL : " << _params.max_conflict_clause_length << endl;
00534     );
00535   }
00536     }
00537     //first find out the clause to delete and mark them
00538     for (vector<CClause>::iterator itr = clauses().begin() + init_num_clauses(); 
00539    itr != clauses().end(); ++itr) {
00540   CClause & cl = * itr;
00541   if (!cl.in_use() || cl.num_lits() < _params.min_num_clause_lits_for_delete ) continue;
00542   int val_0_lits = 0, val_1_lits = 0, unknown_lits = 0;
00543   for (int i=0; i< cl.num_lits(); ++i) {
00544       int lit_value = literal_value (cl.literal(i));
00545         if (lit_value == 0 ) ++val_0_lits;
00546         else if (lit_value == 1) ++val_1_lits;
00547         else ++unknown_lits;
00548       if (unknown_lits + val_1_lits > _params.max_unrelevance) {
00549     mark_clause_deleted(cl);
00550     _unused_clause_idx_queue.push(itr - clauses().begin());
00551     CHECK (cout << "Deleting Unrelevant clause: " << cl << endl;);
00552     break;
00553       }
00554       if (cl.num_lits() > _params.max_conflict_clause_length && 
00555     (unknown_lits+val_1_lits > 1) ) { //to make sure it's not generating an implication
00556                                       //and it's not an antecedence for other var assignment
00557     mark_clause_deleted(cl);
00558     CHECK (cout << "Deleting too large clause: " << cl << endl;);
00559     _unused_clause_idx_queue.push(itr - clauses().begin());
00560     break;
00561       }
00562   }
00563     }
00564     //now delete the index from variables
00565     if (original_num_deleted == num_deleted_clauses()) 
00566   return ; //didn't delete anything
00567     for (vector<CVariable>::iterator itr = variables().begin(); 
00568    itr != variables().end(); ++ itr) {
00569   for (int i=0; i<2; ++i) { //for each phase
00570       //delete the h_t index from the vars
00571       vector<CLitPoolElement *> & ht_ptr = (*itr).ht_ptr(i);
00572       for (vector<CLitPoolElement *>::iterator my_itr = ht_ptr.begin(); 
00573      my_itr != ht_ptr.end(); ++my_itr) {
00574     if ( (*my_itr)->val() <= 0) {
00575         *my_itr = ht_ptr.back();
00576         ht_ptr.pop_back();
00577         --my_itr;
00578     }
00579       }
00580   }
00581     }
00582     CHECK(cout << "Deleting " << num_deleted_clauses() - original_num_deleted << " Clause ";
00583       cout << " and " << num_deleted_literals() - original_del_lits << " Literals " << endl;);
00584     CHECK_FULL (dump());
00585 }
00586 //============================================================================================
00587 bool CSolver::time_out(void) 
00588 {
00589     if ( (current_cpu_time() - _stats.start_cpu_time)/1000.0 > _params.time_limit )
00590   return true;
00591     return false;
00592 }
00593 
00594 inline bool compare_var_stat(const pair<int, int> & v1, 
00595           const pair<int, int> & v2) 
00596 {
00597     if (v1.second > v2.second) return true;
00598     return false;
00599 }
00600 
00601 void CSolver::update_var_stats(void) 
00602 {
00603     for(unsigned i=1; i< variables().size(); ++i) {
00604   CVariable & var = variable(i);
00605   var.score(0) = var.score(0)/2 + var.lits_count(0) - _last_var_lits_count[0][i];
00606   var.score(1) = var.score(1)/2 + var.lits_count(1) - _last_var_lits_count[1][i];
00607   _last_var_lits_count[0][i] = var.lits_count(0);
00608   _last_var_lits_count[1][i] = var.lits_count(1);
00609   _var_order[i-1] = pair<int, int>(i, var.score());
00610     }
00611     ::stable_sort(_var_order.begin(), _var_order.end(), compare_var_stat);
00612     for (unsigned i=0; i<_var_order.size(); ++i) 
00613   variable(_var_order[i].first).var_score_pos() = i;
00614     _max_score_pos = 0;
00615 }
00616 
00617 bool CSolver::decide_next_branch(void)
00618 {
00619     ++_stats.num_decisions;
00620     if (!_implication_queue.empty()) {
00621   //some hook function did a decision, so skip my own decision making.
00622   //if the front of implication queue is 0, that means it's finished
00623   //because var index start from 1, so 2 *vid + sign won't be 0. 
00624   //else it's a valid decision.
00625   _max_score_pos = 0; //reset the max_score_position.
00626   return _implication_queue.front().first;
00627     }
00628   
00629     int s_var = 0, s_var2;
00630     bool done = false;
00631 
00632     unsigned i, var_idx, sign;
00633     CVariable * ptr;
00634 
00635     for (i=_max_score_pos; i<_var_order.size(); ++i) {
00636       var_idx = _var_order[i].first;
00637       ptr = &(variables()[var_idx]);
00638       if (ptr->value()==UNKNOWN) {
00639         //move th max score position pointer
00640         _max_score_pos = i;
00641         //make some randomness happen
00642         if (--_params.randomness < _params.base_randomness)
00643           _params.randomness = _params.base_randomness;
00644 
00645         int randomness = _params.randomness;
00646         if (randomness >= num_free_variables())
00647           randomness = num_free_variables() - 1;
00648         int skip =random()%(1+randomness);
00649         int index = i;
00650         while (skip > 0) {
00651           ++index;
00652           var_idx = _var_order[index].first;
00653           ptr = &(variables()[var_idx]);
00654           if (ptr->value()==UNKNOWN)
00655             --skip;
00656         }
00657         assert (ptr->value() == UNKNOWN);
00658         sign = ptr->score(0) > ptr->score(1) ? 0 : 1;
00659         s_var = var_idx + var_idx + sign;
00660         break;
00661       }
00662     }
00663     if (s_var < 2) done = true;
00664 
00665     if (_decision_hook) {
00666     decide:
00667       s_var2 = (*_decision_hook)(_decision_hook_cookie, &done);
00668       if (done) {
00669         if (s_var2 == -1) {
00670           // No more decisions
00671           return false;
00672         }
00673         else {
00674           // check for more work
00675           if (!_implication_queue.empty() ||
00676               _conflicts.size() != 0)
00677             return false;
00678           else goto decide;
00679         }
00680       }
00681       else {
00682         if (s_var2 == -1) {
00683           // use SAT choice
00684         }
00685         else {
00686           // use decision
00687           s_var = s_var2;
00688         }
00689       }
00690     }
00691 
00692     if (s_var<2) //no more free vars, solution found,  quit
00693   return false;
00694     ++dlevel();
00695     if (_dlevel_hook) {
00696       (*_dlevel_hook)(_dlevel_hook_cookie, 1);
00697     }
00698     if (dlevel() > _stats.max_dlevel) _stats.max_dlevel = dlevel();
00699     CHECK (cout << "**Decision at Level " << dlevel() ;
00700      cout <<": " << s_var << "\te.g. " << (s_var&0x1?"-":" ") ;
00701      cout <<(s_var>>1)  << endl; );
00702     queue_implication(s_var, NULL_CLAUSE);
00703     return true;
00704 }
00705 
00706 int CSolver::preprocess(bool allowNewClauses) 
00707 {
00708     //1. detect all the unused variables
00709   if (!allowNewClauses) {
00710     vector<int> un_used;
00711     for (int i=1, sz=variables().size(); i<sz; ++i) {
00712   CVariable & v = variable(i);
00713     if (v.lits_count(0) == 0 && v.lits_count(1) == 0) {
00714       un_used.push_back(i);
00715       v.value() = 1; 
00716       v.dlevel() = -1;
00717   }
00718     }
00719     num_free_variables() -= un_used.size();
00720     if (_params.verbosity>1 && un_used.size() > 0) {
00721   cout << un_used.size()<< " Variables are defined but not used " << endl;
00722   if (_params.verbosity > 2) {
00723       for (unsigned i=0; i< un_used.size(); ++i)
00724     cout << un_used[i] << " ";
00725       cout << endl;
00726   }
00727     }
00728     //2. detect all variables with only one phase occuring
00729     vector<int> uni_phased;
00730     for (int i=1, sz=variables().size(); i<sz; ++i) {
00731   CVariable & v = variable(i);
00732   if (v.value() != UNKNOWN)
00733       continue;
00734     if (v.lits_count(0) == 0){ //no positive phased lits.
00735       queue_implication( i+i+1, NULL_CLAUSE);
00736       uni_phased.push_back(-i);
00737   }
00738   else if (v.lits_count(1) == 0){ //no negative phased lits.
00739       queue_implication( i+i, NULL_CLAUSE);
00740       uni_phased.push_back(i);
00741   }
00742     }
00743     if (_params.verbosity>1 && uni_phased.size() > 0) {
00744   cout << uni_phased.size()<< " Variables only appear in one phase." << endl;
00745   if (_params.verbosity > 2) {
00746       for (unsigned i=0; i< uni_phased.size(); ++i)
00747     cout << uni_phased[i] << " ";
00748       cout <<endl;
00749   }
00750     }
00751   }
00752     //3. detect all the unit clauses
00753     for (ClauseIdx i=0, sz=clauses().size(); i<sz; ++i) {
00754   if (clause(i).num_lits() == 1){ //unit clause
00755       queue_implication(find_unit_literal(i), i);
00756   }
00757     }
00758 
00759     if(deduce()==CONFLICT) return CONFLICT;
00760     return NO_CONFLICT;    
00761 }
00762 
00763 void CSolver::real_solve(void)
00764 {
00765     while(1) {
00766         run_periodic_functions();
00767   if (decide_next_branch() || !_implication_queue.empty() ||
00768             _conflicts.size() != 0) {
00769       while (deduce()==CONFLICT) { 
00770     int blevel = analyze_conflicts();
00771     if (blevel <= 0) {
00772         _stats.outcome = UNSATISFIABLE;
00773         return;
00774     }
00775                 else if (_addedUnitClauses.size()) {
00776                   // reassert added unit clauses
00777                   unsigned idx = _addedUnitClauses.size()-1;
00778                   ClauseIdx cl = _addedUnitClauses.back();
00779                   int lit = find_unit_literal(cl);
00780                   while (lit != 0) {
00781                     queue_implication(lit, cl);
00782                     if (idx == 0) break;
00783                     cl = _addedUnitClauses[--idx];
00784                     lit = find_unit_literal(cl);
00785                   }
00786                 }
00787       }
00788   }
00789   else {
00790           _stats.outcome = SATISFIABLE;
00791           return;
00792   }
00793   if (time_out()) { 
00794       _stats.outcome = TIME_OUT;
00795       return; 
00796   }
00797   if (_stats.is_mem_out) {
00798       _stats.outcome = MEM_OUT;
00799       return; 
00800   }
00801     }
00802 }
00803 
00804 int CSolver::solve(bool allowNewClauses)
00805 {
00806     init();
00807     //preprocess 
00808     if(preprocess(allowNewClauses)==CONFLICT) {
00809   _stats.outcome = UNSATISFIABLE;
00810     }
00811     else { //the real search
00812       if (_dlevel_hook) {
00813         (*_dlevel_hook)(_dlevel_hook_cookie, 1);
00814       }
00815       real_solve();
00816     }
00817     _stats.finish_cpu_time = current_cpu_time();
00818     _stats.finish_world_time = current_world_time();
00819     return _stats.outcome;
00820 }
00821 
00822 int CSolver::continueCheck()
00823 {
00824   real_solve();
00825   _stats.finish_cpu_time = current_cpu_time();
00826   _stats.finish_world_time = current_world_time();
00827   return _stats.outcome;
00828 }
00829 
00830 void CSolver::back_track(int blevel)
00831 {
00832     CHECK (cout << "Back track to " << blevel <<" ,currently in "<< dlevel() << " level" << endl;);
00833     CHECK_FULL (dump());
00834     CHECK(verify_integrity());
00835     assert(blevel <= dlevel());
00836     for (int i=dlevel(); i>= blevel; --i) {
00837   vector<int> & assignments = *_assignment_stack[i];
00838   for (int j=assignments.size()-1 ; j>=0; --j) 
00839     unset_var_value(assignments[j]>>1);
00840   num_free_variables() += assignments.size();
00841   assignments.clear();
00842   if (_dlevel_hook) {
00843     (*_dlevel_hook)(_dlevel_hook_cookie, -1);
00844   }
00845     }
00846     dlevel() = blevel - 1;
00847     ++_stats.num_backtracks;
00848     CHECK_FULL (dump());
00849     CHECK(verify_integrity());
00850 }
00851 
00852 int CSolver::deduce(void) 
00853 {
00854 restart:
00855     while (!_implication_queue.empty() && _conflicts.size()==0) {
00856   int literal = _implication_queue.front().first;
00857   int variable_index = literal>>1;
00858   ClauseIdx cl = _implication_queue.front().second;
00859   _implication_queue.pop();
00860   CVariable * the_var = &(variables()[variable_index]);
00861   if ( the_var->value() == UNKNOWN) { // an implication
00862       int dl;
00863       if (_params.back_track_complete)
00864     dl = dlevel();
00865       else 
00866     dl = find_max_clause_dlevel(cl);
00867       set_var_value(variable_index, !(literal&0x1), cl, dl);
00868       the_var = &(variables()[variable_index]);
00869       _assignment_stack[dl]->push_back(literal);
00870       CHECK(verify_integrity());
00871   }
00872   else if (the_var->value() == (literal&0x1) ) { //a conflict
00873       //note: literal & 0x1 == 1 means the literal is in negative phase
00874       _conflicts.push_back(cl);
00875   }
00876     }
00877     if (!_conflicts.size() && _deduction_hook) {
00878       (*_deduction_hook)(_deduction_hook_cookie);
00879       if (!_implication_queue.empty()) goto restart;
00880     }
00881     while(!_implication_queue.empty()) _implication_queue.pop();
00882     return (_conflicts.size()?CONFLICT:NO_CONFLICT);
00883 }
00884 
00885 
00886 void CSolver::verify_integrity(void) 
00887 {
00888 }
00889 
00890 void CSolver::mark_vars_at_level(ClauseIdx cl, int var_idx, int dl)
00891 {
00892     for (CLitPoolElement * itr = clause(cl).literals(); (*itr).val() > 0 ; ++ itr) {
00893   int v = (*itr).var_index();
00894   if (v == var_idx) 
00895       continue;
00896   else if (variable(v).dlevel() == dl) {
00897       if (!variable(v).is_marked()) {
00898     variable(v).set_marked();
00899     ++ _num_marked;
00900       }
00901   }
00902   else {
00903       assert (variable(v).dlevel() < dl);
00904       if (variable(v).in_new_cl() == -1){ //it's not in the new cl
00905     variable(v).set_in_new_cl((*itr).var_sign());
00906     _conflict_lits.push_back((*itr).s_var());
00907       }
00908   }
00909     }
00910 }
00911 
00912 int CSolver::analyze_conflicts(void) {
00913     return conflict_analysis_zchaff();
00914 }
00915 
00916 int CSolver::conflict_analysis_zchaff (void) 
00917 {
00918     assert (_conflicts.size());
00919     assert (_implication_queue.empty());
00920     assert (_num_marked == 0);
00921     int back_level = 0;
00922     ClauseIdx conflict_cl;
00923     vector<ClauseIdx> added_conflict_clauses;
00924     for (int i=0, sz=_conflicts.size(); i<sz; ++i) {
00925   ClauseIdx cl = _conflicts[i];
00926 
00927   if (!is_conflict(cl)) continue;
00928 
00929   back_level = 0; // reset it
00930   while (_conflict_lits.size()) {
00931       CVariable & var = variable(_conflict_lits.back() >> 1);
00932       _conflict_lits.pop_back();
00933       assert (var.in_new_cl() != -1);
00934       var.set_in_new_cl(-1);
00935   }
00936   int max_dlevel = find_max_clause_dlevel(cl); // find the max level, which is the back track level
00937   bool first_time = true; //its the beginning
00938   bool prev_is_uip = false;
00939   mark_vars_at_level (cl, -1 /*var*/, max_dlevel);
00940 
00941   vector <int> & assignments = *_assignment_stack[max_dlevel];
00942   for (int j = assignments.size() - 1; j >= 0; --j ) { //now add conflict lits, and unassign vars
00943       int assigned = assignments[j];
00944       if (variable(assigned>>1).is_marked()) {
00945     variable(assigned>>1).clear_marked();
00946     -- _num_marked; 
00947     ClauseIdx ante_cl = variables()[assigned>>1].get_antecedence();
00948 
00949     if ( (_num_marked == 0 && 
00950           (!first_time) && 
00951           (prev_is_uip == false))
00952           || ante_cl==NULL_CLAUSE) { //conclude add clause
00953         assert (variable(assigned>>1).in_new_cl()==-1);
00954         _conflict_lits.push_back(assigned^0x1);  // add this assignment's reverse, e.g. UIP
00955         int conflict_cl = add_clause(_conflict_lits, false);
00956         if (conflict_cl < 0 ) {
00957       _stats.is_mem_out = true;
00958       _conflicts.clear();
00959       assert (_implication_queue.empty());
00960       return 1; 
00961         }
00962         _conflict_lits.pop_back();  // remove for continue use of _conflict_lits
00963         added_conflict_clauses.push_back(conflict_cl);
00964 
00965         CHECK(cout <<"Conflict clause: " << cl << " : " << clause(cl) << endl;
00966         cout << "**Add Clause " <<conflict_cl<< " : "<<clause(conflict_cl) << endl; 
00967       );
00968 
00969         prev_is_uip = true;
00970         break; //if do this, only one clause will be added.
00971     }
00972     else prev_is_uip = false;
00973 
00974     if ( ante_cl != NULL_CLAUSE ) 
00975         mark_vars_at_level(ante_cl, assigned>>1/*var*/, max_dlevel);
00976     else 
00977         assert (j == 0);
00978     first_time = false;
00979       }
00980   }
00981   back_level = max_dlevel;
00982   back_track(max_dlevel); 
00983     }
00984     assert (_num_marked == 0);
00985     if (back_level==0) //there are nothing to be done
00986       return back_level;
00987 
00988     if (_params.back_track_complete) {
00989   for (unsigned i=0; i< added_conflict_clauses.size(); ++i) {
00990       ClauseIdx cl = added_conflict_clauses[i];
00991       if (find_unit_literal(cl)) { //i.e. if it's a unit clause
00992       int dl = find_max_clause_dlevel(cl);
00993       if (dl < dlevel()) { //thus make sure implied vars are at current dl.
00994           back_track(dl+1);
00995     }
00996       }
00997   }
00998     }
00999     for (int i=0, sz=added_conflict_clauses.size(); i<sz; ++i) {
01000   conflict_cl = added_conflict_clauses[i];
01001   int lit = find_unit_literal(conflict_cl);
01002   if (lit) {
01003       queue_implication(lit, conflict_cl);
01004   }
01005     }
01006 
01007     _conflicts.clear();
01008 
01009     while (_conflict_lits.size()) {
01010   CVariable & var = variable(_conflict_lits.back() >> 1);
01011   _conflict_lits.pop_back();
01012   assert (var.in_new_cl() != -1);
01013   var.set_in_new_cl(-1);
01014     }
01015     CHECK( dump_assignment_stack(););
01016     CHECK(cout << "Conflict Analasis: conflict at level: " << back_level;
01017       cout << "  Assertion Clause is " << conflict_cl<< endl; );
01018     return back_level;
01019 }   
01020 
01021 
01022 
01023 
01024 
01025 
01026 
01027 
01028 
01029 
01030 
01031 
01032 
01033 
01034 
01035