VIS

src/sat/satBDD.c

Go to the documentation of this file.
00001 
00019 #include "satInt.h"
00020 #ifdef BDDcu
00021 #include "cuddInt.h"
00022 #endif
00023 
00024 static char rcsid[] UNUSED = "$Id: satBDD.c,v 1.30 2009/04/11 18:26:37 fabio Exp $";
00025 
00026 /*---------------------------------------------------------------------------*/
00027 /* Constant declarations                                                     */
00028 /*---------------------------------------------------------------------------*/
00029 
00030 #ifdef BDDcu
00031 
00033 /*---------------------------------------------------------------------------*/
00034 /* Static function prototypes                                                */
00035 /*---------------------------------------------------------------------------*/
00036 
00037 static int heapCostCompare(const void *c1, const void *c2);
00038 static int sat_ConvertCNF2BDD(satManager_t *cm, DdManager *mgr, int conflictFlag);
00039 static void sat_FreeLinearHead(satLinearHead_t *head);
00040 static int linearVarCompare(const void * node1, const void * node2);
00041 static int linearElemCompare(const void * node1, const void * node2);
00042 static void sat_GetArrangementByForce(satManager_t *cm, satLinearHead_t *head);
00043 static int sat_PrintCutProfile(satManager_t *cm, satLinearHead_t *head, char *baseName, int printFlag);
00044 static int sat_ClusteringElementMain(satManager_t *cm, satLinearHead_t *head);
00045 static void sat_ComputeVariableRange(satManager_t *cm, satLinearHead_t *head);
00046 static void sat_InitClusteringElement(satManager_t *cm, satLinearHead_t *head);
00047 static void sat_PrintSupportVariable(satLinearHead_t *head, satLinearElem_t *e1);
00048 static void sat_ClusteringGetCandidate(satManager_t *cm, satLinearHead_t *head);
00049 static DdNode *sat_SmoothWithDeadVariable(DdManager *mgr, satArray_t *deadArray, DdNode *bdd1, DdNode *bdd2, int bddAndLimit);
00050 static int sat_ClusteringElement(satManager_t *cm, satLinearHead_t *head);
00051 static void sat_FreeCluster(DdManager *mgr, satLinearCluster_t *clu);
00052 static void sat_CheckDeadNode(satLinearHead_t *head, satLinearCluster_t *clu);
00053 
00055 #endif
00056 
00057 
00058 /*---------------------------------------------------------------------------*/
00059 /* Definition of exported functions                                          */
00060 /*---------------------------------------------------------------------------*/
00061 
00062 #ifdef BDDcu
00063 
00077 void
00078 sat_TryToBuildMonolithicBDD(satManager_t *cm)
00079 {
00080 DdManager *mgr;
00081 int nVariables, flag;
00082 
00083   nVariables = cm->initNumVariables - cm->implicatedSoFar;
00084 
00085   if(nVariables
00086           > cm->option->maxLimitOfVariablesForMonolithicBDD)    return;
00087 
00088   mgr = Cudd_Init((unsigned int)(nVariables+1), 0, CUDD_UNIQUE_SLOTS,
00089                    CUDD_CACHE_SLOTS, getSoftDataLimit() / 10 * 9);
00090   cm->mgr = mgr;
00091   flag = sat_ConvertCNF2BDD(cm, mgr, 0);
00092 
00093   Cudd_Quit(mgr);
00094   cm->mgr = 0;
00095 
00096   if(flag == SAT_BDD_UNSAT)
00097     cm->status = SAT_UNSAT;
00098 
00099   return;
00100 }
00101 
00102 
00114 DdNode *
00115 sat_CofactorBDDArray(
00116         satLinearHead_t *head,
00117         DdManager *mgr,
00118         DdNode *l1,
00119         satArray_t *satArr)
00120 {
00121 int i, vid, inverted;
00122 long v;
00123 DdNode *bdd, *result, *nresult;
00124 satLinearVar_t *var;
00125 
00126   result = l1;
00127   cuddRef(result);
00128   for(i=0; i<satArr->num; i++) {
00129     v = satArr->space[i];
00130     inverted = SATisInverted(v);
00131     v = SATnormalNode(v);
00132     vid = head->edge2vid[SATnodeID(v)];
00133     var = &(head->varHead[vid]);
00134     bdd = inverted ? Cudd_Not(var->bdd) : var->bdd;
00135 
00136     nresult = Cudd_bddConstrain(mgr, result, bdd);
00137     cuddRef(nresult);
00138     Cudd_RecursiveDeref(mgr, result);
00139     result = nresult;
00140   }
00141   return(result);
00142 }
00143 
00157 void
00158 sat_ExtractAssignmentFromBDD(
00159         satLinearHead_t *head,
00160         DdManager *mgr,
00161         satArray_t *arr,
00162         DdNode *cube)
00163 {
00164 DdNode *C, *T, *E, *zero;
00165 
00166   C = Cudd_Regular(cube);
00167   zero = Cudd_Not(DD_ONE(mgr));
00168   if (!cuddIsConstant(C)) {
00169     while (!cuddIsConstant(C)) {
00170       T = cuddT(C);
00171       E = cuddE(C);
00172       if (Cudd_IsComplement(cube)) {
00173         T = Cudd_Not(T);
00174         E = Cudd_Not(E);
00175       }
00176       if (T == zero)  { 
00177           sat_ArrayInsert(arr, ((head->id2edge[C->index]) + 1));
00178           cube = E;
00179       }
00180       else {                   
00181           sat_ArrayInsert(arr, (head->id2edge[C->index]));
00182           cube = T;
00183       }
00184       C = Cudd_Regular(cube);
00185     }
00186   }
00187   return;
00188 }
00189 
00190 
00202 satLinearHead_t *
00203 sat_CreateLinearHead(
00204         satManager_t *cm,
00205         int conflictFlag)
00206 {
00207 satLinearHead_t *head;
00208 satLinearElem_t *elem;
00209 satLinearVar_t *lvar;
00210 satArray_t *cArray, *vArray;
00211 int nVars, nCls, varId;
00212 int j, size, satisfied, inverted;
00213 int value;
00214 long v, *plit, i;
00215 int elemIndex, varIndex;
00216 int clauseLimit;
00217 
00218   nVars = 0;
00219   nCls = 0;
00220   cArray = sat_ArrayAlloc(1024);
00221   vArray = sat_ArrayAlloc(1024);
00222   for(i=satNodeSize; i<cm->initNodesArraySize; i+=satNodeSize) {
00223     if(!(SATflags(i) & IsCNFMask))      continue;
00224     if(SATreadInUse(i) == 0)    continue;
00226     size = SATnumLits(i);
00227     satisfied = 0;
00228     plit = (long *)SATfirstLit(i);
00229     for(j=0; j<size; j++, plit++) {
00230       v = SATgetNode(*plit);
00231       inverted = SATisInverted(v);
00232       v = SATnormalNode(v);
00233       value = SATvalue(v) ^ inverted;
00234       if(value == 1) {
00235         satisfied = 1;
00236         break;
00237       }
00238     }
00239     if(satisfied)       continue;
00240 
00241     nCls++;
00242     SATflags(i) |= VisitedMask;
00243     sat_ArrayInsert(cArray, i);
00244 
00245     plit = (long *)SATfirstLit(i);
00246     for(j=0; j<size; j++, plit++) {
00247       v = SATgetNode(*plit);
00248       v = SATnormalNode(v);
00249       if(SATvalue(v) < 2)       continue;
00250       if(!(SATflags(v) & VisitedMask)) {
00251         nVars++;
00252         SATflags(v) |= VisitedMask;
00253         sat_ArrayInsert(vArray, v);
00254       }
00255     }
00256   }
00257 
00258   if(conflictFlag)
00259     clauseLimit = cm->option->maxLimitOfClausesForBDDDPLL;
00260   else
00261     clauseLimit = cm->option->maxLimitOfClausesForMonolithicBDD;
00262 
00263   if(nCls > clauseLimit) {
00264     if(nVars > 100) {
00265       for(i=0; i<cArray->num; i++) {
00266         v = cArray->space[i];
00267         SATflags(v) &= ResetVisitedMask;
00268       }
00269       sat_ArrayFree(cArray);
00270       for(i=0; i<vArray->num; i++) {
00271         v = vArray->space[i];
00272         SATflags(v) &= ResetVisitedMask;
00273       }
00274       sat_ArrayFree(vArray);
00275       return(0);
00276     }
00277   }
00278 
00279   if(cm->option->verbose > 1) {
00280     fprintf(cm->stdOut, "NOTICE : Apply BDD based method at level %d with %d vars %d cls\n", cm->currentDecision, nVars, nCls);
00281     fflush(cm->stdOut);
00282   }
00283   head = ALLOC(satLinearHead_t, 1);
00284   memset(head, 0, sizeof(satLinearHead_t));
00285   head->clausesArray = cArray;
00286   head->variablesArray = vArray;
00287   head->reordering = 1;
00288   head->nVars = nVars;
00289   head->nCls = nCls;
00290   head->bddLimit = 5000;
00291   head->bddAndLimit = 10000;
00292 
00293   head->elemHead = ALLOC(satLinearElem_t, nCls);
00294   memset(head->elemHead, 0, sizeof(satLinearElem_t)*nCls);
00295   head->varHead = ALLOC(satLinearVar_t, nVars);
00296   memset(head->varHead, 0, sizeof(satLinearVar_t)*nVars);
00297 
00298   head->elemArray = sat_ArrayAlloc(nCls);
00299   head->varArray = sat_ArrayAlloc(nVars);
00300   head->latestClusterArray = sat_ArrayAlloc(32);
00301   head->deadArray = sat_ArrayAlloc(nVars);
00302 
00303   head->id2edge = ALLOC(long, nVars+1);
00304   head->edge2id = ALLOC(int, cm->initNumVariables+1);
00305   head->edge2vid = ALLOC(int, cm->initNumVariables+1);
00306 
00307   varIndex = 0;
00308   for(i=0; i<vArray->num; i++) {
00309     v = vArray->space[i];
00310     SATflags(v) &= ResetVisitedMask;
00311     lvar = &(head->varHead[varIndex]);
00312     head->edge2vid[SATnodeID(v)] = varIndex;
00313     sat_ArrayInsert(head->varArray, (long)lvar);
00314     lvar->order = varIndex++;
00315     lvar->node = v;
00316     lvar->bQuantified = 1;
00317     lvar->clauses = sat_ArrayAlloc(4);
00318   }
00319 
00320   elemIndex = 0;
00321   for(i=0; i<cArray->num; i++) {
00322     v = cArray->space[i];
00323     SATflags(v) &= ResetVisitedMask;
00324     elem = &(head->elemHead[elemIndex]);
00325     sat_ArrayInsert(head->elemArray, (long)elem);
00326     elem->node = v;
00327     elem->order = elemIndex++;
00328 
00329     size = SATnumLits(v);
00330     elem->support = sat_ArrayAlloc(size);
00331     plit = (long *)SATfirstLit(v);
00332     for(j=0; j<size; j++, plit++) {
00333       v = SATgetNode(*plit);
00334       inverted = SATisInverted(v);
00335       v = SATnormalNode(v);
00336       value = SATvalue(v) ^ inverted;
00337       if(value == 0)    {
00338         continue;
00339       }
00340       varId = head->edge2vid[SATnodeID(v)];
00341       lvar = &(head->varHead[varId]);
00342 
00343       sat_ArrayInsert(lvar->clauses, (long)elem);
00344       if(inverted)      lvar = (satLinearVar_t *)SATnot((unsigned long)lvar);
00345       sat_ArrayInsert(elem->support, (long)lvar);
00346     }
00347   }
00348   return(head);
00349 }
00350 
00351 
00363 satLinearCluster_t *
00364 sat_CreateCluster(
00365         satLinearHead_t *head,
00366         satLinearElem_t *e1,
00367         satLinearElem_t *e2,
00368         int flagIndex,
00369         int *idArr)
00370 {
00371 satLinearCluster_t *clu;
00372 satLinearVar_t *var;
00373 satArray_t *support, *deadArray;
00374 int from, to, nDead;
00375 int nv, bddid;
00376 int overlap, bddsize, j;
00377 
00378   memset(idArr, 0, sizeof(int)*(head->nVars));
00379   clu = ALLOC(satLinearCluster_t, 1);
00380   clu->elem1 = e1;
00381   clu->elem2 = e2;
00382   clu->deadArray = 0;
00383   from = e1->order;
00384   to = e2->order;
00385   nDead = 0;
00386   support = e1->support;
00387   for(j=0; j<support->num; j++) {
00388     var = (satLinearVar_t *)support->space[j];
00389     var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
00390     nv = var->node;
00391     bddid = head->edge2id[SATnodeID(nv)];
00392     idArr[bddid] = 1;
00393 
00394     if(var->bQuantified && from <= var->from && var->to <= to) {
00395       nDead++;
00396       if(clu->deadArray == 0) {
00397         deadArray = sat_ArrayAlloc(2);
00398         clu->deadArray = deadArray;
00399       }
00400       else
00401         deadArray = clu->deadArray;
00402       sat_ArrayInsert(deadArray, (long)var);
00403     }
00404   }
00405 
00406   overlap = 0;
00407   support = e2->support;
00408   for(j=0; j<support->num; j++) {
00409     var = (satLinearVar_t *)support->space[j];
00410     var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
00411     nv = var->node;
00412     bddid = head->edge2id[SATnodeID(nv)];
00413     if(idArr[bddid]) {
00414       if(from <= var->from && var->to <= to);
00415       else
00416         overlap++;
00417     }
00418     else {
00419       if(var->bQuantified && from <= var->from && var->to <= to) {
00420         nDead++;
00421         if(clu->deadArray == 0) {
00422           deadArray = sat_ArrayAlloc(2);
00423           clu->deadArray = deadArray;
00424         }
00425         else
00426           deadArray = clu->deadArray;
00427         sat_ArrayInsert(deadArray, (long)var);
00428       }
00429     }
00430   }
00431 
00432   bddsize = Cudd_DagSize(e1->bdd) + Cudd_DagSize(e2->bdd);
00433   clu->overlap = overlap;
00434   clu->cost = (nDead<<7) + (overlap*(1024/bddsize)) + 10000/bddsize;
00435   clu->flag = flagIndex;
00436 
00437   return(clu);
00438 }
00439 
00451 static void
00452 sat_PrintSupportVariable(
00453         satLinearHead_t *head,
00454         satLinearElem_t *e1)
00455 {
00456 satArray_t *support;
00457 satLinearVar_t *var;
00458 int j;
00459 long nv;
00460 
00461 
00462   support = e1->support;
00463   for(j=0; j<support->num; j++) {
00464     var = (satLinearVar_t *)support->space[j];
00465     var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
00466     nv = var->node;
00468     fprintf(stdout, " %ld", nv);
00469   }
00470   fprintf(stdout, "\n");
00471 }
00472 
00484 static int
00485 heapCostCompare(const void *c1, const void *c2)
00486 {
00487 satLinearCluster_t *clu1, *clu2;
00488 
00489   clu1 = (satLinearCluster_t *)c1;
00490   clu2 = (satLinearCluster_t *)c2;
00491   return(clu1->cost < clu2->cost);
00492 }
00493 
00505 static void
00506 sat_ClusteringGetCandidate(
00507         satManager_t *cm,
00508         satLinearHead_t *head)
00509 {
00510 int i, *idArr;
00511 satArray_t *eArr;
00512 satLinearElem_t *e1, *e2;
00513 satLinearCluster_t *clu;
00514 
00515   eArr = head->elemArray;
00516   head->heap = Heap_HeapInitCompare(eArr->num+2, heapCostCompare);
00517 
00518   idArr = ALLOC(int, head->nVars);
00519   for(i=0; i<eArr->num; i++) {
00520 
00521     e1 = (satLinearElem_t *)eArr->space[i];
00522     if(i == eArr->num-1)
00523       continue;
00524     else
00525       e2 = (satLinearElem_t *)eArr->space[i+1];
00526 
00527     e1->flag = 1;
00528     e2->flag = 1;
00529     clu = sat_CreateCluster(head, e1, e2, 1, idArr);
00530 
00531     Heap_HeapInsertCompare(head->heap, (void *)clu, (long)clu);
00532   }
00533 
00534   free(idArr);
00535 
00536 }
00537 
00549 static DdNode *
00550 sat_SmoothWithDeadVariable(
00551         DdManager *mgr,
00552         satArray_t *deadArray,
00553         DdNode *bdd1,
00554         DdNode *bdd2,
00555         int bddAndLimit)
00556 {
00557 satLinearVar_t *var;
00558 DdNode *cube, *ncube;
00559 DdNode *result;
00560 int i;
00561 
00562 
00563   cube = DD_ONE(mgr);
00564   cuddRef(cube);
00565   for(i=0; i<deadArray->num; i++) {
00566     var = (satLinearVar_t *)deadArray->space[i];
00567     ncube = Cudd_bddAnd(mgr,cube,var->bdd);
00568     if(ncube == NULL) {
00569       Cudd_RecursiveDeref(mgr, cube);
00570       return(NULL);
00571     }
00572     cuddRef(ncube);
00573     Cudd_RecursiveDeref(mgr, cube);
00574     cube = ncube;
00575   }
00576 
00577 
00578   result = Cudd_bddAndAbstractLimit(
00579               mgr,bdd1,bdd2,cube,bddAndLimit);
00580   if(result == NULL) {
00581     Cudd_RecursiveDeref(mgr, cube);
00582     return(NULL);
00583   }
00584   cuddRef(result);
00585   Cudd_RecursiveDeref(mgr, cube);
00586   cuddDeref(result);
00587 
00588   return(result);
00589 }
00590 
00602 static int
00603 sat_ClusteringElement(
00604         satManager_t *cm,
00605         satLinearHead_t *head)
00606 {
00607 int modified, total, size;
00608 int found, i, vid, index;
00609 long v;
00610 int *idArr, *idSupport;
00611 int limit, nElem;
00612 satLinearElem_t *e1, *e2;
00613 satLinearVar_t *lvar;
00614 satLinearCluster_t *clu, *tclu;
00615 satArray_t *support, *deadArray;
00616 satArray_t *neArr, *eArr;
00617 DdManager *mgr;
00618 DdNode *result, *zero;
00619 Heap_t *heap;
00620 long dummy;
00621 
00622   heap = head->heap;
00623   modified = 0;
00624 
00625   idArr = ALLOC(int, head->nVars);
00626 
00627   mgr = head->mgr;
00628   eArr = head->elemArray;
00634   zero = Cudd_Not(DD_ONE(mgr));
00635   limit = ((eArr->num)>>1);
00636   nElem = eArr->num;
00637 
00638   if(cm->option->verbose > 3)
00639     fprintf(cm->stdOut, " ------- %d element\n", nElem);
00640 
00641   while(Heap_HeapExtractMin(heap, &clu, &dummy)) {
00642     if(modified > limit) {
00643       sat_FreeCluster(mgr, clu);
00644       continue;
00645     }
00646     e1 = clu->elem1;
00647     e2 = clu->elem2;
00648     if(e1->flag == 0 || e2->flag == 0) {
00649       sat_FreeCluster(mgr, clu);
00650       continue;
00651     }
00652     if(e1->flag > clu->flag || e2->flag > clu->flag) {
00653       sat_FreeCluster(mgr, clu);
00654       continue;
00655     }
00656     deadArray = clu->deadArray;
00657     if(deadArray) {
00658       cuddRef(e1->bdd);
00659       cuddRef(e2->bdd);
00660       result = sat_SmoothWithDeadVariable(
00661               mgr, deadArray, e1->bdd, e2->bdd, head->bddAndLimit);
00662       if(result)
00663         cuddRef(result);
00664       Cudd_RecursiveDeref(mgr, e1->bdd);
00665       Cudd_RecursiveDeref(mgr, e2->bdd);
00666       for(i=0; i<deadArray->num; i++) {
00667         lvar = (satLinearVar_t *)deadArray->space[i];
00668         sat_ArrayInsert(head->deadArray, (long)lvar);
00669       }
00670     }
00671     else {
00672       result = Cudd_bddAndLimit(mgr,e1->bdd,e2->bdd,head->bddAndLimit);
00673       if(result)
00674         cuddRef(result);
00675     }
00676 
00677     total = Cudd_ReadKeys(mgr) - Cudd_ReadDead(mgr);
00678     if(total > 100000 && head->reordering) {
00679       head->reordering = 0;
00680       Cudd_AutodynDisable(mgr);
00681     }
00682 
00683     if(result) {
00685       nElem--;
00686       if(cm->option->verbose > 3) {
00687         fprintf(cm->stdOut, " (%4d %4d) %4d(%3d, %3ld): %d X %d = %d\n",
00688               e1->order, e2->order,
00689               clu->cost, clu->overlap, deadArray ? deadArray->num : 0,
00690               Cudd_DagSize(e1->bdd), Cudd_DagSize(e2->bdd),
00691               Cudd_DagSize(result));
00692         sat_PrintSupportVariable(head, e1);
00693         sat_PrintSupportVariable(head, e2);
00694         if(deadArray) {
00695         for(i=0; i<deadArray->num; i++) {
00696           lvar = (satLinearVar_t *)deadArray->space[i];
00697           fprintf(cm->stdOut, "%ld ", lvar->node);
00698         }
00699         }
00700         fprintf(cm->stdOut, "\n");
00701       }
00702       modified++;
00703       e1->flag += 1;
00704       e2->flag = 0;
00705 
00706       if(nElem < 50) {
00707         sat_ArrayInsert(head->latestClusterArray, (long)(e1->bdd));
00708         cuddRef(e1->bdd);
00709         sat_ArrayInsert(head->latestClusterArray, (long)(e2->bdd));
00710         cuddRef(e2->bdd);
00711       }
00712 
00713       Cudd_RecursiveDeref(mgr, e1->bdd);
00714       Cudd_RecursiveDeref(mgr, e2->bdd);
00715       e1->bdd = result;
00716       e2->bdd = 0;
00717       sat_ArrayFree(e1->support);
00718       e1->support = 0;
00719       support = e2->support;
00720       for(i=0; i<support->num; i++) {
00721         lvar = (satLinearVar_t *)support->space[i];
00722         if(lvar->to == e2->order)
00723           lvar->to = e1->order;
00724         if(lvar->from == e2->order)
00725           lvar->from = e1->order;
00726       }
00727       sat_ArrayFree(e2->support);
00728       e2->support = 0;
00729 
00730       size = (unsigned int)Cudd_ReadSize(mgr);
00731       idSupport = Cudd_SupportIndex(mgr,result);
00732       e1->support = support = sat_ArrayAlloc(10);
00733       for (i = 0; i < size; i++) {
00734         if(idSupport[i]) {
00735           v = head->id2edge[i];
00736           vid = head->edge2vid[SATnodeID(v)];
00737           lvar = &(head->varHead[vid]);
00738           sat_ArrayInsert(support, (long)lvar);
00745         }
00746       }
00747       free(idSupport);
00748 
00749       found = 0;
00750       for(i=e1->order-1; i>=0; i--)  {
00751         e2 = (satLinearElem_t *)eArr->space[i];
00752         if(e2->flag)    {
00753           found = 1;
00754           break;
00755         }
00756       }
00757       if(found) {
00758         tclu = sat_CreateCluster(head, e2, e1, e1->flag, idArr);
00759         Heap_HeapInsertCompare(head->heap, (void *)tclu, (long)tclu);
00760       }
00761 
00762       found = 0;
00763       for(i=e1->order+1; i<eArr->num; i++)  {
00764         e2 = (satLinearElem_t *)eArr->space[i];
00765         if(e2->flag)    {
00766           found = 1;
00767           break;
00768         }
00769       }
00770       if(found) {
00771         tclu = sat_CreateCluster(head, e1, e2, e1->flag, idArr);
00772         Heap_HeapInsertCompare(head->heap, (void *)tclu, (long)tclu);
00773       }
00774     }
00775     sat_FreeCluster(mgr, clu);
00776   }
00777 
00778   Heap_HeapFree(heap);
00779   head->heap = 0;
00780 
00781   free(idArr);
00782 
00783   if(modified) {
00784     eArr = head->elemArray;
00785     neArr = sat_ArrayAlloc(eArr->num);
00786     index = 0;
00787     for(i=0; i<eArr->num; i++) {
00788       e1 = (satLinearElem_t *)eArr->space[i];
00789       if(e1->flag == 0) continue;
00790 
00791       e1->order = index++;
00792       sat_ArrayInsert(neArr, (long)e1);
00793     }
00794     sat_ArrayFree(eArr);
00795     head->elemArray = neArr;
00796   }
00797 
00798   if(head->elemArray->num == 1)
00799     modified = 0;
00800 
00801   return(modified);
00802 }
00803 
00804 
00816 static void
00817 sat_FreeCluster(DdManager *mgr, satLinearCluster_t *clu)
00818 {
00819 satArray_t *deadArray;
00820 
00821   deadArray = clu->deadArray;
00822   if(deadArray) {
00823     sat_ArrayFree(deadArray);
00824   }
00825   free(clu);
00826 }
00827 
00828 
00840 static void
00841 sat_CheckDeadNode(
00842         satLinearHead_t *head,
00843         satLinearCluster_t *clu)
00844 {
00845 satArray_t *deadArray, *eArr;
00846 satArray_t *support;
00847 satLinearVar_t *var, *tvar;
00848 satLinearElem_t *elem;
00849 int i, j, k;
00850 
00851 
00852   if(clu->deadArray) {
00853     deadArray = clu->deadArray;
00854     for(i=0; i<deadArray->num; i++) {
00855       var = (satLinearVar_t *)deadArray->space[i];
00856       eArr = head->elemArray;
00857       for(j=0; j<var->from; j++) {
00858         elem = (satLinearElem_t *)eArr->space[j];
00859         if(elem->flag == 0)     continue;
00860         support = elem->support;
00861         for(k=0; k<support->num; k++) {
00862           tvar = (satLinearVar_t *)support->space[k];
00863           tvar = (satLinearVar_t *)SATnormalNode((unsigned long)tvar);
00864           if(var == tvar) {
00865             fprintf(stdout, "Error : wrong variable range\n");
00866           }
00867         }
00868       }
00869       for(j=var->to+1; j<eArr->num; j++) {
00870         elem = (satLinearElem_t *)eArr->space[j];
00871         if(elem->flag == 0)     continue;
00872         support = elem->support;
00873         for(k=0; k<support->num; k++) {
00874           tvar = (satLinearVar_t *)support->space[k];
00875           tvar = (satLinearVar_t *)SATnormalNode((unsigned long)tvar);
00876           if(var == tvar) {
00877             fprintf(stdout, "Error : wrong variable range\n");
00878           }
00879         }
00880       }
00881     }
00882   }
00883 }
00884 
00899 static int
00900 sat_ConvertCNF2BDD(
00901         satManager_t *cm,
00902         DdManager *mgr,
00903         int conflictFlag)
00904 {
00905 satLinearHead_t *head;
00906 DdNode *result, *cube;
00907 DdNode *l1, *l2;
00908 DdNode *nl1, *nl2;
00909 satArray_t *satArr, *arr;
00910 int limitCut;
00911 int flag, length;
00912 int cut, i;
00913 
00914   head = sat_CreateLinearHead(cm, conflictFlag);
00915 
00916   if(head == 0) return(0);
00917 
00918   head->mgr = mgr;
00919 
00920   sat_GetArrangementByForce(cm, head);
00921 
00922   if(cm->option->verbose > 3)
00923     cut = sat_PrintCutProfile(cm, head, "final", 1);
00924   else
00925     cut = sat_PrintCutProfile(cm, head, "final", 0);
00926 
00927   if(conflictFlag)
00928     limitCut = cm->option->maxLimitOfCutSizeForBDDDPLL;
00929   else
00930     limitCut = cm->option->maxLimitOfCutSizeForMonolithicBDD;
00931   if(cut > limitCut) {
00932     sat_FreeLinearHead(head);
00933     return(SAT_BDD_BACKTRACK);
00934   }
00935 
00936   flag = sat_ClusteringElementMain(cm, head);
00937 
00938   if(flag == SAT_BDD_SAT) {
00939     arr = head->latestClusterArray;
00940     satArr = sat_ArrayAlloc(16);
00941     for(i=arr->num-1; i>=0; i--) {
00942       l1 = (DdNode *)arr->space[i];
00943       i--;
00944       l2 = (DdNode *)arr->space[i];
00945       nl1 = sat_CofactorBDDArray(head, mgr, l1, satArr);
00946       nl2 = sat_CofactorBDDArray(head, mgr, l2, satArr);
00947       result = Cudd_bddAndLimit(mgr, nl1, nl2, head->bddAndLimit);
00948       cuddRef(result);
00949       Cudd_RecursiveDeref(mgr, nl1);
00950       Cudd_RecursiveDeref(mgr, nl2);
00951       cube = Cudd_LargestCube(mgr, result, &length);
00952       cuddRef(cube);
00953       sat_ExtractAssignmentFromBDD(head, mgr, satArr, cube);
00954       Cudd_RecursiveDeref(mgr, cube);
00955       Cudd_RecursiveDeref(mgr, result);
00956     }
00957     cm->assignByBDD = satArr;
00958   }
00959   sat_FreeLinearHead(head);
00960 
00961   return(flag);
00962 }
00963 
00975 static void
00976 sat_FreeLinearHead(satLinearHead_t *head)
00977 {
00978 satLinearElem_t *elem;
00979 satLinearVar_t *var;
00980 satArray_t *eArr, *vArr, *arr;
00981 satArray_t *support, *clauses;
00982 DdNode *bdd;
00983 int i;
00984 
00985   eArr = head->elemArray;
00986   if(eArr) {
00987     for(i=0; i<eArr->num; i++) {
00988       elem = (satLinearElem_t *)(eArr->space[i]);
00989       support = elem->support;
00990       if(support)
00991         sat_ArrayFree(support);
00992       if(elem->bdd)
00993         Cudd_RecursiveDeref(head->mgr, elem->bdd);
00994     }
00995   }
00996   vArr = head->varArray;
00997   if(vArr) {
00998     for(i=0; i<vArr->num; i++) {
00999       var = (satLinearVar_t *)vArr->space[i];
01000       clauses = var->clauses;
01001       if(clauses)
01002         sat_ArrayFree(clauses);
01003       if(var->bdd)
01004         Cudd_RecursiveDeref(head->mgr, var->bdd);
01005     }
01006   }
01007 
01008   if(head->variablesArray)
01009     sat_ArrayFree(head->variablesArray);
01010   if(head->clausesArray)
01011     sat_ArrayFree(head->clausesArray);
01012 
01013   if(head->elemHead)
01014     free(head->elemHead);
01015   if(head->varHead)
01016     free(head->varHead);
01017   if(head->id2edge)
01018     free(head->id2edge);
01019   if(head->edge2id)
01020     free(head->edge2id);
01021   if(head->edge2vid)
01022     free(head->edge2vid);
01023 
01024   if(head->latestClusterArray)  {
01025     arr = head->latestClusterArray;
01026     for(i=0; i<arr->num; i++) {
01027       bdd = (DdNode *)arr->space[i];
01028       Cudd_RecursiveDeref(head->mgr, bdd);
01029     }
01030     sat_ArrayFree(arr);
01031     head->latestClusterArray = 0;
01032   }
01033 
01034   if(head->deadArray)
01035     free(head->deadArray);
01036   free(head);
01037 }
01038 
01039 
01051 static int
01052 linearVarCompare(
01053   const void * node1,
01054   const void * node2)
01055 {
01056   satLinearVar_t *d1;
01057   satLinearVar_t *d2;
01058 
01059   d1 = *(satLinearVar_t **)(node1);
01060   d2 = *(satLinearVar_t **)(node2);
01061 
01062   return (d1->pos > d2->pos);
01063 }
01064 
01076 static int
01077 linearElemCompare(
01078   const void * node1,
01079   const void * node2)
01080 {
01081   satLinearElem_t *d1;
01082   satLinearElem_t *d2;
01083 
01084   d1 = *(satLinearElem_t **)(node1);
01085   d2 = *(satLinearElem_t **)(node2);
01086 
01087   return (d1->pos > d2->pos);
01088 }
01089 
01101 static void
01102 sat_GetArrangementByForce(
01103         satManager_t *cm,
01104         satLinearHead_t *head)
01105 {
01106 int iteration;
01107 double prespan, span;
01108 int from, to, sum;
01109 int i, j, inverted;
01110 satLinearElem_t *elem;
01111 satLinearVar_t *var;
01112 satArray_t *eArr, *vArr;
01113 satArray_t *support, *clauses;
01114 
01115   iteration = 0;
01116   prespan = MAXINT;
01117   eArr = head->elemArray;
01118   vArr = head->varArray;
01119   while(1) {
01120     iteration++;
01121     if(iteration > 200) break;
01122 
01123     span = 0;
01124     for(i=0; i<eArr->num; i++) {
01125       elem = (satLinearElem_t *)(eArr->space[i]);
01126       support = elem->support;
01127       sum = 0;
01128       from = MAXINT;
01129       to = -1;
01130       for(j=0; j<support->num; j++) {
01131         var = (satLinearVar_t *)(support->space[j]);
01132         inverted = SATisInverted((unsigned long)var);
01133         var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
01134         sum += var->order;
01135         if(var->order < from)   from = var->order;
01136         if(to < var->order)     to = var->order;
01137       }
01138       if(from != MAXINT && to != -1)
01139         span += (double)(to - from);
01140       elem->pos = sum / (double)(support->num);
01141     }
01142 
01143     if(iteration > 2 && (prespan * 0.9999) < span)
01144       break;
01145     prespan = span;
01146 
01147     qsort(eArr->space, eArr->num, sizeof(satLinearElem_t *), linearElemCompare);
01148     for(i=0; i<eArr->num; i++) {
01149       elem = (satLinearElem_t *)eArr->space[i];
01150       elem->order = i;
01151     }
01152 
01153     for(i=0; i<vArr->num; i++) {
01154       var = (satLinearVar_t *)vArr->space[i];
01155       clauses = var->clauses;
01156       sum = 0;
01157       for(j=0; j<clauses->num; j++) {
01158         elem = (satLinearElem_t *)clauses->space[j];
01159         sum += elem->order;
01160       }
01161       var->pos = sum / (double)(clauses->num);
01162     }
01163 
01164     qsort(vArr->space, vArr->num, sizeof(satLinearVar_t *), linearVarCompare);
01165     for(i=0; i<vArr->num; i++) {
01166       var = (satLinearVar_t *)vArr->space[i];
01167       var->order = i;
01168     }
01169   }
01170   if(cm->option->verbose > 3)
01171     fprintf(cm->stdOut, "NOTICE : %d iteration for force based arrangement\n", iteration);
01172 }
01173 
01185 static int
01186 sat_PrintCutProfile(
01187         satManager_t *cm,
01188         satLinearHead_t *head,
01189         char *baseName,
01190         int printFlag)
01191 {
01192 st_table *cutTable;
01193 st_generator *gen;
01194 FILE *fout = NIL(FILE);
01195 int i, j, cut, sum;
01196 int to, from;
01197 char filename[1024];
01198 satArray_t *support, *clauses, *eArr, *vArr;
01199 satLinearElem_t *elem;
01200 satLinearVar_t *var;
01201 double span;
01202 
01203   eArr = head->elemArray;
01204   span = 0;
01205   for(i=0; i<eArr->num; i++) {
01206     elem = (satLinearElem_t *)eArr->space[i];
01207     support = elem->support;
01208     sum = 0;
01209     to = -1;
01210     from = MAXINT;
01211     for(j=0; j<support->num; j++) {
01212       var = (satLinearVar_t *)support->space[j];
01213       var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
01214       sum += var->order;
01215       if(to < var->order)       to = var->order;
01216       if(var->order < from)     from = var->order;
01217     }
01218     elem->to = to;
01219     if(from != MAXINT && to != -1)
01220       span += (double)(to - from);
01221   }
01222 
01223   cut = 0;
01224   if(printFlag) {
01225     sprintf(filename, "%s.data", baseName);
01226     fout = fopen(filename, "w");
01227   }
01228   cutTable = st_init_table(st_ptrcmp, st_ptrhash);
01229   vArr = head->varArray;
01230   for(i=0; i<vArr->num; i++) {
01231     var = (satLinearVar_t *)vArr->space[i];
01232     clauses = var->clauses;
01233     for(j=0; j<clauses->num; j++) {
01234       elem = (satLinearElem_t *)clauses->space[j];
01235       st_insert(cutTable, (char *)elem, (char *)elem);
01236     }
01237     st_foreach_item(cutTable, gen, &elem, &elem) {
01238       if(elem->to <= i)
01239         st_delete(cutTable, &elem, NIL(char *));
01240     }
01241     if(cut < cutTable->num_entries)
01242       cut = cutTable->num_entries;
01243     if(printFlag)
01244       fprintf(fout, "%d %d\n", i, cutTable->num_entries);
01245   }
01246   st_free_table(cutTable);
01247 
01248   if(printFlag) {
01249     fclose(fout);
01250     sprintf(filename, "%s.gnu", baseName);
01251     fout = fopen(filename, "w");
01252     fprintf(fout, "set terminal postscript \n");
01253     fprintf(fout, "set output \"%s.ps\"\n", baseName);
01254     fprintf(fout, "set title \"profile of live variable span %f cut %d\"\n",
01255             span, cut);
01256     fprintf(fout, "plot \"%s.data\" using 1:2 title \"%s\" with lines\n", baseName, "cut");
01257     fclose(fout);
01258   }
01259 
01260   return cut;
01261 
01262 }
01263 
01275 static int
01276 sat_ClusteringElementMain(
01277         satManager_t *cm,
01278         satLinearHead_t *head)
01279 {
01280 int modified;
01281 satLinearElem_t *elem;
01282 DdNode *one;
01283 
01284   Cudd_AutodynEnable(head->mgr, CUDD_REORDER_SIFT);
01285 
01286   sat_InitClusteringElement(cm, head);
01287 
01288   while(1) {
01289     sat_ComputeVariableRange(cm, head);
01290     sat_ClusteringGetCandidate(cm, head);
01291     modified = sat_ClusteringElement(cm, head);
01292     if(modified == 0)   break;
01293   }
01294 
01295   if(head->elemArray->num == 1) {
01296     one = DD_ONE(head->mgr);
01297     elem = (satLinearElem_t *)(head->elemArray->space[0]);
01298     if(elem->bdd == one)                return(SAT_BDD_SAT);
01299     else if(elem->bdd == Cudd_Not(one)) return(SAT_BDD_UNSAT);
01300     else                                return(SAT_BDD_BACKTRACK);
01301   }
01302   else {
01303     return(SAT_BDD_BACKTRACK);
01304   }
01305 }
01306 
01318 static void
01319 sat_ComputeVariableRange(
01320         satManager_t *cm,
01321         satLinearHead_t *head)
01322 {
01323 satArray_t *support, *vArr, *eArr;
01324 satLinearElem_t *elem;
01325 satLinearVar_t *var;
01326 int i, j;
01327 
01328   vArr = head->varArray;
01329   eArr = head->elemArray;
01330 
01331   for(i=0; i<vArr->num; i++) {
01332     var = (satLinearVar_t *)vArr->space[i];
01333     var->from = MAXINT;
01334     var->to = -1;
01335   }
01336 
01337   for(i=0; i<eArr->num; i++) {
01338     elem = (satLinearElem_t *)eArr->space[i];
01339     support = elem->support;
01340     for(j=0; j<support->num; j++) {
01341       var = (satLinearVar_t *)support->space[j];
01342       var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
01343       if(elem->order < var->from)       var->from = elem->order;
01344       if(var->to < elem->order)         var->to = elem->order;
01345     }
01346   }
01347 }
01348 
01360 static void
01361 sat_InitClusteringElement(
01362         satManager_t *cm,
01363         satLinearHead_t *head)
01364 {
01365 DdNode *sum, *nsum, *one;
01366 DdManager *mgr;
01367 satLinearElem_t *elem;
01368 satLinearVar_t *var;
01369 satArray_t *support, *vArr, *eArr;
01370 int i, j, index;
01371 long nv;
01372 int inverted;
01373 
01374   mgr = head->mgr;
01375   vArr = head->varArray;
01376   eArr = head->elemArray;
01377   index = 0;
01378   one = DD_ONE(mgr);
01379 
01380   for(i=0; i<vArr->num; i++) {
01381     var = (satLinearVar_t *)vArr->space[i];
01382     nv = var->node;
01383     head->id2edge[index] = nv;
01384     head->edge2id[SATnodeID(nv)] = index;
01385     var->bdd = cuddUniqueInter(mgr,index,one,Cudd_Not(one));
01386     cuddRef(var->bdd);
01387     index++;
01388   }
01389 
01390   for(i=0; i<eArr->num; i++) {
01391     elem = (satLinearElem_t *)eArr->space[i];
01392     support = elem->support;
01393     sum = Cudd_Not(one);
01394     cuddRef(sum);
01395     for(j=0; j<support->num; j++) {
01396       var = (satLinearVar_t *)support->space[j];
01397       inverted = SATisInverted((unsigned long)var);
01398       var = (satLinearVar_t *)SATnormalNode((unsigned long)var);
01399       nsum = Cudd_bddAnd(mgr,Cudd_Not(sum),
01400                              (inverted ? var->bdd : Cudd_Not(var->bdd)));
01401       nsum = Cudd_Not(nsum);
01402       cuddRef(nsum);
01403 
01404       Cudd_RecursiveDeref(mgr,sum);
01405       sum = nsum;
01406     }
01407     elem->bdd = sum;
01408   }
01409 }
01410 
01411 #endif
01412 #ifndef BDDcu
01413 
01426 void
01427 sat_TryToBuildMonolithicBDD(satManager_t *cm)
01428 {
01429   fprintf(stderr, "Warning : This feature is only availabe with CUDD package\n");
01430   return;
01431 }
01432 #endif