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 
00171     _var_order.resize(num_vars-1);
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<int>& 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         assert((unsigned)var_idx < variables().size());
00206         int var_sign = lits[i]&0x1;
00207         lit_pool_push_back( ((var_idx<<1) + var_sign) << 2);
00208         ++variable(var_idx).lits_count(var_sign);
00209         int lit_value = literal_value(clause(new_cl).literal(i));
00210 
00211         if (lit_value == 1) {
00212           satisfied = true;
00213         }
00214         else if (lit_value != 0) {
00215           ++num_unknown;
00216         }
00217     }
00218     is_conflict = !satisfied && (num_unknown == 0);
00219     is_unit = !satisfied && (num_unknown == 1);
00220     assert(_stats.is_solver_started || num_unknown == n_lits);
00221     lit_pool_push_back(-new_cl); //push in the clause idx in the end
00222     //d. set the head/tail pointers
00223     if (clause(new_cl).num_lits() > 1) {
00224         //add the ht. note: ht must be the last free var
00225         int max_idx = -1, max_dl = -1;
00226         CClause & cl = clause(new_cl);
00227         int i, sz = cl.num_lits();
00228         int other_ht_idx;
00229         for (i=0; i< sz; ++i) {
00230             int v_idx = cl.literals()[i].var_index();
00231             if (variable(v_idx).value()==UNKNOWN) {
00232                 int v_sign = cl.literals()[i].var_sign();
00233                 variable(v_idx).ht_ptr(v_sign).push_back( & cl.literals()[i]);
00234                 cl.literals()[i].set_ht(1);
00235                 other_ht_idx = i;
00236                 break;
00237             }
00238             else {
00239                 if (variable(v_idx).dlevel() > max_dl) {
00240                     max_dl = variable(v_idx).dlevel();
00241                     max_idx = i;
00242                 }
00243             }
00244         }
00245         if (i >= sz) {
00246             //no unknown literals. so use the max dl literal
00247             int v_idx = cl.literals()[max_idx].var_index();
00248             int v_sign = cl.literals()[max_idx].var_sign();
00249             variable(v_idx).ht_ptr(v_sign).push_back( & cl.literals()[max_idx]);
00250             cl.literals()[max_idx].set_ht(1);
00251             other_ht_idx = max_idx;
00252         }
00253         max_idx = -1; max_dl = -1;
00254         for (i=sz-1; i>=0; --i) {
00255             if (i==other_ht_idx ) continue;
00256             int v_idx = cl.literals()[i].var_index();
00257             if (variable(v_idx).value()==UNKNOWN) {
00258                 int v_sign = cl.literals()[i].var_sign();
00259                 variable(v_idx).ht_ptr(v_sign).push_back( & cl.literals()[i]);
00260                 cl.literals()[i].set_ht(-1);
00261                 break;
00262             }
00263             else {
00264                 if (variable(v_idx).dlevel() > max_dl) {
00265                     max_dl = variable(v_idx).dlevel();
00266                     max_idx = i;
00267                 }
00268             }
00269         }
00270         if (i < 0) {
00271             int v_idx = cl.literals()[max_idx].var_index();
00272             int v_sign = cl.literals()[max_idx].var_sign();
00273             CLitPoolElement * lit_ptr = & cl.literals()[max_idx];
00274             variable(v_idx).ht_ptr(v_sign).push_back(lit_ptr);
00275             cl.literals()[max_idx].set_ht(-1);
00276         }
00277     }
00278     //update some statistics
00279     ++CDatabase::_stats.num_added_clauses; 
00280     CDatabase::_stats.num_added_literals += n_lits;
00281     if (is_unit && _stats.is_solver_started) {
00282       if (n_lits == 1) _addedUnitClauses.push_back(new_cl);
00283       int lit = find_unit_literal(new_cl);
00284       assert(lit);
00285       queue_implication(lit, new_cl);
00286     }
00287     else if (addConflicts && is_conflict) {
00288       _conflicts.push_back(new_cl);
00289     }
00290     return new_cl;
00291 }
00292 
00293 
00294 void CSolver::set_var_value(int v, int value, ClauseIdx ante, int dl)
00295 {
00296     assert (value == 0 || value == 1);
00297     CHECK_FULL(dump());
00298     CHECK(verify_integrity());
00299     CHECK (cout << "Setting\t" << (value>0?"+":"-") << v 
00300            << " at " << dl << " because " << ante<< endl;);
00301     ++_stats.num_implications ;
00302     --num_free_variables();
00303     if (_assignment_hook) {
00304       (*_assignment_hook)(_assignment_hook_cookie, v, value);
00305     }
00306     CVariable & var = _variables[v];
00307     assert (var.value() == UNKNOWN);
00308     var.dlevel() = dl;
00309     var.value() = value;
00310     var.set_antecedence(ante);
00311     vector<CLitPoolElement *> & ht_ptrs = var.ht_ptr(value);
00312     if (dl == dlevel()) 
00313         set_var_value_with_current_dl(v, ht_ptrs);
00314     else 
00315         set_var_value_not_current_dl(v, ht_ptrs);
00316 }
00317 
00318 
00319 void CSolver::set_var_value_with_current_dl(int v, vector<CLitPoolElement *> & ht_ptrs)
00320 {
00321     ClauseIdx cl_idx;
00322     CLitPoolElement * ht_ptr, * other_ht_ptr, * ptr;
00323     int dir;
00324     for (vector <CLitPoolElement *>::iterator itr = ht_ptrs.begin(); itr != ht_ptrs.end(); ++itr) {
00325         ht_ptr = *itr;
00326         dir = ht_ptr->direction();
00327         ptr = ht_ptr;
00328         while(1) {
00329             ptr += dir;
00330             if (ptr->val() <= 0) {
00331                 if (dir == 1) 
00332                     cl_idx = - ptr->val();
00333                 if (dir == ht_ptr->direction()) {
00334                     ptr = ht_ptr;
00335                     dir = -dir;
00336                     continue;
00337                 }
00338                 int the_value = literal_value (*other_ht_ptr);
00339                 if (the_value == 0) //a conflict
00340                     _conflicts.push_back(cl_idx);
00341                 else if ( the_value != 1) //e.g. unknown
00342                     queue_implication (other_ht_ptr->s_var(), cl_idx);
00343                 break;
00344             }
00345             if (ptr->is_ht()) {
00346                 other_ht_ptr = ptr;
00347                 continue;
00348             }
00349             if (literal_value(*ptr) == 0) 
00350                 continue;
00351             //now it's value is either 1 or unknown
00352             int v1 = ptr->var_index();
00353             int sign = ptr->var_sign();
00354             variable(v1).ht_ptr(sign).push_back(ptr);
00355             ht_ptr->unset_ht();
00356             ptr->set_ht(dir);
00357 
00358             *itr = ht_ptrs.back();
00359             ht_ptrs.pop_back();
00360             --itr;
00361             break;
00362         }
00363     }
00364 }
00365 
00366 void CSolver::set_var_value_not_current_dl(int v, vector<CLitPoolElement *> & ht_ptrs)
00367 {
00368     ClauseIdx cl_idx;
00369     CLitPoolElement * ht_ptr, * other_ht_ptr, * ptr, * max_ptr = NULL;
00370     int dir,max_dl;
00371 
00372     for (vector <CLitPoolElement *>::iterator itr = ht_ptrs.begin(); 
00373          itr != ht_ptrs.end(); ++itr) {
00374         max_dl = -1;
00375         ht_ptr = *itr;
00376         dir = ht_ptr->direction();
00377         ptr = ht_ptr;
00378         while(1) {
00379             ptr += dir;
00380             if (ptr->val() <= 0) {
00381                 if (dir == 1) 
00382                     cl_idx = - ptr->val();
00383                 if (dir == ht_ptr->direction()) {
00384                     ptr = ht_ptr;
00385                     dir = -dir;
00386                     continue;
00387                 }
00388                 if (variable(ht_ptr->var_index()).dlevel() < max_dl) {
00389                     int v1 = max_ptr->var_index();
00390                     int sign = max_ptr->var_sign();
00391                     variable(v1).ht_ptr(sign).push_back(max_ptr);
00392                     ht_ptr->unset_ht();
00393                     max_ptr->set_ht(dir);
00394                     *itr = ht_ptrs.back();
00395                     ht_ptrs.pop_back();
00396                     --itr;
00397                 }
00398                 int the_value = literal_value (*other_ht_ptr);
00399                 if (the_value == 0) //a conflict
00400                     _conflicts.push_back(cl_idx);
00401                 else if ( the_value != 1) //e.g. unknown
00402                     queue_implication (other_ht_ptr->s_var(), cl_idx);
00403                 break;
00404             }
00405             if (ptr->is_ht()) {
00406                 other_ht_ptr = ptr;
00407                 continue;
00408             }
00409             if (literal_value(*ptr) == 0) {
00410                 if (variable(ptr->var_index()).dlevel() > max_dl) {
00411                     max_dl = variable(ptr->var_index()).dlevel();
00412                     max_ptr = ptr;
00413                 }
00414                 continue;
00415             }
00416             //now it's value is either 1 or unknown
00417             int v1 = ptr->var_index();
00418             int sign = ptr->var_sign();
00419             variable(v1).ht_ptr(sign).push_back(ptr);
00420             ht_ptr->unset_ht();
00421             ptr->set_ht(dir);
00422 
00423             *itr = ht_ptrs.back();
00424             ht_ptrs.pop_back();
00425             --itr;
00426             break;
00427         }
00428     }
00429 }
00430 
00431 void CSolver::unset_var_value(int v)
00432 {
00433     CHECK(cout <<"Unset var " << (variable(v).value()?"+":"-") << v << endl;);
00434     CVariable & var = variable(v);
00435     if (var.var_score_pos() < _max_score_pos)
00436         _max_score_pos = var.var_score_pos();
00437     var.value() = UNKNOWN;
00438     var.set_antecedence(NULL_CLAUSE);
00439     var.dlevel() = -1;
00440     if (_assignment_hook) {
00441       (*_assignment_hook)(_assignment_hook_cookie, v, -1);
00442     }
00443 }
00444 
00445 int CSolver::find_max_clause_dlevel(ClauseIdx cl)
00446 {
00447 //if cl has single literal, then dlevel should be 0 
00448     int max_level = 0;
00449     if (cl == NULL_CLAUSE || cl == FLIPPED) 
00450         return dlevel();
00451     for (int i=0, sz= clause(cl).num_lits(); i<sz;  ++i) {
00452         int var_idx =((clause(cl).literals())[i]).var_index();
00453         if (_variables[var_idx].value() != UNKNOWN) {
00454             if (max_level < _variables[var_idx].dlevel())
00455                 max_level =  _variables[var_idx].dlevel();
00456         }
00457     }
00458     return max_level; 
00459 }
00460 
00461 void CSolver::dump_assignment_stack(ostream & os) {
00462     cout << "Assignment Stack:  ";
00463     for (int i=0; i<= dlevel(); ++i) {
00464         if ((*_assignment_stack[i]).size() > 0)
00465         if (variable( (*_assignment_stack[i])[0]>>1).get_antecedence()==FLIPPED)
00466             cout << "*" ;
00467         cout << "(" <<i << ":";
00468         for (unsigned j=0; j<(*_assignment_stack[i]).size(); ++j )
00469             cout << ((*_assignment_stack[i])[j]&0x1?"-":"+")
00470                  << ((*_assignment_stack[i])[j] >> 1) << " ";
00471         cout << ") " << endl;
00472     }
00473     cout << endl;
00474 }
00475 
00476 
00477 bool CDatabase::is_conflict(ClauseIdx cl)
00478 {
00479     CLitPoolElement * lits = clause(cl).literals();
00480     for (int i=0, sz= clause(cl).num_lits(); i<sz;  ++i)
00481         if (literal_value(lits[i]) != 0)
00482                 return false;
00483     return true;
00484 }
00485 
00486 bool CDatabase::is_satisfied(ClauseIdx cl)
00487 {
00488     CLitPoolElement * lits = clause(cl).literals();
00489     for (int i=0, sz= clause(cl).num_lits(); i<sz; ++i) 
00490         if (literal_value(lits[i]) == 1) 
00491             return true;
00492     return false;
00493 }
00494 
00495 int CDatabase::find_unit_literal(ClauseIdx cl) 
00496 {
00497 //if it's not unit, return 0.
00498     int unassigned = 0;
00499     for (int i=0, sz= clause(cl).num_lits(); i<sz;  ++i) {
00500         int var_idx =((clause(cl).literals())[i]).var_index();
00501         if (_variables[var_idx].value() == UNKNOWN) {
00502             if (unassigned == 0) 
00503                 unassigned = clause(cl).literals()[i].s_var();
00504             else //more than one unassigned
00505                 return 0;
00506         }
00507     }
00508     return unassigned;
00509 }
00510 
00511 void CSolver::delete_unrelevant_clauses(void) 
00512 {
00513     CHECK_FULL (dump());
00514     int original_num_deleted = num_deleted_clauses();
00515     if (CDatabase::_stats.mem_used_up) {
00516         CDatabase::_stats.mem_used_up = false;
00517         if (++CDatabase::_stats.mem_used_up_counts < 5) {
00518             _params.max_unrelevance = (int) (_params.max_unrelevance * 0.8);
00519             if (_params.max_unrelevance < 4)
00520                 _params.max_unrelevance = 4;
00521             _params.min_num_clause_lits_for_delete = (int) (_params.min_num_clause_lits_for_delete* 0.8);
00522             if (_params.min_num_clause_lits_for_delete < 10)
00523                 _params.min_num_clause_lits_for_delete = 10;
00524             _params.max_conflict_clause_length = (int) (_params.max_conflict_clause_length*0.8);
00525             if (_params.max_conflict_clause_length < 50 )
00526                 _params.max_conflict_clause_length = 50;
00527             CHECK(
00528             cout << "Forced to reduce unrelevance in clause deletion. " << endl;
00529             cout <<"MaxUnrel: " << _params.max_unrelevance 
00530                  << "  MinLenDel: " << _params.min_num_clause_lits_for_delete
00531                  << "  MaxLenCL : " << _params.max_conflict_clause_length << endl;
00532                 );
00533         }
00534     }
00535     //first find out the clause to delete and mark them
00536     for (vector<CClause>::iterator itr = clauses().begin() + init_num_clauses(); 
00537          itr != clauses().end(); ++itr) {
00538         CClause & cl = * itr;
00539         if (!cl.in_use() || cl.num_lits() < _params.min_num_clause_lits_for_delete ) continue;
00540         int val_0_lits = 0, val_1_lits = 0, unknown_lits = 0;
00541         for (int i=0; i< cl.num_lits(); ++i) {
00542             int lit_value = literal_value (cl.literal(i));
00543             if (lit_value == 0 ) ++val_0_lits;
00544             else if (lit_value == 1) ++val_1_lits;
00545             else ++unknown_lits;
00546             if (unknown_lits + val_1_lits > _params.max_unrelevance) {
00547                 mark_clause_deleted(cl);
00548                 _unused_clause_idx_queue.push(itr - clauses().begin());
00549                 CHECK (cout << "Deleting Unrelevant clause: " << cl << endl;);
00550                 break;
00551             }
00552             if (cl.num_lits() > _params.max_conflict_clause_length && 
00553                 (unknown_lits+val_1_lits > 1) ) { //to make sure it's not generating an implication
00554                                                   //and it's not an antecedence for other var assignment
00555                 mark_clause_deleted(cl);
00556                 CHECK (cout << "Deleting too large clause: " << cl << endl;);
00557                 _unused_clause_idx_queue.push(itr - clauses().begin());
00558                 break;
00559             }
00560         }
00561     }
00562     //now delete the index from variables
00563     if (original_num_deleted == num_deleted_clauses()) 
00564         return ; //didn't delete anything
00565     for (vector<CVariable>::iterator itr = variables().begin(); 
00566          itr != variables().end(); ++ itr) {
00567         for (int i=0; i<2; ++i) { //for each phase
00568             //delete the h_t index from the vars
00569             vector<CLitPoolElement *> & ht_ptr = (*itr).ht_ptr(i);
00570             for (vector<CLitPoolElement *>::iterator my_itr = ht_ptr.begin(); 
00571                  my_itr != ht_ptr.end(); ++my_itr) {
00572                 if ( (*my_itr)->val() <= 0) {
00573                     *my_itr = ht_ptr.back();
00574                     ht_ptr.pop_back();
00575                     --my_itr;
00576                 }
00577             }
00578         }
00579     }
00580     CHECK(cout << "Deleting " << num_deleted_clauses() - original_num_deleted << " Clause ";
00581       cout << " and " << num_deleted_literals() - original_del_lits << " Literals " << endl;);
00582     CHECK_FULL (dump());
00583 }
00584 //============================================================================================
00585 bool CSolver::time_out(void) 
00586 {
00587     if ( (current_cpu_time() - _stats.start_cpu_time)/1000.0 > _params.time_limit )
00588         return true;
00589     return false;
00590 }
00591 
00592 inline bool compare_var_stat(const pair<int, int> & v1, 
00593                             const pair<int, int> & v2) 
00594 {
00595     if (v1.second > v2.second) return true;
00596     return false;
00597 }
00598 
00599 void CSolver::update_var_stats(void) 
00600 {
00601     for(unsigned i=1; i< variables().size(); ++i) {
00602         CVariable & var = variable(i);
00603         var.score(0) = var.score(0)/2 + var.lits_count(0) - _last_var_lits_count[0][i];
00604         var.score(1) = var.score(1)/2 + var.lits_count(1) - _last_var_lits_count[1][i];
00605         _last_var_lits_count[0][i] = var.lits_count(0);
00606         _last_var_lits_count[1][i] = var.lits_count(1);
00607         _var_order[i-1] = pair<int, int>(i, var.score());
00608     }
00609     ::stable_sort(_var_order.begin(), _var_order.end(), compare_var_stat);
00610     for (unsigned i=0; i<_var_order.size(); ++i) 
00611         variable(_var_order[i].first).var_score_pos() = i;
00612     _max_score_pos = 0;
00613 }
00614 
00615 bool CSolver::decide_next_branch(void)
00616 {
00617     ++_stats.num_decisions;
00618     if (!_implication_queue.empty()) {
00619         //some hook function did a decision, so skip my own decision making.
00620         //if the front of implication queue is 0, that means it's finished
00621         //because var index start from 1, so 2 *vid + sign won't be 0. 
00622         //else it's a valid decision.
00623         _max_score_pos = 0; //reset the max_score_position.
00624         return _implication_queue.front().first;
00625     }
00626         
00627     int s_var = 0;
00628     bool done = false;
00629 
00630     if (_decision_hook) {
00631       s_var = (*_decision_hook)(_decision_hook_cookie, &done);
00632     }
00633     if (!done && s_var < 2) {
00634       unsigned i, var_idx, sign;
00635       CVariable * ptr;
00636 
00637     for (i=_max_score_pos; i<_var_order.size(); ++i) {
00638         var_idx = _var_order[i].first;
00639         ptr = &(variables()[var_idx]);
00640         if (ptr->value()==UNKNOWN) {
00641             //move th max score position pointer
00642             _max_score_pos = i;
00643             //make some randomness happen
00644             if (--_params.randomness < _params.base_randomness)
00645                 _params.randomness = _params.base_randomness;
00646 
00647             int randomness = _params.randomness;
00648             if (randomness >= num_free_variables())
00649                 randomness = num_free_variables() - 1;
00650             int skip =random()%(1+randomness);
00651             int index = i;
00652             while (skip > 0) {
00653                 ++index;
00654                 var_idx = _var_order[index].first;
00655                 ptr = &(variables()[var_idx]);
00656                 if (ptr->value()==UNKNOWN)
00657                     --skip;
00658             }
00659             assert (ptr->value() == UNKNOWN);
00660             sign = ptr->score(0) > ptr->score(1) ? 0 : 1;
00661             s_var = var_idx + var_idx + sign;
00662             break;
00663         }
00664     }
00665     }
00666 
00667     if (s_var<2) //no more free vars, solution found,  quit
00668         return false;
00669     ++dlevel();
00670     if (_dlevel_hook) {
00671       (*_dlevel_hook)(_dlevel_hook_cookie, 1);
00672     }
00673     if (dlevel() > _stats.max_dlevel) _stats.max_dlevel = dlevel();
00674     CHECK (cout << "**Decision at Level " << dlevel() ;
00675            cout <<": " << s_var << "\te.g. " << (s_var&0x1?"-":" ") ;
00676            cout <<(s_var>>1)  << endl; );
00677     queue_implication(s_var, NULL_CLAUSE);
00678     return true;
00679 }
00680 
00681 int CSolver::preprocess(bool allowNewClauses) 
00682 {
00683     //1. detect all the unused variables
00684   if (!allowNewClauses) {
00685     vector<int> un_used;
00686     for (int i=1, sz=variables().size(); i<sz; ++i) {
00687         CVariable & v = variable(i);
00688         if (v.lits_count(0) == 0 && v.lits_count(1) == 0) {
00689             un_used.push_back(i);
00690             v.value() = 1; 
00691             v.dlevel() = -1;
00692         }
00693     }
00694     num_free_variables() -= un_used.size();
00695     if (_params.verbosity>1 && un_used.size() > 0) {
00696         cout << un_used.size()<< " Variables are defined but not used " << endl;
00697         if (_params.verbosity > 2) {
00698             for (unsigned i=0; i< un_used.size(); ++i)
00699                 cout << un_used[i] << " ";
00700             cout << endl;
00701         }
00702     }
00703     //2. detect all variables with only one phase occuring
00704     vector<int> uni_phased;
00705     for (int i=1, sz=variables().size(); i<sz; ++i) {
00706         CVariable & v = variable(i);
00707         if (v.value() != UNKNOWN)
00708             continue;
00709         if (v.lits_count(0) == 0){ //no positive phased lits.
00710             queue_implication( i+i+1, NULL_CLAUSE);
00711             uni_phased.push_back(-i);
00712         }
00713         else if (v.lits_count(1) == 0){ //no negative phased lits.
00714             queue_implication( i+i, NULL_CLAUSE);
00715             uni_phased.push_back(i);
00716         }
00717     }
00718     if (_params.verbosity>1 && uni_phased.size() > 0) {
00719         cout << uni_phased.size()<< " Variables only appear in one phase." << endl;
00720         if (_params.verbosity > 2) {
00721             for (unsigned i=0; i< uni_phased.size(); ++i)
00722                 cout << uni_phased[i] << " ";
00723             cout <<endl;
00724         }
00725     }
00726   }
00727     //3. detect all the unit clauses
00728     for (ClauseIdx i=0, sz=clauses().size(); i<sz; ++i) {
00729         if (clause(i).num_lits() == 1){ //unit clause
00730             queue_implication(find_unit_literal(i), i);
00731         }
00732     }
00733 
00734     if(deduce()==CONFLICT) return CONFLICT;
00735     return NO_CONFLICT;    
00736 }
00737 
00738 void CSolver::real_solve(void)
00739 {
00740     while(1) {
00741         run_periodic_functions();
00742         if (decide_next_branch() || !_implication_queue.empty() ||
00743             _conflicts.size() != 0) {
00744             while (deduce()==CONFLICT) { 
00745                 int blevel = analyze_conflicts();
00746                 if (blevel <= 0) {
00747                     _stats.outcome = UNSATISFIABLE;
00748                     return;
00749                 }
00750                 else if (_addedUnitClauses.size()) {
00751                   // reassert added unit clauses
00752                   unsigned idx = _addedUnitClauses.size()-1;
00753                   ClauseIdx cl = _addedUnitClauses.back();
00754                   int lit = find_unit_literal(cl);
00755                   while (lit != 0) {
00756                     queue_implication(lit, cl);
00757                     if (idx == 0) break;
00758                     cl = _addedUnitClauses[--idx];
00759                     lit = find_unit_literal(cl);
00760                   }
00761                 }
00762             }
00763         }
00764         else {
00765           _stats.outcome = SATISFIABLE;
00766           return;
00767         }
00768         if (time_out()) { 
00769             _stats.outcome = TIME_OUT;
00770             return; 
00771         }
00772         if (_stats.is_mem_out) {
00773             _stats.outcome = MEM_OUT;
00774             return; 
00775         }
00776     }
00777 }
00778 
00779 int CSolver::solve(bool allowNewClauses)
00780 {
00781     init();
00782     //preprocess 
00783     if(preprocess(allowNewClauses)==CONFLICT) {
00784         _stats.outcome = UNSATISFIABLE;
00785     }
00786     else { //the real search
00787       if (_dlevel_hook) {
00788         (*_dlevel_hook)(_dlevel_hook_cookie, 1);
00789       }
00790       real_solve();
00791     }
00792     _stats.finish_cpu_time = current_cpu_time();
00793     _stats.finish_world_time = current_world_time();
00794     return _stats.outcome;
00795 }
00796 
00797 int CSolver::continueCheck()
00798 {
00799   real_solve();
00800   _stats.finish_cpu_time = current_cpu_time();
00801   _stats.finish_world_time = current_world_time();
00802   return _stats.outcome;
00803 }
00804 
00805 void CSolver::back_track(int blevel)
00806 {
00807     CHECK (cout << "Back track to " << blevel <<" ,currently in "<< dlevel() << " level" << endl;);
00808     CHECK_FULL (dump());
00809     CHECK(verify_integrity());
00810     assert(blevel <= dlevel());
00811     for (int i=dlevel(); i>= blevel; --i) {
00812         vector<int> & assignments = *_assignment_stack[i];
00813         for (int j=assignments.size()-1 ; j>=0; --j) 
00814                 unset_var_value(assignments[j]>>1);
00815         num_free_variables() += assignments.size();
00816         assignments.clear();
00817         if (_dlevel_hook) {
00818           (*_dlevel_hook)(_dlevel_hook_cookie, -1);
00819         }
00820     }
00821     dlevel() = blevel - 1;
00822     ++_stats.num_backtracks;
00823     CHECK_FULL (dump());
00824     CHECK(verify_integrity());
00825 }
00826 
00827 int CSolver::deduce(void) 
00828 {
00829 restart:
00830     while (!_implication_queue.empty() && _conflicts.size()==0) {
00831         int literal = _implication_queue.front().first;
00832         int variable_index = literal>>1;
00833         ClauseIdx cl = _implication_queue.front().second;
00834         _implication_queue.pop();
00835         CVariable * the_var = &(variables()[variable_index]);
00836         if ( the_var->value() == UNKNOWN) { // an implication
00837             int dl;
00838             if (_params.back_track_complete)
00839                 dl = dlevel();
00840             else 
00841                 dl = find_max_clause_dlevel(cl);
00842             set_var_value(variable_index, !(literal&0x1), cl, dl);
00843             the_var = &(variables()[variable_index]);
00844             _assignment_stack[dl]->push_back(literal);
00845             CHECK(verify_integrity());
00846         }
00847         else if (the_var->value() == (literal&0x1) ) { //a conflict
00848             //note: literal & 0x1 == 1 means the literal is in negative phase
00849             _conflicts.push_back(cl);
00850         }
00851     }
00852     if (!_conflicts.size() && _deduction_hook) {
00853       (*_deduction_hook)(_deduction_hook_cookie);
00854       if (!_implication_queue.empty()) goto restart;
00855     }
00856     while(!_implication_queue.empty()) _implication_queue.pop();
00857     return (_conflicts.size()?CONFLICT:NO_CONFLICT);
00858 }
00859 
00860 
00861 void CSolver::verify_integrity(void) 
00862 {
00863 }
00864 
00865 void CSolver::mark_vars_at_level(ClauseIdx cl, int var_idx, int dl)
00866 {
00867     for (CLitPoolElement * itr = clause(cl).literals(); (*itr).val() > 0 ; ++ itr) {
00868         int v = (*itr).var_index();
00869         if (v == var_idx) 
00870             continue;
00871         else if (variable(v).dlevel() == dl) {
00872             if (!variable(v).is_marked()) {
00873                 variable(v).set_marked();
00874                 ++ _num_marked;
00875             }
00876         }
00877         else {
00878             assert (variable(v).dlevel() < dl);
00879             if (variable(v).in_new_cl() == -1){ //it's not in the new cl
00880                 variable(v).set_in_new_cl((*itr).var_sign());
00881                 _conflict_lits.push_back((*itr).s_var());
00882             }
00883         }
00884     }
00885 }
00886 
00887 int CSolver::analyze_conflicts(void) {
00888     return conflict_analysis_zchaff();
00889 }
00890 
00891 int CSolver::conflict_analysis_zchaff (void) 
00892 {
00893     assert (_conflicts.size());
00894     assert (_implication_queue.empty());
00895     assert (_num_marked == 0);
00896     static int entries = 0;
00897     ++ entries;
00898     int back_level = 0;
00899     ClauseIdx conflict_cl;
00900     vector<ClauseIdx> added_conflict_clauses;
00901     for (int i=0, sz=_conflicts.size(); i<sz; ++i) {
00902         ClauseIdx cl = _conflicts[i];
00903 
00904         if (!is_conflict(cl)) continue;
00905 
00906         back_level = 0; // reset it
00907         while (_conflict_lits.size()) {
00908             CVariable & var = variable(_conflict_lits.back() >> 1);
00909             _conflict_lits.pop_back();
00910             assert (var.in_new_cl() != -1);
00911             var.set_in_new_cl(-1);
00912         }
00913         int max_dlevel = find_max_clause_dlevel(cl); // find the max level, which is the back track level
00914         bool first_time = true; //its the beginning
00915         bool prev_is_uip = false;
00916         mark_vars_at_level (cl, -1 /*var*/, max_dlevel);
00917 
00918         vector <int> & assignments = *_assignment_stack[max_dlevel];
00919         for (int j = assignments.size() - 1; j >= 0; --j ) { //now add conflict lits, and unassign vars
00920             int assigned = assignments[j];
00921             if (variable(assigned>>1).is_marked()) {
00922                 variable(assigned>>1).clear_marked();
00923                 -- _num_marked; 
00924                 ClauseIdx ante_cl = variables()[assigned>>1].get_antecedence();
00925 
00926                 if ( (_num_marked == 0 && 
00927                       (!first_time) && 
00928                       (prev_is_uip == false))
00929                       || ante_cl==NULL_CLAUSE) { //conclude add clause
00930                     assert (variable(assigned>>1).in_new_cl()==-1);
00931                     _conflict_lits.push_back(assigned^0x1);  // add this assignment's reverse, e.g. UIP
00932                     int conflict_cl = add_clause(_conflict_lits, false);
00933                     if (conflict_cl < 0 ) {
00934                         _stats.is_mem_out = true;
00935                         _conflicts.clear();
00936                         assert (_implication_queue.empty());
00937                         return 1; 
00938                     }
00939                     _conflict_lits.pop_back();  // remove for continue use of _conflict_lits
00940                     added_conflict_clauses.push_back(conflict_cl);
00941 
00942                     CHECK(cout <<"Conflict clause: " << cl << " : " << clause(cl) << endl;
00943                           cout << "**Add Clause " <<conflict_cl<< " : "<<clause(conflict_cl) << endl; 
00944                         );
00945 
00946                     prev_is_uip = true;
00947                     break; //if do this, only one clause will be added.
00948                 }
00949                 else prev_is_uip = false;
00950 
00951                 if ( ante_cl != NULL_CLAUSE ) 
00952                     mark_vars_at_level(ante_cl, assigned>>1/*var*/, max_dlevel);
00953                 else 
00954                     assert (j == 0);
00955                 first_time = false;
00956             }
00957         }
00958         back_level = max_dlevel;
00959         back_track(max_dlevel); 
00960     }
00961     assert (_num_marked == 0);
00962     if (back_level==0) //there are nothing to be done
00963             return back_level;
00964 
00965     if (_params.back_track_complete) {
00966         for (unsigned i=0; i< added_conflict_clauses.size(); ++i) {
00967             ClauseIdx cl = added_conflict_clauses[i];
00968             if (find_unit_literal(cl)) { //i.e. if it's a unit clause
00969                 int dl = find_max_clause_dlevel(cl);
00970                 if (dl < dlevel()) { //thus make sure implied vars are at current dl.
00971                     back_track(dl+1);
00972                 }
00973             }
00974         }
00975     }
00976     int cnt = 0;
00977     for (int i=0, sz=added_conflict_clauses.size(); i<sz; ++i) {
00978         conflict_cl = added_conflict_clauses[i];
00979         int lit = find_unit_literal(conflict_cl);
00980         if (lit) {
00981             queue_implication(lit, conflict_cl);
00982             ++cnt;
00983         }
00984     }
00985     assert (cnt > 0);
00986     assert (!_params.back_track_complete || cnt == 1);
00987 
00988     _conflicts.clear();
00989 
00990     while (_conflict_lits.size()) {
00991         CVariable & var = variable(_conflict_lits.back() >> 1);
00992         _conflict_lits.pop_back();
00993         assert (var.in_new_cl() != -1);
00994         var.set_in_new_cl(-1);
00995     }
00996     CHECK( dump_assignment_stack(););
00997     CHECK(cout << "Conflict Analasis: conflict at level: " << back_level;
00998           cout << "  Assertion Clause is " << conflict_cl<< endl; );
00999     return back_level;
01000 }               
01001 
01002 
01003 
01004 
01005 
01006 
01007 
01008 
01009 
01010 
01011 
01012 
01013 
01014 
01015 
01016 

Generated on Thu Apr 13 16:57:36 2006 for CVC Lite by  doxygen 1.4.4