代码解读:
功能——collectFirstUIP(CRef confl)函数功能是基于蕴含图做基于第一唯一蕴含点fristUIP切割线,对参与冲突的变元计算活跃度增量。
基本思想——冲突子句各文字及其对应reason子句的各个文字参与了冲突的形成,这些文字变元活跃度需要更新;
更新的增量基于:(1)该文字距离冲突层路径长度(远近);
(2)该变元在各条路径上出现的次数。
重点关注以下几个量:
involved_lits 保持参与活跃度增加处理的文字 involved_lits.push(p);
var_iLevel_tmp[v] 各个变元出现点距离冲突层的最长路径
level_incs 分级序列值,这个比较明确离的远和离得近具有不同的值。变元被指派时所在层越大计算活跃度度时增量值就越大。
以上各量用于最终计算 activity_distance[v] += var_iLevel_tmp[v] * level_incs[var_iLevel_tmp[v]-1];
算法中重点的技巧环节:使用各层前向分支数pathCs[.]和可见性seen的切换实现确定蕴含图各条路径以及依照路径查找到指定的文字
pathCs[k] 从冲突层开始一层层(实际就冲突层及其各变元所对应蕴含子句的文字所在层)往前回溯时,由pathCs[k]记录各层向前回溯路径的数量
seen[v] 首先冲突子句变元可见,可以变元前推至reason子句变元可见后,可见性关闭。
=========================================================================================================================================================================
1 // pathCs[k] is the number of variables assigned at level k, 2 // it is initialized to 0 at the begining and reset to 0 after the function execution 3 bool Solver::collectFirstUIP(CRef confl){ 4 involved_lits.clear(); //初始化求解器专门用于冲突(基于蕴含图分析)阶段的数据成员,该向量收集参与冲突生成的变元 5 int max_level = 1; 6 Clause& c = ca[confl]; 7 int minLevel = decisionLevel(); 8 9 for(int i = 0; i < c.size(); i++) { 10 Var v = var(c[i]); 11 // assert(!seen[v]); 12 if (level(v) > 0) { 13 seen[v] = 1; 14 var_iLevel_tmp[v] = 1; //??????? 15 pathCs[level(v)]++; 16 if (minLevel > level(v)) { 17 minLevel = level(v); 18 assert(minLevel > 0); 19 } 20 // varBumpActivity(v); 21 } 22 }
======================================================================
冲突子句中各变元可见(将被操作);minLevel确定为冲突子句中各文字之中所处层的最小值
pathCs[level(v)]++;将冲突子句的变元计入各层的变元数;
=======================================================================
23 24 25 //printf("collectFirstUIP minLevel:%d\n", minLevel); 26 27 int limit = trail_lim[minLevel - 1];//获取最小层首元素在trail的位置号 28 //printf("the limit is %d\n", limit); 29 30 for(int i=trail.size()-1; i>=limit; i--) { 31 Lit p = trail[i]; Var v = var(p); 32 33 if (seen[v]) { 34 int currentDecLevel = level(v); 35 // if (currentDecLevel==decisionLevel()) 36 // varBumpActivity(v); 37 seen[v]=0; 38 if (--pathCs[currentDecLevel]!=0) { 39 assert(reason(v) != CRef_Undef); 40 Clause& rc = ca[reason(v)]; 41 int reasonVarLevel = var_iLevel_tmp[v] + 1; 42 if(reasonVarLevel>max_level) max_level = reasonVarLevel; 43 if (rc.size()==2 && value(rc[0])==l_False) { 44 // Special case for binary clauses 45 // The first one has to be SAT 46 assert(value(rc[1]) != l_False); 47 Lit tmp = rc[0]; 48 rc[0] = rc[1], rc[1] = tmp; 49 } 50 51 for (int j = 1; j < rc.size(); j++){ 52 Lit q = rc[j]; Var v1=var(q); 53 if (level(v1) > 0) { 54 if (minLevel>level(v1)) {//从个reason子句中各文字中考察排查文字的最小层,更新排查trail的位置下限 55 minLevel=level(v1); limit=trail_lim[minLevel-1]; assert(minLevel>0); 56 } 57 if (seen[v1]) { 58 if (var_iLevel_tmp[v1]<reasonVarLevel) 59 var_iLevel_tmp[v1]=reasonVarLevel;//参与冲突生成的路径加1,表明离得比假定的远; 60 } 61 else { 62 var_iLevel_tmp[v1]=reasonVarLevel;//reason中除去蕴含文字,其余的文字(决策或隐含决策文字)是第一次出现,获得路径值 63 // varBumpActivity(v1); 64 seen[v1] = 1; //让这些reason子句中起支配作用的变元可见(可见性由冲突子句变元传递给其支配变元) 65 pathCs[level(v1)]++; //计入这些支配变元所在层的变元数 66 } 67 } 68 } 69 70 } 71 involved_lits.push(p); 72 } 73 }
======================================================================
冲突子句中各文字及其前方个支配文字可见键入队列involve_lits;被考察变元在蕴含图中距离冲突的路径长度
pathCs[level(v)]++;将冲突子句的变元计入各层的变元数;
=======================================================================
74 75 double inc = var_iLevel_inc;//初始参数:各层变元活跃度更新时的基础增量值,建议值为1 76 vec<int> level_incs; level_incs.clear(); 77 for(int i=0;i<max_level;i++){ 78 level_incs.push(inc); 79 inc = inc/my_var_decay;//my_var_decay建议值为0.6,层数越大上述增量值越大;这样参与冲突形成的层数越大的变元更新增量值越大 80 } 81 82 for(int i = 0; i < involved_lits.size(); i++){ 83 Var v =var(involved_lits[i]); 84 // double old_act=activity_distance[v]; 85 // activity_distance[v] +=var_iLevel_inc * var_iLevel_tmp[v]; 86 activity_distance[v] += var_iLevel_tmp[v] * level_incs[var_iLevel_tmp[v]-1]; 87 88 if(activity_distance[v]>1e100){ 89 for(int vv = 0; vv<nVars(); vv++) 90 activity_distance[vv] *= 1e-100; 91 var_iLevel_inc *= 1e-100; 92 for(int j = 0; j < max_level; j++) level_incs[j] *= 1e-100; 93 }//某变元活跃度即将越界,处理方式是全体变元活跃度集体大幅度衰减,并将增量基准和各层增量标准做相应衰减 94 if (order_heap_distance.inHeap(v)){ 95 order_heap_distance.decrease(v);} //参与冲突生成的变元在最小堆中的位置做相应提升。.decrease(v)内部对应的是函数precdateup(v) 96 97 //var_iLevel_inc *= (1 / my_var_decay); 98 } 99 100 printf("collectFirstUIP have been used.\n\n"); 101 102 var_iLevel_inc = level_incs[level_incs.size()-1];//本次运行完为下一次冲突时运行该函数指定每层基准增量值,增量起点抬高了。 103 return true; 104 }