Exponential Recency Weighted Average Branching Heuristic for SAT Solvers

Jia Hui Liang, Vijay Ganesh, Pascal Poupart,等. Exponential Recency Weighted Average Branching Heuristic for SAT Solvers[C]// Thirtieth Aaai Conference on Artificial Intelligence. AAAI Press, 2016.

 

conflict history-based branching heuristic (CHB)

 


Abstract

Modern conflict-driven clause-learning SAT solvers routinely solve large real-world instances with millions of clauses and variables in them. Their success crucially depends on effective branching heuristics. In this paper, we propose a new branching heuristic inspired by the exponential recency weighted average algorithm used to solve the bandit problem. The branching heuristic, we call CHB, learns online which variables to branch on by leveraging the feedback received from conflict analysis.译文:通过利用从冲突分析中得到的反馈,在线学习哪些变量可以进行分支。

 

We evaluated CHB on 1200 instances from the SAT Competition 2013 and 2014 instances, and showed that CHB solves significantly more instances than VSIDS, currently the most effective branching heuristic in widespread use.More precisely, we implemented CHB as part of the MiniSat and Glucose solvers, and performed an apple-to-apple comparison with their VSIDS-based variants. CHB-based MiniSat (resp. CHB-based Glucose) solved approximately 16.1% (resp. 5.6%) more instances than their VSIDS-based variants.

Additionally, CHB-based solvers are much more efficient at constructing first preimage attacks on step-reduced SHA-1 and MD5 cryptographic hash functions, than their VSIDS-based counterparts.译文:此外,基于chb的求解器在构造针对阶减SHA-1和MD5加密哈希函数的第一次原像攻击时,比基于vsid的求解器要高效得多。

 

To the best of our knowledge, CHB is the first branching heuristic to solve significantly more instances than VSIDS on a large, diverse benchmark of real-world instances.

Modern conflict-driven clause-learning SAT solvers routinely solve large real-world instances with millions of clauses and variables in them. Their success crucially depends on effective branching heuristics.

 my study notes

 

 
  1. Marques-Silva and Sakallah invented the CDCL technique (Marques-Silva and Sakallah 1999), 
  2. designing branching heuristics such as
    • DLIS (Marques-Silva 1999),
    • BerkMin (Goldberg and Novikov 2007), and Jeroslav-Wang (Jeroslow and Wang 1990),
    • the VSIDS branching heuristic and its variants remain( 2001)

                   remain as the most effective ones in widespread use today.

Lagoudakis and Littman took 7 well-known SAT
branching heuristics (MAXO, MOMS, MAMS, Jeroslaw-
Wang, UP, GUP, SUP) and used reinforcement learning to
switch between the heuristics dynamically during the run of
the solver (Lagoudakis and Littman 2001).

译文:
Lagoudakis和Littman采用了7个著名的SAT分支启发法(MAXO, MOMS, MAMS, Jeroslaw-)Wang, UP, GUP, SUP)和使用强化学习在求解器运行期间在启发式之间动态切换(Lagoudakis和Littman 2001)。译文:他们的技术需要对类似的实例进行离线培训。

Second, until very recently, little was understood as to why the VSIDS branching heuristic and its variants are so effective.译文:其次,直到最近,人们对为什么VSIDS分支启发式及其变体如此有效还知之甚少。

Inspired by the bandit framework and reinforcement learning, we learn to choose good variables to branch based on past experience. Our goal is to leverage the theory and practice of a rich sub-field of reinforcement learning to  plain and design an effective branching heuristic for solving real-world problems.

 译文:受到bandit框架和强化学习的启发,我们学会根据过去的经验选择好的变量进行分支。我们的目标是利用理论和实践的丰富子领域的强化学习,以平原和设计一个有效的分支启发式解决实际问题。

分支决策变元的选择包含强化学习的思想

 The branching heuristic proposed in this paper, CHB, is completely online and learns which variable to branch on

dynamically as the input instance is being solved. By online  we mean that the heuristic learns only during the olving
process, and there is no offline learning.

译文:本文提出的分支启发式CHB是完全在线的,并在求解输入实例时动态地学习在哪个变量上进行分支。线上是指启发式只在存活过程中学习,而不存在线下学习。

 

 Exponential Recency Weighted Average (ERWA)

 

 The CHB Branching Heuristic

 

 
 
 
 
 

Future Work

The connection between branching heuristics and reinforcement learning opens many new opportunities for future improvements to branching heuristics and SAT solving in general.译文:分支启发式和强化学习之间的联系为分支启发式和SAT解决的未来改进打开了许多新的机会。


We detail some of our future work below that builds on the foundation laid by this paper. 译文:在本文所奠定的基础上,我们将在下面详细说明我们未来的一些工作。

Modern CDCL SAT solvers maintain lots of state features such as the partial assignment, trail, learnt clause database, saved phases, etc. 译文:现代CDCL SAT求解器维护了许多状态特性,如部分赋值、跟踪、学习子句数据库、保存阶段等。

The technique proposed in this paper is based on the multi-armed bandit setting, and it can be extended to a full Markov decision process by conditioning the choice of variables on some  of the solvers’ state features. More research is needed to find a stateful model that works well in practice by balancing the trade-off between the gain in information due to states and the cost of increased model complexity.

 

