以下代码基于cadical-rel-1.5.3版本,来源于:

 

Solver 在cadical.hpp文件中声明求解器类型。其中成员函数比较有趣的是:

int val (int lit); // Line 57,   返回文字的值;assert(val(liter)),断言文字liter为非零,即是有效文字;
// Get value (-lit=false, lit=true) of valid non-zero literal.
bool failed (int lit); // Determine whether the valid non-zero literal is in the core.                      
void copy (Solver & other) const; // Line 

//===================================================================

除了函数'val', 'fixed', 'failed'和'frozen'外,每当将文字用作参数时,
通常会隐式地添加和初始化变量。但是,库内部保留了一个可查询的最大变量索引函数vars()。
//===================================================================
 bign (lit);

sign (lit);

//获取文字的符号inline int sign (int lit) { return (lit > 0) - (lit < 0); }
vals[idx] = tmp; //tep值为1或-1 举例文字-8,tep = -1,则确保该负文字取值为真赋值vals[8] = -1,vals[-8] = 1
vals[-idx] = -tmp;

 
 
  1 class Solver {
  2 
  3 public:
  4 
  5   // ====== BEGIN IPASIR ===================================================
  6 
  7   // This section implements the corresponding IPASIR functionality.
  8 
  9   Solver ();
 10   ~Solver ();
 11 
 12   static const char * signature ();     // name of this library
 13 
 14   // Core functionality as in the IPASIR incremental SAT solver interface.
 15   // (recall 'READY = CONFIGURING | UNKNOWN | SATISFIED | UNSATISFIED').
 16   // Further note that 'lit' is required to be different from 'INT_MIN' and
 17   // different from '0' except for 'add'.
 18 
 19   // Add valid literal to clause or zero to terminate clause.
 20   //
 21   //   require (VALID)                  // recall 'VALID = READY | ADDING'
 22   //   if (lit) ensure (ADDING)         // and thus VALID but not READY
 23   //   if (!lit) ensure (UNKNOWN)       // and thus READY
 24   //
 25   void add (int lit);
 26 
 27   // Assume valid non zero literal for next call to 'solve'.  These
 28   // assumptions are reset after the call to 'solve' as well as after
 29   // returning from 'simplify' and 'lookahead.
 30   //
 31   //   require (READY)
 32   //   ensure (UNKNOWN)
 33   //
 34   void assume (int lit);
 35 
 36   // Try to solve the current formula.  Returns
 37   //
 38   //    0 = UNSOLVED     (limit reached or interrupted through 'terminate')
 39   //   10 = SATISFIABLE
 40   //   20 = UNSATISFIABLE
 41   //
 42   //   require (READY)
 43   //   ensure (UNKNOWN | SATISFIED | UNSATISFIED)
 44   //
 45   // Note, that while in this call the solver actually transitions to state
 46   // 'SOLVING', which however is only visible from a different context,
 47   // i.e., from a different thread or from a signal handler.  Only right
 48   // before returning from this call it goes into a 'READY' state.
 49   //
 50   int solve ();
 51 
 52   // Get value (-lit=false, lit=true) of valid non-zero literal.
 53   //
 54   //   require (SATISFIED)
 55   //   ensure (SATISFIED)
 56   //
 57   int val (int lit);
 58 
 59   // Determine whether the valid non-zero literal is in the core.
 60   // Returns 'true' if the literal is in the core and 'false' otherwise.
 61   // Note that the core does not have to be minimal.
 62   //
 63   //   require (UNSATISFIED)
 64   //   ensure (UNSATISFIED)
 65   //
 66   bool failed (int lit);
 67 
 68   // Add call-back which is checked regularly for termination.  There can
 69   // only be one terminator connected.  If a second (non-zero) one is added
 70   // the first one is implicitly disconnected.
 71   //
 72   //   require (VALID)
 73   //   ensure (VALID)
 74   //
 75   void connect_terminator (Terminator * terminator);
 76   void disconnect_terminator ();
 77 
 78   // Add call-back which allows to export learned clauses.
 79   //
 80   //   require (VALID)
 81   //   ensure (VALID)
 82   //
 83   void connect_learner (Learner * learner);
 84   void disconnect_learner ();
 85 
 86   // ====== END IPASIR =====================================================
 87 
 88   //------------------------------------------------------------------------
 89   // Adds a literal to the constraint clause. Same functionality as 'add' but
 90   // the clause only exists for the next call to solve (same lifetime as
 91   // assumptions). Only one constraint may exists at a time. A new constraint
 92   // replaces the old.
 93   // The main application of this functonality is the model checking algorithm
 94   // IC3. See our FMCAD'21 paper [FroleyksBiere-FMCAD'19] for more details.
 95   //
 96   // Add valid literal to the constraint clause or zero to terminate it.
 97   //
 98   //   require (VALID)                     // recall 'VALID = READY | ADDING'
 99   //   if (lit) ensure (ADDING)            // and thus VALID but not READY
100   //   if (!lit) && !adding_clause ensure (UNKNOWN) // and thus READY
101   //
102   void constrain (int lit);
103 
104   // Determine whether the constraint was used to proof the unsatisfiability.
105   // Note that the formula might still be unsatisfiable without the constraint.
106   //
107   //   require (UNSATISFIED)
108   //   ensure (UNSATISFIED)
109   //
110   bool constraint_failed ();
111 
112   //------------------------------------------------------------------------
113   // This function determines a good splitting literal.  The result can be
114   // zero if the formula is proven to be satisfiable or unsatisfiable.  This
115   // can then be checked by 'state ()'.  If the formula is empty and
116   // the function is not able to determine satisfiability also zero is
117   // returned but the state remains unknown.
118   //
119   //   require (READY)
120   //   ensure (UNKNOWN|SATISFIED|UNSATISFIED)
121   //
122   int lookahead(void);
123 
124   struct CubesWithStatus {
125     int status;
126     std::vector<std::vector<int>> cubes;
127   };
128 
129   CubesWithStatus generate_cubes(int, int min_depth = 0);
130 
131   void reset_assumptions ();
132   void reset_constraint ();
133 
134   // Return the current state of the solver as defined above.
135   //
136   const State & state () const { return _state; }
137 
138   // Similar to 'state ()' but using the staddard competition exit codes of
139   // '10' for 'SATISFIABLE', '20' for 'UNSATISFIABLE' and '0' otherwise.
140   //
141   int status () const {
142          if (_state == SATISFIED)   return 10;
143     else if (_state == UNSATISFIED) return 20;
144     else                            return 0;
145   }
146 
147   /*----------------------------------------------------------------------*/
148 
149   static const char * version ();    // return version string
150 
151   /*----------------------------------------------------------------------*/
152   // Copy 'this' into a fresh 'other'.  The copy procedure is not a deep
153   // clone, but only copies irredundant clauses and units.  It also makes
154   // sure that witness reconstruction works with the copy as with the
155   // original formula such that both solvers have the same models.
156   // Assumptions are not copied.  Options however are copied as well as
157   // flags which remember the current state of variables in preprocessing.
158   //
159   //   require (READY)          // for 'this'
160   //   ensure (READY)           // for 'this'
161   //
162   //   other.require (CONFIGURING)
163   //   other.ensure (CONFIGURING | UNKNOWN)
164   //
165   void copy (Solver & other) const;
复制过程不是深度克隆,而是只复制非冗余子句和单元。
它还确保见证重建可以像处理原始公式一样处理副本,以便两个求解器具有相同的模型。
Assumptions不会被复制。然而,选项和标记被复制,这些标记在预处理中记住了变量的当前状态。
166 167 /*----------------------------------------------------------------------*/ 168 // Variables are usually added and initialized implicitly whenever a 169 // literal is used as an argument except for the functions 'val', 'fixed', 170 // 'failed' and 'frozen'. However, the library internally keeps a maximum 171 // variable index, which can be queried. 172 // 173 // require (VALID | SOLVING) 174 // ensure (VALID | SOLVING) 175 // 176 int vars ();
除了'val', 'fixed', 'failed'和'frozen'函数外,变量通常会被隐式地添加和初始化。
但是,库内部保留了一个最大变量索引,可以进行查询。
177 178 // Increase the maximum variable index explicitly. This function makes 179 // sure that at least 'min_max_var' variables are initialized. Since it 180 // might need to reallocate tables, it destroys a satisfying assignment 181 // and has the same state transition and conditions as 'assume' etc. 182 // 183 // require (READY) 184 // ensure (UNKNOWN) 185 // 186 void reserve (int min_max_var); 187 188 #ifndef NTRACING 189 //------------------------------------------------------------------------ 190 // This function can be used to write API calls to a file. The same 191 // format is used which 'mobical' can read, execute and also shrink 192 // through delta debugging. 193 // 194 // Tracing API calls can also be achieved by using the environment 195 // variable 'CADICAL_API_TRACE'. That alternative is useful if you do not 196 // want to change the source code using the solver, e.g., if you only have 197 // a binary with the solver linked in. However, that method only allows 198 // to trace one solver instance, while with the following function API 199 // tracing can be enabled for different solver instances individually. 200 // 201 // The solver will flush the file after every trace API call but does not 202 // close it during deletion. It remains owned by the user of the library. 203 // 204 // require (VALID) 205 // ensure (VALID) 206 // 207 void trace_api_calls (FILE * file); 208 #endif 209 210 //------------------------------------------------------------------------ 211 // Option handling. 212 213 // Determine whether 'name' is a valid option name. 214 // 215 static bool is_valid_option (const char * name); 216 217 // Determine whether 'name' enables a specific preprocessing technique. 218 // 219 static bool is_preprocessing_option (const char * name); 220 221 // Determine whether 'arg' is a valid long option of the form '--<name>', 222 // '--<name>=<val>' or '--no-<name>' similar to 'set_long_option' below. 223 // Legal values are 'true', 'false', or '[-]<mantissa>[e<exponent>]'. 224 225 static bool is_valid_long_option (const char * arg); 226 227 // Get the current value of the option 'name'. If 'name' is invalid then 228 // zero is returned. Here '--...' arguments as invalid options. 229 // 230 int get (const char * name); 231 232 // Set the default verbose message prefix (default "c "). 233 // 234 void prefix (const char * verbose_message_prefix); 235 236 // Explicit version of setting an option. If the option '<name>' exists 237 // and '<val>' can be parsed then 'true' is returned. If the option value 238 // is out of range the actual value is computed as the closest (minimum or 239 // maximum) value possible, but still 'true' is returned. 240 // 241 // require (CONFIGURING) 242 // ensure (CONFIGURING) 243 // 244 // Thus options can only bet set right after initialization. 245 // 246 bool set (const char * name, int val); 247 248 // This function accepts options in command line syntax: 249 // 250 // '--<name>=<val>', '--<name>', or '--no-<name>' 251 // 252 // It actually calls the previous 'set' function after parsing 'arg'. The 253 // same values are expected as for 'is_valid_long_option' above and as 254 // with 'set' any value outside of the range of legal values for a 255 // particular option are set to either the minimum or maximum depending on 256 // which side of the valid interval they lie. 257 // 258 // require (CONFIGURING) 259 // ensure (CONFIGURING) 260 // 261 bool set_long_option (const char * arg); 262 263 // Determine whether 'name' is a valid configuration. 264 // 265 static bool is_valid_configuration (const char *); 266 267 // Overwrite (some) options with the forced values of the configuration. 268 // The result is 'true' iff the 'name' is a valid configuration. 269 // 270 // require (CONFIGURING) 271 // ensure (CONFIGURING) 272 // 273 bool configure (const char *); 274 275 // Increase preprocessing and inprocessing limits by '10^<val>'. Values 276 // below '0' are ignored and values above '9' are reduced to '9'. 277 // 278 // require (READY) 279 // ensure (READY) 280 // 281 void optimize (int val); 282 283 // Specify search limits, where currently 'name' can be "conflicts", 284 // "decisions", "preprocessing", or "localsearch". The first two limits 285 // are unbounded by default. Thus using a negative limit for conflicts or 286 // decisions switches back to the default of unlimited search (for that 287 // particular limit). The preprocessing limit determines the number of 288 // preprocessing rounds, which is zero by default. Similarly, the local 289 // search limit determines the number of local search rounds (also zero by 290 // default). As with 'set', the return value denotes whether the limit 291 // 'name' is valid. These limits are only valid for the next 'solve' or 292 // 'simplify' call and reset to their default after 'solve' returns (as 293 // well as overwritten and reset during calls to 'simplify' and 294 // 'lookahead'). We actually also have an internal "terminate" limit 295 // which however should only be used for testing and debugging. 296 // 297 // require (READY) 298 // ensure (READY) 299 // 300 bool limit (const char * arg, int val); 301 bool is_valid_limit (const char * arg);
//=====================================================================================

      指定搜索限制,当前“name”可以是“conflicts”、“decisions”、“pre - processing”或“localsearch”。

      默认情况下,前两个限制是无限制的。因此,对于冲突或决策使用负限制将切换回默认的无限搜索(对于特定的限制)。

      预处理限制决定预处理轮数,默认为0。

      类似地,本地搜索限制决定了本地搜索轮的数量(默认情况下也是零)。与'set'一样,返回值表示是否限制'name'有效。

      这些限制仅对下一个“solve”或“simplify”调用有效,并在“solve”返回后重置为默认值(以及在调用“simplify”

          和“lookahead”期间重写和重置)。

     实际上,我们也有一个内部的“终止”限制,但是只能用于测试和调试。

     //=======================================================================================

302 
303   // The number of currently active variables and clauses can be queried by
304   // these functions.  Variables become active if a clause is added with it.
305   // They become inactive if they are eliminated or fixed at the root level
306   // Clauses become inactive if they are satisfied, subsumed, eliminated.
307   // Redundant clauses are reduced regularly and thus the 'redundant'
308   // function is less useful.
309   //
310   //   require (VALID)
311   //   ensure (VALID)
312   //
313   int active () const;          // Number of active variables.
314   int64_t redundant () const;   // Number of active redundant clauses.
315   int64_t irredundant () const; // Number of active irredundant clauses.
316 
317   //------------------------------------------------------------------------
318   // This function executes the given number of preprocessing rounds. It is
319   // similar to 'solve' with 'limits ("preprocessing", rounds)' except that
320   // no CDCL nor local search, nor lucky phases are executed.  The result
321   // values are also the same: 0=unknown, 10=satisfiable, 20=unsatisfiable.
322   // As 'solve' it resets current assumptions and limits before returning.
323   // The numbers of rounds should not be negative.  If the number of rounds
324   // is zero only clauses are restored (if necessary) and top level unit
325   // propagation is performed, which both take some time.
326   //
327   //   require (READY)
328   //   ensure (UNKNOWN | SATISFIED | UNSATISFIED)
329   //
330   int simplify (int rounds = 3);
331 
332   //------------------------------------------------------------------------
333   // Force termination of 'solve' asynchronously.
334   //
335   //  require (SOLVING | READY)
336   //  ensure (UNKNOWN)           // actually not immediately (synchronously)
337   //
338   void terminate ();
339 
340   //------------------------------------------------------------------------
341 
342   // We have the following common reference counting functions, which avoid
343   // to restore clauses but require substantial user guidance.  This was the
344   // only way to use inprocessing in incremental SAT solving in Lingeling
345   // (and before in MiniSAT's 'freeze' / 'thaw') and which did not use
346   // automatic clause restoring.  In general this is slower than
347   // restoring clauses and should not be used.
348   //
349   // In essence the user freezes variables which potentially are still
350   // needed in clauses added or assumptions used after the next 'solve'
351   // call.  As in Lingeling you can freeze a variable multiple times, but
352   // then have to melt it the same number of times again in order to enable
353   // variable eliminating on it etc.  The arguments can be literals
354   // (negative indices) but conceptually variables are frozen.
355   //
356   // In the old way of doing things without restore you should not use a
357   // variable incrementally (in 'add' or 'assume'), which was used before
358   // and potentially could have been eliminated in a previous 'solve' call.
359   // This can lead to spurious satisfying assignment.  In order to check
360   // this API contract one can use the 'checkfrozen' option.  This has the
361   // drawback that restoring clauses implicitly would fail with a fatal
362   // error message even if in principle the solver could just restore
363   // clauses. Thus this option is disabled by default.
364   //
365   // See our SAT'19 paper [FazekasBiereScholl-SAT'19] for more details.
366   //
367   //   require (VALID)
368   //   ensure (VALID)
369   //
370   bool frozen (int lit) const;
371   void freeze (int lit);
372   void melt (int lit);          // Also needs 'require (frozen (lit))'.
373 
374   //------------------------------------------------------------------------
375 
376   // Root level assigned variables can be queried with this function.
377   // It returns '1' if the literal is implied by the formula, '-1' if its
378   // negation is implied, or '0' if this is unclear at this point.
379   //
380   //   require (VALID)
381   //   ensure (VALID)
382   //
383   int fixed (int lit) const;
可以使用此函数查询根级别分配的变量。如果字面量由公式暗示,则返回'1',
如果隐含其否定则返回'-1',如果此时不清楚则返回'0'。
384 385 //------------------------------------------------------------------------ 386 // Force the default decision phase of a variable to a certain value. 387 // 388 void phase (int lit); 389 void unphase (int lit); 390 391 //------------------------------------------------------------------------ 392 393 // Enables clausal proof tracing in DRAT format and returns 'true' if 394 // successfully opened for writing. Writing proofs has to be enabled 395 // before calling 'solve', 'add' and 'dimacs', that is in state 396 // 'CONFIGURING'. Otherwise only partial proofs would be written. 397 // 398 // require (CONFIGURING) 399 // ensure (CONFIGURING) 400 // 401 bool trace_proof (FILE * file, const char * name); // Write DRAT proof. 402 bool trace_proof (const char * path); // Open & write proof. 403 404 // Flush proof trace file. 405 // 406 // require (VALID) 407 // ensure (VALID) 408 // 409 void flush_proof_trace (); 410 411 // Close proof trace early. 412 // 413 // require (VALID) 414 // ensure (VALID) 415 // 416 void close_proof_trace (); 417 418 //------------------------------------------------------------------------ 419 420 static void usage (); // print usage information for long options 421 422 static void configurations (); // print configuration usage options 423 424 // require (!DELETING) 425 // ensure (!DELETING) 426 // 427 void statistics (); // print statistics 428 void resources (); // print resource usage (time and memory) 429 430 // require (VALID) 431 // ensure (VALID) 432 // 433 void options (); // print current option and value list 434 435 //------------------------------------------------------------------------ 436 // Traverse irredundant clauses or the extension stack in reverse order. 437 // 438 // The return value is false if traversal is aborted early due to one of 439 // the visitor functions returning false. See description of the 440 // iterators below for more details on how to use these functions. 441 // 442 // require (VALID) 443 // ensure (VALID) 444 // 445 bool traverse_clauses (ClauseIterator &) const; 446 bool traverse_witnesses_backward (WitnessIterator &) const; 447 bool traverse_witnesses_forward (WitnessIterator &) const; 448 449 //------------------------------------------------------------------------ 450 // Files with explicit path argument support compressed input and output 451 // if appropriate helper functions 'gzip' etc. are available. They are 452 // called through opening a pipe to an external command. 453 // 454 // If the 'strict' argument is zero then the number of variables and 455 // clauses specified in the DIMACS headers are ignored, i.e., the header 456 // 'p cnf 0 0' is always legal. If the 'strict' argument is larger '1' 457 // strict formatting of the header is required, i.e., single spaces 458 // everywhere and no trailing white space. 459 // 460 // Returns zero if successful and otherwise an error message. 461 // 462 // require (VALID) 463 // ensure (VALID) 464 // 465 const char * read_dimacs (FILE * file, 466 const char * name, int & vars, int strict = 1); 467 468 const char * read_dimacs (const char * path, int & vars, int strict = 1); 469 470 // The following routines work the same way but parse both DIMACS and 471 // INCCNF files (with 'p inccnf' header and 'a <cube>' lines). If the 472 // parser finds and 'p inccnf' header or cubes then '*incremental' is set 473 // to true and the cubes are stored in the given vector (each cube 474 // terminated by a zero). 475 476 const char * read_dimacs (FILE * file, 477 const char * name, int & vars, int strict, 478 bool & incremental, std::vector<int> & cubes); 479 480 const char * read_dimacs (const char * path, int & vars, int strict, 481 bool & incremental, std::vector<int> & cubes); 482 483 //------------------------------------------------------------------------ 484 // Write current irredundant clauses and all derived unit clauses 485 // to a file in DIMACS format. Clauses on the extension stack are 486 // not included, nor any redundant clauses. 487 // 488 // The 'min_max_var' parameter gives a lower bound on the number '<vars>' 489 // of variables used in the DIMACS 'p cnf <vars> ...' header. 490 // 491 // Returns zero if successful and otherwise an error message. 492 // 493 // require (VALID) 494 // ensure (VALID) 495 // 496 const char * write_dimacs (const char * path, int min_max_var = 0); 497 498 // The extension stack for reconstruction a solution can be written too. 499 // 500 const char * write_extension (const char * path); 501 502 // Print build configuration to a file with prefix 'c '. If the file 503 // is '<stdout>' or '<stderr>' then terminal color codes might be used. 504 // 505 static void build (FILE * file, const char * prefix = "c "); 506 507 private: 508 509 //==== start of state ==================================================== 510 511 // The solver is in the state ADDING if either the current clause or the 512 // constraint (or both) is not yet terminated. 513 bool adding_clause; 514 bool adding_constraint; 515 516 State _state; // API states as discussed above. 517 518 /*----------------------------------------------------------------------*/ 519 520 // The 'Solver' class is a 'facade' object for 'External'. It exposes the 521 // public API of 'External' but hides everything else (except for the some 522 // private functions). It is supposed to make it easier to understand the 523 // API and use the solver through the API. 524 525 // This approach has the benefit of decoupling this header file from all 526 // internal data structures, which is particularly useful if the rest of 527 // the source is not available. For instance if only a CaDiCaL library is 528 // installed in a system, then only this header file has to be installed 529 // too, and still allows to compile and link against the library. 530 531 /*----------------------------------------------------------------------*/ 532 533 // More precisely the CaDiCaL code is split into three layers: 534 // 535 // Solver: facade object providing the actual API of the solver 536 // External: communication layer between 'Solver' and 'Internal' 537 // Internal: the actual solver code 538 // 539 // The 'External' and 'Internal' layers are declared and implemented in 540 // the corresponding '{external,internal}.{hpp,cpp}' files (as expected), 541 // while the 'Solver' facade class is defined in 'cadical.hpp' (here) but 542 // implemented in 'solver.cpp'. The reason for this naming mismatch is, 543 // that we want to use 'cadical.hpp' for the library header (this header 544 // file) and call the binary of the stand alone SAT also 'cadical', which 545 // is more naturally implemented in 'cadical.cpp'. 546 // 547 // Separating 'External' from 'Internal' also allows us to map external 548 // literals to internal literals, which is useful with many fixed or 549 // eliminated variables (during 'compact' the internal variable range is 550 // reduced and external variables are remapped). Such an approach is also 551 // necessary, if we want to use extended resolution in the future (such as 552 // bounded variable addition). 553 // 554 Internal * internal; // Hidden internal solver. 555 External * external; // Hidden API to internal solver mapping. 556 557 #ifndef NTRACING 558 // The API calls to the solver can be traced by setting the environment 559 // variable 'CADICAL_API_TRACE' to point to the path of a file to which 560 // API calls are written. The same format is used which 'mobical' can 561 // read, execute and also shrink through delta debugging. 562 // 563 // The environment variable is read in the constructor and the trace is 564 // opened for writing and then closed again in the destructor. 565 // 566 // Alternatively one case use 'trace_api_calls'. Both 567 // 568 bool close_trace_api_file; // Close file if owned by solver it. 569 FILE * trace_api_file; // Also acts as flag that we are tracing. 570 571 static bool tracing_api_through_environment; 572 573 //===== end of state ==================================================== 574 575 void trace_api_call (const char *) const; 576 void trace_api_call (const char *, int) const; 577 void trace_api_call (const char *, const char *, int) const; 578 #endif 579 580 void transition_to_unknown_state (); 581 582 //------------------------------------------------------------------------ 583 // Used in the stand alone solver application 'App' and the model based 584 // tester 'Mobical'. So only these two classes need direct access to the 585 // otherwise more application specific functions listed here together with 586 // the internal DIMACS parser. 587 588 friend class App; 589 friend class Mobical; 590 friend class Parser; 591 592 // Read solution in competition format for debugging and testing. 593 // 594 // require (VALID) 595 // ensure (VALID) 596 // 597 const char * read_solution (const char * path); 598 599 // Cross-compilation with 'MinGW' needs some work-around for 'printf' 600 // style printing of 64-bit numbers including warning messages. The 601 // followings lines are copies of similar code in 'inttypes.hpp' but we 602 // want to keep the 'cadical.hpp' header file stand-alone. 603 604 # ifndef PRINTF_FORMAT 605 # ifdef __MINGW32__ 606 # define __USE_MINGW_ANSI_STDIO 1 607 # define PRINTF_FORMAT __MINGW_PRINTF_FORMAT 608 # else 609 # define PRINTF_FORMAT printf 610 # endif 611 # endif 612 613 // This gives warning messages for wrong 'printf' style format string usage. 614 // Apparently (on 'gcc 9' at least) the first argument is 'this' here. 615 // 616 // TODO: support for other compilers (beside 'gcc' and 'clang'). 617 618 # define CADICAL_ATTRIBUTE_FORMAT(FORMAT_POSITION,VARIADIC_ARGUMENT_POSITION) \ 619 __attribute__ ((format (PRINTF_FORMAT, FORMAT_POSITION, VARIADIC_ARGUMENT_POSITION))) 620 621 // Messages in a common style. 622 // 623 // require (VALID | DELETING) 624 // ensure (VALID | DELETING) 625 // 626 void section (const char *); // print section header 627 void message (const char *, ...) // ordinary message 628 CADICAL_ATTRIBUTE_FORMAT (2, 3); 629 630 void message (); // empty line - only prefix 631 void error (const char *, ...) // produce error message 632 CADICAL_ATTRIBUTE_FORMAT (2, 3); 633 634 // Explicit verbose level ('section' and 'message' use '0'). 635 // 636 // require (VALID | DELETING) 637 // ensure (VALID | DELETING) 638 // 639 void verbose (int level, const char *, ...) 640 CADICAL_ATTRIBUTE_FORMAT (3, 4); 641 642 // Factoring out common code to both 'read_dimacs' functions above. 643 // 644 // require (VALID) 645 // ensure (VALID) 646 // 647 const char * read_dimacs (File *, int &, int strict, 648 bool * incremental = 0, 649 std::vector<int> * = 0); 650 651 // Factored out common code for 'solve', 'simplify' and 'lookahead'. 652 // 653 int call_external_solve_and_check_results (bool preprocess_only); 654 655 //------------------------------------------------------------------------ 656 // Print DIMACS file to '<stdout>' for debugging and testing purposes, 657 // including derived units and assumptions. Since it will print in terms 658 // of internal literals it is otherwise not really useful. To write a 659 // DIMACS formula in terms of external variables use 'write_dimacs'. 660 // 661 // require (!INITIALIZING) 662 // ensure (!INITIALIZING) 663 // 664 void dump_cnf (); 665 friend struct DumpCall; // Mobical calls 'dump_cnf' in 'DumpCall::execute' 666 }; 667 668 /*========================================================================*/ 669 670 // Connected terminators are checked for termination regularly. If the 671 // 'terminate' function of the terminator returns true the solver is 672 // terminated synchronously as soon it calls this function. 673 674 class Terminator { 675 public: 676 virtual ~Terminator () { } 677 virtual bool terminate () = 0; 678 }; 679 680 // Connected learners which can be used to export learned clauses. 681 // The 'learning' can check the size of the learn clause and only if it 682 // returns true then the individual literals of the learned clause are given 683 // to the learn through 'learn' one by one terminated by a zero literal. 684 685 class Learner { 686 public: 687 virtual ~Learner () { } 688 virtual bool learning (int size) = 0; 689 virtual void learn (int lit) = 0; 690 }; 691 692 /*------------------------------------------------------------------------*/ 693 694 // Allows to traverse all remaining irredundant clauses. Satisfied and 695 // eliminated clauses are not included, nor any derived units unless such 696 // a unit literal is frozen. Falsified literals are skipped. If the solver 697 // is inconsistent only the empty clause is traversed. 698 // 699 // If 'clause' returns false traversal aborts early. 700 701 class ClauseIterator { 702 public: 703 virtual ~ClauseIterator () { } 704 virtual bool clause (const std::vector<int> &) = 0; 705 };

 

   
  Clause 见文件clause.hpp
   
 1 struct Clause {
 2 #ifdef LOGGING
 3   int64_t id;         // Only useful for debugging.
 4 #endif
 5 
 6   bool conditioned:1; // Tried for globally blocked clause elimination.
 7   bool covered:1;     // Already considered for covered clause elimination.
 8   bool enqueued:1;    // Enqueued on backward queue.
 9   bool frozen:1;      // Temporarily frozen (in covered clause elimination).
10   bool garbage:1;     // can be garbage collected unless it is a 'reason'
11   bool gate:1 ;       // Clause part of a gate (function definition).
12   bool hyper:1;       // redundant hyper binary or ternary resolved
13   bool instantiated:1;// tried to instantiate
14   bool keep:1;        // always keep this clause (if redundant)
15   bool moved:1;       // moved during garbage collector ('copy' valid)
16   bool reason:1;      // reason / antecedent clause can not be collected
17   bool redundant:1;   // aka 'learned' so not 'irredundant' (original)
18   bool transred:1;    // already checked for transitive reduction
19   bool subsume:1;     // not checked in last subsumption round
20   unsigned used:2;    // resolved in conflict analysis since last 'reduce'
21   bool vivified:1;    // clause already vivified
22   bool vivify:1;      // clause scheduled to be vivified
23 
24   // The glucose level ('LBD' or short 'glue') is a heuristic value for the
25   // expected usefulness of a learned clause, where smaller glue is consider
26   // more useful.  During learning the 'glue' is determined as the number of
27   // decisions in the learned clause.  Thus the glue of a clause is a strict
28   // upper limit on the smallest number of decisions needed to make it
29   // propagate.  For instance a binary clause will propagate if one of its
30   // literals is set to false.  Similarly a learned clause with glue 1 can
31   // propagate after one decision, one with glue 2 after 2 decisions etc.
32   // In some sense the glue is an abstraction of the size of the clause.
33   //
34   // See the IJCAI'09 paper by Audemard & Simon for more details.  We
35   // switched back and forth between keeping the glue stored in a clause and
36   // using it only initially to determine whether it is kept, that is
37   // survives clause reduction.  The latter strategy is not bad but also
38   // does not allow to use glue values for instance in 'reduce'.
39   //
40   // More recently we also update the glue and promote clauses to lower
41   // level tiers during conflict analysis.  The idea of using three tiers is
42   // also due to Chanseok Oh and thus used in all recent 'Maple...' solvers.
43   // Tier one are the always kept clauses with low glue at most
44   // 'opts.reducetier1glue' (default '2'). The second tier contains all
45   // clauses with glue larger than 'opts.reducetier1glue' but smaller or
46   // equal than 'opts.reducetier2glue' (default '6').  The third tier
47   // consists of clauses with glue larger than 'opts.reducetier2glue'.
48   //
49   // Clauses in tier one are not deleted in 'reduce'. Clauses in tier
50   // two require to be unused in two consecutive 'reduce' intervals before
51   // being collected while for clauses in tier three not being used since
52   // the last 'reduce' call makes them deletion candidates.  Clauses derived
53   // by hyper binary or ternary resolution (even though small and thus with
54   // low glue) are always removed if they remain unused during one interval.
55   // See 'mark_useless_redundant_clauses_as_garbage' in 'reduce.cpp' and
56   // 'bump_clause' in 'analyze.cpp'.
57   //
58   int glue;
59 
60   int size;         // Actual size of 'literals' (at least 2).
61   int pos;          // Position of last watch replacement [Gent'13].
62 
63   union {
64 
65     int literals[2];    // Of variadic 'size' (shrunken if strengthened).
66 
67     Clause * copy;      // Only valid if 'moved', then that's where to.
68     //
69     // The 'copy' field is only valid for 'moved' clauses in the moving
70     // garbage collector 'copy_non_garbage_clauses' for keeping clauses
71     // compactly in a contiguous memory arena.  Otherwise, most of
72     // the time, 'literals' is valid.  See 'collect.cpp' for details.
73   };

 

   
   Var 见文件var.hpp
   
1 struct Var {
2 
3   // Note that none of these members is valid unless the variable is
4   // assigned.  During unassigning a variable we do not reset it.
5 
6   int level;         // decision level
7   int trail;         // trail height at assignment
8   Clause * reason;   // implication graph edge during search
9 };

 

   
   Level 见文件level.hpp
   
struct Level {

  int decision;         // decision literal of this level
  int trail;            // trail start of this level

  struct {
    int count;          // how many variables seen during 'analyze'
    int trail;          // smallest trail position seen on this level
  } seen;

  void reset () { seen.count = 0; seen.trail = INT_MAX; }

  Level (int d, int t) : decision (d), trail (t) { reset (); }
  Level () { }
};

 

   
   
Internal 见文件 Internal.hpp
 

 重点的成员函数

(1)理解文字、变元量表示、存储与操作

Var & var (int lit)        { return vtab[vidx (lit)]; }  // Line 322

// Unsigned literals (abs) with checks.
//
int vidx (int lit) const {
    int idx;
    assert (lit);
    assert (lit != INT_MIN);
    idx = abs (lit);
    assert (idx <= max_var);
    return idx;
}

//=============================================================================

---------- cadical-rel-1.5.3\src\internal.hpp


[310] unsigned vlit (int lit) { return (lit < 0) + 2u * (unsigned) vidx (lit); }

int u2i (unsigned u) {
    assert (u > 1);
    int res = u/2;
    assert (res <= max_var);
    if (u & 1) res = -res;
   return res;
}

由以上两个函数可知,Cadical对文字的表示是由正负整数来分别表示的;这与minisat系列的表示方式不同.两者之间可以进行转换.

internal.hpp文件中 struct Internal类型声明中有数据成员

        vector<int> i2e; // maps internal 'idx' to external 'lit'

 


[322] Var & var (int lit) { return vtab[vidx (lit)]; }  依据文字查询Var类型的元素,vtab中存由位置1-maxv分别对应的Var类型的元素

 

 

顺便了解一下各种成员变量,它们都是向量类型,且索引位置序号都是由变元量来对应。

vector<double> stab;     // table of variable scores [1,max_var]
vector<Var> vtab;          // variable table [1,max_var]

vector<Flags> ftab;     // variable and literal flags
vector<int64_t> btab;      // enqueue time stamps for queue
vector<int64_t> gtab;   // time stamp table to recompute glue
vector<Occs> otab;    // table of occurrences for all literals
vector<int> ptab;    // table for caching probing attempts
vector<int64_t> ntab;    // number of one-sided occurrences table
vector<Bins> big;    // binary implication graph
vector<Watches> wtab;    // table of watches for all literals

vector<signed char> marks;   // signed marks [1,max_var]
vector<unsigned> frozentab;    // frozen counters [1,max_var]

Queue queue; // variable move to front decision queue
Links links; // table of links for decision queue


[323] Link & link (int lit) { return links[vidx (lit)]; }
[324] Flags & flags (int lit) { return ftab[vidx (lit)]; }
[325] int64_t & bumped (int lit) { return btab[vidx (lit)]; }
[327] double & score (int lit) { return stab[vidx (lit)]; }
[330] flags (int lit) const { return ftab[vidx (lit)]; }
[350] signed char res = marks [ vidx (lit) ];
[356] marks[vidx (lit)] = sign (lit);
[361] marks [ vidx (lit) ] = 0;
[369] signed char res = marks [ vidx (lit) ] >> 6;
[374] signed char & m = marks[vidx (lit)];
[387] signed char & m = marks[vidx (lit)];
[407] return marks[vidx (lit)] & (1<<bit);
[412] marks[vidx (lit)] |= (1<<bit);
[418] marks[vidx (lit)] &= ~(1<<bit);
[425] unsigned res = marks [ vidx (lit) ];
[431] marks[vidx (lit)] |= bign (lit);
[1075] const int idx = vidx (lit);
[1097] int idx = vidx (lit);
[1105] int idx = vidx (lit);
[1115] bool frozen (int lit) { return frozentab[vidx (lit)] > 0; }

//=============================================================================

 

(2)理解二值观察-与观察元的建立

// Watch literal 'lit' in clause with blocking literal 'blit'.
// Inlined here, since it occurs in the tight inner loop of 'propagate'.
//
inline void watch_literal (int lit, int blit, Clause * c) {
assert (lit != blit);
Watches & ws = watches (lit);
ws.push_back (Watch (blit, c));
LOG (c, "watch %d blit %d in", lit, blit);
}

// Add two watches to a clause. This is used initially during allocation
// of a clause and during connecting back all watches after preprocessing.
//
inline void watch_clause (Clause * c) {
const int l0 = c->literals[0];
const int l1 = c->literals[1];
watch_literal (l0, l1, c);
watch_literal (l1, l0, c);
}

inline void unwatch_clause (Clause * c) {
const int l0 = c->literals[0];
const int l1 = c->literals[1];
remove_watch (watches (l0), c);
remove_watch (watches (l1), c);
}

 

(3)与传播文字相关的量存储结构

size_t propagated;          // next trail position to propagate
size_t propagated2;        // next binary trail position to propagate
size_t best_assigned;     // best maximum assigned ever
size_t target_assigned;  // maximum assigned without conflict
size_t no_conflict_until;  // largest trail prefix without conflict
vector<int> trail;             // currently assigned literals

Queue queue;                // variable move to front decision queue
Links links;                     // table of links for decision queue

 

(4)与变元对应指标相关的量

signed char * vals;                           // assignment [-max_var,max_var]
vector<signed char> marks;            // signed marks [1,max_var]
vector<unsigned> frozentab;           // frozen counters [1,max_var]
vector<int> i2e;                                // maps internal 'idx' to external 'lit'

vector<double> stab;                      // table of variable scores [1,max_var]
vector<Var> vtab;                           // variable table [1,max_var]
vector<int> parents;                       // parent literals during probing
vector<Flags> ftab;                        // variable and literal flags
vector<int64_t> btab;                     // enqueue time stamps for queue
vector<int64_t> gtab;                     // time stamp table to recompute glue

vector<int> ptab;                            // table for caching probing attempts
vector<int64_t> ntab;                     // number of one-sided occurrences table

 

()

double score_inc;                          // current score increment
ScoreSchedule scores;                 // score based decision priority queue

vector<Occs> otab;                       // table of occurrences for all literals

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

 

   
   Queue 见文件queue.hpp
   
 1 struct Queue {
 2 
 3   // We use integers instead of variable pointers.  This is more compact and
 4   // also avoids issues due to moving the variable table during 'resize'.
 5 
 6   int first, last;    // anchors (head/tail) for doubly linked list
 7   int unassigned;     // all variables after this one are assigned
 8   int64_t bumped;     // see 'Internal.update_queue_unassigned'
 9 
10   Queue () : first (0), last (0), unassigned (0), bumped (0) { }
11 
12   // We explicitly provide the mapping of integer indices to links to the
13   // following two (inlined) functions.  This avoids including
14   // 'internal.hpp' and breaks a cyclic dependency, so we can keep their
15   // code here in this header file.  Otherwise they are just ordinary doubly
16   // linked list 'dequeue' and 'enqueue' operations.
17 
18   inline void dequeue (Links & links, int idx) {
19     Link & l = links[idx];
20     if (l.prev) links[l.prev].next = l.next; else first = l.next;
21     if (l.next) links[l.next].prev = l.prev; else last = l.prev;
22   }
23 
24   inline void enqueue (Links & links, int idx) {
25     Link & l = links[idx];
26     if ((l.prev = last)) links[last].next = idx; else first = idx;
27     last = idx;
28     l.next = 0;
29   }
30 };

 在queue.cpp文件中,还声明了Link类型

\cadical-rel-1.5.3\src\queue.hpp
[6] // Links for double linked decision queue.
[15] typedef vector<Link> Links;
[37] inline void dequeue (Links & links, int idx) {
[43] inline void enqueue (Links & links, int idx) {

 1 // Links for double linked decision queue.
 2 
 3 struct Link {
 4 
 5   int prev, next;    // variable indices
 6 
 7   // initialized explicitly in 'init_queue'
 8 };
 9 
10 typedef vector<Link> Links;
11 
12 // Variable move to front (VMTF) decision queue ordered by 'bumped'.  See
13 // our SAT'15 paper for an explanation on how this works.

 

   
   
   
   
posted on 2023-04-15 10:16  海阔凭鱼跃越  阅读(170)  评论(0编辑  收藏  举报