CaDiCal是SAT竞赛2019年的亚军(离冠军相差无几),其编程形式自成一派,代码需要认真研读。
该程序组合了CDCL和SLS的最新特性。
2020年SAT竞赛的冠军kassat是CaDiCal的C语言版本。CaDiCal原有的C++版本有很多注释帮助理解,更适合入门。
该系统的由众多小的文件组成,不像minsat已经归类到几个大的文件之中。
个人认为应该首先从inernal.hpp和internal.cpp入手。
关于inernal.hpp的作用
1.首先该文件几乎包含全部其它类定义的头文件——从这些头文件的排列顺序,也可以了解相互之间的关系。
All internal headers are included here. This gives a nice overview on what is needed altogether. The 'Internal' class needs almost all the headers anyhow (since the idea is to avoid pointer references as much as 译文:拥有所有头文件的另一个好处是'。cpp的文件只需要包含这个。 |
1 #include "arena.hpp" 2 #include "averages.hpp" 3 #include "bins.hpp" 4 #include "block.hpp" 5 #include "cadical.hpp" 6 #include "checker.hpp" 7 #include "clause.hpp" 8 #include "config.hpp" 9 #include "contract.hpp" 10 #include "cover.hpp" 11 #include "elim.hpp" 12 #include "ema.hpp" 13 #include "external.hpp" 14 #include "file.hpp" 15 #include "flags.hpp" 16 #include "format.hpp" 17 #include "heap.hpp" 18 #include "instantiate.hpp" 19 #include "internal.hpp" 20 #include "level.hpp" 21 #include "limit.hpp" 22 #include "logging.hpp" 23 #include "message.hpp" 24 #include "observer.hpp" 25 #include "occs.hpp" 26 #include "options.hpp" 27 #include "parse.hpp" 28 #include "phases.hpp" 29 #include "profile.hpp" 30 #include "proof.hpp" 31 #include "queue.hpp" 32 #include "radix.hpp" 33 #include "random.hpp" 34 #include "range.hpp" 35 #include "reluctant.hpp" 36 #include "resources.hpp" 37 #include "score.hpp" 38 #include "stats.hpp" 39 #include "terminal.hpp" 40 #include "tracer.hpp" 41 #include "util.hpp" 42 #include "var.hpp" 43 #include "version.hpp" 44 #include "vivify.hpp" 45 #include "watch.hpp" CaDiCal总共121个文件,此处加上相应的.cpp文件共90个左右。 |
1 // Fatal internal error which leads to abort. 2 // 3 void fatal_message_start (); 4 void fatal_message_end (); 5 void fatal (const char *, ...); 6 7 /*------------------------------------------------------------------------*/ 8 9 // Has to be put here, i.e., not into 'score.hpp', since we need the 10 // definition of 'Internal::score' above (after '#include "score.hpp"'). 11 12 inline bool score_smaller::operator () (unsigned a, unsigned b) { 13 14 // Avoid computing twice 'abs' in 'score ()'. 15 // 16 assert (1 <= a); 17 assert (a <= (unsigned) internal->max_var); 18 assert (1 <= b); 19 assert (b <= (unsigned) internal->max_var); 20 double s = internal->stab[a]; 21 double t = internal->stab[b]; 22 23 if (s < t) return true; 24 if (s > t) return false; 25 26 return a > b; 27 } 28 29 /*------------------------------------------------------------------------*/ 30 31 // Implemented here for keeping it all inline (requires Internal::fixed). 32 33 inline int External::fixed (int elit) const { 34 assert (elit); 35 assert (elit != INT_MIN); 36 int eidx = abs (elit); 37 if (eidx > max_var) return 0; 38 int ilit = e2i [eidx]; 39 if (!ilit) return 0; 40 if (elit < 0) ilit = -ilit; 41 return internal->fixed (ilit); 42 } 43 44 /*------------------------------------------------------------------------*/ 45 46 // We want to have termination checks inlined, particularly the first 47 // function which appears in preprocessor loops. Even though this first 48 // 'termination_forced' is set asynchronously, this should not lead to a 49 // data race issue (it also has been declared 'volatile'). 50 51 inline bool Internal::terminated_asynchronously (int factor) 52 { 53 // First way of asynchronous termination is through 'terminate' which sets 54 // the 'termination_forced' flag directly. The second way is through a 55 // call back to a 'terminator' if it is non-zero, which however is costly. 56 // 57 if (termination_forced) 58 { 59 LOG ("termination asynchronously forced"); 60 return true; 61 } 62 63 // This is only for testing and debugging asynchronous termination calls. 64 // In production code this could be removed but then should not be costly 65 // and keeping it will allow to test correctness of asynchronous 66 // termination on the production platform too. After this triggers we 67 // have to set the 'termination_forced' flag, such that subsequent calls 68 // to this function do not check this again. 69 // 70 if (lim.terminate.forced) { 71 assert (lim.terminate.forced > 0); 72 if (lim.terminate.forced-- == 1) { 73 LOG ("internally forcing termination"); 74 termination_forced = true; 75 return true; 76 } 77 LOG ("decremented internal forced termination limit to %" PRId64, 78 lim.terminate.forced); 79 } 80 81 // The second way of asynchronous termination is through registering and 82 // calling an external 'Terminator' object. This is of course more costly 83 // than just checking a (volatile though) boolean flag, particularly in 84 // tight loops. To avoid this cost we only call the terminator in 85 // intervals of 'opts.terminateint', which in addition can be scaled up by 86 // the argument 'factor'. If the terminator returns 'true' we set the 87 // 'termination_forced' flag to 'true' in order to remember the 88 // termination status and to avoid the terminator again. Setting this 89 // flag leads to the first test above to succeed in subsequent calls. 90 // 91 if (external->terminator && !lim.terminate.check--) { 92 assert (factor > 0); 93 assert (INT_MAX/factor > opts.terminateint); 94 lim.terminate.check = factor * opts.terminateint; 95 if (external->terminator->terminate ()) { 96 termination_forced = true; // Cache it. 97 LOG ("connected terminator forces termination"); 98 return true; 99 } 100 } 101 102 return false; 103 } 104 105 /*------------------------------------------------------------------------*/ 106 107 inline bool Internal::search_limits_hit () 108 { 109 assert (!preprocessing); 110 assert (!localsearching); 111 112 if (lim.conflicts >= 0 && 113 stats.conflicts >= lim.conflicts) { 114 LOG ("conflict limit %" PRId64 " reached", lim.conflicts); 115 return true; 116 } 117 118 if (lim.decisions >= 0 && 119 stats.decisions >= lim.decisions) { 120 LOG ("decision limit %" PRId64 " reached", lim.decisions); 121 return true; 122 } 123 124 return false; 125 } 126 127 /*------------------------------------------------------------------------*/ 可以看到,该编程方法中在internal.hpp中定义了属于其它类的函数,如line12、line33。 |
下面给出的是internal结构体的定义: |
1 struct Internal { 2 3 /*----------------------------------------------------------------------*/ 4 5 // The actual internal state of the solver is set and maintained in this 6 // section. This is currently only used for debugging and testing. 7 8 enum Mode { 9 BLOCK = (1<<0), 10 CONDITION= (1<<1), 11 COVER = (1<<2), 12 DECOMP = (1<<3), 13 DEDUP = (1<<4), 14 ELIM = (1<<5), 15 LUCKY = (1<<6), 16 PROBE = (1<<7), 17 SEARCH = (1<<8), 18 SIMPLIFY = (1<<9), 19 SUBSUME = (1<<10), 20 TERNARY = (1<<11), 21 TRANSRED = (1<<12), 22 VIVIFY = (1<<13), 23 WALK = (1<<14), 24 }; 25 26 bool in_mode (Mode m) const { return (mode & m) != 0; } 27 void set_mode (Mode m) { assert (!(mode & m)); mode |= m; } 28 void reset_mode (Mode m) { assert (mode & m); mode &= ~m; } 29 void require_mode (Mode m) const { assert (mode & m), (void) m; } 30 31 /*----------------------------------------------------------------------*/ 32 33 int mode; // current internal state 34 bool unsat; // empty clause found or learned 35 bool iterating; // report learned unit ('i' line) 36 bool localsearching; // true during local search 37 bool lookingahead; // true during look ahead 38 bool preprocessing; // true during preprocessing 39 bool protected_reasons; // referenced reasons are protected 40 bool force_saved_phase; // force saved phase in decision 41 bool searching_lucky_phases; // during 'lucky_phases' 42 bool stable; // true during stabilization phase 43 bool reported; // reported in this solving call 44 char rephased; // last type of resetting phases 45 Reluctant reluctant; // restart counter in stable mode 46 size_t vsize; // actually allocated variable data size 47 int max_var; // internal maximum variable index 48 int level; // decision level ('control.size () - 1') 49 Phases phases; // saved, target and best phases 50 signed char * vals; // assignment [-max_var,max_var] 51 vector<signed char> marks; // signed marks [1,max_var] 52 vector<unsigned> frozentab; // frozen counters [1,max_var] 53 vector<int> i2e; // maps internal 'idx' to external 'lit' 54 Queue queue; // variable move to front decision queue 55 Links links; // table of links for decision queue 56 double score_inc; // current score increment 57 ScoreSchedule scores; // score based decision priority queue 58 vector<double> stab; // table of variable scores [1,max_var] 59 vector<Var> vtab; // variable table [1,max_var] 60 vector<int> parents; // parent literals during probing 61 vector<Flags> ftab; // variable and literal flags 62 vector<int64_t> btab; // enqueue time stamps for queue 63 vector<int64_t> gtab; // time stamp table to recompute glue 64 vector<Occs> otab; // table of occurrences for all literals 65 vector<int> ptab; // table for caching probing attempts 66 vector<int64_t> ntab; // number of one-sided occurrences table 67 vector<Bins> big; // binary implication graph 68 vector<Watches> wtab; // table of watches for all literals 69 Clause * conflict; // set in 'propagation', reset in 'analyze' 70 Clause * ignore; // ignored during 'vivify_propagate' 71 size_t propagated; // next trail position to propagate 72 size_t propagated2; // next binary trail position to propagate 73 size_t best_assigned; // best maximum assigned ever 74 size_t target_assigned; // maximum assigned without conflict 75 size_t no_conflict_until; // largest trail prefix without conflict 76 vector<int> trail; // currently assigned literals 77 vector<int> clause; // simplified in parsing & learning 78 vector<int> assumptions; // assumed literals 79 vector<int> original; // original added literals 80 vector<int> levels; // decision levels in learned clause 81 vector<int> analyzed; // analyzed literals in 'analyze' 82 vector<int> minimized; // removable or poison in 'minimize' 83 vector<int> probes; // remaining scheduled probes 84 vector<Level> control; // 'level + 1 == control.size ()' 85 vector<Clause*> clauses; // ordered collection of all clauses 86 Averages averages; // glue, size, jump moving averages 87 Limit lim; // limits for various phases 88 Last last; // statistics at last occurrence 89 Inc inc; // increments on limits 90 Proof * proof; // clausal proof observers if non zero 91 Checker * checker; // online proof checker observing proof 92 Tracer * tracer; // proof to file tracer observing proof 93 Options opts; // run-time options 94 Stats stats; // statistics 95 #ifndef QUIET 96 Profiles profiles; // time profiles for various functions 97 bool force_phase_messages; // force 'phase (...)' messages 98 #endif 99 Arena arena; // memory arena for moving garbage collector 100 Format error_message; // provide persistent error message 101 string prefix; // verbose messages prefix 102 103 Internal * internal; // proxy to 'this' in macros 104 External * external; // proxy to 'external' buddy in 'Solver' 105 106 /*----------------------------------------------------------------------*/ 107 108 // Asynchronous termination flag written by 'terminate' and read by 109 // 'terminated_asynchronously' (the latter at the end of this header). 110 // 111 volatile bool termination_forced; 112 113 /*----------------------------------------------------------------------*/ 114 115 const Range vars; // Provides safe variable iteration. 116 const Sange lits; // Provides safe literal iteration. 117 118 /*----------------------------------------------------------------------*/ 119 120 Internal (); 121 ~Internal (); 122 123 /*----------------------------------------------------------------------*/ 124 125 // Internal delegates and helpers for corresponding functions in 126 // 'External' and 'Solver'. The 'init_vars' function initializes 127 // variables up to and including the requested variable index. 128 // 129 void init_vars (int new_max_var); 130 131 void init_enqueue (int idx); 132 void init_queue (int old_max_var, int new_max_var); 133 134 void init_scores (int old_max_var, int new_max_var); 135 136 void add_original_lit (int lit); 137 138 // Enlarge tables. 139 // 140 void enlarge_vals (size_t new_vsize); 141 void enlarge (int new_max_var); 142 143 // A variable is 'active' if it is not eliminated nor fixed. 144 // 145 bool active (int lit) { return flags(lit).active (); } 146 147 int active () const { 148 int res = stats.active; 149 #ifndef NDEBUG 150 int tmp = max_var; 151 tmp -= stats.unused; 152 tmp -= stats.now.fixed; 153 tmp -= stats.now.eliminated; 154 tmp -= stats.now.substituted; 155 tmp -= stats.now.pure; 156 assert (tmp >= 0); 157 assert (tmp == res); 158 #endif 159 return res; 160 } 161 162 void reactivate (int lit); // During 'restore'. 163 164 // Currently remaining active redundant and irredundant clauses. 165 166 int64_t redundant () const { return stats.current.redundant; } 167 168 int64_t irredundant () const { return stats.current.irredundant; } 169 170 double clause_variable_ratio () const { 171 return relative (irredundant (), active ()); 172 } 173 174 // Scale values relative to clause variable ratio. 175 // 176 double scale (double v) const; 177 178 // Unsigned literals (abs) with checks. 179 // 180 int vidx (int lit) const { 181 int idx; 182 assert (lit); 183 assert (lit != INT_MIN); 184 idx = abs (lit); 185 assert (idx <= max_var); 186 return idx; 187 } 188 189 // Unsigned version with LSB denoting sign. This is used in indexing arrays 190 // by literals. The idea is to keep the elements in such an array for both 191 // the positive and negated version of a literal close together. 192 // 193 unsigned vlit (int lit) { return (lit < 0) + 2u * (unsigned) vidx (lit); } 194 195 int u2i (unsigned u) { 196 assert (u > 1); 197 int res = u/2; 198 assert (res <= max_var); 199 if (u & 1) res = -res; 200 return res; 201 } 202 203 // Helper functions to access variable and literal data. 204 // 205 Var & var (int lit) { return vtab[vidx (lit)]; } 206 Link & link (int lit) { return links[vidx (lit)]; } 207 Flags & flags (int lit) { return ftab[vidx (lit)]; } 208 int64_t & bumped (int lit) { return btab[vidx (lit)]; } 209 int & propfixed (int lit) { return ptab[vlit (lit)]; } 210 double & score (int lit) { return stab[vidx (lit)]; } 211 212 const Flags & 213 flags (int lit) const { return ftab[vidx (lit)]; } 214 215 bool occurring () const { return !otab.empty (); } 216 bool watching () const { return !wtab.empty (); } 217 218 Bins & bins (int lit) { return big[vlit (lit)]; } 219 Occs & occs (int lit) { return otab[vlit (lit)]; } 220 int64_t & noccs (int lit) { return ntab[vlit (lit)]; } 221 Watches & watches (int lit) { return wtab[vlit (lit)]; } 222 223 // Variable bumping through exponential VSIDS (EVSIDS) as in MiniSAT. 224 // 225 bool use_scores () const { return opts.score && stable; } 226 void bump_variable_score (int lit); 227 void bump_variable_score_inc (); 228 void rescale_variable_scores (); 229 230 // Marking variables with a sign (positive or negative). 231 // 232 signed char marked (int lit) const { 233 signed char res = marks [ vidx (lit) ]; 234 if (lit < 0) res = -res; 235 return res; 236 } 237 void mark (int lit) { 238 assert (!marked (lit)); 239 marks[vidx (lit)] = sign (lit); 240 assert (marked (lit) > 0); 241 assert (marked (-lit) < 0); 242 } 243 void unmark (int lit) { 244 marks [ vidx (lit) ] = 0; 245 assert (!marked (lit)); 246 } 247 248 // Use only bits 6 and 7 to store the sign or zero. The remaining 249 // bits can be use as additional flags. 250 // 251 signed char marked67 (int lit) const { 252 signed char res = marks [ vidx (lit) ] >> 6; 253 if (lit < 0) res = -res; 254 return res; 255 } 256 void mark67 (int lit) { 257 signed char & m = marks[vidx (lit)]; 258 const signed char mask = 0x3f; 259 #ifndef NDEBUG 260 const signed char bits = m & mask; 261 #endif 262 m = (m & mask) | (sign (lit) << 6); 263 assert (marked (lit) > 0); 264 assert (marked (-lit) < 0); 265 assert ((m & mask) == bits); 266 assert (marked67 (lit) > 0); 267 assert (marked67 (-lit) < 0); 268 } 269 void unmark67 (int lit) { 270 signed char & m = marks[vidx (lit)]; 271 const signed char mask = 0x3f; 272 #ifndef NDEBUG 273 const signed bits = m & mask; 274 #endif 275 m &= mask; 276 assert ((m & mask) == bits); 277 } 278 279 void unmark (vector<int> & lits) { 280 for (const auto & lit : lits) 281 unmark (lit); 282 } 283 284 // The other 6 bits of the 'marks' bytes can be used as additional 285 // (unsigned) marking bits. Currently we only use the least significant 286 // bit in 'condition' to mark variables in the conditional part. 287 // 288 bool getbit (int lit, int bit) const { 289 assert (0 <= bit), assert (bit < 6); 290 return marks[vidx (lit)] & (1<<bit); 291 } 292 void setbit (int lit, int bit) { 293 assert (0 <= bit), assert (bit < 6); 294 assert (!getbit (lit, bit)); 295 marks[vidx (lit)] |= (1<<bit); 296 assert (getbit (lit, bit)); 297 } 298 void unsetbit (int lit, int bit) { 299 assert (0 <= bit), assert (bit < 6); 300 assert (getbit (lit, bit)); 301 marks[vidx (lit)] &= ~(1<<bit); 302 assert (!getbit (lit, bit)); 303 } 304 305 // Marking individual literals. 306 // 307 bool marked2 (int lit) const { 308 unsigned res = marks [ vidx (lit) ]; 309 assert (res <= 3); 310 unsigned bit = bign (lit); 311 return (res & bit) != 0; 312 } 313 void mark2 (int lit) { 314 marks[vidx (lit)] |= bign (lit); 315 assert (marked2 (lit)); 316 } 317 318 // Marking and unmarking of all literals in a clause. 319 // 320 void mark_clause (); // mark 'this->clause' 321 void mark (Clause *); 322 void mark2 (Clause *); 323 void unmark_clause (); // unmark 'this->clause' 324 void unmark (Clause *); 325 326 // Watch literal 'lit' in clause with blocking literal 'blit'. 327 // Inlined here, since it occurs in the tight inner loop of 'propagate'. 328 // 329 inline void watch_literal (int lit, int blit, Clause * c) { 330 assert (lit != blit); 331 Watches & ws = watches (lit); 332 ws.push_back (Watch (blit, c)); 333 LOG (c, "watch %d blit %d in", lit, blit); 334 } 335 336 // Add two watches to a clause. This is used initially during allocation 337 // of a clause and during connecting back all watches after preprocessing. 338 // 339 inline void watch_clause (Clause * c) { 340 const int l0 = c->literals[0]; 341 const int l1 = c->literals[1]; 342 watch_literal (l0, l1, c); 343 watch_literal (l1, l0, c); 344 } 345 346 inline void unwatch_clause (Clause * c) { 347 const int l0 = c->literals[0]; 348 const int l1 = c->literals[1]; 349 remove_watch (watches (l0), c); 350 remove_watch (watches (l1), c); 351 } 352 353 // Update queue to point to last potentially still unassigned variable. 354 // All variables after 'queue.unassigned' in bump order are assumed to be 355 // assigned. Then update the 'queue.bumped' field and log it. This is 356 // inlined here since it occurs in several inner loops. 357 // 358 inline void update_queue_unassigned (int idx) { 359 assert (0 < idx); 360 assert (idx <= max_var); 361 queue.unassigned = idx; 362 queue.bumped = btab[idx]; 363 LOG ("queue unassigned now %d bumped %" PRId64 "", idx, btab[idx]); 364 } 365 366 void bump_queue (int idx); 367 368 // Mark (active) variables as eliminated, substituted, pure or fixed, 369 // which turns them into inactive variables. 370 // 371 void mark_eliminated (int); 372 void mark_substituted (int); 373 void mark_active (int); 374 void mark_fixed (int); 375 void mark_pure (int); 376 377 // Managing clauses in 'clause.cpp'. Without explicit 'Clause' argument 378 // these functions work on the global temporary 'clause'. 379 // 380 Clause * new_clause (bool red, int glue = 0); 381 void promote_clause (Clause *, int new_glue); 382 size_t shrink_clause (Clause *, int new_size); 383 void deallocate_clause (Clause *); 384 void delete_clause (Clause *); 385 void mark_garbage (Clause *); 386 void assign_original_unit (int); 387 void add_new_original_clause (); 388 Clause * new_learned_redundant_clause (int glue); 389 Clause * new_hyper_binary_resolved_clause (bool red, int glue); 390 Clause * new_clause_as (const Clause * orig); 391 Clause * new_resolved_irredundant_clause (); 392 393 // Forward reasoning through propagation in 'propagate.cpp'. 394 // 395 int assignment_level (int lit, Clause*); 396 void search_assign (int lit, Clause *); 397 void search_assign_driving (int lit, Clause * reason); 398 void search_assume_decision (int decision); 399 void assign_unit (int lit); 400 bool propagate (); 401 402 // Undo and restart in 'backtrack.cpp'. 403 // 404 void unassign (int lit); 405 void update_target_and_best (); 406 void backtrack (int target_level = 0); 407 408 // Minimized learned clauses in 'minimize.cpp'. 409 // 410 bool minimize_literal (int lit, int depth = 0); 411 void minimize_clause (); 412 413 // Learning from conflicts in 'analyze.cc'. 414 // 415 void learn_empty_clause (); 416 void learn_unit_clause (int lit); 417 void bump_variable (int lit); 418 void bump_variables (); 419 int recompute_glue (Clause *); 420 void bump_clause (Clause *); 421 void clear_analyzed_literals (); 422 void clear_analyzed_levels (); 423 void clear_minimized_literals (); 424 bool bump_also_reason_literal (int lit); 425 void bump_also_reason_literals (int lit, int limit); 426 void bump_also_all_reason_literals (); 427 void analyze_literal (int lit, int & open); 428 void analyze_reason (int lit, Clause *, int & open); 429 Clause * new_driving_clause (const int glue, int & jump); 430 int find_conflict_level (int & forced); 431 int determine_actual_backtrack_level (int jump); 432 void analyze (); 433 void iterate (); // report learned unit clause 434 435 // Use last learned clause to subsume some more. 436 // 437 void eagerly_subsume_recently_learned_clauses (Clause *); 438 439 // Restarting policy in 'restart.cc'. 440 // 441 bool stabilizing (); 442 bool restarting (); 443 int reuse_trail (); 444 void restart (); 445 446 // Functions to set and reset certain 'phases'. 447 // 448 void clear_phases (vector<signed char> &); // reset to zero 449 void copy_phases (vector<signed char> &); // copy 'vals' to 'argument' 450 451 // Resetting the saved phased in 'rephase.cpp'. 452 // 453 bool rephasing (); 454 char rephase_best (); 455 char rephase_flipping (); 456 char rephase_inverted (); 457 char rephase_original (); 458 char rephase_random (); 459 char rephase_walk (); 460 void shuffle_scores (); 461 void shuffle_queue (); 462 void rephase (); 463 464 // Lucky feasible case checking. 465 // 466 int unlucky (int res); 467 int trivially_false_satisfiable (); 468 int trivially_true_satisfiable (); 469 int forward_false_satisfiable (); 470 int forward_true_satisfiable (); 471 int backward_false_satisfiable (); 472 int backward_true_satisfiable (); 473 int positive_horn_satisfiable (); 474 int negative_horn_satisfiable (); 475 476 // Asynchronous terminating check. 477 // 478 bool terminated_asynchronously (int factor = 1); 479 480 bool search_limits_hit (); 481 482 void terminate () { 483 LOG ("forcing asynchronous termination"); 484 termination_forced = true; 485 } 486 487 // Reducing means determining useless clauses with 'reduce' in 488 // 'reduce.cpp' as well as root level satisfied clause and then removing 489 // those which are not used as reason anymore with garbage collection. 490 // 491 bool flushing (); 492 bool reducing (); 493 void protect_reasons (); 494 void mark_clauses_to_be_flushed (); 495 void mark_useless_redundant_clauses_as_garbage (); 496 bool propagate_out_of_order_units (); 497 void unprotect_reasons (); 498 void reduce (); 499 500 // Garbage collection in 'collect.cpp' called from 'reduce' and during 501 // inprocessing and preprocessing. 502 // 503 int clause_contains_fixed_literal (Clause *); 504 void remove_falsified_literals (Clause *); 505 void mark_satisfied_clauses_as_garbage (); 506 void copy_clause (Clause *); 507 void flush_watches (int lit, Watches &); 508 size_t flush_occs (int lit); 509 void flush_all_occs_and_watches (); 510 void update_reason_references (); 511 void copy_non_garbage_clauses (); 512 void delete_garbage_clauses (); 513 void check_clause_stats (); 514 void check_var_stats (); 515 bool arenaing (); 516 void garbage_collection (); 517 518 // Set-up occurrence list counters and containers. 519 // 520 void init_occs (); 521 void init_bins (); 522 void init_noccs (); 523 void reset_occs (); 524 void reset_bins (); 525 void reset_noccs (); 526 527 // Operators on watches. 528 // 529 void init_watches (); 530 void connect_watches (bool irredundant_only = false); 531 void sort_watches (); 532 void clear_watches (); 533 void reset_watches (); 534 535 // Regular forward subsumption checking in 'subsume.cpp'. 536 // 537 bool subsuming (); 538 void strengthen_clause (Clause *, int); 539 void subsume_clause (Clause * subsuming, Clause * subsumed); 540 int subsume_check (Clause * subsuming, Clause * subsumed); 541 int try_to_subsume_clause (Clause *, vector<Clause*> & shrunken); 542 void reset_subsume_bits (); 543 bool subsume_round (); 544 void subsume (bool update_limits = true); 545 546 // Covered clause elimination of large clauses. 547 // 548 void covered_literal_addition (int lit, Coveror &); 549 void asymmetric_literal_addition (int lit, Coveror &); 550 void cover_push_extension (int lit, Coveror &); 551 bool cover_propagate_asymmetric (int lit, Clause * ignore, Coveror &); 552 bool cover_propagate_covered (int lit, Coveror &); 553 bool cover_clause (Clause * c, Coveror &); 554 int64_t cover_round (); 555 bool cover (); 556 557 // Strengthening through vivification in 'vivify.cpp'. 558 // 559 void flush_vivification_schedule (Vivifier &); 560 bool consider_to_vivify_clause (Clause * candidate, bool redundant_mode); 561 void vivify_analyze_redundant (Vivifier &, Clause * start, bool &); 562 bool vivify_all_decisions (Clause * candidate, int subsume); 563 void vivify_post_process_analysis (Clause * candidate, int subsume); 564 void vivify_strengthen (Clause * candidate); 565 void vivify_assign (int lit, Clause *); 566 void vivify_assume (int lit); 567 bool vivify_propagate (); 568 void vivify_clause (Vivifier &, Clause * candidate); 569 void vivify_round (bool redundant_mode, int64_t delta); 570 void vivify (); 571 572 // Compacting (shrinking internal variable tables) in 'compact.cpp' 573 // 574 bool compacting (); 575 void compact (); 576 577 // Transitive reduction of binary implication graph in 'transred.cpp' 578 // 579 void transred (); 580 581 // We monitor the maximum size and glue of clauses during 'reduce' and 582 // thus can predict if a redundant extended clause is likely to be kept in 583 // the next 'reduce' phase. These clauses are target of subsumption and 584 // vivification checks, in addition to irredundant clauses. Their 585 // variables are also marked as being 'added'. 586 // 587 bool likely_to_be_kept_clause (Clause * c) { 588 if (!c->redundant) return true; 589 if (c->keep) return true; 590 if (c->glue > lim.keptglue) return false; 591 if (c->size > lim.keptsize) return false; 592 return true; 593 } 594 595 // We mark variables in added or shrunken clauses as 'subsume' candidates 596 // if the clause is likely to be kept in the next 'reduce' phase (see last 597 // function above). This gives a persistent (across consecutive 598 // interleaved search and inprocessing phases) set of variables which have 599 // to be reconsidered in subsumption checks, i.e., only clauses with 600 // 'subsume' marked variables are checked to be forward subsumed. 601 // A similar technique is used to reduce the effort in hyper ternary 602 // resolution to focus on variables in new ternary clauses. 603 // 604 void mark_subsume (int lit) { 605 Flags & f = flags (lit); 606 if (f.subsume) return; 607 LOG ("marking %d as subsuming literal candidate", abs (lit)); 608 stats.mark.subsume++; 609 f.subsume = true; 610 } 611 void mark_ternary (int lit) { 612 Flags & f = flags (lit); 613 if (f.ternary) return; 614 LOG ("marking %d as ternary resolution literal candidate", abs (lit)); 615 stats.mark.ternary++; 616 f.ternary = true; 617 } 618 void mark_added (int lit, int size, bool redundant); 619 void mark_added (Clause *); 620 621 bool marked_subsume (int lit) const { return flags (lit).subsume; } 622 623 // If irredundant clauses are removed or literals in clauses are removed, 624 // then variables in such clauses should be reconsidered to be eliminated 625 // through bounded variable elimination. In contrast to 'subsume' the 626 // 'elim' flag is restricted to 'irredundant' clauses only. For blocked 627 // clause elimination it is better to have a more precise signed version, 628 // which allows to independently mark positive and negative literals. 629 // 630 void mark_elim (int lit) { 631 Flags & f = flags (lit); 632 if (f.elim) return; 633 LOG ("marking %d as elimination literal candidate", lit); 634 stats.mark.elim++; 635 f.elim = true; 636 } 637 void mark_block (int lit) { 638 Flags & f = flags (lit); 639 const unsigned bit = bign (lit); 640 if (f.block & bit) return; 641 LOG ("marking %d as blocking literal candidate", lit); 642 stats.mark.block++; 643 f.block |= bit; 644 } 645 void mark_removed (int lit) { 646 mark_elim (lit); 647 mark_block (-lit); 648 } 649 void mark_removed (Clause *, int except = 0); 650 651 // The following two functions are only used for testing & debugging. 652 653 bool marked_block (int lit) const { 654 const Flags & f = flags (lit); 655 const unsigned bit = bign (lit); 656 return (f.block & bit) != 0; 657 } 658 void unmark_block (int lit) { 659 Flags & f = flags (lit); 660 const unsigned bit = bign (lit); 661 f.block &= ~bit; 662 } 663 664 // During scheduling literals for blocked clause elimination we skip those 665 // literals which occur negated in a too large clause. 666 // 667 void mark_skip (int lit) { 668 Flags & f = flags (lit); 669 const unsigned bit = bign (lit); 670 if (f.skip & bit) return; 671 LOG ("marking %d to be skipped as blocking literal", lit); 672 f.skip |= bit; 673 } 674 bool marked_skip (int lit) { 675 const Flags & f = flags (lit); 676 const unsigned bit = bign (lit); 677 return (f.skip & bit) != 0; 678 } 679 680 // Blocked Clause elimination in 'block.cpp'. 681 // 682 bool is_blocked_clause (Clause *c, int pivot); 683 void block_schedule (Blocker &); 684 size_t block_candidates (Blocker &, int lit); 685 Clause * block_impossible (Blocker &, int lit); 686 void block_literal_with_at_least_two_negative_occs (Blocker &, int lit); 687 void block_literal_with_one_negative_occ (Blocker &, int lit); 688 void block_pure_literal (Blocker &, int lit); 689 void block_reschedule_clause (Blocker &, int lit, Clause *); 690 void block_reschedule (Blocker &, int lit); 691 void block_literal (Blocker &, int lit); 692 bool block (); 693 694 // Find gates in 'gates.cpp' for bounded variable substitution. 695 // 696 int second_literal_in_binary_clause (Eliminator &, Clause *, int first); 697 void mark_binary_literals (Eliminator &, int pivot); 698 void find_and_gate (Eliminator &, int pivot); 699 void find_equivalence (Eliminator &, int pivot); 700 701 bool get_ternary_clause (Clause *, int &, int &, int &); 702 bool match_ternary_clause (Clause *, int, int, int); 703 Clause * find_ternary_clause (int, int, int); 704 705 bool get_clause (Clause *, vector<int> &); 706 bool is_clause (Clause *, const vector<int> &); 707 Clause * find_clause (const vector<int> &); 708 void find_xor_gate (Eliminator &, int pivot); 709 710 void find_if_then_else (Eliminator &, int pivot); 711 712 void find_gate_clauses (Eliminator &, int pivot); 713 void unmark_gate_clauses (Eliminator &); 714 715 // Bounded variable elimination in 'elim.cpp'. 716 // 717 bool eliminating (); 718 double compute_elim_score (unsigned lit); 719 void mark_redundant_clauses_with_eliminated_variables_as_garbage (); 720 void unmark_binary_literals (Eliminator &); 721 bool resolve_clauses (Eliminator &, Clause *, int pivot, Clause *); 722 void mark_eliminated_clauses_as_garbage (Eliminator &, int pivot); 723 bool elim_resolvents_are_bounded (Eliminator &, int pivot); 724 void elim_update_removed_lit (Eliminator &, int lit); 725 void elim_update_removed_clause (Eliminator &, Clause *, int except = 0); 726 void elim_update_added_clause (Eliminator &, Clause *); 727 void elim_add_resolvents (Eliminator &, int pivot); 728 void elim_backward_clause (Eliminator &, Clause *); 729 void elim_backward_clauses (Eliminator &); 730 void elim_propagate (Eliminator &, int unit); 731 void elim_on_the_fly_self_subsumption (Eliminator &, Clause *, int); 732 void try_to_eliminate_variable (Eliminator &, int pivot); 733 void increase_elimination_bound (); 734 int elim_round (bool & completed); 735 void elim (bool update_limits = true); 736 737 void inst_assign (int lit); 738 bool inst_propagate (); 739 void collect_instantiation_candidates (Instantiator &); 740 bool instantiate_candidate (int lit, Clause *); 741 void instantiate (Instantiator &); 742 743 // Hyper ternary resolution. 744 // 745 bool ternary_find_binary_clause (int, int); 746 bool ternary_find_ternary_clause (int, int, int); 747 Clause * new_hyper_ternary_resolved_clause (bool red); 748 bool hyper_ternary_resolve (Clause *, int, Clause *); 749 void ternary_lit (int pivot, int64_t & steps, int64_t & htrs); 750 void ternary_idx (int idx, int64_t & steps, int64_t & htrs); 751 bool ternary_round (int64_t & steps, int64_t & htrs); 752 bool ternary (); 753 754 // Probing in 'probe.cpp'. 755 // 756 bool probing (); 757 void failed_literal (int lit); 758 void probe_assign_unit (int lit); 759 void probe_assign_decision (int lit); 760 void probe_assign (int lit, int parent); 761 void mark_duplicated_binary_clauses_as_garbage (); 762 int get_parent_reason_literal (int lit); 763 void set_parent_reason_literal (int lit, int reason); 764 int probe_dominator (int a, int b); 765 int hyper_binary_resolve (Clause*); 766 void probe_propagate2 (); 767 bool probe_propagate (); 768 bool is_binary_clause (Clause * c, int &, int &); 769 void generate_probes (); 770 void flush_probes (); 771 int next_probe (); 772 bool probe_round (); 773 void probe (bool update_limits = true); 774 775 // ProbSAT/WalkSAT implementation called initially or from 'rephase'. 776 // 777 void walk_save_minimum (Walker &); 778 Clause * walk_pick_clause (Walker &); 779 unsigned walk_break_value (int lit); 780 int walk_pick_lit (Walker &, Clause *); 781 void walk_flip_lit (Walker &, int lit); 782 int walk_round (int64_t limit, bool prev); 783 void walk (); 784 785 // Detect strongly connected components in the binary implication graph 786 // (BIG) and equivalent literal substitution (ELS) in 'decompose.cpp'. 787 // 788 bool decompose_round (); 789 void decompose (); 790 791 // Assumption handling. 792 // 793 void assume (int); // New assumption literal. 794 void reset_assumptions (); // Reset after 'solve' call. 795 void reset_limits (); // Reset after 'solve' call. 796 void failing (); // Prepare failed assumptions. 797 798 bool failed (int lit) { // Literal failed assumption? 799 Flags & f = flags (lit); 800 const unsigned bit = bign (lit); 801 return (f.failed & bit) != 0; 802 } 803 804 bool assumed (int lit) { // Marked as assumption. 805 Flags & f = flags (lit); 806 const unsigned bit = bign (lit); 807 return (f.assumed & bit) != 0; 808 } 809 810 // Forcing decision variables to a certain phase. 811 // 812 void phase (int lit); 813 void unphase (int lit); 814 815 // Globally blocked clause elimination. 816 // 817 bool is_autarky_literal (int lit) const; 818 bool is_conditional_literal (int lit) const; 819 void mark_as_conditional_literal (int lit); 820 void unmark_as_conditional_literal (int lit); 821 // 822 bool is_in_candidate_clause (int lit) const; 823 void mark_in_candidate_clause (int lit); 824 void unmark_in_candidate_clause (int lit); 825 // 826 void condition_assign (int lit); 827 void condition_unassign (int lit); 828 // 829 bool conditioning (); 830 long condition_round (long unassigned_literal_propagation_limit); 831 void condition (bool update_limits = true); 832 833 // Part on picking the next decision in 'decide.cpp'. 834 // 835 bool satisfied (); 836 int next_decision_variable_on_queue (); 837 int next_decision_variable_with_best_score (); 838 int next_decision_variable (); 839 int decide_phase (int idx, bool target); 840 int likely_phase (int idx); 841 int decide (); // 0=decision, 20=failed 842 843 // Internal functions to enable explicit search limits. 844 // 845 void limit_terminate (int); 846 void limit_decisions (int); // Force decision limit. 847 void limit_conflicts (int); // Force conflict limit. 848 void limit_preprocessing (int); // Enable 'n' preprocessing rounds. 849 void limit_local_search (int); // Enable 'n' local search rounds. 850 851 // External versions can access limits by 'name'. 852 // 853 static bool is_valid_limit (const char *name); 854 bool limit (const char * name, int); // 'true' if 'name' valid 855 856 // Set all the CDCL search limits and increments for scheduling 857 // inprocessing, restarts, clause database reductions, etc. 858 // 859 void init_report_limits (); 860 void init_preprocessing_limits (); 861 void init_search_limits (); 862 863 // The computed averages are local to the 'stable' and 'unstable' phase. 864 // Their main use is to be reported in 'report', except for the 'glue' 865 // averages, which are used to schedule (prohibit actually) restarts 866 // during 'unstable' phases ('stable' phases use reluctant doubling). 867 // 868 void init_averages (); 869 void swap_averages (); 870 871 int try_to_satisfy_formula_by_saved_phases (); 872 void produce_failed_assumptions (); 873 874 // Main solve & search functions in 'internal.cpp'. 875 // 876 // We have three pre-solving techniques. These consist of preprocessing, 877 // local search and searching for lucky phases, which in full solving 878 // mode except for the last are usually optional and then followed by 879 // the main CDCL search loop with inprocessing. If only preprocessing 880 // is requested from 'External::simplifiy' only preprocessing is called 881 // though. This is all orchestrated by the 'solve' function. 882 // 883 int already_solved (); 884 int restore_clauses (); 885 bool preprocess_round (int round); 886 int preprocess (); 887 int local_search_round (int round); 888 int local_search (); 889 int lucky_phases (); 890 int cdcl_loop_with_inprocessing (); 891 void reset_solving (); 892 int solve (bool preprocess_only = false); 893 894 // Perform look ahead and return the most occurring literal. 895 // 896 int lookahead(); 897 CubesWithStatus generate_cubes(int); 898 int most_occurring_literal(); 899 int lookahead_probing(); 900 int lookahead_next_probe(); 901 void lookahead_flush_probes(); 902 void lookahead_generate_probes(); 903 bool terminating_asked(); 904 905 #ifndef QUIET 906 // Built in profiling in 'profile.cpp' (see also 'profile.hpp'). 907 // 908 void start_profiling (Profile & p, double); 909 void stop_profiling (Profile & p, double); 910 911 double update_profiles (); // Returns 'time ()'. 912 void print_profile (); 913 #endif 914 915 // Get the value of an internal literal: -1=false, 0=unassigned, 1=true. 916 // We use a redundant table for both negative and positive literals. This 917 // allows a branch-less check for the value of literal and is considered 918 // substantially faster than negating the result if the argument is 919 // negative. We also avoid taking the absolute value. 920 // 921 signed char val (int lit) const { 922 assert (-max_var <= lit); 923 assert (lit); 924 assert (lit <= max_var); 925 return vals[lit]; 926 } 927 928 // As 'val' but restricted to the root-level value of a literal. 929 // It is not that time critical and also needs to check the decision level 930 // of the variable anyhow. 931 // 932 int fixed (int lit) { 933 assert (-max_var <= lit); 934 assert (lit); 935 assert (lit <= max_var); 936 const int idx = vidx (lit); 937 int res = vals[idx]; 938 if (res && vtab[idx].level) res = 0; 939 if (lit < 0) res = -res; 940 return res; 941 } 942 943 // Map back an internal literal to an external. 944 // 945 int externalize (int lit) { 946 assert (lit != INT_MIN); 947 const int idx = abs (lit); 948 assert (idx); 949 assert (idx <= max_var); 950 int res = i2e[idx]; 951 if (lit < 0) res = -res; 952 return res; 953 } 954 955 // Explicit freezing and melting of variables. 956 // 957 void freeze (int lit) { 958 int idx = vidx (lit); 959 unsigned & ref = frozentab[idx]; 960 if (ref < UINT_MAX) { 961 ref++; 962 LOG ("variable %d frozen %u times", idx, ref); 963 } else LOG ("variable %d remains frozen forever", idx); 964 } 965 void melt (int lit) { 966 int idx = vidx (lit); 967 unsigned & ref = frozentab[idx]; 968 if (ref < UINT_MAX) { 969 if (!--ref) { 970 LOG ("variable %d completely molten", idx); 971 } else 972 LOG ("variable %d melted once but remains frozen %u times", 973 lit, ref); 974 } else LOG ("variable %d remains frozen forever", idx); 975 } 976 bool frozen (int lit) { return frozentab[vidx (lit)] > 0; } 977 978 // Parsing functions in 'parse.cpp'. 979 // 980 const char * parse_dimacs (FILE *); 981 const char * parse_dimacs (const char *); 982 const char * parse_solution (const char *); 983 984 // Enable and disable proof logging and checking. 985 // 986 void new_proof_on_demand (); 987 void close_trace (); // Stop proof tracing. 988 void flush_trace (); // Flush proof trace file. 989 void trace (File *); // Start write proof file. 990 void check (); // Enable online proof checking. 991 992 // Dump to '<stdout>' as DIMACS for debugging. 993 // 994 void dump (Clause *); 995 void dump (); 996 997 // Export and traverse all irredundant (non-unit) clauses. 998 // 999 bool traverse_clauses (ClauseIterator &); 1000 1001 /*----------------------------------------------------------------------*/ 1002 1003 double solve_time (); // accumulated time spent in 'solve ()' 1004 1005 double process_time (); // since solver was initialized 1006 double real_time (); // since solver was initialized 1007 1008 double time () { 1009 return opts.realtime ? real_time () : process_time (); 1010 } 1011 1012 // Regularly reports what is going on in 'report.cpp'. 1013 // 1014 void report (char type, int verbose_level = 0); 1015 void report_solving(int); 1016 1017 void print_statistics (); 1018 void print_resource_usage (); 1019 1020 1021 /*----------------------------------------------------------------------*/ 1022 1023 #ifndef QUIET 1024 1025 void print_prefix (); 1026 1027 // Non-verbose messages and warnings, i.e., always printed unless 'quiet' 1028 // is set, which disables messages at run-time, or even 'QUIET' is defined 1029 // through the configuration option './configure --quiet', which disables 1030 // such messages completely at compile-time. 1031 // 1032 void vmessage (const char *, va_list &); 1033 void message (const char *, ...); 1034 void message (); // empty line 1035 1036 // Verbose messages with explicit verbose 'level' controlled by 1037 // 'opts.verbose' (verbose level '0' gives the same as 'message'). 1038 // 1039 void vverbose (int level, const char * fmt, va_list &); 1040 void verbose (int level, const char * fmt, ...); 1041 void verbose (int level); 1042 1043 // This is for printing section headers in the form 1044 // 1045 // c ---- [ <title> ] --------------------- 1046 // 1047 // nicely aligned (and of course is ignored if 'quiet' is set). 1048 // 1049 void section (const char * title); 1050 1051 // Print verbose message about phases if 'opts.verbose > 1' (but not if 1052 // 'quiet' is set). Note that setting 'log' or '-l' forces all verbose 1053 // output (and also ignores 'quiet' set to true'). The 'phase' argument 1054 // is used to print a 'phase' prefix for the message as follows: 1055 // 1056 // c [<phase>] ... 1057 // 1058 void phase (const char * phase, const char *, ...); 1059 1060 // Same as the last 'phase' above except that the prefix gets a count: 1061 // 1062 // c [<phase>-<count>] ... 1063 // 1064 void phase (const char * phase, int64_t count, const char *, ...); 1065 #endif 1066 1067 // Print error messages which are really always printed (even if 'quiet' 1068 // is set). This leads to exit the current process with exit status '1'. 1069 // 1070 // TODO add possibility to use a call back instead of calling exit. 1071 // 1072 void error_message_end (); 1073 void verror (const char *, va_list &); 1074 void error (const char *, ...); 1075 void error_message_start (); 1076 1077 // Warning messages. 1078 // 1079 void warning (const char *, ...); 1080 }; 看一下关于internal的注释: The actual internal state of the solver is set and maintained in this section. This is currently only used for debugging and testing.译文:求解器的实际内部状态在本节中设置和维护。目前仅用于调试和测试。 |
起始部分还前置声明的类型 struct Coveror; struct External; struct Walker; 定义的立方体状态类型 struct CubesWithStatus { int status; std::vector<std::vector<int>> cubes; }; |
// Fatal internal error which leads to abort.//void fatal_message_start ();void fatal_message_end ();void fatal (const char *, ...);
/*------------------------------------------------------------------------*/
// Has to be put here, i.e., not into 'score.hpp', since we need the// definition of 'Internal::score' above (after '#include "score.hpp"').
inline bool score_smaller::operator () (unsigned a, unsigned b) {
// Avoid computing twice 'abs' in 'score ()'. // assert (1 <= a); assert (a <= (unsigned) internal->max_var); assert (1 <= b); assert (b <= (unsigned) internal->max_var); double s = internal->stab[a]; double t = internal->stab[b];
if (s < t) return true; if (s > t) return false;
return a > b;}
/*------------------------------------------------------------------------*/
// Implemented here for keeping it all inline (requires Internal::fixed).
inline int External::fixed (int elit) const { assert (elit); assert (elit != INT_MIN); int eidx = abs (elit); if (eidx > max_var) return 0; int ilit = e2i [eidx]; if (!ilit) return 0; if (elit < 0) ilit = -ilit; return internal->fixed (ilit);}
/*------------------------------------------------------------------------*/
// We want to have termination checks inlined, particularly the first// function which appears in preprocessor loops. Even though this first// 'termination_forced' is set asynchronously, this should not lead to a// data race issue (it also has been declared 'volatile').
inline bool Internal::terminated_asynchronously (int factor){ // First way of asynchronous termination is through 'terminate' which sets // the 'termination_forced' flag directly. The second way is through a // call back to a 'terminator' if it is non-zero, which however is costly. // if (termination_forced) { LOG ("termination asynchronously forced"); return true; }
// This is only for testing and debugging asynchronous termination calls. // In production code this could be removed but then should not be costly // and keeping it will allow to test correctness of asynchronous // termination on the production platform too. After this triggers we // have to set the 'termination_forced' flag, such that subsequent calls // to this function do not check this again. // if (lim.terminate.forced) { assert (lim.terminate.forced > 0); if (lim.terminate.forced-- == 1) { LOG ("internally forcing termination"); termination_forced = true; return true; } LOG ("decremented internal forced termination limit to %" PRId64, lim.terminate.forced); }
// The second way of asynchronous termination is through registering and // calling an external 'Terminator' object. This is of course more costly // than just checking a (volatile though) boolean flag, particularly in // tight loops. To avoid this cost we only call the terminator in // intervals of 'opts.terminateint', which in addition can be scaled up by // the argument 'factor'. If the terminator returns 'true' we set the // 'termination_forced' flag to 'true' in order to remember the // termination status and to avoid the terminator again. Setting this // flag leads to the first test above to succeed in subsequent calls. // if (external->terminator && !lim.terminate.check--) { assert (factor > 0); assert (INT_MAX/factor > opts.terminateint); lim.terminate.check = factor * opts.terminateint; if (external->terminator->terminate ()) { termination_forced = true; // Cache it. LOG ("connected terminator forces termination"); return true; } }
return false;}
/*------------------------------------------------------------------------*/
inline bool Internal::search_limits_hit (){ assert (!preprocessing); assert (!localsearching);
if (lim.conflicts >= 0 && stats.conflicts >= lim.conflicts) { LOG ("conflict limit %" PRId64 " reached", lim.conflicts); return true; }
if (lim.decisions >= 0 && stats.decisions >= lim.decisions) { LOG ("decision limit %" PRId64 " reached", lim.decisions); return true; }
return false;}
/*------------------------------------------------------------------------*/