We modeled our branching heuristic on ERWA, a technique used to solve the bandit problem. However, perhaps
a more powerful model will capture both the branching heuristic and clause learning.译文:我们在ERWA上建模了分支启发式,ERWA是一种用于解决强盗问题的技术。然而,也许更强大的模型将同时捕获分支启发式和子句学习

It is evident that the branching heuristic and clause learning drive each other, so a model capturing both aspects can lead to algorithms that not only choose better branching variables, but also learn higher quality clauses.译文:很明显,分支启发式和子句学习是相互推动的,因此,一个抓住这两个方面的模型,不仅能够选择更好的分支变量,而且能够学习更高质量的子句。

It is clear that such a model is outside the bandit framework, due to the additional feedback from clause learning to the branching heuristic in the form of learnt clauses. More work is needed to construct new models that include more aspects of CDCL such as clause learning.译文:很明显,这样的模型是在bandit框架之外的,因为从子句学习到以学习子句形式的分支启发式的额外反馈。需要做更多的工作来构建包含CDCL更多方面的新模型,比如子句学习。

 

代码解读

Jia Hui Liang老师2016年参加竞赛的求解器有两个主要革新:CHB和LRB。

CHB的思路是从冲突分析中得到的反馈,每个变元从参与决策、传播和冲突分析的历史(记录相应的时间节点——用当时的冲突次数标定时刻)信息中获得reward,基于activity_CHB的大小选择下一次分支决策变量;

LRB的思路与上述思想大致类似,所不同的是反馈的是边缘生存期参与冲突分析及构造学习字句的比例。

由于是同一个作者,在实现代码中,activity_CHB在不同的策略版本中分别代表两种活跃度。实际上LRB策略代码中应当使用activity_LRB,以免引起错觉和误会

 

CHB策略相关代码


 

solver.h中定义与CHB相关的量

double step_size;            //  alfa
int action;                       // 传播上一阶段的trail.size()
vec<uint32_t> conflicted;       //  记录每个变元
void updateQ(Var v, double multi);    //  辅助函数计算冲突发生时(或当前传播阶段结束)当前传播段中文字变元对应活跃度

