[10] | 1 | // ********************************************************************* |
---|
| 2 | // Copyright 2000-2004, Princeton University. All rights reserved. |
---|
| 3 | // By using this software the USER indicates that he or she has read, |
---|
| 4 | // understood and will comply with the following: |
---|
| 5 | // |
---|
| 6 | // --- Princeton University hereby grants USER nonexclusive permission |
---|
| 7 | // to use, copy and/or modify this software for internal, noncommercial, |
---|
| 8 | // research purposes only. Any distribution, including commercial sale |
---|
| 9 | // or license, of this software, copies of the software, its associated |
---|
| 10 | // documentation and/or modifications of either is strictly prohibited |
---|
| 11 | // without the prior consent of Princeton University. Title to copyright |
---|
| 12 | // to this software and its associated documentation shall at all times |
---|
| 13 | // remain with Princeton University. Appropriate copyright notice shall |
---|
| 14 | // be placed on all software copies, and a complete copy of this notice |
---|
| 15 | // shall be included in all copies of the associated documentation. |
---|
| 16 | // No right is granted to use in advertising, publicity or otherwise |
---|
| 17 | // any trademark, service mark, or the name of Princeton University. |
---|
| 18 | // |
---|
| 19 | // |
---|
| 20 | // --- This software and any associated documentation is provided "as is" |
---|
| 21 | // |
---|
| 22 | // PRINCETON UNIVERSITY MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS |
---|
| 23 | // OR IMPLIED, INCLUDING THOSE OF MERCHANTABILITY OR FITNESS FOR A |
---|
| 24 | // PARTICULAR PURPOSE, OR THAT USE OF THE SOFTWARE, MODIFICATIONS, OR |
---|
| 25 | // ASSOCIATED DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, |
---|
| 26 | // TRADEMARKS OR OTHER INTELLECTUAL PROPERTY RIGHTS OF A THIRD PARTY. |
---|
| 27 | // |
---|
| 28 | // Princeton University shall not be liable under any circumstances for |
---|
| 29 | // any direct, indirect, special, incidental, or consequential damages |
---|
| 30 | // with respect to any claim by USER or any third party on account of |
---|
| 31 | // or arising from the use, or inability to use, this software or its |
---|
| 32 | // associated documentation, even if Princeton University has been advised |
---|
| 33 | // of the possibility of those damages. |
---|
| 34 | // ******************************************************************** |
---|
| 35 | |
---|
| 36 | #include <iostream> |
---|
| 37 | #include <algorithm> |
---|
| 38 | #include <fstream> |
---|
| 39 | #include <vector> |
---|
| 40 | #include <map> |
---|
| 41 | #include <set> |
---|
| 42 | #include <queue> |
---|
| 43 | |
---|
| 44 | using namespace std; |
---|
| 45 | |
---|
| 46 | #include "zchaff_solver.h" |
---|
| 47 | |
---|
| 48 | // #define VERIFY_ON |
---|
| 49 | |
---|
| 50 | #ifdef VERIFY_ON |
---|
| 51 | ofstream verify_out("resolve_trace"); |
---|
| 52 | #endif |
---|
| 53 | |
---|
| 54 | void CSolver::re_init_stats(void) { |
---|
| 55 | _stats.is_mem_out = false; |
---|
| 56 | _stats.outcome = UNDETERMINED; |
---|
| 57 | _stats.next_restart = _params.restart.first_restart; |
---|
| 58 | _stats.restart_incr = _params.restart.backtrack_incr; |
---|
| 59 | _stats.next_cls_deletion = _params.cls_deletion.interval; |
---|
| 60 | _stats.next_var_score_decay = _params.decision.decay_period; |
---|
| 61 | _stats.current_randomness = _params.decision.base_randomness; |
---|
| 62 | |
---|
| 63 | _stats.total_bubble_move = 0; |
---|
| 64 | _stats.num_decisions = 0; |
---|
| 65 | _stats.num_decisions_stack_conf = 0; |
---|
| 66 | _stats.num_decisions_vsids = 0; |
---|
| 67 | _stats.num_decisions_shrinking = 0; |
---|
| 68 | _stats.num_backtracks = 0; |
---|
| 69 | _stats.max_dlevel = 0; |
---|
| 70 | _stats.num_implications = 0; |
---|
| 71 | _stats.num_restarts = 0; |
---|
| 72 | _stats.num_del_orig_cls = 0; |
---|
| 73 | _stats.num_shrinkings = 0; |
---|
| 74 | _stats.start_cpu_time = get_cpu_time(); |
---|
| 75 | _stats.finish_cpu_time = 0; |
---|
| 76 | _stats.random_seed = 0; |
---|
| 77 | } |
---|
| 78 | |
---|
| 79 | void CSolver::init_stats(void) { |
---|
| 80 | re_init_stats(); |
---|
| 81 | |
---|
| 82 | _stats.been_reset = true; |
---|
| 83 | _stats.num_free_variables = 0; |
---|
| 84 | _stats.num_free_branch_vars = 0; |
---|
| 85 | } |
---|
| 86 | |
---|
| 87 | void CSolver::init_parameters(void) { |
---|
| 88 | _params.verbosity = 0; |
---|
| 89 | _params.time_limit = 3600 * 24; // a day |
---|
| 90 | _params.shrinking.size = 95; |
---|
| 91 | _params.shrinking.enable = true; |
---|
| 92 | _params.shrinking.upper_bound = 800; |
---|
| 93 | _params.shrinking.lower_bound = 600; |
---|
| 94 | _params.shrinking.upper_delta = -5; |
---|
| 95 | _params.shrinking.lower_delta = 10; |
---|
| 96 | _params.shrinking.window_width = 20; |
---|
| 97 | _params.shrinking.bound_update_frequency = 20; |
---|
| 98 | |
---|
| 99 | _params.decision.base_randomness = 0; |
---|
| 100 | _params.decision.decay_period = 40; |
---|
| 101 | _params.decision.bubble_init_step = 0x400; |
---|
| 102 | |
---|
| 103 | _params.cls_deletion.enable = true ; |
---|
| 104 | _params.cls_deletion.head_activity = 500; |
---|
| 105 | _params.cls_deletion.tail_activity = 10; |
---|
| 106 | _params.cls_deletion.head_num_lits = 6; |
---|
| 107 | _params.cls_deletion.tail_num_lits = 45; |
---|
| 108 | _params.cls_deletion.tail_vs_head = 16; |
---|
| 109 | _params.cls_deletion.interval = 600; |
---|
| 110 | |
---|
| 111 | _params.restart.enable = true; |
---|
| 112 | _params.restart.interval = 700; |
---|
| 113 | _params.restart.first_restart = 7000; |
---|
| 114 | _params.restart.backtrack_incr = 700; |
---|
| 115 | } |
---|
| 116 | |
---|
| 117 | CSolver::CSolver(void) { |
---|
| 118 | init_parameters(); |
---|
| 119 | init_stats(); |
---|
| 120 | _dlevel = 0; |
---|
| 121 | _force_terminate = false; |
---|
| 122 | _implication_id = 0; |
---|
| 123 | _num_marked = 0; |
---|
| 124 | _num_in_new_cl = 0; |
---|
| 125 | _outside_constraint_hook = NULL; |
---|
| 126 | _sat_hook = NULL; |
---|
| 127 | } |
---|
| 128 | |
---|
| 129 | CSolver::~CSolver(void) { |
---|
| 130 | while (!_assignment_stack.empty()) { |
---|
| 131 | delete _assignment_stack.back(); |
---|
| 132 | _assignment_stack.pop_back(); |
---|
| 133 | } |
---|
| 134 | } |
---|
| 135 | |
---|
| 136 | void CSolver::set_time_limit(float t) { |
---|
| 137 | _params.time_limit = t; |
---|
| 138 | } |
---|
| 139 | |
---|
| 140 | float CSolver::elapsed_cpu_time(void) { |
---|
| 141 | return get_cpu_time() - _stats.start_cpu_time; |
---|
| 142 | } |
---|
| 143 | |
---|
| 144 | float CSolver::cpu_run_time(void) { |
---|
| 145 | return (_stats.finish_cpu_time - _stats.start_cpu_time); |
---|
| 146 | } |
---|
| 147 | |
---|
| 148 | void CSolver::set_variable_number(int n) { |
---|
| 149 | assert(num_variables() == 0); |
---|
| 150 | CDatabase::set_variable_number(n); |
---|
| 151 | _stats.num_free_variables = num_variables(); |
---|
| 152 | while (_assignment_stack.size() <= num_variables()) |
---|
| 153 | _assignment_stack.push_back(new vector<int>); |
---|
| 154 | assert(_assignment_stack.size() == num_variables() + 1); |
---|
| 155 | } |
---|
| 156 | |
---|
| 157 | int CSolver::add_variable(void) { |
---|
| 158 | int num = CDatabase::add_variable(); |
---|
| 159 | ++_stats.num_free_variables; |
---|
| 160 | while (_assignment_stack.size() <= num_variables()) |
---|
| 161 | _assignment_stack.push_back(new vector<int>); |
---|
| 162 | assert(_assignment_stack.size() == num_variables() + 1); |
---|
| 163 | return num; |
---|
| 164 | } |
---|
| 165 | |
---|
| 166 | void CSolver::set_mem_limit(int s) { |
---|
| 167 | CDatabase::set_mem_limit(s); |
---|
| 168 | } |
---|
| 169 | |
---|
| 170 | void CSolver::set_randomness(int n) { |
---|
| 171 | _params.decision.base_randomness = n; |
---|
| 172 | } |
---|
| 173 | |
---|
| 174 | void CSolver::set_random_seed(int seed) { |
---|
| 175 | srand(seed); |
---|
| 176 | } |
---|
| 177 | |
---|
| 178 | void CSolver::enable_cls_deletion(bool allow) { |
---|
| 179 | _params.cls_deletion.enable = allow; |
---|
| 180 | } |
---|
| 181 | |
---|
| 182 | void CSolver::add_hook(HookFunPtrT fun, int interval) { |
---|
| 183 | pair<HookFunPtrT, int> a(fun, interval); |
---|
| 184 | _hooks.push_back(pair<int, pair<HookFunPtrT, int> > (0, a)); |
---|
| 185 | } |
---|
| 186 | |
---|
| 187 | void CSolver::run_periodic_functions(void) { |
---|
| 188 | // a. restart |
---|
| 189 | if (_params.restart.enable && _stats.num_backtracks > _stats.next_restart && |
---|
| 190 | _shrinking_cls.empty()) { |
---|
| 191 | _stats.next_restart = _stats.num_backtracks + _stats.restart_incr; |
---|
| 192 | delete_unrelevant_clauses(); |
---|
| 193 | restart(); |
---|
| 194 | if (_stats.num_restarts % 5 == 1) |
---|
| 195 | compact_lit_pool(); |
---|
| 196 | cout << "\rDecision: " << _assignment_stack[0]->size() << "/" |
---|
| 197 | <<num_variables() << "\tTime: " << get_cpu_time() - |
---|
| 198 | _stats.start_cpu_time << "/" << _params.time_limit << flush; |
---|
| 199 | } |
---|
| 200 | |
---|
| 201 | // b. decay variable score |
---|
| 202 | if (_stats.num_backtracks > _stats.next_var_score_decay) { |
---|
| 203 | _stats.next_var_score_decay = _stats.num_backtracks + |
---|
| 204 | _params.decision.decay_period; |
---|
| 205 | decay_variable_score(); |
---|
| 206 | } |
---|
| 207 | |
---|
| 208 | // c. run hook functions |
---|
| 209 | for (unsigned i = 0; i< _hooks.size(); ++i) { |
---|
| 210 | pair<int, pair<HookFunPtrT, int> > & hook = _hooks[i]; |
---|
| 211 | if (_stats.num_decisions >= hook.first) { |
---|
| 212 | hook.first += hook.second.second; |
---|
| 213 | hook.second.first((void *) this); |
---|
| 214 | } |
---|
| 215 | } |
---|
| 216 | } |
---|
| 217 | |
---|
| 218 | void CSolver::init_solve(void) { |
---|
| 219 | CDatabase::init_stats(); |
---|
| 220 | re_init_stats(); |
---|
| 221 | _stats.been_reset = false; |
---|
| 222 | |
---|
| 223 | assert(_conflicts.empty()); |
---|
| 224 | assert(_conflict_lits.empty()); |
---|
| 225 | assert(_num_marked == 0); |
---|
| 226 | assert(_num_in_new_cl == 0); |
---|
| 227 | assert(_dlevel == 0); |
---|
| 228 | |
---|
| 229 | for (unsigned i = 0, sz = variables()->size(); i < sz; ++i) { |
---|
| 230 | variable(i).score(0) = variable(i).lits_count(0); |
---|
| 231 | variable(i).score(1) = variable(i).lits_count(1); |
---|
| 232 | } |
---|
| 233 | |
---|
| 234 | _ordered_vars.resize(num_variables()); |
---|
| 235 | update_var_score(); |
---|
| 236 | |
---|
| 237 | set_random_seed(_stats.random_seed); |
---|
| 238 | |
---|
| 239 | top_unsat_cls = clauses()->size() - 1; |
---|
| 240 | |
---|
| 241 | _stats.shrinking_benefit = 0; |
---|
| 242 | _shrinking_cls.clear(); |
---|
| 243 | _stats.shrinking_cls_length = 0; |
---|
| 244 | } |
---|
| 245 | |
---|
| 246 | void CSolver::set_var_value(int v, int value, ClauseIdx ante, int dl) { |
---|
| 247 | assert(value == 0 || value == 1); |
---|
| 248 | CVariable & var = variable(v); |
---|
| 249 | assert(var.value() == UNKNOWN); |
---|
| 250 | assert(dl == dlevel()); |
---|
| 251 | |
---|
| 252 | var.set_dlevel(dl); |
---|
| 253 | var.set_value(value); |
---|
| 254 | var.antecedent() = ante; |
---|
| 255 | var.assgn_stack_pos() = _assignment_stack[dl]->size(); |
---|
| 256 | _assignment_stack[dl]->push_back(v * 2 + !value); |
---|
| 257 | set_var_value_BCP(v, value); |
---|
| 258 | |
---|
| 259 | ++_stats.num_implications ; |
---|
| 260 | if (var.is_branchable()) |
---|
| 261 | --num_free_variables(); |
---|
| 262 | } |
---|
| 263 | |
---|
| 264 | void CSolver::set_var_value_BCP(int v, int value) { |
---|
| 265 | vector<CLitPoolElement *> & watchs = variable(v).watched(value); |
---|
| 266 | for (vector <CLitPoolElement *>::iterator itr = watchs.begin(); |
---|
| 267 | itr != watchs.end(); ++itr) { |
---|
| 268 | ClauseIdx cl_idx; |
---|
| 269 | CLitPoolElement * other_watched = *itr; |
---|
| 270 | CLitPoolElement * watched = *itr; |
---|
| 271 | int dir = watched->direction(); |
---|
| 272 | CLitPoolElement * ptr = watched; |
---|
| 273 | while (true) { |
---|
| 274 | ptr += dir; |
---|
| 275 | if (ptr->val() <= 0) { // reached one end of the clause |
---|
| 276 | if (dir == 1) // reached the right end, i.e. spacing element is cl_id |
---|
| 277 | cl_idx = ptr->get_clause_index(); |
---|
| 278 | if (dir == watched->direction()) { // we haven't go both directions. |
---|
| 279 | ptr = watched; |
---|
| 280 | dir = -dir; // change direction, go the other way |
---|
| 281 | continue; |
---|
| 282 | } |
---|
| 283 | // otherwise, we have already go through the whole clause |
---|
| 284 | int the_value = literal_value(*other_watched); |
---|
| 285 | if (the_value == 0) // a conflict |
---|
| 286 | _conflicts.push_back(cl_idx); |
---|
| 287 | else if (the_value != 1) // i.e. unknown |
---|
| 288 | queue_implication(other_watched->s_var(), cl_idx); |
---|
| 289 | break; |
---|
| 290 | } |
---|
| 291 | if (ptr->is_watched()) { // literal is the other watched lit, skip it. |
---|
| 292 | other_watched = ptr; |
---|
| 293 | continue; |
---|
| 294 | } |
---|
| 295 | if (literal_value(*ptr) == 0) // literal value is 0, keep going |
---|
| 296 | continue; |
---|
| 297 | // now the literal's value is either 1 or unknown, watch it instead |
---|
| 298 | int v1 = ptr->var_index(); |
---|
| 299 | int sign = ptr->var_sign(); |
---|
| 300 | variable(v1).watched(sign).push_back(ptr); |
---|
| 301 | ptr->set_watch(dir); |
---|
| 302 | // remove the original watched literal from watched list |
---|
| 303 | watched->unwatch(); |
---|
| 304 | *itr = watchs.back(); // copy the last element in it's place |
---|
| 305 | watchs.pop_back(); // remove the last element |
---|
| 306 | --itr; // do this so with don't skip one during traversal |
---|
| 307 | break; |
---|
| 308 | } |
---|
| 309 | } |
---|
| 310 | } |
---|
| 311 | |
---|
| 312 | void CSolver::unset_var_value(int v) { |
---|
| 313 | if (v == 0) |
---|
| 314 | return; |
---|
| 315 | CVariable & var = variable(v); |
---|
| 316 | var.set_value(UNKNOWN); |
---|
| 317 | var.set_antecedent(NULL_CLAUSE); |
---|
| 318 | var.set_dlevel(-1); |
---|
| 319 | var.assgn_stack_pos() = -1; |
---|
| 320 | |
---|
| 321 | if (var.is_branchable()) { |
---|
| 322 | ++num_free_variables(); |
---|
| 323 | if (var.var_score_pos() < _max_score_pos) |
---|
| 324 | _max_score_pos = var.var_score_pos(); |
---|
| 325 | } |
---|
| 326 | } |
---|
| 327 | |
---|
| 328 | void CSolver::dump_assignment_stack(ostream & os ) { |
---|
| 329 | os << "Assignment Stack: "; |
---|
| 330 | for (int i = 0; i <= dlevel(); ++i) { |
---|
| 331 | os << "(" <<i << ":"; |
---|
| 332 | for (unsigned j = 0; j < (*_assignment_stack[i]).size(); ++j) { |
---|
| 333 | os << ((*_assignment_stack[i])[j]&0x1?"-":"+") |
---|
| 334 | << ((*_assignment_stack[i])[j] >> 1) << " "; |
---|
| 335 | } |
---|
| 336 | os << ") " << endl; |
---|
| 337 | } |
---|
| 338 | os << endl; |
---|
| 339 | } |
---|
| 340 | |
---|
| 341 | void CSolver::dump_implication_queue(ostream & os) { |
---|
| 342 | _implication_queue.dump(os); |
---|
| 343 | } |
---|
| 344 | |
---|
| 345 | void CSolver::delete_clause_group(int gid) { |
---|
| 346 | assert(is_gid_allocated(gid)); |
---|
| 347 | |
---|
| 348 | if (_stats.been_reset == false) |
---|
| 349 | reset(); // if delete some clause, then implication queue are invalidated |
---|
| 350 | |
---|
| 351 | for (vector<CClause>::iterator itr = clauses()->begin(); |
---|
| 352 | itr != clauses()->end(); ++itr) { |
---|
| 353 | CClause & cl = *itr; |
---|
| 354 | if (cl.status() != DELETED_CL) { |
---|
| 355 | if (cl.gid(gid) == true) { |
---|
| 356 | mark_clause_deleted(cl); |
---|
| 357 | } |
---|
| 358 | } |
---|
| 359 | } |
---|
| 360 | |
---|
| 361 | // delete the index from variables |
---|
| 362 | for (vector<CVariable>::iterator itr = variables()->begin(); |
---|
| 363 | itr != variables()->end(); ++itr) { |
---|
| 364 | for (unsigned i = 0; i < 2; ++i) { // for each phase |
---|
| 365 | // delete the lit index from the vars |
---|
| 366 | #ifdef KEEP_LIT_CLAUSES |
---|
| 367 | vector<ClauseIdx> & lit_clauses = (*itr).lit_clause(i); |
---|
| 368 | for (vector<ClauseIdx>::iterator itr1 = lit_clauses.begin(); |
---|
| 369 | itr1 != lit_clauses.end(); ++itr1) { |
---|
| 370 | if (clause(*itr1).status() == DELETED_CL) { |
---|
| 371 | *itr1 = lit_clauses.back(); |
---|
| 372 | lit_clauses.pop_back(); |
---|
| 373 | --itr1; |
---|
| 374 | } |
---|
| 375 | } |
---|
| 376 | #endif |
---|
| 377 | // delete the watched index from the vars |
---|
| 378 | vector<CLitPoolElement *> & watched = (*itr).watched(i); |
---|
| 379 | for (vector<CLitPoolElement *>::iterator itr1 = watched.begin(); |
---|
| 380 | itr1 != watched.end(); ++itr1) { |
---|
| 381 | if ((*itr1)->val() <= 0) { |
---|
| 382 | *itr1 = watched.back(); |
---|
| 383 | watched.pop_back(); |
---|
| 384 | --itr1; |
---|
| 385 | } |
---|
| 386 | } |
---|
| 387 | } |
---|
| 388 | } |
---|
| 389 | free_gid(gid); |
---|
| 390 | } |
---|
| 391 | |
---|
| 392 | void CSolver::reset(void) { |
---|
| 393 | if (_stats.been_reset) |
---|
| 394 | return; |
---|
| 395 | if (num_variables() == 0) |
---|
| 396 | return; |
---|
| 397 | back_track(0); |
---|
| 398 | _conflicts.clear(); |
---|
| 399 | while (!_implication_queue.empty()) |
---|
| 400 | _implication_queue.pop(); |
---|
| 401 | |
---|
| 402 | _stats.outcome = UNDETERMINED; |
---|
| 403 | _stats.been_reset = true; |
---|
| 404 | } |
---|
| 405 | |
---|
| 406 | void CSolver::delete_unrelevant_clauses(void) { |
---|
| 407 | unsigned original_del_cls = num_deleted_clauses(); |
---|
| 408 | int num_conf_cls = num_clauses() - init_num_clauses() + num_del_orig_cls(); |
---|
| 409 | int head_count = num_conf_cls / _params.cls_deletion.tail_vs_head; |
---|
| 410 | int count = 0; |
---|
| 411 | for (vector<CClause>::iterator itr = clauses()->begin(); |
---|
| 412 | itr != clauses()->end() - 1; ++itr) { |
---|
| 413 | CClause & cl = *itr; |
---|
| 414 | if (cl.status() != CONFLICT_CL) { |
---|
| 415 | continue; |
---|
| 416 | } |
---|
| 417 | bool cls_sat_at_dl_0 = false; |
---|
| 418 | for (int i = 0, sz = cl.num_lits(); i < sz; ++i) { |
---|
| 419 | if (literal_value(cl.literal(i)) == 1 && |
---|
| 420 | variable(cl.literal(i).var_index()).dlevel() == 0) { |
---|
| 421 | cls_sat_at_dl_0 = true; |
---|
| 422 | break; |
---|
| 423 | } |
---|
| 424 | } |
---|
| 425 | if (cls_sat_at_dl_0) { |
---|
| 426 | int val_0_lits = 0, val_1_lits = 0, unknown_lits = 0; |
---|
| 427 | for (unsigned i = 0; i < cl.num_lits(); ++i) { |
---|
| 428 | int lit_value = literal_value(cl.literal(i)); |
---|
| 429 | if (lit_value == 0) |
---|
| 430 | ++val_0_lits; |
---|
| 431 | if (lit_value == 1) |
---|
| 432 | ++val_1_lits; |
---|
| 433 | if (lit_value == UNKNOWN) |
---|
| 434 | ++unknown_lits; |
---|
| 435 | if (unknown_lits + val_1_lits > 1) { |
---|
| 436 | mark_clause_deleted(cl); |
---|
| 437 | break; |
---|
| 438 | } |
---|
| 439 | } |
---|
| 440 | continue; |
---|
| 441 | } |
---|
| 442 | |
---|
| 443 | count++; |
---|
| 444 | int max_activity = _params.cls_deletion.head_activity - |
---|
| 445 | (_params.cls_deletion.head_activity - |
---|
| 446 | _params.cls_deletion.tail_activity) * |
---|
| 447 | count/num_conf_cls; |
---|
| 448 | int max_conf_cls_size; |
---|
| 449 | |
---|
| 450 | if (head_count > 0) { |
---|
| 451 | max_conf_cls_size = _params.cls_deletion.head_num_lits; |
---|
| 452 | --head_count; |
---|
| 453 | } else { |
---|
| 454 | max_conf_cls_size = _params.cls_deletion.tail_num_lits; |
---|
| 455 | } |
---|
| 456 | |
---|
| 457 | if (cl.activity() > max_activity) |
---|
| 458 | continue; |
---|
| 459 | |
---|
| 460 | int val_0_lits = 0, val_1_lits = 0, unknown_lits = 0, lit_value; |
---|
| 461 | for (unsigned i = 0; i < cl.num_lits(); ++i) { |
---|
| 462 | lit_value = literal_value(cl.literal(i)); |
---|
| 463 | if (lit_value == 0) |
---|
| 464 | ++val_0_lits; |
---|
| 465 | else if (lit_value == 1) |
---|
| 466 | ++val_1_lits; |
---|
| 467 | else |
---|
| 468 | ++unknown_lits; |
---|
| 469 | if ((unknown_lits > max_conf_cls_size)) { |
---|
| 470 | mark_clause_deleted(cl); |
---|
| 471 | break; |
---|
| 472 | } |
---|
| 473 | } |
---|
| 474 | } |
---|
| 475 | |
---|
| 476 | // if none were recently marked for deletion... |
---|
| 477 | if (original_del_cls == num_deleted_clauses()) |
---|
| 478 | return; |
---|
| 479 | |
---|
| 480 | // delete the index from variables |
---|
| 481 | for (vector<CVariable>::iterator itr = variables()->begin(); |
---|
| 482 | itr != variables()->end(); ++itr) { |
---|
| 483 | for (unsigned i = 0; i < 2; ++i) { // for each phase |
---|
| 484 | // delete the lit index from the vars |
---|
| 485 | #ifdef KEEP_LIT_CLAUSES |
---|
| 486 | vector<ClauseIdx> & lit_clauses = (*itr).lit_clause(i); |
---|
| 487 | for (vector<ClauseIdx>::iterator itr1 = lit_clauses.begin(); |
---|
| 488 | itr1 != lit_clauses.end(); ++itr1) { |
---|
| 489 | if (clause(*itr1).status() == DELETED_CL) { |
---|
| 490 | *itr1 = lit_clauses.back(); |
---|
| 491 | lit_clauses.pop_back(); |
---|
| 492 | --itr1; |
---|
| 493 | } |
---|
| 494 | } |
---|
| 495 | #endif |
---|
| 496 | // delete the watched index from the vars |
---|
| 497 | vector<CLitPoolElement *> & watched = (*itr).watched(i); |
---|
| 498 | for (vector<CLitPoolElement *>::iterator itr1 = watched.begin(); |
---|
| 499 | itr1 != watched.end(); ++itr1) { |
---|
| 500 | if ((*itr1)->val() <= 0) { |
---|
| 501 | *itr1 = watched.back(); |
---|
| 502 | watched.pop_back(); |
---|
| 503 | --itr1; |
---|
| 504 | } |
---|
| 505 | } |
---|
| 506 | } |
---|
| 507 | } |
---|
| 508 | |
---|
| 509 | for (unsigned i = 1, sz = variables()->size(); i < sz; ++i) { |
---|
| 510 | if (variable(i).dlevel() != 0) { |
---|
| 511 | variable(i).score(0) = variable(i).lits_count(0); |
---|
| 512 | variable(i).score(1) = variable(i).lits_count(1); |
---|
| 513 | if (variable(i).lits_count(0) == 0 && variable(i).value() == UNKNOWN) { |
---|
| 514 | queue_implication(i * 2 + 1, NULL_CLAUSE); |
---|
| 515 | } |
---|
| 516 | else if (variable(i).lits_count(1) == 0 && |
---|
| 517 | variable(i).value() == UNKNOWN) { |
---|
| 518 | queue_implication(i * 2, NULL_CLAUSE); |
---|
| 519 | } |
---|
| 520 | } else { |
---|
| 521 | variable(i).score(0) = 0; |
---|
| 522 | variable(i).score(1) = 0; |
---|
| 523 | } |
---|
| 524 | } |
---|
| 525 | update_var_score(); |
---|
| 526 | } |
---|
| 527 | |
---|
| 528 | bool CSolver::time_out(void) { |
---|
| 529 | return (get_cpu_time() - _stats.start_cpu_time> _params.time_limit); |
---|
| 530 | } |
---|
| 531 | |
---|
| 532 | void CSolver::adjust_variable_order(int * lits, int n_lits) { |
---|
| 533 | // note lits are signed vars, not CLitPoolElements |
---|
| 534 | for (int i = 0; i < n_lits; ++i) { |
---|
| 535 | int var_idx = lits[i] >> 1; |
---|
| 536 | CVariable & var = variable(var_idx); |
---|
| 537 | assert(var.value() != UNKNOWN); |
---|
| 538 | int orig_score = var.score(); |
---|
| 539 | ++variable(var_idx).score(lits[i] & 0x1); |
---|
| 540 | int new_score = var.score(); |
---|
| 541 | if (orig_score == new_score) |
---|
| 542 | continue; |
---|
| 543 | int pos = var.var_score_pos(); |
---|
| 544 | int orig_pos = pos; |
---|
| 545 | assert(_ordered_vars[pos].first == & var); |
---|
| 546 | assert(_ordered_vars[pos].second == orig_score); |
---|
| 547 | int bubble_step = _params.decision.bubble_init_step; |
---|
| 548 | for (pos = orig_pos ; pos >= 0; pos -= bubble_step) { |
---|
| 549 | if (_ordered_vars[pos].second >= new_score) |
---|
| 550 | break; |
---|
| 551 | } |
---|
| 552 | pos += bubble_step; |
---|
| 553 | for (bubble_step = bubble_step >> 1; bubble_step > 0; |
---|
| 554 | bubble_step = bubble_step >> 1) { |
---|
| 555 | if (pos - bubble_step >= 0 && |
---|
| 556 | _ordered_vars[pos - bubble_step].second < new_score) |
---|
| 557 | pos -= bubble_step; |
---|
| 558 | } |
---|
| 559 | // now found the position, do a swap |
---|
| 560 | _ordered_vars[orig_pos] = _ordered_vars[pos]; |
---|
| 561 | _ordered_vars[orig_pos].first->set_var_score_pos(orig_pos); |
---|
| 562 | _ordered_vars[pos].first = & var; |
---|
| 563 | _ordered_vars[pos].second = new_score; |
---|
| 564 | _ordered_vars[pos].first->set_var_score_pos(pos); |
---|
| 565 | _stats.total_bubble_move += orig_pos - pos; |
---|
| 566 | } |
---|
| 567 | } |
---|
| 568 | |
---|
| 569 | void CSolver::decay_variable_score(void) { |
---|
| 570 | unsigned i, sz; |
---|
| 571 | for (i = 1, sz = variables()->size(); i < sz; ++i) { |
---|
| 572 | CVariable & var = variable(i); |
---|
| 573 | var.score(0) /= 2; |
---|
| 574 | var.score(1) /= 2; |
---|
| 575 | } |
---|
| 576 | for (i = 0, sz = _ordered_vars.size(); i < sz; ++i) { |
---|
| 577 | _ordered_vars[i].second = _ordered_vars[i].first->score(); |
---|
| 578 | } |
---|
| 579 | } |
---|
| 580 | |
---|
| 581 | bool CSolver::decide_next_branch(void) { |
---|
| 582 | if (dlevel() > 0) |
---|
| 583 | assert(_assignment_stack[dlevel()]->size() > 0); |
---|
| 584 | if (!_implication_queue.empty()) { |
---|
| 585 | // some hook function did a decision, so skip my own decision making. |
---|
| 586 | // if the front of implication queue is 0, that means it's finished |
---|
| 587 | // because var index start from 1, so 2 *vid + sign won't be 0. |
---|
| 588 | // else it's a valid decision. |
---|
| 589 | return (_implication_queue.front().lit != 0); |
---|
| 590 | } |
---|
| 591 | int s_var = 0; |
---|
| 592 | if (_params.shrinking.enable) { |
---|
| 593 | while (!_shrinking_cls.empty()) { |
---|
| 594 | s_var = _shrinking_cls.begin()->second; |
---|
| 595 | _shrinking_cls.erase(_shrinking_cls.begin()); |
---|
| 596 | if (variable(s_var >> 1).value() == UNKNOWN) { |
---|
| 597 | _stats.num_decisions++; |
---|
| 598 | _stats.num_decisions_shrinking++; |
---|
| 599 | ++dlevel(); |
---|
| 600 | queue_implication(s_var ^ 0x1, NULL_CLAUSE); |
---|
| 601 | return true; |
---|
| 602 | } |
---|
| 603 | } |
---|
| 604 | } |
---|
| 605 | |
---|
| 606 | if (_outside_constraint_hook != NULL) |
---|
| 607 | _outside_constraint_hook(this); |
---|
| 608 | |
---|
| 609 | if (!_implication_queue.empty()) |
---|
| 610 | return (_implication_queue.front().lit != 0); |
---|
| 611 | |
---|
| 612 | ++_stats.num_decisions; |
---|
| 613 | if (num_free_variables() == 0) // no more free vars |
---|
| 614 | return false; |
---|
| 615 | |
---|
| 616 | bool cls_sat = true; |
---|
| 617 | int i, sz, var_idx, score, max_score = -1; |
---|
| 618 | |
---|
| 619 | for (; clause(top_unsat_cls).status() != ORIGINAL_CL; --top_unsat_cls) { |
---|
| 620 | CClause &cl=clause(top_unsat_cls); |
---|
| 621 | if (cl.status() != CONFLICT_CL) |
---|
| 622 | continue; |
---|
| 623 | cls_sat = false; |
---|
| 624 | if (cl.sat_lit_idx() < (int)cl.num_lits() && |
---|
| 625 | literal_value(cl.literal(cl.sat_lit_idx())) == 1) |
---|
| 626 | cls_sat = true; |
---|
| 627 | if (!cls_sat) { |
---|
| 628 | max_score = -1; |
---|
| 629 | for (i = 0, sz = cl.num_lits(); i < sz; ++i) { |
---|
| 630 | var_idx = cl.literal(i).var_index(); |
---|
| 631 | if (literal_value(cl.literal(i)) == 1) { |
---|
| 632 | cls_sat = true; |
---|
| 633 | cl.sat_lit_idx() = i; |
---|
| 634 | break; |
---|
| 635 | } |
---|
| 636 | else if (variable(var_idx).value() == UNKNOWN) { |
---|
| 637 | score = variable(var_idx).score(); |
---|
| 638 | if (score > max_score) { |
---|
| 639 | max_score = score; |
---|
| 640 | s_var = var_idx * 2; |
---|
| 641 | } |
---|
| 642 | } |
---|
| 643 | } |
---|
| 644 | } |
---|
| 645 | if (!cls_sat) |
---|
| 646 | break; |
---|
| 647 | } |
---|
| 648 | if (!cls_sat && max_score != -1) { |
---|
| 649 | ++dlevel(); |
---|
| 650 | if (dlevel() > _stats.max_dlevel) |
---|
| 651 | _stats.max_dlevel = dlevel(); |
---|
| 652 | CVariable& v = variable(s_var >> 1); |
---|
| 653 | if (v.score(0) < v.score(1)) |
---|
| 654 | s_var += 1; |
---|
| 655 | else if (v.score(0) == v.score(1)) { |
---|
| 656 | if (v.two_lits_count(0) > v.two_lits_count(1)) |
---|
| 657 | s_var+=1; |
---|
| 658 | else if (v.two_lits_count(0) == v.two_lits_count(1)) |
---|
| 659 | s_var+=rand()%2; |
---|
| 660 | } |
---|
| 661 | assert(s_var >= 2); |
---|
| 662 | queue_implication(s_var, NULL_CLAUSE); |
---|
| 663 | ++_stats.num_decisions_stack_conf; |
---|
| 664 | return true; |
---|
| 665 | } |
---|
| 666 | |
---|
| 667 | for (unsigned i = _max_score_pos; i < _ordered_vars.size(); ++i) { |
---|
| 668 | CVariable & var = *_ordered_vars[i].first; |
---|
| 669 | if (var.value() == UNKNOWN && var.is_branchable()) { |
---|
| 670 | // move th max score position pointer |
---|
| 671 | _max_score_pos = i; |
---|
| 672 | // make some randomness happen |
---|
| 673 | if (--_stats.current_randomness < _params.decision.base_randomness) |
---|
| 674 | _stats.current_randomness = _params.decision.base_randomness; |
---|
| 675 | int randomness = _stats.current_randomness; |
---|
| 676 | if (randomness >= num_free_variables()) |
---|
| 677 | randomness = num_free_variables() - 1; |
---|
| 678 | int skip = rand() % (1 + randomness); |
---|
| 679 | int index = i; |
---|
| 680 | while (skip > 0) { |
---|
| 681 | ++index; |
---|
| 682 | if (_ordered_vars[index].first->value() == UNKNOWN && |
---|
| 683 | _ordered_vars[index].first->is_branchable()) |
---|
| 684 | --skip; |
---|
| 685 | } |
---|
| 686 | CVariable * ptr = _ordered_vars[index].first; |
---|
| 687 | assert(ptr->value() == UNKNOWN && ptr->is_branchable()); |
---|
| 688 | int sign = 0; |
---|
| 689 | if (ptr->score(0) < ptr->score(1)) |
---|
| 690 | sign += 1; |
---|
| 691 | else if (ptr->score(0) == ptr->score(1)) { |
---|
| 692 | if (ptr->two_lits_count(0) > ptr->two_lits_count(1)) |
---|
| 693 | sign += 1; |
---|
| 694 | else if (ptr->two_lits_count(0) == ptr->two_lits_count(1)) |
---|
| 695 | sign += rand() % 2; |
---|
| 696 | } |
---|
| 697 | int var_idx = ptr - &(*variables()->begin()); |
---|
| 698 | s_var = var_idx + var_idx + sign; |
---|
| 699 | break; |
---|
| 700 | } |
---|
| 701 | } |
---|
| 702 | assert(s_var >= 2); // there must be a free var somewhere |
---|
| 703 | ++dlevel(); |
---|
| 704 | if (dlevel() > _stats.max_dlevel) |
---|
| 705 | _stats.max_dlevel = dlevel(); |
---|
| 706 | ++_stats.num_decisions_vsids; |
---|
| 707 | _implication_id = 0; |
---|
| 708 | queue_implication(s_var, NULL_CLAUSE); |
---|
| 709 | return true; |
---|
| 710 | } |
---|
| 711 | |
---|
| 712 | int CSolver::preprocess(void) { |
---|
| 713 | assert(dlevel() == 0); |
---|
| 714 | |
---|
| 715 | // 1. detect all the unused variables |
---|
| 716 | vector<int> un_used; |
---|
| 717 | for (unsigned i = 1, sz = variables()->size(); i < sz; ++i) { |
---|
| 718 | CVariable & v = variable(i); |
---|
| 719 | if (v.lits_count(0) == 0 && v.lits_count(1) == 0) { |
---|
| 720 | un_used.push_back(i); |
---|
| 721 | queue_implication(i+i, NULL_CLAUSE); |
---|
| 722 | int r = deduce(); |
---|
| 723 | assert(r == NO_CONFLICT); |
---|
| 724 | } |
---|
| 725 | } |
---|
| 726 | if (_params.verbosity > 1 && un_used.size() > 0) { |
---|
| 727 | cout << un_used.size() << " Variables are defined but not used " << endl; |
---|
| 728 | if (_params.verbosity > 2) { |
---|
| 729 | for (unsigned i = 0; i< un_used.size(); ++i) |
---|
| 730 | cout << un_used[i] << " "; |
---|
| 731 | cout << endl; |
---|
| 732 | } |
---|
| 733 | } |
---|
| 734 | |
---|
| 735 | // 2. detect all variables with only one phase occuring (i.e. pure literals) |
---|
| 736 | vector<int> uni_phased; |
---|
| 737 | for (unsigned i = 1, sz = variables()->size(); i < sz; ++i) { |
---|
| 738 | CVariable & v = variable(i); |
---|
| 739 | if (v.value() != UNKNOWN) |
---|
| 740 | continue; |
---|
| 741 | if (v.lits_count(0) == 0) { // no positive phased lits. |
---|
| 742 | queue_implication(i+i+1, NULL_CLAUSE); |
---|
| 743 | uni_phased.push_back(-i); |
---|
| 744 | } |
---|
| 745 | else if (v.lits_count(1) == 0) { // no negative phased lits. |
---|
| 746 | queue_implication(i+i, NULL_CLAUSE); |
---|
| 747 | uni_phased.push_back(i); |
---|
| 748 | } |
---|
| 749 | } |
---|
| 750 | if (_params.verbosity > 1 && uni_phased.size() > 0) { |
---|
| 751 | cout << uni_phased.size() << " Variables only appear in one phase." <<endl; |
---|
| 752 | if (_params.verbosity > 2) { |
---|
| 753 | for (unsigned i = 0; i< uni_phased.size(); ++i) |
---|
| 754 | cout << uni_phased[i] << " "; |
---|
| 755 | cout <<endl; |
---|
| 756 | } |
---|
| 757 | } |
---|
| 758 | |
---|
| 759 | // 3. Unit clauses |
---|
| 760 | for (unsigned i = 0, sz = clauses()->size(); i < sz; ++i) { |
---|
| 761 | if (clause(i).status() != DELETED_CL && |
---|
| 762 | clause(i).num_lits() == 1 && |
---|
| 763 | variable(clause(i).literal(0).var_index()).value() == UNKNOWN) |
---|
| 764 | queue_implication(clause(i).literal(0).s_var(), i); |
---|
| 765 | } |
---|
| 766 | |
---|
| 767 | if (deduce() == CONFLICT) { |
---|
| 768 | cout << " CONFLICT during preprocess " <<endl; |
---|
| 769 | #ifdef VERIFY_ON |
---|
| 770 | for (unsigned i = 1; i < variables()->size(); ++i) { |
---|
| 771 | if (variable(i).value() != UNKNOWN) { |
---|
| 772 | assert(variable(i).dlevel() <= 0); |
---|
| 773 | int ante = variable(i).antecedent(); |
---|
| 774 | int ante_id = 0; |
---|
| 775 | if (ante >= 0) { |
---|
| 776 | ante_id = clause(ante).id(); |
---|
| 777 | verify_out << "VAR: " << i |
---|
| 778 | << " L: " << variable(i).assgn_stack_pos() |
---|
| 779 | << " V: " << variable(i).value() |
---|
| 780 | << " A: " << ante_id |
---|
| 781 | << " Lits:"; |
---|
| 782 | for (unsigned j = 0; j < clause(ante).num_lits(); ++j) |
---|
| 783 | verify_out <<" " << clause(ante).literal(j).s_var(); |
---|
| 784 | verify_out << endl; |
---|
| 785 | } |
---|
| 786 | } |
---|
| 787 | } |
---|
| 788 | verify_out << "CONF: " << clause(_conflicts[0]).id() << " =="; |
---|
| 789 | for (unsigned i = 0; i < clause(_conflicts[0]).num_lits(); ++i) { |
---|
| 790 | int svar = clause(_conflicts[0]).literal(i).s_var(); |
---|
| 791 | verify_out << " " << svar; |
---|
| 792 | } |
---|
| 793 | verify_out << endl; |
---|
| 794 | #endif |
---|
| 795 | return CONFLICT; |
---|
| 796 | } |
---|
| 797 | if (_params.verbosity > 1) { |
---|
| 798 | cout << _assignment_stack[0]->size() << " vars set during preprocess; " |
---|
| 799 | << endl; |
---|
| 800 | } |
---|
| 801 | return NO_CONFLICT; |
---|
| 802 | } |
---|
| 803 | |
---|
| 804 | void CSolver::mark_var_unbranchable(int vid) { |
---|
| 805 | if (variable(vid).is_branchable()) { |
---|
| 806 | variable(vid).disable_branch(); |
---|
| 807 | if (variable(vid).value() == UNKNOWN) |
---|
| 808 | --num_free_variables(); |
---|
| 809 | } |
---|
| 810 | } |
---|
| 811 | |
---|
| 812 | void CSolver::mark_var_branchable(int vid) { |
---|
| 813 | CVariable & var = variable(vid); |
---|
| 814 | if (!var.is_branchable()) { |
---|
| 815 | var.enable_branch(); |
---|
| 816 | if (var.value() == UNKNOWN) { |
---|
| 817 | ++num_free_variables(); |
---|
| 818 | if (var.var_score_pos() < _max_score_pos) |
---|
| 819 | _max_score_pos = var.var_score_pos(); |
---|
| 820 | } |
---|
| 821 | } |
---|
| 822 | } |
---|
| 823 | |
---|
| 824 | ClauseIdx CSolver::add_orig_clause(int * lits, int n_lits, int gid) { |
---|
| 825 | int cid = add_clause_with_gid(lits, n_lits, gid); |
---|
| 826 | if (cid >= 0) { |
---|
| 827 | clause(cid).set_status(ORIGINAL_CL); |
---|
| 828 | clause(cid).activity() = 0; |
---|
| 829 | } |
---|
| 830 | return cid; |
---|
| 831 | } |
---|
| 832 | |
---|
| 833 | ClauseIdx CSolver::add_clause_with_gid(int * lits, int n_lits, int gid) { |
---|
| 834 | unsigned gflag; |
---|
| 835 | if (gid == PERMANENT_GID ) |
---|
| 836 | gflag = 0; |
---|
| 837 | else if (gid == VOLATILE_GID) { |
---|
| 838 | gflag = (~0x0); |
---|
| 839 | } else { |
---|
| 840 | assert(gid <= WORD_WIDTH && gid > 0); |
---|
| 841 | gflag = (1 << (gid- 1)); |
---|
| 842 | } |
---|
| 843 | ClauseIdx cid = add_clause(lits, n_lits, gflag); |
---|
| 844 | if (cid < 0) { |
---|
| 845 | _stats.is_mem_out = true; |
---|
| 846 | _stats.outcome = MEM_OUT; |
---|
| 847 | } |
---|
| 848 | return cid; |
---|
| 849 | } |
---|
| 850 | |
---|
| 851 | ClauseIdx CSolver::add_conflict_clause(int * lits, int n_lits, int gflag) { |
---|
| 852 | ClauseIdx cid = add_clause(lits, n_lits, gflag); |
---|
| 853 | if (cid >= 0) { |
---|
| 854 | clause(cid).set_status(CONFLICT_CL); |
---|
| 855 | clause(cid).activity() = 0; |
---|
| 856 | } else { |
---|
| 857 | _stats.is_mem_out = true; |
---|
| 858 | _stats.outcome = MEM_OUT; |
---|
| 859 | } |
---|
| 860 | return cid; |
---|
| 861 | } |
---|
| 862 | |
---|
| 863 | void CSolver::real_solve(void) { |
---|
| 864 | while (_stats.outcome == UNDETERMINED) { |
---|
| 865 | run_periodic_functions(); |
---|
| 866 | if (decide_next_branch()) { |
---|
| 867 | while (deduce() == CONFLICT) { |
---|
| 868 | int blevel; |
---|
| 869 | blevel = analyze_conflicts(); |
---|
| 870 | if (blevel < 0) { |
---|
| 871 | _stats.outcome = UNSATISFIABLE; |
---|
| 872 | return; |
---|
| 873 | } |
---|
| 874 | } |
---|
| 875 | } else { |
---|
| 876 | if (_sat_hook != NULL && _sat_hook(this)) |
---|
| 877 | continue; |
---|
| 878 | _stats.outcome = SATISFIABLE; |
---|
| 879 | return; |
---|
| 880 | } |
---|
| 881 | if (time_out()) { |
---|
| 882 | _stats.outcome = TIME_OUT; |
---|
| 883 | return; |
---|
| 884 | } |
---|
| 885 | if (_force_terminate) { |
---|
| 886 | _stats.outcome = ABORTED; |
---|
| 887 | return; |
---|
| 888 | } |
---|
| 889 | if (_stats.is_mem_out) { |
---|
| 890 | _stats.outcome = MEM_OUT; |
---|
| 891 | return; |
---|
| 892 | } |
---|
| 893 | } |
---|
| 894 | } |
---|
| 895 | |
---|
| 896 | int CSolver::solve(void) { |
---|
| 897 | if (_stats.outcome == UNDETERMINED) { |
---|
| 898 | init_solve(); |
---|
| 899 | |
---|
| 900 | if (preprocess() == CONFLICT) |
---|
| 901 | _stats.outcome = UNSATISFIABLE; |
---|
| 902 | else // the real search |
---|
| 903 | real_solve(); |
---|
| 904 | cout << endl; |
---|
| 905 | _stats.finish_cpu_time = get_cpu_time(); |
---|
| 906 | } |
---|
| 907 | return _stats.outcome; |
---|
| 908 | } |
---|
| 909 | |
---|
| 910 | void CSolver::back_track(int blevel) { |
---|
| 911 | assert(blevel <= dlevel()); |
---|
| 912 | for (int i = dlevel(); i >= blevel; --i) { |
---|
| 913 | vector<int> & assignments = *_assignment_stack[i]; |
---|
| 914 | for (int j = assignments.size() - 1 ; j >= 0; --j) |
---|
| 915 | unset_var_value(assignments[j]>>1); |
---|
| 916 | assignments.clear(); |
---|
| 917 | } |
---|
| 918 | dlevel() = blevel - 1; |
---|
| 919 | if (dlevel() < 0 ) |
---|
| 920 | dlevel() = 0; |
---|
| 921 | ++_stats.num_backtracks; |
---|
| 922 | } |
---|
| 923 | |
---|
| 924 | int CSolver::deduce(void) { |
---|
| 925 | while (!_implication_queue.empty()) { |
---|
| 926 | const CImplication & imp = _implication_queue.front(); |
---|
| 927 | int lit = imp.lit; |
---|
| 928 | int vid = lit>>1; |
---|
| 929 | ClauseIdx cl = imp.antecedent; |
---|
| 930 | _implication_queue.pop(); |
---|
| 931 | CVariable & var = variable(vid); |
---|
| 932 | if (var.value() == UNKNOWN) { // an implication |
---|
| 933 | set_var_value(vid, !(lit & 0x1), cl, dlevel()); |
---|
| 934 | } |
---|
| 935 | else if (var.value() == (unsigned)(lit & 0x1)) { |
---|
| 936 | // a conflict |
---|
| 937 | // note: literal & 0x1 == 1 means the literal is in negative phase |
---|
| 938 | // when a conflict occure at not current dlevel, we need to backtrack |
---|
| 939 | // to resolve the problem. |
---|
| 940 | // conflict analysis will only work if the conflict occure at |
---|
| 941 | // the top level (current dlevel) |
---|
| 942 | _conflicts.push_back(cl); |
---|
| 943 | break; |
---|
| 944 | } else { |
---|
| 945 | // so the variable have been assigned before |
---|
| 946 | // update its antecedent with a shorter one |
---|
| 947 | if (var.antecedent() != NULL_CLAUSE && |
---|
| 948 | clause(cl).num_lits() < clause(var.antecedent()).num_lits()) |
---|
| 949 | var.antecedent() = cl; |
---|
| 950 | assert(var.dlevel() <= dlevel()); |
---|
| 951 | } |
---|
| 952 | } |
---|
| 953 | // if loop exited because of a conflict, we need to clean implication queue |
---|
| 954 | while (!_implication_queue.empty()) |
---|
| 955 | _implication_queue.pop(); |
---|
| 956 | return (_conflicts.size() ? CONFLICT : NO_CONFLICT); |
---|
| 957 | } |
---|
| 958 | |
---|
| 959 | void CSolver::verify_integrity(void) { |
---|
| 960 | for (unsigned i = 1; i < variables()->size(); ++i) { |
---|
| 961 | if (variable(i).value() != UNKNOWN) { |
---|
| 962 | int pos = variable(i).assgn_stack_pos(); |
---|
| 963 | int value = variable(i).value(); |
---|
| 964 | int dlevel = variable(i).dlevel(); |
---|
| 965 | assert((*_assignment_stack[dlevel])[pos] == (int) (i+i+1-value)); |
---|
| 966 | } |
---|
| 967 | } |
---|
| 968 | for (unsigned i = 0; i < clauses()->size(); ++i) { |
---|
| 969 | if (clause(i).status() == DELETED_CL) |
---|
| 970 | continue; |
---|
| 971 | CClause & cl = clause(i); |
---|
| 972 | int num_0 = 0; |
---|
| 973 | int num_1 = 0; |
---|
| 974 | int num_unknown = 0; |
---|
| 975 | int watched[2]; |
---|
| 976 | int watch_index = 0; |
---|
| 977 | watched[1] = watched[0] = 0; |
---|
| 978 | for (unsigned j = 0; j < cl.num_lits(); ++j) { |
---|
| 979 | CLitPoolElement lit = cl.literal(j); |
---|
| 980 | int vid = lit.var_index(); |
---|
| 981 | if (variable(vid).value() == UNKNOWN) { |
---|
| 982 | ++num_unknown; |
---|
| 983 | } else { |
---|
| 984 | if (literal_value(lit) == 0) |
---|
| 985 | ++num_0; |
---|
| 986 | else |
---|
| 987 | ++num_1; |
---|
| 988 | } |
---|
| 989 | if (lit.is_watched()) { |
---|
| 990 | watched[watch_index] = lit.s_var(); |
---|
| 991 | ++watch_index; |
---|
| 992 | } |
---|
| 993 | } |
---|
| 994 | if (watch_index == 0) { |
---|
| 995 | assert(cl.num_lits() == 1); |
---|
| 996 | continue; |
---|
| 997 | } |
---|
| 998 | assert(watch_index == 2); |
---|
| 999 | for (unsigned j = 0; j < cl.num_lits(); ++j) { |
---|
| 1000 | CLitPoolElement lit = cl.literal(j); |
---|
| 1001 | int vid1 = (watched[0]>>1); |
---|
| 1002 | if (variable(vid1).value() == (unsigned)(watched[0] & 0x1)) { |
---|
| 1003 | if (!lit.is_watched()) { |
---|
| 1004 | assert(literal_value(lit) == 0); |
---|
| 1005 | assert(variable(lit.var_index()).dlevel() <= |
---|
| 1006 | variable(vid1).dlevel()); |
---|
| 1007 | } |
---|
| 1008 | } |
---|
| 1009 | int vid2 = (watched[1]>>1); |
---|
| 1010 | if (variable(vid2).value() == (unsigned)(watched[1] & 0x1)) { |
---|
| 1011 | if (!lit.is_watched()) { |
---|
| 1012 | assert(literal_value(lit) == 0); |
---|
| 1013 | assert(variable(lit.var_index()).dlevel() <= |
---|
| 1014 | variable(vid1).dlevel()); |
---|
| 1015 | } |
---|
| 1016 | } |
---|
| 1017 | } |
---|
| 1018 | } |
---|
| 1019 | } |
---|
| 1020 | |
---|
| 1021 | void CSolver::mark_vars(ClauseIdx cl, int var_idx) { |
---|
| 1022 | assert(_resolvents.empty() || var_idx != -1); |
---|
| 1023 | #ifdef VERIFY_ON |
---|
| 1024 | _resolvents.push_back(clause(cl).id()); |
---|
| 1025 | #endif |
---|
| 1026 | for (CLitPoolElement* itr = clause(cl).literals(); (*itr).val() > 0; ++itr) { |
---|
| 1027 | int v = (*itr).var_index(); |
---|
| 1028 | if (v == var_idx) |
---|
| 1029 | continue; |
---|
| 1030 | else if (variable(v).dlevel() == dlevel()) { |
---|
| 1031 | if (!variable(v).is_marked()) { |
---|
| 1032 | variable(v).set_marked(); |
---|
| 1033 | ++_num_marked; |
---|
| 1034 | if (_mark_increase_score) { |
---|
| 1035 | int tmp = itr->s_var(); |
---|
| 1036 | adjust_variable_order(&tmp, 1); |
---|
| 1037 | } |
---|
| 1038 | } |
---|
| 1039 | } else { |
---|
| 1040 | assert(variable(v).dlevel() < dlevel()); |
---|
| 1041 | if (variable(v).new_cl_phase() == UNKNOWN) { // it's not in the new cl |
---|
| 1042 | // We can remove the variable assigned at dlevel 0 if |
---|
| 1043 | // we are nog going to use incremental SAT. |
---|
| 1044 | // if(variable(v).dlevel()){ |
---|
| 1045 | ++_num_in_new_cl; |
---|
| 1046 | variable(v).set_new_cl_phase((*itr).var_sign()); |
---|
| 1047 | _conflict_lits.push_back((*itr).s_var()); |
---|
| 1048 | // } |
---|
| 1049 | } else { |
---|
| 1050 | // if this variable is already in the new clause, it must |
---|
| 1051 | // have the same phase |
---|
| 1052 | assert(variable(v).new_cl_phase() == (*itr).var_sign()); |
---|
| 1053 | } |
---|
| 1054 | } |
---|
| 1055 | } |
---|
| 1056 | } |
---|
| 1057 | |
---|
| 1058 | int CSolver::analyze_conflicts(void) { |
---|
| 1059 | assert(!_conflicts.empty()); |
---|
| 1060 | assert(_conflict_lits.size() == 0); |
---|
| 1061 | assert(_implication_queue.empty()); |
---|
| 1062 | assert(_num_marked == 0); |
---|
| 1063 | if (dlevel() == 0) { // already at level 0. Conflict means unsat. |
---|
| 1064 | #ifdef VERIFY_ON |
---|
| 1065 | for (unsigned i = 1; i < variables()->size(); ++i) { |
---|
| 1066 | if (variable(i).value() != UNKNOWN) { |
---|
| 1067 | assert(variable(i).dlevel() <= 0); |
---|
| 1068 | int ante = variable(i).antecedent(); |
---|
| 1069 | int ante_id = 0; |
---|
| 1070 | if (ante >= 0) { |
---|
| 1071 | ante_id = clause(ante).id(); |
---|
| 1072 | assert(clause(ante).status() != DELETED_CL); |
---|
| 1073 | verify_out << "VAR: " << i |
---|
| 1074 | << " L: " << variable(i).assgn_stack_pos() |
---|
| 1075 | << " V: " << variable(i).value() |
---|
| 1076 | << " A: " << ante_id |
---|
| 1077 | << " Lits:"; |
---|
| 1078 | for (unsigned j = 0; j < clause(ante).num_lits(); ++j) |
---|
| 1079 | verify_out << " " << clause(ante).literal(j).s_var(); |
---|
| 1080 | verify_out << endl; |
---|
| 1081 | } |
---|
| 1082 | } |
---|
| 1083 | } |
---|
| 1084 | ClauseIdx shortest; |
---|
| 1085 | shortest = _conflicts.back(); |
---|
| 1086 | unsigned len = clause(_conflicts.back()).num_lits(); |
---|
| 1087 | while (!_conflicts.empty()) { |
---|
| 1088 | if (clause(_conflicts.back()).num_lits() < len) { |
---|
| 1089 | shortest = _conflicts.back(); |
---|
| 1090 | len = clause(_conflicts.back()).num_lits(); |
---|
| 1091 | } |
---|
| 1092 | _conflicts.pop_back(); |
---|
| 1093 | } |
---|
| 1094 | verify_out << "CONF: " << clause(shortest).id() << " =="; |
---|
| 1095 | for (unsigned i = 0; i < clause(shortest).num_lits(); ++i) { |
---|
| 1096 | int svar = clause(shortest).literal(i).s_var(); |
---|
| 1097 | verify_out << " " << svar; |
---|
| 1098 | } |
---|
| 1099 | verify_out << endl; |
---|
| 1100 | #endif |
---|
| 1101 | _conflicts.clear(); |
---|
| 1102 | back_track(0); |
---|
| 1103 | return -1; |
---|
| 1104 | } |
---|
| 1105 | return conflict_analysis_firstUIP(); |
---|
| 1106 | } |
---|
| 1107 | |
---|
| 1108 | // when all the literals involved are in _conflict_lits |
---|
| 1109 | // call this function to finish the adding clause and backtrack |
---|
| 1110 | |
---|
| 1111 | int CSolver::finish_add_conf_clause(int gflag) { |
---|
| 1112 | ClauseIdx added_cl = add_conflict_clause(&(*_conflict_lits.begin()), |
---|
| 1113 | _conflict_lits.size(), gflag); |
---|
| 1114 | if (added_cl < 0) { // memory out. |
---|
| 1115 | _stats.is_mem_out = true; |
---|
| 1116 | _conflicts.clear(); |
---|
| 1117 | assert(_implication_queue.empty()); |
---|
| 1118 | return 1; |
---|
| 1119 | } |
---|
| 1120 | |
---|
| 1121 | top_unsat_cls = clauses()->size() - 1; |
---|
| 1122 | |
---|
| 1123 | #ifdef VERIFY_ON |
---|
| 1124 | verify_out << "CL: " << clause(added_cl).id() << " <="; |
---|
| 1125 | for (unsigned i = 0; i< _resolvents.size(); ++i) |
---|
| 1126 | verify_out << " " << _resolvents[i]; |
---|
| 1127 | verify_out << endl; |
---|
| 1128 | _resolvents.clear(); |
---|
| 1129 | #endif |
---|
| 1130 | |
---|
| 1131 | adjust_variable_order(&(*_conflict_lits.begin()), _conflict_lits.size()); |
---|
| 1132 | |
---|
| 1133 | if (_params.shrinking.enable) { |
---|
| 1134 | _shrinking_cls.clear(); |
---|
| 1135 | if (_stats.shrinking_cls_length != 0) { |
---|
| 1136 | int benefit = _stats.shrinking_cls_length - _conflict_lits.size(); |
---|
| 1137 | _stats.shrinking_benefit += benefit; |
---|
| 1138 | _stats.shrinking_cls_length = 0; |
---|
| 1139 | _recent_shrinkings.push(benefit); |
---|
| 1140 | if (_recent_shrinkings.size() > _params.shrinking.window_width) { |
---|
| 1141 | _stats.shrinking_benefit -= _recent_shrinkings.front(); |
---|
| 1142 | _recent_shrinkings.pop(); |
---|
| 1143 | } |
---|
| 1144 | } |
---|
| 1145 | if (_conflict_lits.size() > _params.shrinking.size) { |
---|
| 1146 | _shrinking_cls.clear(); |
---|
| 1147 | for (unsigned i = 0, sz = _conflict_lits.size(); i < sz; ++i) { |
---|
| 1148 | _shrinking_cls.insert(pair<int, int> |
---|
| 1149 | (variable(_conflict_lits[i]>>1).dlevel(), _conflict_lits[i])); |
---|
| 1150 | } |
---|
| 1151 | int prev_dl = _shrinking_cls.begin()->first; |
---|
| 1152 | multimap<int, int>::iterator itr, itr_del; |
---|
| 1153 | int last_dl = _shrinking_cls.rbegin()->first; |
---|
| 1154 | |
---|
| 1155 | bool found_gap = false; |
---|
| 1156 | for (itr = _shrinking_cls.begin(); itr->first != last_dl;) { |
---|
| 1157 | if (itr->first - prev_dl > 2) { |
---|
| 1158 | found_gap = true; |
---|
| 1159 | break; |
---|
| 1160 | } |
---|
| 1161 | prev_dl = itr->first; |
---|
| 1162 | itr_del = itr; |
---|
| 1163 | ++itr; |
---|
| 1164 | _shrinking_cls.erase(itr_del); |
---|
| 1165 | } |
---|
| 1166 | if (found_gap && _shrinking_cls.size() > 0 && prev_dl < dlevel() - 1) { |
---|
| 1167 | _stats.shrinking_cls_length = _conflict_lits.size(); |
---|
| 1168 | ++_stats.num_shrinkings; |
---|
| 1169 | back_track(prev_dl + 1); |
---|
| 1170 | _conflicts.clear(); |
---|
| 1171 | #ifdef VERIFY_ON |
---|
| 1172 | _resolvents.clear(); |
---|
| 1173 | #endif |
---|
| 1174 | _num_in_new_cl = 0; |
---|
| 1175 | for (unsigned i = 0, sz = _conflict_lits.size(); i < sz; ++i) |
---|
| 1176 | variable(_conflict_lits[i]>>1).set_new_cl_phase(UNKNOWN); |
---|
| 1177 | _conflict_lits.clear(); |
---|
| 1178 | if (_stats.num_shrinkings % |
---|
| 1179 | _params.shrinking.bound_update_frequency == 0 && |
---|
| 1180 | _recent_shrinkings.size() == _params.shrinking.window_width) { |
---|
| 1181 | if (_stats.shrinking_benefit > _params.shrinking.upper_bound) |
---|
| 1182 | _params.shrinking.size += _params.shrinking.upper_delta; |
---|
| 1183 | else if (_stats.shrinking_benefit < _params.shrinking.lower_bound) |
---|
| 1184 | _params.shrinking.size += _params.shrinking.lower_delta; |
---|
| 1185 | } |
---|
| 1186 | return prev_dl; |
---|
| 1187 | } |
---|
| 1188 | } |
---|
| 1189 | } |
---|
| 1190 | int back_dl = 0; |
---|
| 1191 | int unit_lit = -1; |
---|
| 1192 | |
---|
| 1193 | for (unsigned i = 0; i < clause(added_cl).num_lits(); ++i) { |
---|
| 1194 | int vid = clause(added_cl).literal(i).var_index(); |
---|
| 1195 | int sign =clause(added_cl).literal(i).var_sign(); |
---|
| 1196 | assert(variable(vid).value() != UNKNOWN); |
---|
| 1197 | assert(literal_value(clause(added_cl).literal(i)) == 0); |
---|
| 1198 | int dl = variable(vid).dlevel(); |
---|
| 1199 | if (dl < dlevel()) { |
---|
| 1200 | if (dl > back_dl) |
---|
| 1201 | back_dl = dl; |
---|
| 1202 | } else { |
---|
| 1203 | assert(unit_lit == -1); |
---|
| 1204 | unit_lit = vid + vid + sign; |
---|
| 1205 | } |
---|
| 1206 | } |
---|
| 1207 | if (back_dl == 0) { |
---|
| 1208 | _stats.next_restart = _stats.num_backtracks + _stats.restart_incr; |
---|
| 1209 | _stats.next_cls_deletion = _stats.num_backtracks + |
---|
| 1210 | _params.cls_deletion.interval; |
---|
| 1211 | } |
---|
| 1212 | |
---|
| 1213 | back_track(back_dl + 1); |
---|
| 1214 | queue_implication(unit_lit, added_cl); |
---|
| 1215 | |
---|
| 1216 | // after resolve the first conflict, others must also be resolved |
---|
| 1217 | // for (unsigned i = 1; i < _conflicts.size(); ++i) |
---|
| 1218 | // assert(!is_conflicting(_conflicts[i])); |
---|
| 1219 | |
---|
| 1220 | _conflicts.clear(); |
---|
| 1221 | |
---|
| 1222 | while (!_conflict_lits.empty()) { |
---|
| 1223 | int svar = _conflict_lits.back(); |
---|
| 1224 | _conflict_lits.pop_back(); |
---|
| 1225 | CVariable & var = variable(svar >> 1); |
---|
| 1226 | assert(var.new_cl_phase() == (unsigned)(svar & 0x1)); |
---|
| 1227 | --_num_in_new_cl; |
---|
| 1228 | var.set_new_cl_phase(UNKNOWN); |
---|
| 1229 | } |
---|
| 1230 | assert(_num_in_new_cl == 0); |
---|
| 1231 | return back_dl; |
---|
| 1232 | } |
---|
| 1233 | |
---|
| 1234 | int CSolver::conflict_analysis_firstUIP(void) { |
---|
| 1235 | int min_conf_id = _conflicts[0]; |
---|
| 1236 | int min_conf_length = -1; |
---|
| 1237 | ClauseIdx cl; |
---|
| 1238 | unsigned gflag; |
---|
| 1239 | _mark_increase_score = false; |
---|
| 1240 | if (_conflicts.size() > 1) { |
---|
| 1241 | for (vector<ClauseIdx>::iterator ci = _conflicts.begin(); |
---|
| 1242 | ci != _conflicts.end(); ci++) { |
---|
| 1243 | assert(_num_in_new_cl == 0); |
---|
| 1244 | assert(dlevel() > 0); |
---|
| 1245 | cl = *ci; |
---|
| 1246 | mark_vars(cl, -1); |
---|
| 1247 | // current dl must be the conflict cl. |
---|
| 1248 | vector <int> & assignments = *_assignment_stack[dlevel()]; |
---|
| 1249 | // now add conflict lits, and unassign vars |
---|
| 1250 | for (int i = assignments.size() - 1; i >= 0; --i) { |
---|
| 1251 | int assigned = assignments[i]; |
---|
| 1252 | if (variable(assigned >> 1).is_marked()) { |
---|
| 1253 | // this variable is involved in the conflict clause or its antecedent |
---|
| 1254 | variable(assigned>>1).clear_marked(); |
---|
| 1255 | --_num_marked; |
---|
| 1256 | ClauseIdx ante_cl = variable(assigned>>1).get_antecedent(); |
---|
| 1257 | if ( _num_marked == 0 ) { |
---|
| 1258 | // the first UIP encountered, conclude add clause |
---|
| 1259 | assert(variable(assigned>>1).new_cl_phase() == UNKNOWN); |
---|
| 1260 | // add this assignment's reverse, e.g. UIP |
---|
| 1261 | _conflict_lits.push_back(assigned ^ 0x1); |
---|
| 1262 | ++_num_in_new_cl; |
---|
| 1263 | variable(assigned>>1).set_new_cl_phase((assigned^0x1)&0x1); |
---|
| 1264 | break; |
---|
| 1265 | } else { |
---|
| 1266 | assert(ante_cl != NULL_CLAUSE); |
---|
| 1267 | mark_vars(ante_cl, assigned >> 1); |
---|
| 1268 | } |
---|
| 1269 | } |
---|
| 1270 | } |
---|
| 1271 | if (min_conf_length == -1 || |
---|
| 1272 | (int)_conflict_lits.size() < min_conf_length) { |
---|
| 1273 | min_conf_length = _conflict_lits.size(); |
---|
| 1274 | min_conf_id = cl; |
---|
| 1275 | } |
---|
| 1276 | |
---|
| 1277 | for (vector<int>::iterator vi = _conflict_lits.begin(); vi != |
---|
| 1278 | _conflict_lits.end(); ++vi) { |
---|
| 1279 | int s_var = *vi; |
---|
| 1280 | CVariable & var = variable(s_var >> 1); |
---|
| 1281 | assert(var.new_cl_phase() == (unsigned)(s_var & 0x1)); |
---|
| 1282 | var.set_new_cl_phase(UNKNOWN); |
---|
| 1283 | } |
---|
| 1284 | _num_in_new_cl = 0; |
---|
| 1285 | _conflict_lits.clear(); |
---|
| 1286 | #ifdef VERIFY_ON |
---|
| 1287 | _resolvents.clear(); |
---|
| 1288 | #endif |
---|
| 1289 | } |
---|
| 1290 | } |
---|
| 1291 | |
---|
| 1292 | assert(_num_marked == 0); |
---|
| 1293 | cl = min_conf_id; |
---|
| 1294 | clause(cl).activity() += 5; |
---|
| 1295 | _mark_increase_score = true; |
---|
| 1296 | mark_vars(cl, -1); |
---|
| 1297 | gflag = clause(cl).gflag(); |
---|
| 1298 | vector <int> & assignments = *_assignment_stack[dlevel()]; |
---|
| 1299 | for (int i = assignments.size() - 1; i >= 0; --i) { |
---|
| 1300 | int assigned = assignments[i]; |
---|
| 1301 | if (variable(assigned >> 1).is_marked()) { |
---|
| 1302 | variable(assigned>>1).clear_marked(); |
---|
| 1303 | --_num_marked; |
---|
| 1304 | ClauseIdx ante_cl = variable(assigned>>1).get_antecedent(); |
---|
| 1305 | if ( _num_marked == 0 ) { |
---|
| 1306 | _conflict_lits.push_back(assigned ^ 0x1); |
---|
| 1307 | ++_num_in_new_cl; |
---|
| 1308 | variable(assigned >> 1).set_new_cl_phase((assigned ^ 0x1) & 0x1); |
---|
| 1309 | break; |
---|
| 1310 | } else { |
---|
| 1311 | gflag |= clause(ante_cl).gflag(); |
---|
| 1312 | mark_vars(ante_cl, assigned >> 1); |
---|
| 1313 | clause(ante_cl).activity() += 5; |
---|
| 1314 | } |
---|
| 1315 | } |
---|
| 1316 | } |
---|
| 1317 | return finish_add_conf_clause(gflag); |
---|
| 1318 | } |
---|
| 1319 | |
---|
| 1320 | void CSolver::print_cls(ostream & os) { |
---|
| 1321 | for (unsigned i = 0; i < clauses()->size(); ++i) { |
---|
| 1322 | CClause & cl = clause(i); |
---|
| 1323 | if (cl.status() == DELETED_CL) |
---|
| 1324 | continue; |
---|
| 1325 | if (cl.status() == ORIGINAL_CL) { |
---|
| 1326 | os <<"0 "; |
---|
| 1327 | } else { |
---|
| 1328 | assert(cl.status() == CONFLICT_CL); |
---|
| 1329 | os << "A "; |
---|
| 1330 | } |
---|
| 1331 | for (unsigned j = 1; j < 33; ++j) |
---|
| 1332 | os << (cl.gid(j) ? 1 : 0); |
---|
| 1333 | os << "\t"; |
---|
| 1334 | for (unsigned j = 0; j < cl.num_lits(); ++j) { |
---|
| 1335 | os << (cl.literal(j).var_sign() ? "-":"") |
---|
| 1336 | << cl.literal(j).var_index() << " "; |
---|
| 1337 | } |
---|
| 1338 | os <<"0" << endl; |
---|
| 1339 | } |
---|
| 1340 | } |
---|
| 1341 | |
---|
| 1342 | int CSolver::mem_usage(void) { |
---|
| 1343 | int mem_dbase = CDatabase::mem_usage(); |
---|
| 1344 | int mem_assignment = 0; |
---|
| 1345 | for (int i = 0; i < _stats.max_dlevel; ++i) |
---|
| 1346 | mem_assignment += _assignment_stack[i]->capacity() * sizeof(int); |
---|
| 1347 | mem_assignment += sizeof(vector<int>)* _assignment_stack.size(); |
---|
| 1348 | return mem_dbase + mem_assignment; |
---|
| 1349 | } |
---|
| 1350 | |
---|
| 1351 | void CSolver::clean_up_dbase(void) { |
---|
| 1352 | assert(dlevel() == 0); |
---|
| 1353 | |
---|
| 1354 | int mem_before = mem_usage(); |
---|
| 1355 | // 1. remove all the learned clauses |
---|
| 1356 | for (vector<CClause>::iterator itr = clauses()->begin(); |
---|
| 1357 | itr != clauses()->end() - 1; ++itr) { |
---|
| 1358 | CClause & cl = * itr; |
---|
| 1359 | if (cl.status() != ORIGINAL_CL) |
---|
| 1360 | mark_clause_deleted(cl); |
---|
| 1361 | } |
---|
| 1362 | // delete_unrelevant_clauses() is specialized using berkmin deletion strategy |
---|
| 1363 | |
---|
| 1364 | // 2. free up the mem for the vectors if possible |
---|
| 1365 | for (unsigned i = 0; i < variables()->size(); ++i) { |
---|
| 1366 | for (unsigned j = 0; j < 2; ++j) { // both phase |
---|
| 1367 | vector<CLitPoolElement *> watched; |
---|
| 1368 | vector<CLitPoolElement *> & old_watched = variable(i).watched(j); |
---|
| 1369 | watched.reserve(old_watched.size()); |
---|
| 1370 | for (vector<CLitPoolElement *>::iterator itr = old_watched.begin(); |
---|
| 1371 | itr != old_watched.end(); ++itr) |
---|
| 1372 | watched.push_back(*itr); |
---|
| 1373 | // because watched is a temp mem allocation, it will get deleted |
---|
| 1374 | // out of the scope, but by swap it with the old_watched, the |
---|
| 1375 | // contents are reserved. |
---|
| 1376 | old_watched.swap(watched); |
---|
| 1377 | #ifdef KEEP_LIT_CLAUSES |
---|
| 1378 | vector<int> lits_cls; |
---|
| 1379 | vector<int> & old_lits_cls = variable(i).lit_clause(j); |
---|
| 1380 | lits_cls.reserve(old_lits_cls.size()); |
---|
| 1381 | for (vector<int>::iterator itr1 = old_lits_cls.begin(); itr1 != |
---|
| 1382 | old_lits_cls.end(); ++itr1) |
---|
| 1383 | lits_cls.push_back(*itr1); |
---|
| 1384 | old_lits_cls.swap(lits_cls); |
---|
| 1385 | #endif |
---|
| 1386 | } |
---|
| 1387 | } |
---|
| 1388 | |
---|
| 1389 | int mem_after = mem_usage(); |
---|
| 1390 | if (_params.verbosity > 0) { |
---|
| 1391 | cout << "Database Cleaned, releasing (approximately) " |
---|
| 1392 | << mem_before - mem_after << " Bytes" << endl; |
---|
| 1393 | } |
---|
| 1394 | } |
---|
| 1395 | |
---|
| 1396 | void CSolver::update_var_score(void) { |
---|
| 1397 | for (unsigned i = 1, sz = variables()->size(); i < sz; ++i) { |
---|
| 1398 | _ordered_vars[i-1].first = & variable(i); |
---|
| 1399 | _ordered_vars[i-1].second = variable(i).score(); |
---|
| 1400 | } |
---|
| 1401 | ::stable_sort(_ordered_vars.begin(), _ordered_vars.end(), cmp_var_stat); |
---|
| 1402 | for (unsigned i = 0, sz = _ordered_vars.size(); i < sz; ++i) |
---|
| 1403 | _ordered_vars[i].first->set_var_score_pos(i); |
---|
| 1404 | _max_score_pos = 0; |
---|
| 1405 | } |
---|
| 1406 | |
---|
| 1407 | void CSolver::restart(void) { |
---|
| 1408 | _stats.num_restarts += 1; |
---|
| 1409 | if (_params.verbosity > 1 ) |
---|
| 1410 | cout << "Restarting ... " << endl; |
---|
| 1411 | if (dlevel() > 0) |
---|
| 1412 | back_track(1); |
---|
| 1413 | assert(dlevel() == 0); |
---|
| 1414 | } |
---|
| 1415 | |
---|
| 1416 | // this function can be called within a solving process. i.e. not after |
---|
| 1417 | // solve() terminate |
---|
| 1418 | int CSolver::add_clause_incr(int * lits, int num_lits, int gid) { |
---|
| 1419 | // Do not mess up with shrinking. |
---|
| 1420 | assert(!_params.shrinking.enable || _shrinking_cls.empty()); |
---|
| 1421 | unsigned gflag; |
---|
| 1422 | _stats.outcome = UNDETERMINED; |
---|
| 1423 | |
---|
| 1424 | if (gid == PERMANENT_GID) |
---|
| 1425 | gflag = 0; |
---|
| 1426 | else if (gid == VOLATILE_GID) { |
---|
| 1427 | gflag = ~0x0; |
---|
| 1428 | } else { |
---|
| 1429 | assert(gid <= WORD_WIDTH && gid > 0); |
---|
| 1430 | gflag = (1 << (gid - 1)); |
---|
| 1431 | } |
---|
| 1432 | |
---|
| 1433 | int cl = add_clause(lits, num_lits, gflag); |
---|
| 1434 | if (cl < 0) |
---|
| 1435 | return -1; |
---|
| 1436 | clause(cl).set_status(ORIGINAL_CL); |
---|
| 1437 | |
---|
| 1438 | if (clause(cl).num_lits() == 1) { |
---|
| 1439 | int var_idx = clause(cl).literal(0).var_index(); |
---|
| 1440 | if (literal_value(clause(cl).literal(0)) == 0 && |
---|
| 1441 | variable(var_idx).dlevel() == 0) { |
---|
| 1442 | back_track(0); |
---|
| 1443 | if (preprocess() == CONFLICT) |
---|
| 1444 | _stats.outcome = UNSATISFIABLE; |
---|
| 1445 | } else { |
---|
| 1446 | if (dlevel() > 0) |
---|
| 1447 | back_track(1); |
---|
| 1448 | queue_implication(clause(cl).literal(0).s_var(), cl); |
---|
| 1449 | } |
---|
| 1450 | return cl; |
---|
| 1451 | } |
---|
| 1452 | |
---|
| 1453 | for (unsigned i = 0, sz = clause(cl).num_lits(); i < sz; ++i) { |
---|
| 1454 | int var_idx = lits[i] >> 1; |
---|
| 1455 | int value = variable(var_idx).value(); |
---|
| 1456 | if (value == UNKNOWN) |
---|
| 1457 | continue; |
---|
| 1458 | if (variable(var_idx).dlevel() == 0 && |
---|
| 1459 | variable(var_idx).antecedent() == -1 && |
---|
| 1460 | literal_value(clause(cl).literal(i)) == 0) { |
---|
| 1461 | back_track(0); |
---|
| 1462 | if (preprocess() == CONFLICT) |
---|
| 1463 | _stats.outcome = UNSATISFIABLE; |
---|
| 1464 | return cl; |
---|
| 1465 | } |
---|
| 1466 | } |
---|
| 1467 | |
---|
| 1468 | int max_level = 0; |
---|
| 1469 | int max_level2 = 0; |
---|
| 1470 | int unit_lit = 0; |
---|
| 1471 | int unknown_count = 0; |
---|
| 1472 | int num_sat = 0; |
---|
| 1473 | int sat_dlevel = -1, max_lit = 0; |
---|
| 1474 | bool already_sat = false; |
---|
| 1475 | |
---|
| 1476 | for (unsigned i = 0, sz = clause(cl).num_lits(); |
---|
| 1477 | unknown_count < 2 && i < sz; ++i) { |
---|
| 1478 | int var_idx = lits[i] / 2; |
---|
| 1479 | int value = variable(var_idx).value(); |
---|
| 1480 | if (value == UNKNOWN) { |
---|
| 1481 | unit_lit = clause(cl).literal(i).s_var(); |
---|
| 1482 | ++unknown_count; |
---|
| 1483 | } else { |
---|
| 1484 | int dl = variable(var_idx).dlevel(); |
---|
| 1485 | if (dl >= max_level) { |
---|
| 1486 | max_level2 = max_level; |
---|
| 1487 | max_level = dl; |
---|
| 1488 | max_lit = clause(cl).literal(i).s_var(); |
---|
| 1489 | } |
---|
| 1490 | else if (dl > max_level2) |
---|
| 1491 | max_level2 = dl; |
---|
| 1492 | if (literal_value(clause(cl).literal(i)) == 1) { |
---|
| 1493 | already_sat = true; |
---|
| 1494 | ++num_sat; |
---|
| 1495 | sat_dlevel = dl; |
---|
| 1496 | } |
---|
| 1497 | } |
---|
| 1498 | } |
---|
| 1499 | if (unknown_count == 0) { |
---|
| 1500 | if (already_sat) { |
---|
| 1501 | assert(sat_dlevel > -1); |
---|
| 1502 | if (num_sat == 1 && sat_dlevel == max_level && max_level > max_level2) { |
---|
| 1503 | back_track(max_level2 + 1); |
---|
| 1504 | assert(max_lit > 1); |
---|
| 1505 | queue_implication(max_lit, cl); |
---|
| 1506 | } |
---|
| 1507 | } else { |
---|
| 1508 | assert(is_conflicting(cl)); |
---|
| 1509 | if (max_level > max_level2) { |
---|
| 1510 | back_track(max_level2 + 1); |
---|
| 1511 | assert(max_lit > 1); |
---|
| 1512 | queue_implication(max_lit, cl); |
---|
| 1513 | } else { |
---|
| 1514 | back_track(max_level); |
---|
| 1515 | if (max_level == 0 && preprocess() == CONFLICT) |
---|
| 1516 | _stats.outcome = UNSATISFIABLE; |
---|
| 1517 | } |
---|
| 1518 | } |
---|
| 1519 | } |
---|
| 1520 | else if (unknown_count == 1) { |
---|
| 1521 | if (!already_sat) { |
---|
| 1522 | if (max_level < dlevel()) |
---|
| 1523 | back_track(max_level + 1); |
---|
| 1524 | queue_implication(unit_lit, cl); |
---|
| 1525 | } |
---|
| 1526 | } |
---|
| 1527 | return cl; |
---|
| 1528 | } |
---|