0cadical-基本数据结构

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
possible). Most implementation files need to see the definition of the 'Internal' too. Thus there is no real advantage in trying to reduce the number of header files included here. The other benefit of having all header files here is that '.cpp' files then only need to include this.

译文:拥有所有头文件的另一个好处是'。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;}
/*------------------------------------------------------------------------*/

猜你喜欢

转载自www.cnblogs.com/yuweng1689/p/13169022.html
今日推荐