重点看一下第48行congflicted的赋值------记录了变元
 
  1 void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, int& out_lbd)
  2 {
  3     int pathC = 0;
  4     Lit p     = lit_Undef;
  5 
  6     // Generate conflict clause:
  7     //
  8     out_learnt.push();      // (leave room for the asserting literal)
  9     int index   = trail.size() - 1;
 10 
 11     // Trying to reduce proof size.
 12     add_oc.clear();
 13     do{
 14         assert(confl != CRef_Undef); // (otherwise should be UIP)
 15         Clause& c = ca[confl];
 16 
 17         // For binary clauses, we don't rearrange literals in propagate(), so check and make sure the first is an implied lit.
 18         if (p != lit_Undef && c.size() == 2 && value(c[0]) == l_False){
 19             assert(value(c[1]) == l_True);
 20             Lit tmp = c[0];
 21             c[0] = c[1], c[1] = tmp; }
 22 
 23         bool migrate_bin = false;
 24         bool otf_simp = !drup_file || (c.size() < 10 && (!c.learnt() || c.mark() == CORE));
 25         for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){
 26             Lit q = c[j];
 27 
 28             if (otf_simp && j >= 2  // For now, should use only "premise_bin" if printing proof.
 29                   && ((!drup_file && (premise[toInt(~q)] == ~c[0] || premise[toInt(c[0])] == q
 30                                    || premise[toInt(~q)] == ~c[1] || premise[toInt(c[1])] == q))
 31                       || premise_bin[toInt(~q)] == ~c[0] || premise_bin[toInt(c[0])] == q
 32                       || premise_bin[toInt(~q)] == ~c[1] || premise_bin[toInt(c[1])] == q)){
 33                 if (drup_file && add_oc.size() == 0)
 34                     for (int k = 0; k < c.size(); k++)
 35                         add_oc.push(c[k]);
 36 
 37                 lit_elim++;
 38                 c[j--] = c.last();
 39                 c.shrink(1); // FIXME: fix (statistical) memory leak.
 40                 if (c.learnt()) learnts_literals--;
 41                 else            clauses_literals--;
 42 
 43                 if (c.size() == 2)
 44                     migrate_bin = true;
 45             }else if (!seen[var(q)] && level(var(q)) > 0){
 46                 varBumpActivity(var(q), .5);
 47                 add_tmp.push(q);
 48                 conflicted[var(q)] = conflicts;//此次冲突分析记录下变元参与冲突分析的时刻,用于下次冲突时计算间隔
 49                 seen[var(q)] = 1;
 50                 if (level(var(q)) >= decisionLevel()){
 51                     pathC++;
 52                 }else
 53                     out_learnt.push(q);
 54             }
 55         }
 56 
 57         if (drup_file && add_oc.size() != 0){
 58             drup('a', c, drup_file);
 59             drup('d', add_oc, drup_file);
 60             add_oc.clear(); }
 61 
 62         // Update LBD if improved.
 63         if (c.learnt() && c.mark() != CORE && !migrate_bin){
 64             int lbd = computeLBD(c);
 65             if (lbd < c.lbd()){
 66                 if (c.lbd() <= 30) c.removable(false); // Protect once from reduction.
 67                 c.set_lbd(lbd);
 68                 if (lbd <= core_lbd_cut){
 69                     learnts_core.push(confl);
 70                     c.mark(CORE);
 71                 }else if (lbd <= 6 && c.mark() == LOCAL){
 72                     // Bug: 'cr' may already be in 'learnts_tier2', e.g., if 'cr' was demoted from TIER2
 73                     // to LOCAL previously and if that 'cr' is not cleaned from 'learnts_tier2' yet.
 74                     learnts_tier2.push(confl);
 75                     c.mark(TIER2); }
 76             }
 77 
 78             if (c.mark() == TIER2)
 79                 c.touched() = conflicts;
 80             else if (c.mark() == LOCAL)
 81                 claBumpActivity(c);
 82         }
 83 
 84         if (migrate_bin){
 85             assert(c.size() == 2); assert(!c.learnt() || c.mark() == CORE);
 86             assert(p == lit_Undef || value(c[0]) == l_True);
 87 
 88             static vec<Lit> bin_tmp(2);
 89             bin_tmp[0] = c[0]; bin_tmp[1] = c[1];
 90 
 91             bool learnt = c.learnt();  // We need a copy, as 'alloc' may invalidate the 'c' reference.
 92             CRef cr = ca.alloc(bin_tmp, learnt);
 93             if (p != lit_Undef)
 94                 vardata[var(bin_tmp[0])].reason = cr;
 95 
 96             if (learnt){
 97                 learnts_core.push(cr);
 98                 ca[cr].mark(CORE);
 99                 ca[cr].set_lbd(1);
100             }else
101                 clauses.push(cr);
102             // attachClause(cr)
103             watches_bin[~bin_tmp[0]].push(Watcher(cr, bin_tmp[1]));
104             watches_bin[~bin_tmp[1]].push(Watcher(cr, bin_tmp[0]));
105             // removeClause(confl) without detachClause(confl)
106             ca[confl].mark(1);
107             ca.free(confl);
108             // detachClause(confl)
109             watches.smudge(~bin_tmp[0]);
110             watches.smudge(~bin_tmp[1]);
111         }
112 
113         // Select next clause to look at:
114         while (!seen[var(trail[index--])]);
115         p     = trail[index+1];
116         confl = reason(var(p));
117         seen[var(p)] = 0;
118         pathC--;
119 
120     }while (pathC > 0);
121     out_learnt[0] = ~p;
122 
123     // Simplify conflict clause:
124     //
125     int i, j;
126     out_learnt.copyTo(analyze_toclear);
127     if (ccmin_mode == 2){
128         uint32_t abstract_level = 0;
129         for (i = 1; i < out_learnt.size(); i++)
130             abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict)
131 
132         for (i = j = 1; i < out_learnt.size(); i++)
133             if (reason(var(out_learnt[i])) == CRef_Undef || !litRedundant(out_learnt[i], abstract_level))
134                 out_learnt[j++] = out_learnt[i];
135         
136     }else if (ccmin_mode == 1){
137         for (i = j = 1; i < out_learnt.size(); i++){
138             Var x = var(out_learnt[i]);
139 
140             if (reason(x) == CRef_Undef)
141                 out_learnt[j++] = out_learnt[i];
142             else{
143                 Clause& c = ca[reason(var(out_learnt[i]))];
144                 for (int k = c.size() == 2 ? 0 : 1; k < c.size(); k++)
145                     if (!seen[var(c[k])] && level(var(c[k])) > 0){
146                         out_learnt[j++] = out_learnt[i];
147                         break; }
148             }
149         }
150     }else
151         i = j = out_learnt.size();
152 
153     max_literals += out_learnt.size();
154     out_learnt.shrink(i - j);
155     tot_literals += out_learnt.size();
156 
157     out_lbd = computeLBD(out_learnt);
158     if (out_lbd <= 6 && out_learnt.size() <= 30) // Try further minimization?
159         if (binResMinimize(out_learnt))
160             out_lbd = computeLBD(out_learnt); // Recompute LBD if minimized.
161 
162     // Find correct backtrack level:
163     //
164     if (out_learnt.size() == 1)
165         out_btlevel = 0;
166     else{
167         int max_i = 1;
168         // Find the first literal assigned at the next-highest level:
169         for (int i = 2; i < out_learnt.size(); i++)
170             if (level(var(out_learnt[i])) > level(var(out_learnt[max_i])))
171                 max_i = i;
172         // Swap-in this literal at index 1:
173         Lit p             = out_learnt[max_i];
174         out_learnt[max_i] = out_learnt[1];
175         out_learnt[1]     = p;
176         out_btlevel       = level(var(p));
177     }
178 
179     for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0;    // ('seen[]' is now cleared)
180 
181     for (int i = 0; i < add_tmp.size(); i++){
182         Var v = var(add_tmp[i]);
183         if (level(v) >= out_btlevel - 1)
184             varBumpActivity(v, 1);
185     }
186     add_tmp.clear();
187 }

 

 action = trail.size();//求解器数据成员action记录的队列的长度,也是传播下一个阶段的开始位置。

 1 lbool Solver::search(int& nof_conflicts)
 2 {
 3     assert(ok);
 4     int         backtrack_level;
 5     int         lbd;
 6     vec<Lit>    learnt_clause;
 7     bool        cached = false;
 8     starts++;
 9 
10     action = trail.size();
11     bool otf_probing = !drup_file && conflicts >= 50000 && starts % 10 == 0;
12     for (;;){
13         CRef confl = propagate(otf_probing);
14 
15         for (int a = action; a < trail.size(); a++){
16             Var v = var(trail[a]);
17             updateQ(v, confl == CRef_Undef ? 0.9 : 1.0); }
18         //conflictAnalyze
19         。。。
20 }

搜索过程中,propagete函数一次调用结束(运行遇到冲突、或没有遇到冲突但没有可传播的子句),传播队列新传播的文字序列对应的变元获得活跃度回报值(由于冲突造成传播终止时,multi为1,非冲突造成传播终止时,multi略低,为0.9.

 
 1 void Solver::updateQ(Var v, double multi) {
 2     uint32_t age = conflicts - conflicted[v] + 1;
 3     double adjusted_reward = step_size * multi / age;
 4     double old_activity = activity_CHB[v];
 5     activity_CHB[v] = adjusted_reward + ((1 - step_size) * old_activity);
 6     if (order_heap_CHB.inHeap(v))
 7         if (activity_CHB[v] > old_activity)
 8             order_heap_CHB.decrease(v);
 9         else
10             order_heap_CHB.increase(v);
11 }
conflicted[v]标定时刻——此次参与冲突分析的时刻,用于下一次冲突分析时计算时间间隔
adjusted_reward的值与age成反比,age为从conflicted[v]标定时刻至冲突分析回溯标定时刻的时间间隔。
 

 


 

LRB策略相关代码:选择下一个决策文字时,现有队列中的所有文字变元

solver.h中定义的成员变量

vec<uint32_t> picked;                   //记录变元传播进入trail的时刻
vec<uint32_t> conflicted;               //在!VSIDS决策分支模式下,记录变元从进入队列trail后参与冲突分析并作为学习子句的次数。

注意:conflicted在LRB中该量记录变元时刻而不是次数。


vec<uint32_t> almost_conflicted;   //同上条件下,参与冲突分析时处在蕴含图reason一侧的次数;

 

公式中,L(I)为该变元进入trail队列之后至被回溯取消期间发生的冲突次数;即,age = conflicts - canceled[v];

conflicted[v]是其中参与冲突分析作为学习子句文字的次数;

almost_conflicted是参与冲突分析且作为reason一侧时的次数;

公式中,r=P(v,I)/L(I)为conflicted[v]的占比;A(v,I)/L(I)是almost_conflicted占比;

 

 

 1 Lit Solver::pickBranchLit()
 2 {
 3     Var next = var_Undef;
 4     //    Heap<VarOrderLt>& order_heap = VSIDS ? order_heap_VSIDS : order_heap_CHB;
 5     Heap<VarOrderLt>& order_heap = DISTANCE ? order_heap_distance : ((!VSIDS)? order_heap_CHB:order_heap_VSIDS);
 6 
 7     // Random decision:
 8     /*if (drand(random_seed) < random_var_freq && !order_heap.empty()){
 9         next = order_heap[irand(random_seed,order_heap.size())];
10         if (value(next) == l_Undef && decision[next])
11             rnd_decisions++; }*/
12 
13     // Activity based decision:
14     while (next == var_Undef || value(next) != l_Undef || !decision[next])
15         if (order_heap.empty())
16             return lit_Undef;
17         else{
18 #ifdef ANTI_EXPLORATION
19             if (!VSIDS){
20                 Var v = order_heap_CHB[0];
21                 uint32_t age = conflicts - canceled[v];
22                 while (age > 0){
23                     double decay = pow(0.95, age);
24                     activity_CHB[v] *= decay;
25                     if (order_heap_CHB.inHeap(v))
26                         order_heap_CHB.increase(v);
27                     canceled[v] = conflicts;
28                     v = order_heap_CHB[0];
29                     age = conflicts - canceled[v];
30                 }
31             }
32 #endif
33             next = order_heap.removeMin();
34         }
35 
36     return mkLit(next, polarity[next]);
37 }

1.选择决策变元时更新activity_CHB ——注意,此处通过line22的while循环语句,将所有传播至回退阶段参与CHB计算的变元的activity_CHB进行衰减处理。

 

 1 void Solver::uncheckedEnqueue(Lit p, int level, CRef from)
 2 {
 3     assert(value(p) == l_Undef);
 4     Var x = var(p);
 5     if (!VSIDS){
 6         picked[x] = conflicts;
 7         conflicted[x] = 0;
 8         almost_conflicted[x] = 0;
 9 #ifdef ANTI_EXPLORATION
10         uint32_t age = conflicts - canceled[var(p)];
11         if (age > 0){
12             double decay = pow(0.95, age);//体现:据上次使用(参与冲突分析)时间越长,对活跃度贡献越小。
13             activity_CHB[var(p)] *= decay;
14             if (order_heap_CHB.inHeap(var(p)))
15                 order_heap_CHB.increase(var(p));
16         }
17 #endif
18     }
19 
20     assigns[x] = lbool(!sign(p));
21     vardata[x] = mkVarData(from, level);
22     trail.push_(p);
23 }
2.传播阶段计算变元的activity_CHB

line5-18为较minisat新增的部分,其中:

    • picked[x]记录变元进入传播队列trail的时刻(用conflicts记录求解器运行时间进度);
    • canceled[var(p)]为该变元上次参与回溯时刻(上次被使用的时刻)
 

 

 1 // Revert to the state at given level (keeping all assignment at 'level' but not beyond).
 2 //
 3 void Solver::cancelUntil(int bLevel) {
 4     
 5     if (decisionLevel() > bLevel){
 6 #ifdef PRINT_OUT
 7         std::cout << "bt " << bLevel << "\n";
 8 #endif                
 9         add_tmp.clear();
10         for (int c = trail.size()-1; c >= trail_lim[bLevel]; c--)
11         {
12             Var      x  = var(trail[c]);
13 
14             if (level(x) <= bLevel)
15             {
16                 add_tmp.push(trail[c]);
17             }
18             else
19             {
20                  if (!VSIDS){
21                     uint32_t age = conflicts - picked[x];
22                     if (age > 0){
23                         double adjusted_reward = ((double) (conflicted[x] + almost_conflicted[x])) / ((double) age);
24                         double old_activity = activity_CHB[x];
25                         activity_CHB[x] = step_size * adjusted_reward + ((1 - step_size) * old_activity);
26                         if (order_heap_CHB.inHeap(x)){
27                             if (activity_CHB[x] > old_activity)
28                                 order_heap_CHB.decrease(x);
29                             else
30                                 order_heap_CHB.increase(x);
31                         }
32                     }
33 #ifdef ANTI_EXPLORATION
34                     canceled[x] = conflicts;
35 #endif
36                 }
37                 
38                 assigns [x] = l_Undef;
39 #ifdef PRINT_OUT
40                 std::cout << "undo " << x << "\n";
41 #endif                
42                 if (phase_saving > 1 || (phase_saving == 1) && c > trail_lim.last())
43                     polarity[x] = sign(trail[c]);
44                 insertVarOrder(x);
45             }
46         }
47         qhead = trail_lim[bLevel];
48         trail.shrink(trail.size() - trail_lim[bLevel]);
49         trail_lim.shrink(trail_lim.size() - bLevel);
50         for (int nLitId = add_tmp.size() - 1; nLitId >= 0; --nLitId)
51         {
52             trail.push_(add_tmp[nLitId]);
53         }
54         
55         add_tmp.clear();
56     } 
57 }
3.回溯阶段计算并更新变元的activity_CHB

 

seach函数中冲突发生时:

if (VSIDS){
            if (--timer == 0 && var_decay < 0.95) timer = 5000, var_decay += 0.01;
            }else
                if (step_size > min_step_size) step_size -= step_size_dec;

 

4.移动平均的alfa(代码中为)的动态调整。

step_size初始值为0.4;
min_step_size定位0.06;
step_size_dec为0.000001
  1 lbool Solver::solve_()
  2 {
  3     signal(SIGALRM, SIGALRM_switch);
  4     alarm(2500);
  5 
  6     model.clear();
  7     conflict.clear();
  8     if (!ok) return l_False;
  9 
 10     solves++;
 11 
 12     max_learnts               = nClauses() * learntsize_factor;
 13     learntsize_adjust_confl   = learntsize_adjust_start_confl;
 14     learntsize_adjust_cnt     = (int)learntsize_adjust_confl;
 15     lbool   status            = l_Undef;
 16 
 17     if (verbosity >= 1){
 18         printf("c ============================[ Search Statistics ]==============================\n");
 19         printf("c | Conflicts |          ORIGINAL         |          LEARNT          | Progress |\n");
 20         printf("c |           |    Vars  Clauses Literals |    Limit  Clauses Lit/Cl |          |\n");
 21         printf("c ===============================================================================\n");
 22     }
 23 
 24     add_tmp.clear();
 25 
 26     VSIDS = true;
 27     int init = 10000;
 28     while (status == l_Undef && init > 0 /*&& withinBudget()*/)
 29         status = search(init);
 30     VSIDS = false;
 31 
 32     duplicates_added_conflicts = 0;
 33     duplicates_added_minimization=0;
 34     duplicates_added_tier2 =0;    
 35 
 36     dupl_db_size=0;
 37     size_t dupl_db_size_limit = dupl_db_init_size;
 38 
 39     // Search:
 40     int curr_restarts = 0;
 41     while (status == l_Undef /*&& withinBudget()*/){
 42         if (dupl_db_size >= dupl_db_size_limit){    
 43             printf("c Duplicate learnts added (Minimization) %i\n",duplicates_added_minimization);    
 44             printf("c Duplicate learnts added (conflicts) %i\n",duplicates_added_conflicts);    
 45             printf("c Duplicate learnts added (tier2) %i\n",duplicates_added_tier2);    
 46             printf("c Duptime: %i\n",duptime.count());
 47             printf("c Number of conflicts: %i\n",conflicts);
 48             printf("c Core size: %i\n",learnts_core.size());
 49             
 50             uint32_t removed_duplicates = 0;
 51             std::vector<std::vector<uint64_t>> tmp;
 52             //std::map<int32_t,std::map<uint32_t,std::unordered_map<uint64_t,uint32_t>>>  ht;
 53             for (auto & outer_mp: ht){//variables
 54                 for (auto &inner_mp:outer_mp.second){//sizes
 55                     for (auto &in_in_mp: inner_mp.second){
 56                         if (in_in_mp.second >= min_number_of_learnts_copies){
 57                             tmp.push_back({outer_mp.first,inner_mp.first,in_in_mp.first,in_in_mp.second});
 58                         }
 59                     }                    
 60                  }
 61             }          
 62             removed_duplicates = dupl_db_size-tmp.size();  
 63             ht.clear();
 64             for (auto i=0;i<tmp.size();i++){
 65                 ht[tmp[i][0]][tmp[i][1]][tmp[i][2]]=tmp[i][3];
 66             }
 67             //ht_old.clear();
 68             dupl_db_size_limit*=1.1;
 69             dupl_db_size -= removed_duplicates;
 70             printf("c removed duplicate db entries %i \n",removed_duplicates);
 71         }        
 72         if (VSIDS){
 73             int weighted = INT32_MAX;
 74             status = search(weighted);
 75         }else{
 76             int nof_conflicts = luby(restart_inc, curr_restarts) * restart_first;
 77             curr_restarts++;
 78             status = search(nof_conflicts);
 79         }
 80         if (!VSIDS && switch_mode){
 81             VSIDS = true;
 82             printf("c Switched to VSIDS.\n");
 83             fflush(stdout);
 84             picked.clear();
 85             conflicted.clear();
 86             almost_conflicted.clear();
 87 #ifdef ANTI_EXPLORATION
 88             canceled.clear();
 89 #endif
 90         }
 91     }
 92 
 93     if (verbosity >= 1)
 94         printf("c ===============================================================================\n");
 95 
 96 #ifdef BIN_DRUP
 97     if (drup_file && status == l_False) binDRUP_flush(drup_file);
 98 #endif
 99 
100     if (status == l_True){
101         // Extend & copy model:
102         model.growTo(nVars());
103         for (int i = 0; i < nVars(); i++) model[i] = value(i);
104     }else if (status == l_False && conflict.size() == 0)
105         ok = false;
106 
107     cancelUntil(0);
108     return status;
109 }

 

5.activity_CHB与其它活跃度策略的组合使用

 

  1 void Solver::analyze(CRef confl, vec<Lit>& out_learnt, int& out_btlevel, int& out_lbd)
  2 {
  3     int pathC = 0;
  4     Lit p     = lit_Undef;
  5 
  6     // Generate conflict clause:
  7     //
  8     out_learnt.push();      // (leave room for the asserting literal)
  9     int index   = trail.size() - 1;
 10 
 11     do{
 12         assert(confl != CRef_Undef); // (otherwise should be UIP)
 13         Clause& c = ca[confl];
 14 
 15         // For binary clauses, we don't rearrange literals in propagate(), so check and make sure the first is an implied lit.
 16         if (p != lit_Undef && c.size() == 2 && value(c[0]) == l_False){
 17             assert(value(c[1]) == l_True);
 18             Lit tmp = c[0];
 19             c[0] = c[1], c[1] = tmp; }
 20 
 21         // Update LBD if improved.
 22         if (c.learnt() && c.mark() != CORE){
 23             int lbd = computeLBD(c);
 24             if (lbd < c.lbd()){
 25                 if (c.lbd() <= 30) c.removable(false); // Protect once from reduction.
 26                 c.set_lbd(lbd);
 27                 if (lbd <= core_lbd_cut){
 28                     learnts_core.push(confl);
 29                     c.mark(CORE);
 30                 }else if (lbd <= 6 && c.mark() == LOCAL){
 31                     // Bug: 'cr' may already be in 'learnts_tier2', e.g., if 'cr' was demoted from TIER2
 32                     // to LOCAL previously and if that 'cr' is not cleaned from 'learnts_tier2' yet.
 33                     learnts_tier2.push(confl);
 34                     c.mark(TIER2); }
 35             }
 36 
 37             if (c.mark() == TIER2)
 38                 c.touched() = conflicts;
 39             else if (c.mark() == LOCAL)
 40                 claBumpActivity(c);
 41         }
 42 
 43         for (int j = (p == lit_Undef) ? 0 : 1; j < c.size(); j++){
 44             Lit q = c[j];
 45 
 46             if (!seen[var(q)] && level(var(q)) > 0){
 47                 if (VSIDS){
 48                     varBumpActivity(var(q), .5);
 49                     add_tmp.push(q);
 50                 }else
 51                     conflicted[var(q)]++;
 52                 seen[var(q)] = 1;
 53                 if (level(var(q)) >= decisionLevel()){
 54                     pathC++;
 55                 }else
 56                     out_learnt.push(q);
 57             }
 58         }
 59         
 60         // Select next clause to look at:
 61         while (!seen[var(trail[index--])]);
 62         p     = trail[index+1];
 63         confl = reason(var(p));
 64         seen[var(p)] = 0;
 65         pathC--;
 66 
 67     }while (pathC > 0);
 68     out_learnt[0] = ~p;
 69 
 70     // Simplify conflict clause:
 71     //
 72     int i, j;
 73     out_learnt.copyTo(analyze_toclear);
 74     if (ccmin_mode == 2){
 75         uint32_t abstract_level = 0;
 76         for (i = 1; i < out_learnt.size(); i++)
 77             abstract_level |= abstractLevel(var(out_learnt[i])); // (maintain an abstraction of levels involved in conflict)
 78 
 79         for (i = j = 1; i < out_learnt.size(); i++)
 80             if (reason(var(out_learnt[i])) == CRef_Undef || !litRedundant(out_learnt[i], abstract_level))
 81                 out_learnt[j++] = out_learnt[i];
 82         
 83     }else if (ccmin_mode == 1){
 84         for (i = j = 1; i < out_learnt.size(); i++){
 85             Var x = var(out_learnt[i]);
 86 
 87             if (reason(x) == CRef_Undef)
 88                 out_learnt[j++] = out_learnt[i];
 89             else{
 90                 Clause& c = ca[reason(var(out_learnt[i]))];
 91                 for (int k = c.size() == 2 ? 0 : 1; k < c.size(); k++)
 92                     if (!seen[var(c[k])] && level(var(c[k])) > 0){
 93                         out_learnt[j++] = out_learnt[i];
 94                         break; }
 95             }
 96         }
 97     }else
 98         i = j = out_learnt.size();
 99 
100     max_literals += out_learnt.size();
101     out_learnt.shrink(i - j);
102     tot_literals += out_learnt.size();
103 
104     out_lbd = computeLBD(out_learnt);
105     if (out_lbd <= 6 && out_learnt.size() <= 30) // Try further minimization?
106         if (binResMinimize(out_learnt))
107             out_lbd = computeLBD(out_learnt); // Recompute LBD if minimized.
108 
109     // Find correct backtrack level:
110     //
111     if (out_learnt.size() == 1)
112         out_btlevel = 0;
113     else{
114         int max_i = 1;
115         // Find the first literal assigned at the next-highest level:
116         for (int i = 2; i < out_learnt.size(); i++)
117             if (level(var(out_learnt[i])) > level(var(out_learnt[max_i])))
118                 max_i = i;
119         // Swap-in this literal at index 1:
120         Lit p             = out_learnt[max_i];
121         out_learnt[max_i] = out_learnt[1];
122         out_learnt[1]     = p;
123         out_btlevel       = level(var(p));
124     }
125 
126     if (VSIDS){
127         for (int i = 0; i < add_tmp.size(); i++){
128             Var v = var(add_tmp[i]);
129             if (level(v) >= out_btlevel - 1)
130                 varBumpActivity(v, 1);
131         }
132         add_tmp.clear();
133     }else{
134         seen[var(p)] = true;
135         for(int i = out_learnt.size() - 1; i >= 0; i--){
136             Var v = var(out_learnt[i]);
137             CRef rea = reason(v);
138             if (rea != CRef_Undef){
139                 const Clause& reaC = ca[rea];
140                 for (int i = 0; i < reaC.size(); i++){
141                     Lit l = reaC[i];
142                     if (!seen[var(l)]){
143                         seen[var(l)] = true;
144                         almost_conflicted[var(l)]++;
145                         analyze_toclear.push(l); } } } } }
146 
147     for (int j = 0; j < analyze_toclear.size(); j++) seen[var(analyze_toclear[j])] = 0;    // ('seen[]' is now cleared)
148 }

 

 

 

 

 References

1. 
The community structure of SAT formulas
By: Ansotegui, Carlos; Giraldez-Cru, Jesus; Levy, Jordi.
LNCS ‏  Pages: ‏ 410-423   Published: ‏ 2012
Times Cited: 28
2.
Refining Restarts Strategies for SAT and UNSAT
By: Audemard, G.; Simon, L.
Principles and Practice of Constraint Programming. Proceedings 18th International Conference, CP 2012 ‏  Pages: ‏ 118-26   Published: ‏ 2012
Times Cited: 27
3. 
Glucose 2.3 in the SAT 2013 Competition
By: Audemard, G.; Simon, L.
DEP COMPUTER SCI S B ‏  Pages: ‏ 42-43   Published: ‏ 2013
Times Cited: 15
4. 
Predicting Learnt Clauses Quality in Modern SAT Solvers
By: Audemard, Gilles; Simon, Laurent
21ST INTERNATIONAL JOINT CONFERENCE ON ARTIFICIAL INTELLIGENCE (IJCAI-09), PROCEEDINGS ‏  Pages: ‏ 399-404   Published: ‏ 2009
Times Cited: 165
5. 
Solver and benchmark descriptions
By: Balint, A.; Belov, A.; Heule, M. J. H.; et al.
P SAT COMP 2013 ‏  Volume: ‏ B-2013-1   Published: ‏ 2013
Publisher: University of Helsinki
Times Cited: 2
6. 
Solver and benchmark descriptions.
By: Belov, A.; Diepold, D.; Heule, M. J. H.; et al.
P SAT COMP 2014 ‏  Volume: ‏ B-2014-2   Published: ‏ 2014
Times Cited: 2
7. 
Bounded Model Checking
By: Biere, A; Cimatti, A; Clarke, EM; et al.
ADVANCES IN COMPUTERS, VOL 58: HIGHLY DEPENDABLE SOFTWARE ‏  Book Series: ‏ Advances in Computers   Volume: ‏ 58   Pages: ‏ 117-148   Published: ‏ 2003
Times Cited: 208
8.
Lingeling, plingeling, picosat and precosat at SAT race 2010
By: Biere, A.
FMV Report Series Technical Report ‏  Volume: ‏ 10   Issue: ‏ 1   Published: ‏ 2010
Times Cited: 8
9.
Evaluating CDCL Variable Scoring Schemes
By: Biere, Armin; Froehlich, Andreas
THEORY AND APPLICATIONS OF SATISFIABILITY TESTING - SAT 2015 ‏  Book Series: ‏ Lecture Notes in Computer Science   Volume: ‏ 9340   Pages: ‏ 405-422   Published: ‏ 2015
Times Cited: 16
10
EXE: Automatically Generating Inputs of Death
By: Cadar, Cristian; Ganesh, Vijay; Pawlowski, Peter M.; et al.
ACM TRANSACTIONS ON INFORMATION AND SYSTEM SECURITY ‏  Volume: ‏ 12   Issue: ‏ 2     Article Number: 10   Published: ‏ DEC 2008
Times Cited: 118
11.
Minisat blbd.
By: Chen, J.
P SAT COMP 2014 ‏  Volume: ‏ B-2014-2   Pages: ‏ 45   Published: ‏ 2014
Times Cited: 1
12.
BerkMin: A fast and robust sat-solver
By: Goldberg, Eugene; Novikov, Yakov
DISCRETE APPLIED MATHEMATICS ‏  Volume: ‏ 155   Issue: ‏ 12   Special Issue: ‏ SI   Pages: ‏ 1549-1561   Published: ‏ JUN 15 2007
Times Cited: 39
13
Solving propositional satisfiability problems
By: Jeroslow, R.; Wang, J.
Ann. of Mathematics and Artificial Intelligence ‏  Volume: ‏ 1   Pages: ‏ 167-187   Published: ‏ 1990
Times Cited: 113
14.
Empirical Study of the Anatomy of Modern Sat Solvers
By: Katebi, Hadi; Sakallah, Karem A.; Marques-Silva, Joao P.
THEORY AND APPLICATIONS OF SATISFIABILITY TESTING - SAT 2011 ‏  Book Series: ‏ Lecture Notes in Computer Science   Volume: ‏ 6695   Pages: ‏ 343-356   Published: ‏ 2011
Times Cited: 19
15.
Learning to select branching rules in the DPLL procedure for satisfiability
By: Lagoudakis, M.G.; Littman, M.L.
Electron. Notes Discrete Math ‏  Volume: ‏ 9   Pages: ‏ 344-359   Published: ‏ 2001
Times Cited: 16
16.
Understanding VSIDS branching heuristics in conflict-driven clause-learning SAT solvers
By: Liang, Jia Hui; Ganesh, Vijay; Zulkoski, Ed; et al.
LNCS ‏  Volume: ‏ 9434   Pages: ‏ 225-241   Published: ‏ 2015
Publisher: Springer
Times Cited: 11
17.
The impact of branching heuristics in propositional satisfiability algorithms
By: Marques-Silva, J.
Progress in Artificial Intelligence. 9th Portuguese Conference on Artificial Intelligence, EPIA'99. Proceedings (Lecture Notes in Artificial Intelligence Vol.1695) ‏  Pages: ‏ 62-74   Published: ‏ 1999
Times Cited: 36
18. 
GRASP: A search algorithm for propositional satisfiability
By: Marques-Silva, JP; Sakallah, KA
IEEE TRANSACTIONS ON COMPUTERS ‏  Volume: ‏ 48   Issue: ‏ 5   Pages: ‏ 506-521   Published: ‏ MAY 1999
Times Cited: 583
19. 
Applications of SAT solvers to cryptanalysis of hash functions
By: Mironov, Ilya; Zhang, Lintao
THEORY AND APPLICATIONS OF SATISFIABILITY TESTING - SAT 2006, PROCEEDINGS ‏  Book Series: ‏ LECTURE NOTES IN COMPUTER SCIENCE   Volume: ‏ 4121   Pages: ‏ 102-115   Published: ‏ 2006
Times Cited: 54
20. 
Chaff: Engineering an efficient SAT solver
By: Moskewicz, MW; Madigan, CF; Zhao, Y; et al.
38TH DESIGN AUTOMATION CONFERENCE PROCEEDINGS 2001 ‏  Book Series: ‏ DESIGN AUTOMATION CONFERENCE   Pages: ‏ 530-535   Published: ‏ 2001
Times Cited: 1,151
21.
Planning and SAT
By: Rintanen, Jussi
HANDBOOK OF SATISFIABILITY ‏  Book Series: ‏ Frontiers in Artificial Intelligence and Applications   Volume: ‏ 185   Pages: ‏ 483-504   Published: ‏ 2009
Times Cited: 16
22. 
Glucose: a solver that predicts learnt clauses quality
By: Simon, L.; Audemard, G.
SAT Competition ‏  Pages: ‏ 7-8   Published: ‏ 2009
Times Cited: 3
23. 
Title: [not available]
By: Soos, M.
Cryptominisat 2.5.0. SAT Race competitive event booklet ‏  Published: ‏ 2010
Times Cited: 6
24. 
Minisat v1.13-A SAT solver with con-flict-clause minimization
By: Sorensson, N.; Een, N.
P SYST DESCR SAT COM ‏  Volume: ‏ 2005   Pages: ‏ 53   Published: ‏ 2005
Times Cited: 24
25. 
StarExec: A Cross-Community Infrastructure for Logic Solving
By: Stump, Aaron; Sutcliffe, Geoff; Tinelli, Cesare
AUTOMATED REASONING, IJCAR 2014 ‏  Book Series: ‏ Lecture Notes in Artificial Intelligence   Volume: ‏ 8562   Pages: ‏ 367-373   Published: ‏ 2014
Times Cited: 43
26. 
Title: [not available]
By: Sutton, R.S.; Barto, A.G.
Reinforcement Learning: an Introduction ‏  Volume: ‏ 1   Issue: ‏ 1   Published: ‏ 1998
Publisher: MIT press, Cambridge
Times Cited: 1,003

 

posted on 2020-06-28 09:58  海阔凭鱼跃越  阅读(284)  评论(0编辑  收藏  举报