以下代码基于cadical-rel-1.5.3版本,来源于:
Solver 在cadical.hpp文件中声明求解器类型。其中成员函数比较有趣的是: int val (int lit); // Line 57, 返回文字的值;assert(val(liter)),断言文字liter为非零,即是有效文字;
bool failed (int lit); // Determine whether the valid non-zero literal is in the core. void copy (Solver & other) const; // Line
//=================================================================== bign (lit);
//获取文字的符号inline int sign (int lit) { return (lit > 0) - (lit < 0); }
|
|
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; 指定搜索限制,当前“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;
|
|
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. //============================================================================= ---------- cadical-rel-1.5.3\src\internal.hpp
int u2i (unsigned u) { 由以上两个函数可知,Cadical对文字的表示是由正负整数来分别表示的;这与minisat系列的表示方式不同.两者之间可以进行转换. internal.hpp文件中 struct Internal类型声明中有数据成员 vector<int> i2e; // maps internal 'idx' to external 'lit'
顺便了解一下各种成员变量,它们都是向量类型,且索引位置序号都是由变元量来对应。 vector<double> stab; // table of variable scores [1,max_var] vector<Flags> ftab; // variable and literal flags vector<signed char> marks; // signed marks [1,max_var] Queue queue; // variable move to front decision queue
//=============================================================================
(2)理解二值观察-与观察元的建立 // Watch literal 'lit' in clause with blocking literal 'blit'. // Add two watches to a clause. This is used initially during allocation inline void unwatch_clause (Clause * c) {
(3)与传播文字相关的量存储结构 size_t propagated; // next trail position to propagate Queue queue; // variable move to front decision queue
(4)与变元对应指标相关的量 signed char * vals; // assignment [-max_var,max_var] vector<double> stab; // table of variable scores [1,max_var]
() double score_inc; // current score increment 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(
|
|
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 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.
|
|