⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kb_management.cpp

📁 最快速的可满足性分析工具软件
💻 CPP
字号:
/* * kb_management.cpp: This file contains functions related to  * the management of the knowledge base (clauses). *  * The following functions are in this file: * - add_base_clause  : added 10/11/07 for 2.02 release * - add_conflict_clause * - remove_clause * - satisfied * - simplify_kb * - simplify_original_kb * - sort_clauses_by_scores * - locked * - reduce_kb * * (debugging) * - check_sorted_clause_array * */#include <stdlib.h>#include <stdio.h>#include <iostream>#include <assert.h>#include <math.h>#include "flags.h"#include "structures.h"#include "constants.h"extern my_manager* my_m;/* * Added 10/11/07 for 2.02 release *  * Add clause c to the formula. * Clause c will be treated as a base clause * and it will not be deleted (unless subsumed). *  * Return -1 if the attempt failed (the clause could not be added). *        0 if the clause causes a contradiction. *        1 otherwise. *          *  * This function should only be called when the solver * is at decision level 1 (no decision). This requirement could be relaxed, * but it makes life much easier. * */char add_base_clause(my_clause* c){  int size = c->size;  if(size<=0){    rprintf("Attempting to add clause with size=%d to the formula.\n",size);    return -1;  }  if(my_m->decision_level!=1){    rprintf("Cannot add a clause at level other than 1.\n");    return -1;  }    if(size==1){    //simply assert this at level 1.    return bcp(c->lits[0]);      }    //declare the first 2 literals watched.  add_watched_clause(c->lits[0],c);  add_watched_clause(c->lits[1],c);  //add c to the list of original clauses  if(my_m->cur_cc>=my_m->original_clauses_array_len){    //double the length    my_m->original_clauses = (my_clause**)double_array_len(my_m->original_clauses,&(my_m->original_clauses_array_len),sizeof(my_clause*));  }  my_m->original_clauses[my_m->cur_cc++] = c;  c->index = -(++my_m->cc);    return 1;}/* * Addd the current confict clause (my_m->conflict_clause) to the knowledge base * */void add_conflict_clause(){  my_clause *cdc = my_m->conflict_clause;  int size = cdc->size;  int* levels = my_m->level;  assert(size>1);    my_lit* lits = cdc->lits;    int assertion_level = my_m->assertion_level;  char found = 0;    //in this loop, we also want to make sure that the second literal in the clause  //is falsified at the assertion level to make the 2-watched literal invariant hold.  for(int i=0;i<size;i++){    my_lit l = lits[i];    my_var v = var(l);        increment_literal_score(l);        if(!found && levels[v]==assertion_level){      //swap this literal with literal[1]      my_lit temp = lits[1];      lits[1] = lits[i];      lits[i] = temp;      found = 1;    }      }//end for i  //add it to the appropriate watched lists  declare_watched_literals(cdc);    if(my_m->cur_cdc_count>=my_m->learned_clauses_array_len){    double_learned_clauses_array();  }    my_m->learned_clauses[my_m->cur_cdc_count] = cdc;  my_m->learned_clause_scores[my_m->cur_cdc_count] = 0;    //set clause index  cdc->index = my_m->cur_cdc_count;    //update stats  my_m->cur_cdc_count++;  my_m->cdc_count++;  my_m->cur_cdl_count+= size;  my_m->cdl_count += size;    increment_clause_score(cdc);}//end function add_conflict_clause/* * Remove this clause from the reason array. * Remove this clause from any watched list. * Free this clause. * */void remove_clause(my_clause* c){  my_clause** reason = my_m->reason;  my_var v0 = var(c->lits[0]);  my_var v1 = var(c->lits[1]);    if(reason[v0]==c){    reason[v0] = NULL;  }else if(reason[v1]==c){    reason[v1] = NULL;  }  remove_watched_clause(c->lits[0],c);  remove_watched_clause(c->lits[1],c);  free(c->lits);  free(c);}/* * Return 1 if this clause is satisfied by some literals at level 1 (topmost). * (returning 1 means this clause can be removed from the knowledge base) */char satisfied(my_clause* c){  my_lit* lits = c->lits;  my_lit* status = my_m->status;  for(int i=0;i<c->size;i++){    if(set(lits[i])>0){      //this clause is satisfied      return 1;    }//end if  }//end for i  return 0;}/* * This function should be called after BCP at the topmost level (level 1). * It removes all learned clauses in the knowledge base that are satisfied at the topmost level. * */void simplify_kb(){  if(!my_m->simplify_learned_kb){return;}    int size = my_m->cur_cdc_count;  if(size==0){return;}  int removed_lits = 0;  int j=0;  my_clause** clauses = my_m->learned_clauses;  double* score = my_m->learned_clause_scores;    //for each learned clause  for(int i=0;i<size;i++){    my_clause* c = clauses[i];    if(satisfied(c)){      removed_lits += c->size;      remove_clause(c);    }else{      clauses[i]->index = j;      score[j] = score[i];      clauses[j++] = clauses[i];    }  }  my_m->cur_cdc_count = j;  my_m->cur_cdl_count -= removed_lits;    my_m->kb_simplification_count++;  my_m->num_conflicts_for_next_simplify = my_m->conflicts+my_m->next_simplify_increment;  //as of 6/6/07, the code below does not really do anything  //as my_m->next_simplify_increment is currently 0.  double removed_ratio = ((double)(size-my_m->cur_cdc_count))/size;  if(removed_ratio<0.01){    my_m->next_simplify_increment = (int)(my_m->next_simplify_increment*1.1);  }else{    my_m->next_simplify_increment = (int)(my_m->next_simplify_increment*0.9);;  }    my_m->simplify_learned_kb = 0;}//end function simplify_kb/* * Same as simplify_kb but for original clauses. * */void simplify_original_kb(){   if(!my_m->simplify_orig_kb){return;}  int size = my_m->cur_cc;  int removed_lits = 0;  int j = 0;  my_clause** clauses = my_m->original_clauses;  for(int i=0;i<size;i++){    my_clause* c = clauses[i];        if(satisfied(c)){      removed_lits += c->size;      remove_clause(c);    }else{      clauses[j++] = clauses[i];	      }  }//end for i    my_m->cur_cc = j;  my_m->cur_lit_count -= removed_lits;  //memory usage optimization  if(j<my_m->original_clauses_array_len*0.75){    my_m->original_clauses = (my_clause**)realloc(my_m->original_clauses,sizeof(my_clause*)*j);    my_m->original_clauses_array_len = j;  }     my_m->simplify_orig_kb = 0;}/* * Debugging utility: * Check to make sure arr is sorted correctly. * */void check_sorted_clause_array(my_clause** arr,double* score,int size){  for(int i=0;i<size;i++){    if(arr[i]!=NULL){      if(arr[i]->index != i){	printf("Sorted clause array corrupted: arr[%d]->index = %d\n",i,arr[i]->index);	exit(0);      }    }    if(i<size-1){      if(score[i] > score[i+1]){	printf("Sorted clause array corrupted: score[%d](%.4f) > score[%d](%.4f)\n",i,score[i],i+1,score[i+1]);	exit(0);      }    }  }//end for i}/* * Sort clauses in _arr by their scores in _score in ascending order. * size is the length of _arr and _score. * The sorting algorithm used is merge sort. * This implementation is *not* recursive as we want to minimize the memory overhead. *  * As a result, size has to be a power of 2. See how it is used in reduce_kb. * */void sort_clauses_by_scores(my_clause*** _arr,double** _score,int size)//归并排序{      my_clause** arr = *_arr;  double* score = *_score;  my_clause** target = (my_clause**)calloc(size,sizeof(my_clause*));  double* starget = (double*)calloc(size,sizeof(double));    //assume size = 2^k for some integer k.  int i = 0;    //loop until finish  for(;;i++){     int block_size = (int)(pow(2,i));	    if(block_size>size/2){      break;    }        int lindex = 0;    int rindex = block_size;        int l = 0;    int r = 0;    //for each position in the target array    for(int j=0;j<size;j++){//394      if(l==block_size && r==block_size){//358	lindex += block_size;	rindex += block_size;	l = 0;	r = 0;		double s1 = score[lindex];	double s2 = score[rindex];	if(s1<s2){	  target[j] = arr[lindex];	  starget[j] = score[lindex];	  lindex++;	  l++;	}else{	  target[j] = arr[rindex];	  starget[j] = score[rindex];	  	  rindex++;	  r++;	}      }else if(l==block_size){	target[j] = arr[rindex];	starget[j] = score[rindex];		rindex++;	r++;      }else if(r==block_size){	target[j] = arr[lindex];	starget[j] = score[lindex];		  	lindex++;	l++;      }else{	//both l and r are not empty	double s1 = score[lindex];	double s2 = score[rindex];	if(s1<s2){	  target[j] = arr[lindex];	  starget[j] = score[lindex];  	  lindex++;	  l++;	}else{	  target[j] = arr[rindex];	  starget[j] = score[rindex];	  	  rindex++;	  r++;	}//endif else s1<s2      }//endif else l==block_size && r==block_size            if(target[j]!=NULL){	target[j]->index = j;      }          }//end for j        //done filling up target array    my_clause** temp = target;//之所以在进入之前对之取pow(2,...):一方面保证归并排序的执行,不会留下单个元素的不方便。第二,也是为了这里进行偶数次换,还能再换回来    target = arr;    arr = temp;    double* stemp = starget;    starget = score;    score = stemp;      }//end for i  *_arr = arr;  *_score = score;  free(target);  free(starget);}//end function sort clauses by scores/* * Return 1 iff c is a reason for some literal. * */char locked(my_clause* c){  if(c->size<=1){    return 1;  }    my_clause** reason = my_m->reason;  my_clause* reason1 = reason[var(c->lits[0])];  my_clause* reason2 = reason[var(c->lits[1])];  return (reason1==c || reason2==c);}/* * Attempt to remove approximately half the learned clauses from the knowledge base. *  */void reduce_kb(){    int i;  int num_learned_clauses = my_m->cur_cdc_count;  if(num_learned_clauses<=0){    return;  }  //after this point we can assume that num_learned_clauses is at least 1    double extra_lim = (double)(my_m->clause_score_inc)/num_learned_clauses;    //sort the learned clauses by their activities  double lg = log2(num_learned_clauses);  int new_size = (int)lg;  if(lg!=(int)lg){    new_size = (int)(ceil(lg));  }  new_size = (int)(pow(2,new_size));//为后面的归并排序做准备    my_clause** arr = (my_clause**)calloc(new_size,sizeof(my_clause*));  double* score_arr = (double*)calloc(new_size,sizeof(double));  for(int i=0;i<num_learned_clauses;i++){    arr[i] = my_m->learned_clauses[i];    score_arr[i] = my_m->learned_clause_scores[i];  }    for(int i=num_learned_clauses;i<new_size;i++){    arr[i] = NULL;    score_arr[i] = -100;  }    sort_clauses_by_scores(&arr,&score_arr,new_size);//递增  int kk = 0;  for(int i=new_size-num_learned_clauses;i<new_size;i++){//前面全部是空    my_m->learned_clauses[kk] = arr[i];    my_m->learned_clause_scores[kk] = score_arr[i];    kk++;  }//end for i  free(arr);  free(score_arr);  //finish sorting   my_clause** clause_array = my_m->learned_clauses;  double* score = my_m->learned_clause_scores;  int removed_lits = 0;  int j = 0;    //iterate through the first half of the sorted array  //and remove every clause possible  for(i=0;i<num_learned_clauses/2;i++){    char binary = 0;    if(clause_array[i]->size <= 2){      binary = 1;    }    if(!locked(clause_array[i]) && !binary){      //remove it      removed_lits += clause_array[i]->size;      remove_clause(clause_array[i]);    }else{            clause_array[i]->index = j;      score[j] = score[i];      clause_array[j++] = clause_array[i];    }  }//end for i=j    //iterate through the second half of the sorted array  //and remove clauses whose scores are low enough.  for(;i<num_learned_clauses;i++){    my_clause* cur = clause_array[i];    char binary = 0;    if(clause_array[i]->size <= 2){      binary = 1;    }    if(!locked(cur) && ( score[i] < extra_lim) && !binary){      //remove it      removed_lits += clause_array[i]->size;      remove_clause(clause_array[i]);    }else{      clause_array[i]->index = j;      score[j] = score[i];      clause_array[j++] = clause_array[i];    }  }//end for i  my_m->cur_cdc_count = j;  my_m->cur_cdl_count -= removed_lits;  my_m->kb_reduction_count++;  my_m->max_learned_clauses *= MAX_LEARNED_CLAUSES_MULTIPLIER;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -