00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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;
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;
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
00112 if ( _params.allow_clause_deletion &&
00113 _stats.num_backtracks % _params.clause_deletion_interval == 0)
00114 delete_unrelevant_clauses();
00115
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
00129 if ((_stats.num_decisions % 0xff)==0)
00130 update_var_stats();
00131
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
00183 while (lit_pool_free_space() <= n_lits + 1) {
00184 if (enlarge_lit_pool()==false)
00185 return -1;
00186
00187 }
00188
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
00198 clause(new_cl).init(lit_pool_end(), n_lits);
00199
00200
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);
00222
00223 if (clause(new_cl).num_lits() > 1) {
00224
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
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
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)
00340 _conflicts.push_back(cl_idx);
00341 else if ( the_value != 1)
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
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)
00400 _conflicts.push_back(cl_idx);
00401 else if ( the_value != 1)
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
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
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
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
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
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) ) {
00554
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
00563 if (original_num_deleted == num_deleted_clauses())
00564 return ;
00565 for (vector<CVariable>::iterator itr = variables().begin();
00566 itr != variables().end(); ++ itr) {
00567 for (int i=0; i<2; ++i) {
00568
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
00620
00621
00622
00623 _max_score_pos = 0;
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
00642 _max_score_pos = i;
00643
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)
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
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
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){
00710 queue_implication( i+i+1, NULL_CLAUSE);
00711 uni_phased.push_back(-i);
00712 }
00713 else if (v.lits_count(1) == 0){
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
00728 for (ClauseIdx i=0, sz=clauses().size(); i<sz; ++i) {
00729 if (clause(i).num_lits() == 1){
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
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
00783 if(preprocess(allowNewClauses)==CONFLICT) {
00784 _stats.outcome = UNSATISFIABLE;
00785 }
00786 else {
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) {
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) ) {
00848
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){
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;
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);
00914 bool first_time = true;
00915 bool prev_is_uip = false;
00916 mark_vars_at_level (cl, -1 , max_dlevel);
00917
00918 vector <int> & assignments = *_assignment_stack[max_dlevel];
00919 for (int j = assignments.size() - 1; j >= 0; --j ) {
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) {
00930 assert (variable(assigned>>1).in_new_cl()==-1);
00931 _conflict_lits.push_back(assigned^0x1);
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();
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;
00948 }
00949 else prev_is_uip = false;
00950
00951 if ( ante_cl != NULL_CLAUSE )
00952 mark_vars_at_level(ante_cl, assigned>>1, 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)
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)) {
00969 int dl = find_max_clause_dlevel(cl);
00970 if (dl < dlevel()) {
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