1. kissat结构体的基本数据成员回顾:
//最常用的数据成员访问代码: watches *const all_watches = solver->watches; ward *const arena = BEGIN_STACK (solver->arena); assigned *const assigned = solver->assigned; value *const values = solver->values;
unsigned_array *trail = &solver->trail;
(1)子对象对应的相关类型
1 #include "arena.h" //包含#include "reference.h" #include "stack.h" #include "utilities.h" 2 #include "array.h" 3 #include "assign.h" //包含 #include "reference.h" 4 #include "averages.h" 5 #include "check.h" 6 #include "classify.h" 7 #include "clause.h" 8 #include "cover.h" 9 #include "extend.h" 10 #include "flags.h" 11 #include "format.h" 12 #include "frames.h" 13 #include "heap.h" 14 #include "kimits.h" 15 #include "kissat.h" 16 #include "literal.h" 17 #include "mode.h" 18 #include "options.h" 19 #include "phases.h" 20 #include "profile.h" 21 #include "proof.h" 22 #include "queue.h" 23 #include "random.h" 24 #include "reluctant.h" 25 #include "rephase.h" 26 #include "smooth.h" 27 #include "stack.h" 28 #include "statistics.h" 29 #include "value.h" 30 #include "vector.h" 31 #include "watch.h" 32 33 typedef struct datarank datarank; 34 35 struct datarank { 36 unsigned data; 37 unsigned rank; 38 }; 39 40 typedef struct import import; 41 42 struct import { 43 unsigned lit; 44 bool extension; 45 bool imported; 46 bool eliminated; 47 }; 48 49 typedef struct termination termination; 50 51 struct termination { 52 #ifdef COVERAGE 53 volatile uint64_t flagged; 54 #else 55 volatile bool flagged; 56 #endif 57 volatile void *state; 58 int (*volatile terminate) (void *); 59 }; 60 61 // clang-format off 62 63 typedef STACK (value) eliminated; 64 typedef STACK (import) imports; 65 typedef STACK (datarank) dataranks; 66 typedef STACK (watch) statches; 67 typedef STACK (watch *) patches; 68 69 // clang-format on 70 71 struct kitten; 以上,(1)声明了kissat类型,有诸多子对象分别属于不同的类型; (2)宏定义SATCK(T)的具化类型之后被当作工作栈类型使用;见上述line63-67; (3)绝大多数函数名使用kissat打头命名,参数列表中第一个参数通常为kissat指针,其它参数类型的参数出现,表明该函数中还会用到不是kissat的数据成员使用;另internal.c中通过宏定义将kissat数据成员以大写标识的形式出现,如 #define SCORES (&solver->scores) 因此带了参数kissat执行的函数能访问的数据成员是该类型的数据成员(含子对象)。
|
|
kissat类型声明中的数据成员与成员函数
1 struct kissat { 2 #if !defined(NDEBUG) || defined(METRICS) 3 bool backbone_computing; 4 #endif 5 #ifdef LOGGING 6 bool compacting; 7 #endif 8 bool extended; 9 bool inconsistent; 10 bool iterating; 11 bool preprocessing; 12 bool probing; 13 #ifndef QUIET 14 bool sectioned; 15 #endif 16 bool stable; 17 #if !defined(NDEBUG) || defined(METRICS) 18 bool transitive_reducing; 19 bool vivifying; 20 #endif 21 bool warming; 22 bool watching; 23 24 bool large_clauses_watched_after_binary_clauses; //最长名称的布尔型数据成员 25 26 termination termination; 27 28 unsigned vars; 29 unsigned size; 30 unsigned active; 31 unsigned randec; 32 33 ints export; 34 ints units; 35 imports import; 36 extensions extend; 37 unsigneds witness; 38 39 assigned *assigned; 40 flags *flags; 41 42 mark *marks; 43 44 value *values; 45 phases phases; 46 47 eliminated eliminated; 48 unsigneds etrail; 49 50 links *links; 51 queue queue; 52 53 heap scores; 54 double scinc; 55 56 heap schedule; 57 double scoreshift; 58 59 unsigned level; 60 frames frames; 61 62 unsigned_array trail; 63 unsigned *propagate; 64 65 unsigned best_assigned; 66 unsigned target_assigned; 67 unsigned unflushed; 68 unsigned unassigned; 69 70 unsigneds delayed; 71 72 #if defined(LOGGING) || !defined(NDEBUG) 73 unsigneds resolvent; 74 #endif 75 unsigned resolvent_size; 76 unsigned antecedent_size; 77 78 dataranks ranks; 79 80 unsigneds analyzed; 81 unsigneds levels; 82 unsigneds minimize; 83 unsigneds poisoned; 84 unsigneds promote; 85 unsigneds removable; 86 unsigneds shrinkable; 87 88 clause conflict; 89 90 bool clause_satisfied; 91 bool clause_shrink; 92 bool clause_trivial; 93 94 unsigneds clause; 95 unsigneds shadow; 96 97 arena arena; 98 vectors vectors; 99 reference first_reducible; 100 reference last_irredundant; 101 watches *watches; 102 103 reference last_learned[4]; 104 105 sizes sorter; 106 107 generator random; 108 averages averages[2]; 109 unsigned tier1[2], tier2[2]; 110 reluctant reluctant; 111 112 bounds bounds; 113 classification classification; 114 delays delays; 115 enabled enabled; 116 limited limited; 117 limits limits; 118 remember last; 119 unsigned walked; 120 121 mode mode; 122 123 uint64_t ticks; 124 125 format format; 126 127 statches antecedents[2]; 128 statches gates[2]; 129 patches xorted[2]; 130 unsigneds resolvents; 131 bool resolve_gate; 132 133 struct kitten *kitten; 134 #ifdef METRICS 135 uint64_t *gate_eliminated; 136 #else 137 bool gate_eliminated; 138 #endif 139 bool sweep_incomplete; 140 unsigneds sweep_schedule; 141 142 #if !defined(NDEBUG) || !defined(NPROOFS) 143 unsigneds added; 144 unsigneds removed; 145 #endif 146 147 #if !defined(NDEBUG) || !defined(NPROOFS) || defined(LOGGING) 148 ints original; 149 size_t offset_of_last_original_clause; 150 #endif 151 152 #ifndef QUIET 153 profiles profiles; 154 #endif 155 156 #ifndef NOPTIONS 157 options options; 158 #endif 159 160 #ifndef NDEBUG 161 checker *checker; //该类型的定义居然在checker.c文件内 162 #endif 163 164 #ifndef NPROOFS 165 proof *proof; 166 #endif 167 168 statistics statistics; 169 }; 注意区别: 类型unsigned、类型unsigneds 以及数据成员unsigned unassigned; 类型assigned;有没有assigneds? 以及数据成员 assigned *assigned; 另: ints;
在文件reference.h中: typedef unsigned reference; typedef STACK (reference) references;
在文件stack.h中 typedef STACK (char) chars; |
|
//internal.c 从释放空间来了解求解器用到的向量——注意对应的是lit_idx还是var_idx; 向量是solver的数据成员还是全局的向量。 void kissat_release (kissat *solver) { kissat_require_initialized (solver); kissat_release_heap (solver, SCORES); kissat_release_heap (solver, &solver->schedule); kissat_release_vectors (solver); kissat_release_phases (solver); RELEASE_STACK (solver->export); RELEASE_STACK (solver->import); DEALLOC_VARIABLE_INDEXED (assigned); DEALLOC_VARIABLE_INDEXED (flags); DEALLOC_VARIABLE_INDEXED (links); DEALLOC_LITERAL_INDEXED (marks); DEALLOC_LITERAL_INDEXED (values); DEALLOC_LITERAL_INDEXED (watches); RELEASE_STACK (solver->import); RELEASE_STACK (solver->eliminated); RELEASE_STACK (solver->extend); RELEASE_STACK (solver->witness); RELEASE_STACK (solver->etrail); RELEASE_STACK (solver->delayed); RELEASE_STACK (solver->clause); RELEASE_STACK (solver->shadow); #if defined(LOGGING) || !defined(NDEBUG) RELEASE_STACK (solver->resolvent); #endif RELEASE_STACK (solver->arena); RELEASE_STACK (solver->units); RELEASE_STACK (solver->frames); RELEASE_STACK (solver->sorter); RELEASE_ARRAY (solver->trail, solver->size); RELEASE_STACK (solver->analyzed); RELEASE_STACK (solver->levels); RELEASE_STACK (solver->minimize); RELEASE_STACK (solver->poisoned); RELEASE_STACK (solver->promote); RELEASE_STACK (solver->removable); RELEASE_STACK (solver->shrinkable); RELEASE_STACK (solver->xorted[0]); RELEASE_STACK (solver->xorted[1]); RELEASE_STACK (solver->sweep_schedule); RELEASE_STACK (solver->ranks); RELEASE_STACK (solver->antecedents[0]); RELEASE_STACK (solver->antecedents[1]); RELEASE_STACK (solver->gates[0]); RELEASE_STACK (solver->gates[1]); RELEASE_STACK (solver->resolvents); #if !defined(NDEBUG) || !defined(NPROOFS) RELEASE_STACK (solver->added); RELEASE_STACK (solver->removed); #endif #if !defined(NDEBUG) || !defined(NPROOFS) || defined(LOGGING) RELEASE_STACK (solver->original); #endif #ifndef QUIET RELEASE_STACK (solver->profiles.stack); #endif #ifndef NDEBUG kissat_release_checker (solver); #endif #if !defined(NDEBUG) && defined(METRICS) uint64_t leaked = solver->statistics.allocated_current; if (leaked) if (!getenv ("LEAK")) kissat_fatal ("internally leaking %" PRIu64 " bytes", leaked); #endif kissat_free (0, solver, sizeof *solver); }
|
|
数据成员unflushed记录trail0层的文字数 相关操作: //trail.c
//inlineassign.h 1 static inline void kissat_assign (kissat *solver, const bool probing, 2 const unsigned level, 3 #ifdef FAST_ASSIGN 4 value *values, assigned *assigned, 5 #endif 6 bool binary, unsigned lit, 7 unsigned reason) { 8 const unsigned not_lit = NOT (lit); 9 10 watches watches = WATCHES (not_lit); 11 if (!kissat_empty_vector (&watches)) { 12 watch *w = BEGIN_WATCHES (watches); 13 __builtin_prefetch (w, 0, 1); 14 } 15 16 #ifndef FAST_ASSIGN 17 value *values = solver->values; 18 #endif 19 assert (!values[lit]); 20 assert (!values[not_lit]); 21 22 values[lit] = 1; 23 values[not_lit] = -1; 24 25 assert (solver->unassigned > 0); 26 solver->unassigned--; 27 28 if (!level) { //0层 29 kissat_mark_fixed_literal (solver, lit); 30 assert (solver->unflushed < UINT_MAX); 31 solver->unflushed++; 32 if (reason != UNIT_REASON) { 33 CHECK_AND_ADD_UNIT (lit); 34 ADD_UNIT_TO_PROOF (lit); 35 reason = UNIT_REASON; 36 binary = false; 37 } 38 } 39 40 const size_t trail = SIZE_ARRAY (solver->trail); 41 PUSH_ARRAY (solver->trail, lit); 42 43 const unsigned idx = IDX (lit); 44 45 #if !defined(PROBING_PROPAGATION) 46 if (!probing) { 47 const bool negated = NEGATED (lit); 48 const value new_value = BOOL_TO_VALUE (negated); 49 value *saved = &SAVED (idx); 50 *saved = new_value; 51 } 52 #endif 53 54 struct assigned b; 55 56 b.level = level; 57 b.trail = trail; 58 59 b.analyzed = false; 60 b.binary = binary; 61 b.poisoned = false; 62 b.reason = reason; 63 b.removable = false; 64 b.shrinkable = false; 65 66 #ifndef FAST_ASSIGN 67 assigned *assigned = solver->assigned; 68 #endif 69 struct assigned *a = assigned + idx; 70 *a = b; 71 }
关于单元文字在trail中如何标识可以查询下面相关标识名,从相应文件中分析。 unflushed kissat_fast_assign kissat_flush_trail kissat_update_conflicts_and_trail
另查询:CHECK_AND_ADD_UNIT
//flags.h typedef struct flags flags; struct flags { bool active : 1; bool backbone0 : 1; bool backbone1 : 1; bool eliminate : 1; bool eliminated : 1; unsigned factor : 2; bool fixed : 1; bool subsume : 1; bool sweep : 1; bool transitive : 1; }; //flags.c //0层的元素单独进行mark void kissat_mark_fixed_literal (kissat *solver, unsigned lit) { assert (VALUE (lit) > 0); const unsigned idx = IDX (lit); LOG ("marking internal %s as fixed", LOGVAR (idx)); flags *f = FLAGS (idx); assert (f->active); assert (!f->eliminated); assert (!f->fixed); f->fixed = true; deactivate_variable (solver, f, idx); INC (units); int elit = kissat_export_literal (solver, lit); assert (elit); PUSH_STACK (solver->units, elit); LOG ("pushed external unit literal %d (internal %u)", elit, lit); }
|
|
//checker.c中定义了两个类型,还有大量涉及Hash操作的内容。以下是该文件第50~125行的内容: 1 #include "allocate.h" 2 #include "inline.h" 3 #include "sort.h" 4 5 typedef struct hash hash; 6 typedef struct bucket bucket; 7 8 // clang-format off 9 10 typedef STACK (bucket*) buckets; 11 12 // clang-format on 13 14 struct bucket { 15 bucket *next; 16 unsigned size; 17 unsigned hash; 18 unsigned lits[]; 19 }; 20 21 struct checker { 22 bool inconsistent; 23 24 unsigned vars; 25 unsigned size; 26 27 unsigned buckets; 28 unsigned hashed; 29 30 bucket **table; 31 32 buckets *watches; 33 bool *marks; 34 bool *large; 35 bool *used; 36 signed char *values; 37 38 bool marked; 39 unsigneds imported; 40 41 unsigneds trail; 42 unsigned propagated; 43 44 unsigned nonces[32]; 45 46 uint64_t added; 47 uint64_t blocked; 48 uint64_t checked; 49 uint64_t collisions; 50 uint64_t decisions; 51 uint64_t propagations; 52 uint64_t pure; 53 uint64_t removed; 54 uint64_t satisfied; 55 uint64_t searches; 56 uint64_t unchecked; 57 }; 58 59 #define LOGIMPORTED3(...) \ 60 LOGUNSIGNEDS3 (SIZE_STACK (checker->imported), \ 61 BEGIN_STACK (checker->imported), __VA_ARGS__) 62 63 #define LOGLINE3(...) \ 64 LOGUNSIGNEDS3 (bucket->size, bucket->lits, __VA_ARGS__) 65 66 #define MAX_NONCES (sizeof checker->nonces / sizeof *checker->nonces) 67 68 static inline bool less_unsigned (unsigned a, unsigned b) { return a < b; } 69 70 static void sort_line (kissat *solver, checker *checker) { 71 SORT_STACK (unsigned, checker->imported, less_unsigned); 72 LOGIMPORTED3 ("sorted checker"); 73 }
|
|
2.kissat求解器常用的宏定义:
//internal.hpp | |
#define VARS (solver->vars) #if 0 #define SCORES (&solver->scores)
#define all_variables(IDX) \ #define all_literals(LIT) \ #define all_clauses(C) \ #define capacity_last_learned \ #define real_end_last_learned (solver->last_learned + capacity_last_learned) #define really_all_last_learned(REF_PTR) \ |
|
顺便复习宏定义的较晦涩的用法: define中的三个特殊符号:#,##,#@
(1)x##y表示什么?表示x连接y,举例说:
(2)再来看#@x,其实就是给x加上单引号,结果返回是一个const char。举例说:
char a = ToChar(1);结果就是a='1';
做个越界试验char a = ToChar(123);结果就错了; 但是如果你的参数超过四个字符,编译器就给给你报错了! error C2015: too many characters in constant :P
(3)#x,给x加双引号 char* str = ToString(123132);就成了str="123132"; |
|
//inlineassign.h #ifdef FAST_ASSIGN |
|
//statatic.h中关于宏定义的使用真是叹为观止——居然可以用来定义结构体的数据成员。以下是从第308行开始节选了部分代码。 ......
上面代码节选中COUNTER是该文件中之前给出的另一个宏定义: #define STATISTIC COUNTER 在预定判别条件下宏定义之间互相通用:
宏定义METRICS_COUNTERS_AND_STATISTICS给出在类型statistics的数据成员。!!! #define METRICS_COUNTERS_AND_STATISTICS \ \ METRIC (allocated_collected, 2, PCNT_RESIDENT_SET, "%", "resident set") \ METRIC (allocated_current, 2, PCNT_RESIDENT_SET, "%", "resident set") \ METRIC (allocated_max, 2, PCNT_RESIDENT_SET, "%", "resident set") \ STATISTIC (ands_eliminated, 1, PCNT_ELIMINATED, "%", "eliminated") \ METRIC (ands_extracted, 1, PCNT_EXTRACTED, "%", "extracted") \ METRIC (arena_enlarged, 1, PCNT_ARENA_RESIZED, "%", "resize") \ METRIC (arena_garbage, 1, PCNT_RESIDENT_SET, "%", "resident set") \ METRIC (arena_resized, 1, CONF_INT, "", "interval") \ METRIC (arena_shrunken, 1, PCNT_ARENA_RESIZED, "%", "resize") \ COUNTER (backbone_computations, 2, CONF_INT, "", "interval") \ METRIC (backbone_implied, 1, PER_BACKBONE_UNIT, 0, "per unit") \ METRIC (backbone_probes, 2, PER_VARIABLE, "", "per variable") \ METRIC (backbone_propagations, 2, PCNT_PROPS, "%", "propagations") \ METRIC (backbone_rounds, 2, PER_BACKBONE, 0, "per backbone") \ COUNTER (backbone_ticks, 2, PCNT_TICKS, "%", "ticks") \ STATISTIC (backbone_units, 1, PCNT_VARIABLES, "%", "variables") \ METRIC (best_saved, 1, CONF_INT, "", "interval") \ COUNTER (chronological, 1, PCNT_CONFLICTS, "%", "conflicts") \ COUNTER (clauses_added, 2, PCNT_CLS_ADDED, "%", "added") \ COUNTER (clauses_binary, 2, PCNT_CLS_ADDED, "%", "added") \ STATISTIC (clauses_deleted, 1, PCNT_CLS_ADDED, "%", "added") \ STATISTIC (clauses_factored, 1, PCNT_CLS_ADDED, "%", "added") \ STATISTIC (clauses_improved, 1, PCNT_CLS_LEARNED, "%", "learned") \ COUNTER (clauses_irredundant, 2, PCNT_CLS_ADDED, "%", "added") \ STATISTIC (clauses_kept1, 1, PCNT_CLS_IMPROVED, "%", "improved") \ STATISTIC (clauses_kept2, 1, PCNT_CLS_IMPROVED, "%", "improved") \ STATISTIC (clauses_kept3, 1, PCNT_CLS_IMPROVED, "%", "improved") \ COUNTER (clauses_learned, 2, PCNT_CONFLICTS, "%", "conflicts") \ COUNTER (clauses_original, 2, PCNT_CLS_ADDED, "%", "added") \ STATISTIC (clauses_promoted1, 1, PCNT_CLS_IMPROVED, "%", "improved") \ STATISTIC (clauses_promoted2, 1, PCNT_CLS_IMPROVED, "%", "improved") \ STATISTIC (clauses_reduced, 1, PCNT_CLS_LEARNED, "%", "learned") \ STATISTIC (clauses_reduced_tier1, 1, PCNT_CLS_REDUCED, "%", "reduced") \ STATISTIC (clauses_reduced_tier2, 1, PCNT_CLS_REDUCED, "%", "reduced") \ STATISTIC (clauses_reduced_tier3, 1, PCNT_CLS_REDUCED, "%", "reduced") \ COUNTER (clauses_redundant, 2, NO_SECONDARY, 0, 0) \ STATISTIC (clauses_unfactored, 1, PCNT_CLS_FACTORED, "%", "factored") \ COUNTER (clauses_used, 2, PCNT_CLS_LEARNED, "%", "learned") \ COUNTER (clauses_used_focused, 2, PCNT_CLS_USED, "%", "used") \ COUNTER (clauses_used_stable, 2, PCNT_CLS_USED, "%", "used") \ COUNTER (closures, 2, CONF_INT, "", "interval") \ METRIC (compacted, 1, PCNT_REDUCTIONS, "%", "reductions") \ COUNTER (conflicts, 0, PER_SECOND, 0, "per second") \ COUNTER (congruent, 1, PCNT_VARIABLES, "%", "variables") \ STATISTIC (congruent_ands, 1, PCNT_CONGRUENT, "%", "congruent") \ STATISTIC (congruent_arity, 1, PER_CONGRGATES, 0, "per gate") \ STATISTIC (congruent_arity_ands, 1, PER_CONGRANDS, 0, "per AND") \ STATISTIC (congruent_arity_xors, 1, PER_CONGRXORS, 0, "per XOR") \ STATISTIC (congruent_binaries, 1, PCNT_CLS_ADDED, "%", "clauses added") \ STATISTIC (congruent_ites, 1, PCNT_CONGRUENT, "%", "congruent") \ STATISTIC (congruent_collisions, 1, PER_CONGRLOOKUP, 0, "per lookup") \ STATISTIC (congruent_collisions_find, 1, PCNT_CONGRCOLS, "%", "collisions") \ STATISTIC (congruent_collisions_index, 1, PCNT_CONGRCOLS, "%", "collisions") \ STATISTIC (congruent_collisions_removed, 1, PCNT_CONGRCOLS, "%", "collisions") \ STATISTIC (congruent_equivalences, 1, PCNT_CONGRUENT, "%", "congruent") \ COUNTER (congruent_gates, 2, PER_CLOSURE, 0, "per closure") \ COUNTER (congruent_gates_ands, 2, PCNT_CONGRGATES, "%", "gates") \ COUNTER (congruent_gates_ites, 2, PCNT_CONGRGATES, "%", "gates") \ COUNTER (congruent_gates_xors, 2, PCNT_CONGRGATES, "%", "gates") \ STATISTIC (congruent_indexed, 1, PER_CONGRGATES, 0, "per gate") \ STATISTIC (congruent_lookups, 1, PER_CONGRGATES, 0, "per gate") \ STATISTIC (congruent_lookups_find, 1, PCNT_CONGRLOOKUP, "%", "lookups") \ STATISTIC (congruent_lookups_removed, 1, PCNT_CONGRLOOKUP, "%", "lookups") \ COUNTER (congruent_matched, 2, PCNT_CONGRUENT, "%", "congruent") \ COUNTER (congruent_matched_ands, 2, PCNT_CONGRMATCHED, "%", "matched") \ COUNTER (congruent_matched_ites, 2, PCNT_CONGRMATCHED, "%", "matched") \ COUNTER (congruent_matched_xors, 2, PCNT_CONGRMATCHED, "%", "matched") \ STATISTIC (congruent_rewritten, 1, PCNT_CONGRGATES, "%", "gates") \ STATISTIC (congruent_rewritten_ands, 1, PCNT_CONGREWR, "%", "rewritten") \ STATISTIC (congruent_rewritten_ites, 1, PCNT_CONGREWR, "%", "rewritten") \ STATISTIC (congruent_rewritten_xors, 1, PCNT_CONGREWR, "%", "rewritten") \ STATISTIC (congruent_simplified, 1, PCNT_CONGRGATES, "%", "gates") \ STATISTIC (congruent_simplified_ands, 1, PCNT_CONGRSIMPS, "%", "simplified") \ STATISTIC (congruent_simplified_ites, 1, PCNT_CONGRSIMPS, "%", "simplified") \ STATISTIC (congruent_simplified_xors, 1, PCNT_CONGRSIMPS, "%", "simplified") \ STATISTIC (congruent_subsumed, 1, PCNT_CLS_ORIGINAL, "%", "original") \ STATISTIC (congruent_trivial_ite, 1, PCNT_CONGRUENT, "%", "congruent") \ STATISTIC (congruent_unary, 1, PCNT_CONGRUENT, "%", "congruent") \ STATISTIC (congruent_unary_ands, 1, PCNT_CONGRUNARY, "%", "unary") \ STATISTIC (congruent_unary_ites, 1, PCNT_CONGRUNARY, "%", "unary") \ STATISTIC (congruent_unary_xors, 1, PCNT_CONGRUNARY, "%", "unary") \ STATISTIC (congruent_units, 1, PCNT_VARIABLES, "%", "variables") \ STATISTIC (congruent_xors, 1, PCNT_CONGRUENT, "%", "congruent") \ COUNTER (decisions, 0, PER_CONFLICT, 0, "per conflict") \ METRIC (definitions_checked, 1, PCNT_ELIM_ATTEMPTS, "%", "attempts") \ STATISTIC (definitions_eliminated, 1, PCNT_ELIMINATED, "%", "eliminated") \ METRIC (definitions_extracted, 1, PCNT_EXTRACTED, "%", "extracted") \ STATISTIC (definition_units, 1, PCNT_VARIABLES, "%", "variables") \ METRIC (defragmentations, 1, CONF_INT, "", "interval") \ METRIC (dense_garbage_collections, 2, PCNT_COLLECTIONS, "%", "collections") \ METRIC (dense_propagations, 1, PCNT_PROPS, "%", "propagations") \ METRIC (dense_ticks, 1, PCNT_TICKS, "%", "ticks") \ METRIC (duplicated, 1, PCNT_CLS_ADDED, "%", "added") \ STATISTIC (eagerly_subsumed, 1, PCNT_CLS_LEARNED, "%", "learned") \ STATISTIC (eliminate_attempted, 1, PER_VARIABLE, 0, "per variable") \ COUNTER (eliminated, 1, PCNT_VARIABLES, "%", "variables") \ COUNTER (eliminate_resolutions, 2, PER_SECOND, 0, "per second") \ STATISTIC (eliminate_units, 1, PCNT_VARIABLES, "%", "variables") \ COUNTER (eliminations, 2, CONF_INT, "", "interval") \ STATISTIC (equivalences_eliminated, 1, PCNT_ELIMINATED, "%", "eliminated") \ METRIC (equivalences_extracted, 1, PCNT_EXTRACTED, "%", "extracted") \ METRIC (extensions, 1, PCNT_SEARCHES, "%", "searches") \ COUNTER (factored, 1, PCNT_VARIABLES, "%", "variables") \ COUNTER (factorizations, 2, CONF_INT, "", "interval") \ COUNTER (factor_ticks, 2, PCNT_TICKS, "%", "ticks") \ COUNTER (fast_eliminated, 1, PCNT_ELIMINATED, "%", "eliminated") \ COUNTER (fast_strengthened, 1, PCNT_STRENGTHENED, "%", "per strengthened") \ COUNTER (fast_subsumed, 1, PCNT_SUBSUMED, "%", "per subsumed") \ STATISTIC (fresh, 1, PCNT_VARIABLES, "%", "variables") \ STATISTIC (flipped, 1, PER_WALKS, 0, "per walk") \ METRIC (flushed, 2, PER_FIXED, 0, "per fixed") \ METRIC (focused_decisions, 1, PCNT_DECISIONS, "%", "decisions") \ METRIC (focused_modes, 1, CONF_INT, "", "interval") \ METRIC (focused_propagations, 1, PCNT_PROPS, "%", "propagations") \ METRIC (focused_restarts, 1, PCNT_RESTARTS, "%", "restarts") \ METRIC (focused_ticks, 1, PCNT_TICKS, "%", "ticks") \ COUNTER (forward_checks, 2, NO_SECONDARY, 0, 0) \ COUNTER (forward_steps, 2, PER_FORWARD_CHECK, 0, "per check") \ STATISTIC (forward_strengthened, 1, PCNT_STRENGTHENED, "%", "per strengthened") \ STATISTIC (forward_subsumed, 1, PCNT_SUBSUMED, "%", "per subsumed") \ METRIC (forward_subsumptions, 1, CONF_INT, "", "interval") \ METRIC (garbage_collections, 2, CONF_INT, "", "interval") \ METRIC (gates_checked, 1, PCNT_ELIM_ATTEMPTS, "%", "attempts") \ STATISTIC (gates_eliminated, 1, PCNT_ELIMINATED, "%", "eliminated") \ METRIC (gates_extracted, 1, PCNT_ELIM_ATTEMPTS, "%", "attempts") \ STATISTIC (if_then_else_eliminated, 1, PCNT_ELIMINATED, "%", "eliminated") \ METRIC (if_then_else_extracted, 1, PCNT_EXTRACTED, "%", "extracted") \ METRIC (initial_decisions, 1, PCNT_DECISIONS, "%", "decisions") \ COUNTER (iterations, 1, PCNT_VARIABLES, "%", "variables") \ STATISTIC (jumped_reasons, 1, PCNT_PROPS, "%", "propagations") \ STATISTIC (kitten_conflicts, 1, PER_KITTEN_SOLVED, 0, "per solved") \ STATISTIC (kitten_decisions, 1, PER_KITTEN_SOLVED, 0, "per solved") \ STATISTIC (kitten_flip, 1, NO_SECONDARY, 0, 0) \ STATISTIC (kitten_flipped, 1, PCNT_KITTEN_FLIP, "%", "flip") \ COUNTER (kitten_propagations, 2, PER_KITTEN_SOLVED, 0, "per solved") \ STATISTIC (kitten_sat, 1, PCNT_KITTEN_SOLVED, "%", "solved") \ COUNTER (kitten_solved, 2, NO_SECONDARY, 0, 0) \ COUNTER (kitten_ticks, 2, PER_KITTEN_PROP, 0, "per prop") \ STATISTIC (kitten_unknown, 1, PCNT_KITTEN_SOLVED, "%", "solved") \ STATISTIC (kitten_unsat, 1, PCNT_KITTEN_SOLVED, "%", "solved") \ METRIC (literals_bumped, 1, PER_CLS_LEARNED, 0, "per clause") \ METRIC (literals_deduced, 1, PER_CLS_LEARNED, 0, "per clause") \ COUNTER (literals_factor, 2, PER_VARIABLE, 0, "per variable") \ STATISTIC (literals_factored, 1, PER_CLS_FACTORED, 0, "per factored") \ METRIC (literals_learned, 1, PER_CLS_LEARNED, 0, "per clause") \ METRIC (literals_minimized, 1, PCNT_LITS_DEDUCED, "%", "deduced") \ METRIC (literals_minshrunken, 1, PCNT_LITS_SHRUNKEN, "%", "shrunken") \ METRIC (literals_shrunken, 1, PCNT_LITS_DEDUCED, "%", "deduced") \ STATISTIC (literals_unfactored, 2, PER_CLS_UNFACTORED, 0, "per unfactored") \ METRIC (moved, 1, PCNT_REDUCTIONS, "%", "reductions") \ STATISTIC (on_the_fly_strengthened, 1, PCNT_CONFLICTS, "%", "of conflicts") \ STATISTIC (on_the_fly_subsumed, 1, PCNT_CONFLICTS, "%", "of conflicts") \ METRIC (probing_propagations, 1, PCNT_PROPS, "%", "propagations") \ COUNTER (probings, 2, CONF_INT, "", "interval") \ COUNTER (probing_ticks, 2, PCNT_TICKS, "%", "ticks") \ COUNTER (propagations, 0, PER_SECOND, "", "per second") \ STATISTIC (queue_decisions, 1, PCNT_DECISIONS, "%", "decision") \ STATISTIC (random_decisions, 1, PCNT_DECISIONS, "%", "decision") \ COUNTER (random_sequences, 2, CONF_INT, "", "interval") \ COUNTER (reductions, 1, CONF_INT, "", "interval") \ COUNTER (reordered, 1, CONF_INT, "", "interval") \ STATISTIC (reordered_focused, 1, PCNT_REORDERED, "%", "reordered") \ STATISTIC (reordered_stable, 1, PCNT_REORDERED, "%", "reordered") \ COUNTER (rephased, 1, CONF_INT, "", "interval") \ METRIC (rephased_best, 1, PCNT_REPHASED, "%", "rephased") \ METRIC (rephased_inverted, 1, PCNT_REPHASED, "%", "rephased") \ METRIC (rephased_original, 1, PCNT_REPHASED, "%", "rephased") \ METRIC (rephased_walking, 1, PCNT_REPHASED, "%", "rephased") \ METRIC (rescaled, 2, CONF_INT, "", "interval") \ COUNTER (restarts, 1, CONF_INT, "", "interval") \ STATISTIC (restarts_levels, 1, PER_RESTART, 0, "per restart") \ STATISTIC (restarts_reused_levels, 1, PCNT_RESTARTS_LEVELS, "%", "levels") \ STATISTIC (restarts_reused_trails, 1, PCNT_RESTARTS, "%", "restarts") \ COUNTER (retiered, 2, CONF_INT, "", "interval") \ METRIC (saved_decisions, 1, PCNT_DECISIONS, "%", "decisions") \ METRIC (score_decisions, 0, PCNT_DECISIONS, "%", "decision") \ COUNTER (searches, 2, CONF_INT, "", "interval") \ METRIC (search_propagations, 2, PCNT_PROPS, "%", "propagations") \ COUNTER (search_ticks, 2, PCNT_TICKS, "%", "ticks") \ METRIC (sparse_gcs, 2, PCNT_COLLECTIONS, "%", "collections") \ METRIC (stable_decisions, 1, PCNT_DECISIONS, "%", "decisions") \ METRIC (stable_modes, 2, CONF_INT, "", "interval") \ METRIC (stable_propagations, 1, PCNT_PROPS, "%", "propagations") \ METRIC (stable_restarts, 1, PCNT_RESTARTS, "%", "restarts") \ METRIC (stable_ticks, 2, PCNT_TICKS, "%", "ticks") \ COUNTER (strengthened, 1, PCNT_SUBSUMPTION_CHECK, "%", "checks") \ COUNTER (substituted, 1, PCNT_VARIABLES, "%", "variables") \ COUNTER (substitute_ticks, 2, PCNT_TICKS, "%", "ticks") \ STATISTIC (substitute_units, 1, PCNT_VARIABLES, "%", "variables") \ STATISTIC (substitutions, 2, CONF_INT, "", "interval") \ COUNTER (subsumed, 1, PCNT_SUBSUMPTION_CHECK, "%", "checks") \ COUNTER (subsumption_checks, 2, NO_SECONDARY, 0, 0) \ COUNTER (sweep, 2, CONF_INT, "", "interval") \ STATISTIC (sweep_clauses, 1, PER_SWEEP_VARIABLES, 0, "per sweep_variables") \ COUNTER (sweep_completed, 2, SWEEPS_PER_COMPLETED, 0, "sweeps") \ STATISTIC (sweep_depth, 1, PER_SWEEP_VARIABLES, 0, "per sweep_variables") \ STATISTIC (sweep_environment, 1, PER_SWEEP_VARIABLES, 0, "per sweep_variables") \ COUNTER (sweep_equivalences, 2, PCNT_VARIABLES, "%", "variables") \ STATISTIC (sweep_fixed_backbone, 1, PER_SWEEP_VARIABLES, 0, "per sweep_variables") \ STATISTIC (sweep_flip_backbone, 1, PER_SWEEP_VARIABLES, 0, "per sweep_variables") \ STATISTIC (sweep_flipped_backbone, 1, PCNT_SWEEP_FLIP_BACKBONE, "%", "sweep_flip_backbone") \ STATISTIC (sweep_flip_equivalences, 1, PER_SWEEP_VARIABLES, 0, "per sweep_variables") \ STATISTIC (sweep_flipped_equivalences, 1, PCNT_SWEEP_FLIP_EQUIVALENCES, "%", "sweep_flip_equivalences") \ STATISTIC (sweep_sat, 1, PCNT_SWEEP_SOLVED, "%", "sweep_solved") \ STATISTIC (sweep_sat_backbone, 1, PCNT_SWEEP_SOLVED_BACKBONE, "%", "sweep_solved_backbone") \ STATISTIC (sweep_sat_equivalences, 1, PCNT_SWEEP_SOLVED_EQUIVALENCES, "%", "sweep_solved_equivalences") \ COUNTER (sweep_solved, 2, PCNT_KITTEN_SOLVED, "%", "kitten_solved") \ STATISTIC (sweep_solved_backbone, 1, PCNT_SWEEP_SOLVED, "%", "sweep_solved") \ STATISTIC (sweep_solved_equivalences, 1, PCNT_SWEEP_SOLVED, "%", "sweep_solved") \ STATISTIC (sweep_unknown_backbone, 1, PCNT_SWEEP_SOLVED_BACKBONE, "%", "sweep_solved_backbone") \ STATISTIC (sweep_unknown_equivalences, 1, PCNT_SWEEP_SOLVED_EQUIVALENCES, "%", "sweep_solved_equivalences") \ COUNTER (sweep_units, 2, PCNT_VARIABLES, "%", "variables") \ STATISTIC (sweep_unsat, 1, PCNT_SWEEP_SOLVED, "%", "sweep_solved") \ STATISTIC (sweep_unsat_backbone, 1, PCNT_SWEEP_SOLVED_BACKBONE, "%", "sweep_solve_backbone") \ STATISTIC (sweep_unsat_equivalences, 1, PCNT_SWEEP_SOLVED_EQUIVALENCES, "%", "sweep_solve_equivalences") \ STATISTIC (sweep_variables, 1, PCNT_VARIABLES, "%", "variables") \ COUNTER (switched, 0, CONF_INT, "", "interval") \ METRIC (target_decisions, 1, PCNT_DECISIONS, "%", "decisions") \ METRIC (target_saved, 1, CONF_INT, "", "interval") \ STATISTIC (ticks, 2, PER_PROPAGATION, 0, "per prop") \ METRIC (transitive_probes, 2, PER_VARIABLE, "", "per variable") \ METRIC (transitive_propagations, 2, PCNT_PROPS, "%", "propagations") \ METRIC (transitive_reduced, 1, PCNT_CLS_ADDED, "%", "added") \ METRIC (transitive_reductions, 1, CONF_INT, "", "interval") \ COUNTER (transitive_ticks, 2, PCNT_TICKS, "%", "ticks") \ METRIC (transitive_units, 1, PCNT_VARIABLES, "%", "variables") \ COUNTER (units, 2, PCNT_VARIABLES, "%", "variables") \ COUNTER (variables_activated, 2, PER_VARIABLE, 0, "per variable") \ COUNTER (variables_eliminate, 2, PER_VARIABLE, 0, "variables") \ COUNTER (variables_extension, 2, PER_VARIABLE, 0, "per variable") \ COUNTER (variables_factor, 2, PER_VARIABLE, 0, "per variable") \ COUNTER (variables_original, 2, PER_VARIABLE, 0, "per variable") \ COUNTER (variables_subsume, 2, PER_VARIABLE, 0, "per variable") \ METRIC (vectors_defrags_needed, 1, PCNT_DEFRAGS, "%", "defrags") \ METRIC (vectors_enlarged, 2, CONF_INT, "", "interval") \ COUNTER (vivifications, 2, CONF_INT, "", "interval") \ COUNTER (vivified, 1, PCNT_VIVIFY_CHECK, "%", "checks") \ STATISTIC (vivified_asym, 1, PCNT_VIVIFIED, "%", "vivified") \ STATISTIC (vivified_implied, 1, PCNT_VIVIFIED, "%", "vivified") \ STATISTIC (vivified_instantiated, 1, PCNT_VIVIFIED, "%", "vivified") \ STATISTIC (vivified_instirr, 1, PCNT_VIVIFY_INST, "%", "instantiated") \ STATISTIC (vivified_instred, 1, PCNT_VIVIFY_INST, "%", "instantiated") \ STATISTIC (vivified_irredundant, 1, PCNT_VIVIFIED, "%", "vivified") \ STATISTIC (vivified_promoted, 1, PCNT_VIVIFIED, "%", "vivified") \ STATISTIC (vivified_shrunken, 1, PCNT_VIVIFIED, "%", "vivified") \ STATISTIC (vivified_shrunkirr, 1, PCNT_VIVIFY_SHRUNKEN, "%", "shrunken") \ STATISTIC (vivified_shrunkred, 1, PCNT_VIVIFY_SHRUNKEN, "%", "shrunken") \ STATISTIC (vivified_subirr, 1, PCNT_VIVIFY_SUB, "%", "subsumed") \ STATISTIC (vivified_subred, 1, PCNT_VIVIFY_SUB, "%", "subsumed") \ STATISTIC (vivified_subsumed, 1, PCNT_VIVIFIED, "%", "vivified") \ STATISTIC (vivified_tier1, 1, PCNT_VIVIFIED, "%", "vivified") \ STATISTIC (vivified_tier2, 1, PCNT_VIVIFIED, "%", "vivified") \ STATISTIC (vivified_tier3, 1, PCNT_VIVIFIED, "%", "vivified") \ STATISTIC (vivified_unlearn, 1, PCNT_VIVIFIED, "%", "vivified") \ COUNTER (vivify_checks, 2, PER_VIVIFICATION, "", "per vivify") \ COUNTER (vivify_probes, 2, PER_VIVIFY_CHECK, 0, "per check") \ STATISTIC (vivify_propagations, 2, PCNT_PROPS, "%", "propagations") \ COUNTER (vivify_reused, 2, PCNT_VIVIFY_PROBES, "%", "probes") \ STATISTIC (vivify_ticks, 2, PCNT_TICKS, "%", "ticks") \ STATISTIC (vivify_units, 1, PCNT_VARIABLES, "%", "variables") \ METRIC (walk_decisions, 1, PCNT_WALKS, "%", "walks") \ STATISTIC (walk_improved, 1, PCNT_WALKS, "%", "walks") \ METRIC (walk_previous, 1, PCNT_WALKS, "%", "walks") \ COUNTER (walks, 1, CONF_INT, "", "interval") \ COUNTER (walk_steps, 2, PER_FLIPPED, 0, "per flipped") \ STATISTIC (warming_conflicts, 1, PER_WALKS, 0, "per walk") \ COUNTER (warming_decisions, 2, PER_WALKS, 0, "per walk") \ COUNTER (warming_propagations, 2, PCNT_PROPS, "%", "propagations") \ COUNTER (warmups, 2, PCNT_WALKS, "%", "walks") \ METRIC (weakened, 1, PCNT_CLS_ADDED, "%", "added") // clang-format on
|
|
3.主函数中调用kissat类型指针solver的函数及其相关函数:
//internal.hpp
//inlineassign.h
|
|
与文字对应的属性设置相关的数据结构:可以从以下函数中进行分析学习。 //inline.h 1 static inline void kissat_push_analyzed (kissat *solver, assigned *assigned, 2 unsigned idx) { 3 assert (idx < VARS); 4 struct assigned *a = assigned + idx; 5 assert (!a->analyzed); 6 a->analyzed = true; 7 PUSH_STACK (solver->analyzed, idx); 8 LOG2 ("%s analyzed", LOGVAR (idx)); 9 } 1 static inline void 2 kissat_push_removable (kissat *solver, assigned *assigned, unsigned idx) { 3 assert (idx < VARS); 4 struct assigned *a = assigned + idx; 5 assert (!a->removable); 6 a->removable = true; 7 PUSH_STACK (solver->removable, idx); 8 LOG2 ("%s removable", LOGVAR (idx)); 9 } 1 static inline void kissat_push_poisoned (kissat *solver, assigned *assigned, 2 unsigned idx) { 3 assert (idx < VARS); 4 struct assigned *a = assigned + idx; 5 assert (!a->poisoned); 6 a->poisoned = true; 7 PUSH_STACK (solver->poisoned, idx); 8 LOG2 ("%s poisoned", LOGVAR (idx)); 9 } static inline void kissat_push_shrinkable (kissat *solver, assigned *assigned, unsigned idx) { assert (idx < VARS); struct assigned *a = assigned + idx; assert (!a->shrinkable); a->shrinkable = true; PUSH_STACK (solver->shrinkable, idx); LOG2 ("%s shrinkable", LOGVAR (idx)); }
已知文字后获得对应的观察序列 const unsigned not_lit = NOT (lit); watches watches = WATCHES (not_lit);
|
|
子句的类型声明: struct clause { unsigned glue : LD_MAX_GLUE; bool garbage : 1; bool quotient : 1; bool reason : 1; bool redundant : 1; bool shrunken : 1; bool subsume : 1; bool swept : 1; bool vivify : 1; unsigned used : LD_MAX_USED; unsigned searched; unsigned size; unsigned lits[3]; };
从子句的构造来看,Kissat求解器的子句分为三类: original;irredundant; redundant; 1 reference kissat_new_original_clause (kissat *solver) { 2 const unsigned size = SIZE_STACK (solver->clause); 3 unsigned *lits = BEGIN_STACK (solver->clause); 4 kissat_sort_literals (solver, size, lits); 5 reference res = new_clause (solver, true, false, 0, size, lits); 6 return res; 7 } 8 9 reference kissat_new_irredundant_clause (kissat *solver) { 10 const unsigned size = SIZE_STACK (solver->clause); 11 unsigned *lits = BEGIN_STACK (solver->clause); 12 return new_clause (solver, false, false, 0, size, lits); 13 } 14 15 reference kissat_new_redundant_clause (kissat *solver, unsigned glue) { 16 const unsigned size = SIZE_STACK (solver->clause); 17 unsigned *lits = BEGIN_STACK (solver->clause); 18 return new_clause (solver, false, true, glue, size, lits); 19 }
1 static reference new_clause (kissat *solver, bool original, bool redundant, 2 unsigned glue, unsigned size, unsigned *lits) { 3 reference res; 4 if (size == 2) 5 res = new_binary_clause (solver, original, true, lits[0], lits[1]); 6 else 7 res = new_large_clause (solver, original, redundant, glue, size, lits); 8 kissat_defrag_watches_if_needed (solver); 9 return res; 10 }
1 static void inc_clause (kissat *solver, bool original, bool redundant, 2 bool binary) { 3 if (binary) 4 INC (clauses_binary); 5 else if (redundant) 6 INC (clauses_redundant); 7 else 8 INC (clauses_irredundant); 9 INC (clauses_added); 10 if (original) 11 INC (clauses_original); 12 } 13 14 static void dec_clause (kissat *solver, bool redundant, bool binary) { 15 if (binary) 16 DEC (clauses_binary); 17 else if (redundant) 18 DEC (clauses_redundant); 19 else 20 DEC (clauses_irredundant); 21 }
|
|
4. 相关CDCL模块的学习
4.1 决策变元选择机制
从重启模块reuse中学习相关代码可知:维护了两个活跃度,scores堆和links链表;它们对应两种决策变元选择机制: solver->stable focused_decisions //另有决策机制,后续了解。见decide.c solver->warming solver->randec
//restart.c static unsigned reuse_stable_trail (kissat *solver) { const heap *const scores = SCORES; const unsigned next_idx = kissat_next_decision_variable (solver); const double limit = kissat_get_heap_score (scores, next_idx); unsigned level = solver->level, res = 0; while (res < level) { frame *f = &FRAME (res + 1); const unsigned idx = IDX (f->decision); const double score = kissat_get_heap_score (scores, idx); if (score <= limit) break; res++; } return res; } static unsigned reuse_focused_trail (kissat *solver) { const links *const links = solver->links; const unsigned next_idx = kissat_next_decision_variable (solver); const unsigned limit = links[next_idx].stamp; LOG ("next decision variable stamp %u", limit); unsigned level = solver->level, res = 0; while (res < level) { frame *f = &FRAME (res + 1); const unsigned idx = IDX (f->decision); const unsigned score = links[idx].stamp; if (score <= limit) break; res++; } return res; }
//从决策变元选择相关代码学习: 决策变元相关信息被专门保留在 frames中;——与决策变元相关的技术是否需要重点研究分析? #ifndef _frames_h_INCLUDED #define _frames_h_INCLUDED #include "literal.h" #include "stack.h" #include <stdbool.h> typedef struct frame frame; typedef struct slice slice; struct frame { bool promote; unsigned decision; unsigned trail; unsigned used; #ifndef NDEBUG unsigned saved; #endif }; // clang-format off typedef STACK (frame) frames; // clang-format on struct kissat; #define FRAME(LEVEL) (PEEK_STACK (solver->frames, (LEVEL))) #endif
//inlineframe.h static inline void kissat_push_frame (kissat *solver, unsigned decision) { assert (!solver->level || decision != UINT_MAX); const size_t trail = SIZE_ARRAY (solver->trail); frame frame; frame.decision = decision; frame.promote = false; frame.trail = trail; frame.used = 0; PUSH_STACK (solver->frames, frame); }
//决策变元选择机制的体现代码 //decide.c unsigned kissat_next_decision_variable (kissat *solver) { #ifdef LOGGING const char *type = 0; #endif unsigned res = next_random_decision (solver); if (res == INVALID_IDX) { if (solver->stable) { #ifdef LOGGING type = "maximum score"; #endif res = largest_score_unassigned_variable (solver); INC (score_decisions); } else { #ifdef LOGGING type = "dequeued"; #endif res = last_enqueued_unassigned_variable (solver); INC (queue_decisions); } } else { #ifdef LOGGING type = "random"; #endif INC (random_decisions); } LOG ("next %s decision %s", type, LOGVAR (res)); return res; }
//决策变元的赋值过程 //search.c int kissat_search (kissat *solver) { REPORT (0, '*'); int res = 0; if (solver->inconsistent) res = 20; if (!res && GET_OPTION (luckyearly)) res = kissat_lucky (solver); if (!res && kissat_preprocessing (solver)) res = kissat_preprocess (solver); if (!res && GET_OPTION (luckylate)) res = kissat_lucky (solver); if (!res) kissat_classify (solver); if (!res && searching (solver)) { start_search (solver); while (!res) { clause *conflict = kissat_search_propagate (solver); if (conflict) res = kissat_analyze (solver, conflict); else if (solver->iterating) iterate (solver); else if (!solver->unassigned) res = 10; else if (TERMINATED (search_terminated_1)) break; else if (kissat_reducing (solver)) res = kissat_reduce (solver); else if (kissat_switching_search_mode (solver)) kissat_switch_search_mode (solver); else if (kissat_restarting (solver)) kissat_restart (solver); else if (kissat_reordering (solver)) kissat_reorder (solver); else if (kissat_rephasing (solver)) kissat_rephase (solver); else if (kissat_probing (solver)) res = kissat_probe (solver); else if (kissat_eliminating (solver)) res = kissat_eliminate (solver); else if (conflict_limit_hit (solver)) break; else if (decision_limit_hit (solver)) break; else kissat_decide (solver); } stop_search (solver); } report_search_result (solver, res); return res; }
//decide.c void kissat_decide (kissat *solver) { START (decide); assert (solver->unassigned); if (solver->warming) INC (warming_decisions); else { INC (decisions); if (solver->stable) INC (stable_decisions); else INC (focused_decisions); } solver->level++; assert (solver->level != INVALID_LEVEL); const unsigned idx = kissat_next_decision_variable (solver); //决策变元选择机制被使用 const value value = kissat_decide_phase (solver, idx); unsigned lit = LIT (idx); if (value < 0) lit = NOT (lit); kissat_push_frame (solver, lit); assert (solver->level < SIZE_STACK (solver->frames)); LOG ("decide literal %s", LOGLIT (lit)); kissat_assign_decision (solver, lit); STOP (decide); } void kissat_internal_assume (kissat *solver, unsigned lit) { assert (solver->unassigned); assert (!VALUE (lit)); solver->level++; assert (solver->level != INVALID_LEVEL); kissat_push_frame (solver, lit); assert (solver->level < SIZE_STACK (solver->frames)); LOG ("assuming literal %s", LOGLIT (lit)); kissat_assign_decision (solver, lit); }
//assign.c void kissat_assign_decision (kissat *solver, unsigned lit) { kissat_assign (solver, solver->probing, solver->level, false, lit, DECISION_REASON); LOG ("assign %s decision", LOGLIT (lit)); }
//inlineassign.h
|
|
4.2 相位选择机制
//decide.c void kissat_decide (kissat *solver) { START (decide); assert (solver->unassigned); if (solver->warming) INC (warming_decisions); else { INC (decisions); if (solver->stable) INC (stable_decisions); else INC (focused_decisions); } solver->level++; assert (solver->level != INVALID_LEVEL); const unsigned idx = kissat_next_decision_variable (solver); const value value = kissat_decide_phase (solver, idx); unsigned lit = LIT (idx); if (value < 0) lit = NOT (lit); kissat_push_frame (solver, lit); assert (solver->level < SIZE_STACK (solver->frames)); LOG ("decide literal %s", LOGLIT (lit)); kissat_assign_decision (solver, lit); STOP (decide); }
//decide.c int kissat_decide_phase (kissat *solver, unsigned idx) { bool force = GET_OPTION (forcephase); value *target; if (force) target = 0; else if (!GET_OPTION (target)) target = 0; else if (solver->stable || GET_OPTION (target) > 1) target = solver->phases.target + idx; else target = 0; value *saved; if (force) saved = 0; else if (GET_OPTION (phasesaving)) saved = solver->phases.saved + idx; else saved = 0; value res = 0; if (!solver->stable) { switch ((solver->statistics.switched >> 1) & 7) { case 1: res = INITIAL_PHASE; break; case 3: res = -INITIAL_PHASE; break; } } if (!res && target && (res = *target)) { LOG ("%s uses target decision phase %d", LOGVAR (idx), (int) res); INC (target_decisions); } if (!res && saved && (res = *saved)) { LOG ("%s uses saved decision phase %d", LOGVAR (idx), (int) res); INC (saved_decisions); } if (!res) { res = INITIAL_PHASE; LOG ("%s uses initial decision phase %d", LOGVAR (idx), (int) res); INC (initial_decisions); } assert (res); return res < 0 ? -1 : 1; }
|
|
4.3 布尔约束传播模块
确定传播文字均在solver->trail中; 有三类文字: 0层的单元文字 各层决策文字 蕴涵传播的文字
//传播调用过程: //search.c
//propsearch.c
//propsearch.c
#define PROPAGATE_LITERAL search_propagate_literal
// porplit.h static inline clause *PROPAGATE_LITERAL (kissat *solver, #if defined(PROBING_PROPAGATION) const clause *const ignore, #endif const unsigned lit) { assert (solver->watching); LOG (PROPAGATION_TYPE " propagating %s", LOGLIT (lit)); assert (VALUE (lit) > 0); assert (EMPTY_STACK (solver->delayed)); watches *const all_watches = solver->watches; ward *const arena = BEGIN_STACK (solver->arena); assigned *const assigned = solver->assigned; value *const values = solver->values; const unsigned not_lit = NOT (lit); assert (not_lit < LITS); watches *watches = all_watches + not_lit; watch *const begin_watches = BEGIN_WATCHES (*watches); const watch *const end_watches = END_WATCHES (*watches); watch *q = begin_watches; const watch *p = q; unsigneds *const delayed = &solver->delayed; assert (EMPTY_STACK (*delayed)); const size_t size_watches = SIZE_WATCHES (*watches); uint64_t ticks = 1 + kissat_cache_lines (size_watches, sizeof (watch)); const unsigned idx = IDX (lit); struct assigned *const a = assigned + idx; const bool probing = solver->probing; const unsigned level = a->level; clause *res = 0; while (p != end_watches) { const watch head = *q++ = *p++; const unsigned blocking = head.blocking.lit; assert (VALID_INTERNAL_LITERAL (blocking)); const value blocking_value = values[blocking]; const bool binary = head.type.binary; watch tail; if (!binary) tail = *q++ = *p++; if (blocking_value > 0) continue; if (binary) { if (blocking_value < 0) { res = kissat_binary_conflict (solver, not_lit, blocking); #ifndef CONTINUE_PROPAGATING_AFTER_CONFLICT break; #endif } else { assert (!blocking_value); kissat_fast_binary_assign (solver, probing, level, values, assigned, blocking, not_lit); ticks++; } } else { const reference ref = tail.raw; assert (ref < SIZE_STACK (solver->arena)); clause *const c = (clause *) (arena + ref); ticks++; if (c->garbage) { q -= 2; continue; } unsigned *const lits = BEGIN_LITS (c); const unsigned other = lits[0] ^ lits[1] ^ not_lit; assert (lits[0] != lits[1]); assert (VALID_INTERNAL_LITERAL (other)); assert (not_lit != other); assert (lit != other); const value other_value = values[other]; if (other_value > 0) { q[-2].blocking.lit = other; continue; } const unsigned *const end_lits = lits + c->size; unsigned *const searched = lits + c->searched; assert (c->lits + 2 <= searched); assert (searched < end_lits); unsigned *r, replacement = INVALID_LIT; value replacement_value = -1; for (r = searched; r != end_lits; r++) { replacement = *r; assert (VALID_INTERNAL_LITERAL (replacement)); replacement_value = values[replacement]; if (replacement_value >= 0) break; } if (replacement_value < 0) { for (r = lits + 2; r != searched; r++) { replacement = *r; assert (VALID_INTERNAL_LITERAL (replacement)); replacement_value = values[replacement]; if (replacement_value >= 0) break; } } if (replacement_value >= 0) { c->searched = r - lits; assert (replacement != INVALID_LIT); LOGREF3 (ref, "unwatching %s in", LOGLIT (not_lit)); q -= 2; lits[0] = other; lits[1] = replacement; assert (lits[0] != lits[1]); *r = not_lit; kissat_delay_watching_large (solver, delayed, replacement, other, ref); ticks++; } else if (other_value) { assert (replacement_value < 0); assert (blocking_value < 0); assert (other_value < 0); #if defined(PROBING_PROPAGATION) if (c == ignore) { LOGREF (ref, "conflicting but ignored"); continue; } #endif LOGREF (ref, "conflicting"); res = c; #ifndef CONTINUE_PROPAGATING_AFTER_CONFLICT break; #endif } else { assert (replacement_value < 0); #if defined(PROBING_PROPAGATION) if (c == ignore) { LOGREF (ref, "forcing %s but ignored", LOGLIT (other)); continue; } #endif kissat_fast_assign_reference (solver, values, assigned, other, ref, c); ticks++; } } } solver->ticks += ticks; while (p != end_watches) *q++ = *p++; SET_END_OF_WATCHES (*watches, q); kissat_watch_large_delayed (solver, all_watches, delayed); return res; }
//fastassign.h static inline void kissat_fast_binary_assign ( kissat *solver, const bool probing, const unsigned level, value *values, assigned *assigned, unsigned lit, unsigned other) { if (GET_OPTION (jumpreasons) && level && solver->classification.bigbig) { unsigned other_idx = IDX (other); struct assigned *a = assigned + other_idx; if (a->binary) { LOGBINARY (lit, other, "jumping %s reason", LOGLIT (lit)); INC (jumped_reasons); other = a->reason; } } kissat_fast_assign (solver, probing, level, values, assigned, true, lit, other); LOGBINARY (lit, other, "assign %s reason", LOGLIT (lit)); } static inline void kissat_fast_assign_reference (kissat *solver, value *values, assigned *assigned, unsigned lit, reference ref, clause *reason) { assert (reason == kissat_dereference_clause (solver, ref)); const unsigned level = kissat_assignment_level (solver, values, assigned, lit, reason); assert (level <= solver->level); assert (ref != DECISION_REASON); assert (ref != UNIT_REASON); kissat_fast_assign (solver, solver->probing, level, values, assigned, false, lit, ref); LOGREF (ref, "assign %s reason", LOGLIT (lit)); }
最总落实到函数 #ifdef FAST_ASSIGN #define kissat_assign kissat_fast_assign #endif static inline void kissat_assign (kissat *solver, const bool probing, const unsigned level, #ifdef FAST_ASSIGN value *values, assigned *assigned, #endif bool binary, unsigned lit, unsigned reason) { const unsigned not_lit = NOT (lit); watches watches = WATCHES (not_lit); if (!kissat_empty_vector (&watches)) { watch *w = BEGIN_WATCHES (watches); __builtin_prefetch (w, 0, 1); } #ifndef FAST_ASSIGN value *values = solver->values; #endif assert (!values[lit]); assert (!values[not_lit]); values[lit] = 1; values[not_lit] = -1; assert (solver->unassigned > 0); solver->unassigned--; if (!level) { kissat_mark_fixed_literal (solver, lit); assert (solver->unflushed < UINT_MAX); solver->unflushed++; if (reason != UNIT_REASON) { CHECK_AND_ADD_UNIT (lit); ADD_UNIT_TO_PROOF (lit); reason = UNIT_REASON; binary = false; } } const size_t trail = SIZE_ARRAY (solver->trail); PUSH_ARRAY (solver->trail, lit); const unsigned idx = IDX (lit); #if !defined(PROBING_PROPAGATION) if (!probing) { const bool negated = NEGATED (lit); const value new_value = BOOL_TO_VALUE (negated); value *saved = &SAVED (idx); *saved = new_value; } #endif struct assigned b; b.level = level; b.trail = trail; b.analyzed = false; b.binary = binary; b.poisoned = false; b.reason = reason; b.removable = false; b.shrinkable = false; #ifndef FAST_ASSIGN assigned *assigned = solver->assigned; #endif struct assigned *a = assigned + idx; *a = b; } static inline unsigned kissat_assignment_level (kissat *solver, value *values, assigned *assigned, unsigned lit, clause *reason) { unsigned res = 0; for (all_literals_in_clause (other, reason)) { if (other == lit) continue; assert (values[other] < 0), (void) values; const unsigned other_idx = IDX (other); struct assigned *a = assigned + other_idx; const unsigned level = a->level; if (res < level) res = level; } #ifdef NDEBUG (void) solver; #endif return res; }
由于BCP是用时最多的模块,单独将与传播有关inline函数保存在一个文件中,见inline.h inline.h
|
|
4.智能回退模块
5.重启机制模块
//触发重启的判别//restart.c bool kissat_restarting (kissat *solver) { assert (solver->unassigned); if (!GET_OPTION (restart)) return false; if (!solver->level) return false; if (CONFLICTS < solver->limits.restart.conflicts) return false; if (solver->stable) return kissat_reluctant_triggered (&solver->reluctant); const double fast = AVERAGE (fast_glue); const double slow = AVERAGE (slow_glue); const double margin = (100.0 + GET_OPTION (restartmargin)) / 100.0; const double limit = margin * slow; kissat_extremely_verbose (solver, "restart glue limit %g = " "%.02f * %g (slow glue) %c %g (fast glue)", limit, margin, slow, (limit > fast ? '>' : limit == fast ? '=' : '<'), fast); return (limit <= fast); }
//重启的策略(1)CONFLICTS < solver->limits.restart.conflicts limit的更新在前一次重启实现时进行更新; (2)reluctant.h中定义的reluctant_triggered触发 kissat_reluctant_triggered (&solver->reluctant);
1 #ifndef _reluctant_h_INCLUDED 2 #define _reluctant_h_INCLUDED 3 4 #include <stdbool.h> 5 #include <stdint.h> 6 7 typedef struct reluctant reluctant; 8 9 struct reluctant { 10 bool limited; 11 bool trigger; 12 uint64_t period; 13 uint64_t wait; 14 uint64_t u, v; 15 uint64_t limit; 16 }; 17 18 void kissat_enable_reluctant (reluctant *, uint64_t period, uint64_t limit); 19 void kissat_disable_reluctant (reluctant *); 20 void kissat_tick_reluctant (reluctant *); 21 22 static inline bool kissat_reluctant_triggered (reluctant *reluctant) { 23 if (!reluctant->trigger) 24 return false; 25 reluctant->trigger = false; 26 return true; 27 } 28 29 struct kissat; 30 31 void kissat_init_reluctant (struct kissat *); 32 33 #endif 1 #include "internal.h" 2 #include "logging.h" 3 4 void kissat_enable_reluctant (reluctant *reluctant, uint64_t period, 5 uint64_t limit) { 6 if (limit && period > limit) 7 period = limit; 8 reluctant->limited = (limit > 0); 9 reluctant->trigger = false; 10 reluctant->period = period; 11 reluctant->wait = period; 12 reluctant->u = reluctant->v = 1; 13 reluctant->limit = limit; 14 } 15 16 void kissat_disable_reluctant (reluctant *reluctant) { 17 reluctant->period = 0; 18 } 19 20 void kissat_tick_reluctant (reluctant *reluctant) { 21 if (!reluctant->period) 22 return; 23 24 if (reluctant->trigger) 25 return; 26 27 assert (reluctant->wait > 0); 28 if (--reluctant->wait) 29 return; 30 31 uint64_t u = reluctant->u; 32 uint64_t v = reluctant->v; 33 34 if ((u & -u) == v) { 35 u++; 36 v = 1; 37 } else { 38 assert (UINT64_MAX / 2 >= v); 39 v *= 2; 40 } 41 42 assert (v); 43 assert (UINT64_MAX / v >= reluctant->period); 44 uint64_t wait = v * reluctant->period; 45 46 if (reluctant->limited && wait > reluctant->limit) { 47 u = v = 1; 48 wait = reluctant->period; 49 } 50 51 reluctant->trigger = true; 52 reluctant->wait = wait; 53 reluctant->u = u; 54 reluctant->v = v; 55 } 56 57 void kissat_init_reluctant (kissat *solver) { 58 if (GET_OPTION (reluctant)) { 59 LOG ("enable reluctant doubling with period %d limit %d", 60 GET_OPTION (reluctantint), GET_OPTION (reluctantlim)); 61 kissat_enable_reluctant (&solver->reluctant, GET_OPTION (reluctantint), 62 GET_OPTION (reluctantlim)); 63 } else { 64 LOG ("reluctant doubling disabled and thus no stable restarts"); 65 kissat_disable_reluctant (&solver->reluctant); 66 } 67 }
(3) 学习子句LBD值移动平均的短期和长期的模型 见上述代码的部分:最下部分 由(limit <= fast)确定是否触发。
//重启都干了什么?(1)unsigned level = reuse_trail (solver); (2)kissat_backtrack_in_consistent_state (solver, level); (3)关于下次重启界限的更新 if (!solver->stable) //先看关于下次重启界限的更新 //restart.c void kissat_update_focused_restart_limit (kissat *solver) { assert (!solver->stable); limits *limits = &solver->limits; uint64_t restarts = solver->statistics.restarts; uint64_t delta = GET_OPTION (restartint); if (restarts) delta += kissat_logn (restarts) - 1; limits->restart.conflicts = CONFLICTS + delta; kissat_extremely_verbose (solver, "focused restart limit at %" PRIu64 " after %" PRIu64 " conflicts ", limits->restart.conflicts, delta); } //回溯到0还是复用一部分 1 static unsigned reuse_stable_trail (kissat *solver) { 2 const heap *const scores = SCORES; 3 const unsigned next_idx = kissat_next_decision_variable (solver); 4 const double limit = kissat_get_heap_score (scores, next_idx); 5 unsigned level = solver->level, res = 0; 6 while (res < level) { 7 frame *f = &FRAME (res + 1); 8 const unsigned idx = IDX (f->decision); 9 const double score = kissat_get_heap_score (scores, idx); 10 if (score <= limit) 11 break; 12 res++; 13 } 14 return res; 15 } 16 17 static unsigned reuse_focused_trail (kissat *solver) { 18 const links *const links = solver->links; 19 const unsigned next_idx = kissat_next_decision_variable (solver); 20 const unsigned limit = links[next_idx].stamp; 21 LOG ("next decision variable stamp %u", limit); 22 unsigned level = solver->level, res = 0; 23 while (res < level) { 24 frame *f = &FRAME (res + 1); 25 const unsigned idx = IDX (f->decision); 26 const unsigned score = links[idx].stamp; 27 if (score <= limit) 28 break; 29 res++; 30 } 31 return res; 32 } 33 34 static unsigned reuse_trail (kissat *solver) { 35 assert (solver->level); 36 assert (!EMPTY_STACK (solver->trail)); 37 38 if (!GET_OPTION (restartreusetrail)) 39 return 0; 40 41 unsigned res; 42 43 if (solver->stable) 44 res = reuse_stable_trail (solver); 45 else 46 res = reuse_focused_trail (solver); 47 48 LOG ("matching trail level %u", res); 49 50 if (res) { 51 INC (restarts_reused_trails); 52 ADD (restarts_reused_levels, res); 53 LOG ("restart reuses trail at decision level %u", res); 54 } else 55 LOG ("restarts does not reuse the trail"); 56 57 return res; 58 }
//回溯的实施 1 //restart.c 2 3 void kissat_restart (kissat *solver) { 4 START (restart); 5 INC (restarts); 6 ADD (restarts_levels, solver->level); 7 if (solver->stable) 8 INC (stable_restarts); 9 else 10 INC (focused_restarts); 11 12 13 unsigned level = reuse_trail (solver); 14 kissat_extremely_verbose (solver, 15 "restarting after %" PRIu64 " conflicts" 16 " (limit %" PRIu64 ")", 17 CONFLICTS, solver->limits.restart.conflicts); 18 LOG ("restarting to level %u", level); 19 kissat_backtrack_in_consistent_state (solver, level); 20 21 22 if (!solver->stable) 23 kissat_update_focused_restart_limit (solver); 24 REPORT (1, 'R'); 25 STOP (restart); 26 }
//backtrack.h 1 //backtrack.c 2 3 void kissat_backtrack_without_updating_phases (kissat *solver, 4 unsigned new_level) { 5 assert (solver->level >= new_level); 6 if (solver->level == new_level) 7 return; 8 9 LOG ("backtracking to decision level %u", new_level); 10 11 frame *new_frame = &FRAME (new_level + 1); 12 SET_END_OF_STACK (solver->frames, new_frame); 13 14 value *values = solver->values; 15 unsigned *trail = BEGIN_ARRAY (solver->trail); 16 unsigned *new_end = trail + new_frame->trail; 17 assigned *assigned = solver->assigned; 18 19 unsigned *old_end = END_ARRAY (solver->trail); 20 unsigned unassigned = 0, reassigned = 0; 21 22 unsigned *q = new_end; 23 if (solver->stable) { 24 heap *scores = SCORES; 25 for (const unsigned *p = q; p != old_end; p++) { 26 const unsigned lit = *p; 27 const unsigned idx = IDX (lit); 28 assert (idx < VARS); 29 struct assigned *a = assigned + idx; 30 const unsigned level = a->level; 31 if (level <= new_level) { 32 const unsigned new_trail = q - trail; 33 assert (new_trail <= a->trail); 34 a->trail = new_trail; 35 *q++ = lit; 36 LOG ("reassign %s", LOGLIT (lit)); 37 reassigned++; 38 } else { 39 unassign (solver, values, lit); 40 add_unassigned_variable_back_to_heap (solver, scores, lit); 41 unassigned++; 42 } 43 } 44 } else { 45 links *links = solver->links; 46 for (const unsigned *p = q; p != old_end; p++) { 47 const unsigned lit = *p; 48 const unsigned idx = IDX (lit); 49 assert (idx < VARS); 50 struct assigned *a = assigned + idx; 51 const unsigned level = a->level; 52 if (level <= new_level) { 53 const unsigned new_trail = q - trail; 54 assert (new_trail <= a->trail); 55 a->trail = new_trail; 56 *q++ = lit; 57 LOG ("reassign %s", LOGLIT (lit)); 58 reassigned++; 59 } else { 60 unassign (solver, values, lit); 61 add_unassigned_variable_back_to_queue (solver, links, lit); 62 unassigned++; 63 } 64 } 65 } 66 SET_END_OF_ARRAY (solver->trail, q); 67 68 solver->level = new_level; 69 LOG ("unassigned %u literals", unassigned); 70 LOG ("reassigned %u literals", reassigned); 71 (void) unassigned, (void) reassigned; 72 73 assert (new_end <= END_ARRAY (solver->trail)); 74 LOG ("propagation will resume at trail position %zu", 75 (size_t) (new_end - trail)); 76 solver->propagate = new_end; 77 78 assert (!solver->extended); 79 }
1 #include "backtrack.h" 2 #include "analyze.h" 3 #include "inline.h" 4 #include "inlineheap.h" 5 #include "inlinequeue.h" 6 #include "print.h" 7 #include "proprobe.h" 8 #include "propsearch.h" 9 #include "trail.h" 10 11 static inline void unassign (kissat *solver, value *values, unsigned lit) { 12 LOG ("unassign %s", LOGLIT (lit)); 13 assert (values[lit] > 0); 14 const unsigned not_lit = NOT (lit); 15 values[lit] = values[not_lit] = 0; 16 assert (solver->unassigned < VARS); 17 solver->unassigned++; 18 } 19 20 static inline void add_unassigned_variable_back_to_queue (kissat *solver, 21 links *links, 22 unsigned lit) { 23 assert (!solver->stable); 24 const unsigned idx = IDX (lit); 25 if (links[idx].stamp > solver->queue.search.stamp) 26 kissat_update_queue (solver, links, idx); 27 } 28 29 static inline void add_unassigned_variable_back_to_heap (kissat *solver, 30 heap *scores, 31 unsigned lit) { 32 assert (solver->stable); 33 const unsigned idx = IDX (lit); 34 if (!kissat_heap_contains (scores, idx)) 35 kissat_push_heap (solver, scores, idx); 36 } 37 38 static void kissat_update_target_and_best_phases (kissat *solver) { 39 if (solver->probing) 40 return; 41 42 if (!solver->stable) 43 return; 44 45 const unsigned assigned = kissat_assigned (solver); 46 #ifdef LOGGING 47 LOG ("updating target and best phases"); 48 LOG ("currently %u variables assigned", assigned); 49 #endif 50 51 if (solver->target_assigned < assigned) { 52 kissat_extremely_verbose (solver, 53 "updating target assigned " 54 "trail height from %u to %u", 55 solver->target_assigned, assigned); 56 solver->target_assigned = assigned; 57 kissat_save_target_phases (solver); 58 INC (target_saved); 59 } 60 61 if (solver->best_assigned < assigned) { 62 kissat_extremely_verbose (solver, 63 "updating best assigned " 64 "trail height from %u to %u", 65 solver->best_assigned, assigned); 66 solver->best_assigned = assigned; 67 kissat_save_best_phases (solver); 68 INC (best_saved); 69 } 70 } 71 72 void kissat_backtrack_without_updating_phases (kissat *solver, 73 unsigned new_level) { 74 assert (solver->level >= new_level); 75 if (solver->level == new_level) 76 return; 77 78 LOG ("backtracking to decision level %u", new_level); 79 80 frame *new_frame = &FRAME (new_level + 1); 81 SET_END_OF_STACK (solver->frames, new_frame); 82 83 value *values = solver->values; 84 unsigned *trail = BEGIN_ARRAY (solver->trail); 85 unsigned *new_end = trail + new_frame->trail; 86 assigned *assigned = solver->assigned; 87 88 unsigned *old_end = END_ARRAY (solver->trail); 89 unsigned unassigned = 0, reassigned = 0; 90 91 unsigned *q = new_end; 92 if (solver->stable) { 93 heap *scores = SCORES; 94 for (const unsigned *p = q; p != old_end; p++) { 95 const unsigned lit = *p; 96 const unsigned idx = IDX (lit); 97 assert (idx < VARS); 98 struct assigned *a = assigned + idx; 99 const unsigned level = a->level; 100 if (level <= new_level) { 101 const unsigned new_trail = q - trail; 102 assert (new_trail <= a->trail); 103 a->trail = new_trail; 104 *q++ = lit; 105 LOG ("reassign %s", LOGLIT (lit)); 106 reassigned++; 107 } else { 108 unassign (solver, values, lit); 109 add_unassigned_variable_back_to_heap (solver, scores, lit); 110 unassigned++; 111 } 112 } 113 } else { 114 links *links = solver->links; 115 for (const unsigned *p = q; p != old_end; p++) { 116 const unsigned lit = *p; 117 const unsigned idx = IDX (lit); 118 assert (idx < VARS); 119 struct assigned *a = assigned + idx; 120 const unsigned level = a->level; 121 if (level <= new_level) { 122 const unsigned new_trail = q - trail; 123 assert (new_trail <= a->trail); 124 a->trail = new_trail; 125 *q++ = lit; 126 LOG ("reassign %s", LOGLIT (lit)); 127 reassigned++; 128 } else { 129 unassign (solver, values, lit); 130 add_unassigned_variable_back_to_queue (solver, links, lit); 131 unassigned++; 132 } 133 } 134 } 135 SET_END_OF_ARRAY (solver->trail, q); 136 137 solver->level = new_level; 138 LOG ("unassigned %u literals", unassigned); 139 LOG ("reassigned %u literals", reassigned); 140 (void) unassigned, (void) reassigned; 141 142 assert (new_end <= END_ARRAY (solver->trail)); 143 LOG ("propagation will resume at trail position %zu", 144 (size_t) (new_end - trail)); 145 solver->propagate = new_end; 146 147 assert (!solver->extended); 148 } 149 150 void kissat_backtrack_in_consistent_state (kissat *solver, 151 unsigned new_level) { 152 kissat_update_target_and_best_phases (solver); 153 kissat_backtrack_without_updating_phases (solver, new_level); 154 } 155 156 void kissat_backtrack_after_conflict (kissat *solver, unsigned new_level) { 157 if (solver->level) 158 kissat_backtrack_without_updating_phases (solver, solver->level - 1); 159 kissat_update_target_and_best_phases (solver); 160 kissat_backtrack_without_updating_phases (solver, new_level); 161 } 162 163 void kissat_backtrack_propagate_and_flush_trail (kissat *solver) { 164 if (solver->level) { 165 assert (solver->watching); 166 kissat_backtrack_in_consistent_state (solver, 0); 167 #ifndef NDEBUG 168 clause *conflict = 169 #endif 170 solver->probing ? kissat_probing_propagate (solver, 0, true) 171 : kissat_search_propagate (solver); 172 assert (!conflict); 173 } 174 175 assert (kissat_propagated (solver)); 176 assert (kissat_trail_flushed (solver)); 177 }
|
|
6.冲突分析模块
// 冲突分析的主代码段 1 int kissat_analyze (kissat *solver, clause *conflict) { 2 if (solver->inconsistent) { 3 assert (!solver->level); 4 return 20; 5 } 6 7 START (analyze); 8 if (!solver->probing) { 9 update_trail_average (solver); 10 update_decision_rate_average (solver); 11 #ifndef QUIET 12 UPDATE_AVERAGE (level, solver->level); 13 #endif 14 } 15 int res; 16 do { 17 LOGCLS (conflict, "analyzing conflict %" PRIu64, CONFLICTS); 18 unsigned conflict_level; 19 if (one_literal_on_conflict_level (solver, conflict, &conflict_level)) 20 res = 1; 21 else if (!conflict_level) 22 res = -1; 23 else if (conflict_level == 1) { 24 analyze_failed_literal (solver, conflict); 25 res = 1; 26 } else if ((conflict = 27 kissat_deduce_first_uip_clause (solver, conflict))) { 28 reset_analysis_but_not_analyzed_literals (solver); 29 INC (conflicts); 30 if (CONFLICTS > solver->limits.glue.conflicts) 31 update_tier_limits (solver); 32 res = 0; // And continue with new conflict analysis. 33 } else { 34 if (GET_OPTION (minimize)) { 35 sort_deduced_clause (solver); 36 kissat_minimize_clause (solver); 37 if (GET_OPTION (shrink)) 38 kissat_shrink_clause (solver); 39 } 40 analyze_reason_side_literals (solver); 41 kissat_learn_clause (solver); 42 reset_analysis_but_not_analyzed_literals (solver); 43 res = 1; 44 } 45 if (!EMPTY_STACK (solver->analyzed)) { 46 if (!solver->probing && GET_OPTION (bump)) 47 kissat_bump_analyzed (solver); 48 kissat_reset_only_analyzed_literals (solver); 49 } 50 } while (!res); 51 STOP (analyze); 52 return res > 0 ? 0 : 20; 53 } //分5部分理解。其中第四第五可以连起来分析。
// 红色标出的循环体,主要目的是找到1-UIP,其中需要记录的信息可以从两个清除函数了解: reset_analysis_but_not_analyzed_literals (solver); kissat_reset_only_analyzed_literals (solver); |
|
7. 子句管理(删除模块)
//reduce.c | |
//相关数据结构
|
|
//核心函数-排序之后进行拟删除子句的选择。
1 static bool collect_reducibles (kissat *solver, reducibles *reds, 2 reference start_ref) { 3 assert (start_ref != INVALID_REF); 4 assert (start_ref <= SIZE_STACK (solver->arena)); 5 ward *const arena = BEGIN_STACK (solver->arena); 6 clause *start = (clause *) (arena + start_ref); 7 const clause *const end = (clause *) END_STACK (solver->arena); 8 assert (start < end); 9 while (start != end && !start->redundant) 10 start = kissat_next_clause (start); 11 if (start == end) { 12 solver->first_reducible = INVALID_REF; 13 LOG ("no reducible clause candidate left"); 14 return false; 15 } 16 const reference redundant = (ward *) start - arena; 17 #ifdef LOGGING 18 if (redundant < solver->first_reducible) 19 LOG ("updating start of redundant clauses from %zu to %zu", 20 (size_t) solver->first_reducible, (size_t) redundant); 21 else 22 LOG ("no update to start of redundant clauses %zu", 23 (size_t) solver->first_reducible); 24 #endif 25 solver->first_reducible = redundant; 26 const unsigned tier1 = TIER1; 27 const unsigned tier2 = MAX (tier1, TIER2); 28 assert (tier1 <= tier2); 29 for (clause *c = start; c != end; c = kissat_next_clause (c)) { 30 if (!c->redundant) 31 continue; 32 if (c->garbage) 33 continue; 34 const unsigned used = c->used; 35 if (used) 36 c->used = used - 1; 37 if (c->reason) 38 continue; 39 const unsigned glue = c->glue; 40 if (glue <= tier1 && used) 41 continue; 42 if (glue <= tier2 && used >= MAX_USED - 1) 43 continue; 44 assert (kissat_clause_in_arena (solver, c)); 45 reducible red; 46 const uint64_t negative_size = ~c->size; 47 const uint64_t negative_glue = ~c->glue; 48 red.rank = negative_size | (negative_glue << 32); 49 red.ref = (ward *) c - arena; 50 PUSH_STACK (*reds, red); 51 } 52 if (EMPTY_STACK (*reds)) { 53 kissat_phase (solver, "reduce", GET (reductions), 54 "did not find any reducible redundant clause"); 55 return false; 56 } 57 return true; 58 }
|
|
7.预处理模块
8.随机搜索模块
9.子求解器kitten模块
10.输入及assume模块
11.学习子句管理模块
12.随机行走模块
13.
14. kissat *solver常用数据访问代码整理;
watches *const all_watches = solver->watches; ward *const arena = BEGIN_STACK (solver->arena); assigned *const assigned = solver->assigned; value *const values = solver->values; const unsigned not_lit = NOT (lit);
//已知观察元cur_watcher,获取该观察元所对应子句 const reference ref = cur_watcher.raw; assert (ref < SIZE_STACK (solver->arena)); clause *const c = (clause *) (arena + ref);
//常用状态或进度指示量 // solver->inconsistent = true; //出现UNSAT情况 // const bool probing = solver->probing; // solver->level kissat_require_initialized (solver); } // unsigned seed = GET_OPTION (seed); solver->random = seed; LOG ("initialized random number generator with seed %u", seed); // frame *new_frame = &FRAME (new_level + 1);
static void dump_queue (kissat *solver) { //
void dump_map (kissat *solver) { const unsigned size = SIZE_STACK (solver->export); unsigned first = INVALID_LIT; for (unsigned idx = 0; idx < size; idx++) { const unsigned ilit = LIT (idx); const int elit = PEEK_STACK (solver->export, idx); printf ("map[%u] -> %d", ilit, elit); if (elit) { const unsigned eidx = ABS (elit); const import *const import = &PEEK_STACK (solver->import, eidx); if (import->eliminated) printf (" -> eliminated[%u]", import->lit); else { unsigned mlit = import->lit; if (elit < 0) mlit = NOT (mlit); printf (" -> %u", mlit); } } if (!LEVEL (ilit) && VALUE (ilit)) { if (first == INVALID_LIT) { first = ilit; printf (" #"); } else printf (" *"); } fputc ('\n', stdout); } }
|
|