CVC3
|
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