SVF
cuddReorder.c
Go to the documentation of this file.
1 
75 #include "CUDD/util.h"
76 #include "CUDD/cuddInt.h"
77 
78 /*---------------------------------------------------------------------------*/
79 /* Constant declarations */
80 /*---------------------------------------------------------------------------*/
81 
82 #define DD_MAX_SUBTABLE_SPARSITY 8
83 #define DD_SHRINK_FACTOR 2
84 
85 /*---------------------------------------------------------------------------*/
86 /* Stucture declarations */
87 /*---------------------------------------------------------------------------*/
88 
89 /*---------------------------------------------------------------------------*/
90 /* Type declarations */
91 /*---------------------------------------------------------------------------*/
92 
93 /*---------------------------------------------------------------------------*/
94 /* Variable declarations */
95 /*---------------------------------------------------------------------------*/
96 
97 #ifndef lint
98 static char rcsid[] DD_UNUSED = "$Id: cuddReorder.c,v 1.71 2012/02/05 01:07:19 fabio Exp $";
99 #endif
100 
101 static int *entry;
102 
104 #ifdef DD_STATS
105 int ddTotalNISwaps;
106 #endif
107 
108 /*---------------------------------------------------------------------------*/
109 /* Macro declarations */
110 /*---------------------------------------------------------------------------*/
111 
114 /*---------------------------------------------------------------------------*/
115 /* Static function prototypes */
116 /*---------------------------------------------------------------------------*/
117 
118 static int ddUniqueCompare (int *ptrX, int *ptrY);
119 static Move * ddSwapAny (DdManager *table, int x, int y);
120 static int ddSiftingAux (DdManager *table, int x, int xLow, int xHigh);
121 static Move * ddSiftingUp (DdManager *table, int y, int xLow);
122 static Move * ddSiftingDown (DdManager *table, int x, int xHigh);
123 static int ddSiftingBackward (DdManager *table, int size, Move *moves);
124 static int ddReorderPreprocess (DdManager *table);
125 static int ddReorderPostprocess (DdManager *table);
126 static int ddShuffle (DdManager *table, int *permutation);
127 static int ddSiftUp (DdManager *table, int x, int xLow);
128 static void bddFixTree (DdManager *table, MtrNode *treenode);
129 static int ddUpdateMtrTree (DdManager *table, MtrNode *treenode, int *perm, int *invperm);
130 static int ddCheckPermuation (DdManager *table, MtrNode *treenode, int *perm, int *invperm);
131 
135 /*---------------------------------------------------------------------------*/
136 /* Definition of exported functions */
137 /*---------------------------------------------------------------------------*/
138 
139 
171 int
173  DdManager * table /* DD manager */,
174  Cudd_ReorderingType heuristic /* method used for reordering */,
175  int minsize /* bound below which no reordering occurs */)
176 {
177  DdHook *hook;
178  int result;
179  unsigned int nextDyn;
180 #ifdef DD_STATS
181  unsigned int initialSize;
182  unsigned int finalSize;
183 #endif
184  unsigned long localTime;
185 
186  /* Don't reorder if there are too many dead nodes. */
187  if (table->keys - table->dead < (unsigned) minsize)
188  return(1);
189 
190  if (heuristic == CUDD_REORDER_SAME) {
191  heuristic = table->autoMethod;
192  }
193  if (heuristic == CUDD_REORDER_NONE) {
194  return(1);
195  }
196 
197  /* This call to Cudd_ReduceHeap does initiate reordering. Therefore
198  ** we count it.
199  */
200  table->reorderings++;
201 
202  localTime = util_cpu_time();
203 
204  /* Run the hook functions. */
205  hook = table->preReorderingHook;
206  while (hook != NULL) {
207  int res = (hook->f)(table, "BDD", (void *)heuristic);
208  if (res == 0) return(0);
209  hook = hook->next;
210  }
211 
212  if (!ddReorderPreprocess(table)) return(0);
214 
215  if (table->keys > table->peakLiveNodes) {
216  table->peakLiveNodes = table->keys;
217  }
218 #ifdef DD_STATS
219  initialSize = table->keys - table->isolated;
220  ddTotalNISwaps = 0;
221 
222  switch(heuristic) {
223  case CUDD_REORDER_RANDOM:
225  (void) fprintf(table->out,"#:I_RANDOM ");
226  break;
227  case CUDD_REORDER_SIFT:
233  (void) fprintf(table->out,"#:I_SIFTING ");
234  break;
241  (void) fprintf(table->out,"#:I_WINDOW ");
242  break;
244  (void) fprintf(table->out,"#:I_ANNEAL ");
245  break;
247  (void) fprintf(table->out,"#:I_GENETIC ");
248  break;
249  case CUDD_REORDER_LINEAR:
251  (void) fprintf(table->out,"#:I_LINSIFT ");
252  break;
253  case CUDD_REORDER_EXACT:
254  (void) fprintf(table->out,"#:I_EXACT ");
255  break;
256  default:
257  return(0);
258  }
259  (void) fprintf(table->out,"%8d: initial size",initialSize);
260 #endif
261 
262  /* See if we should use alternate threshold for maximum growth. */
263  if (table->reordCycle && table->reorderings % table->reordCycle == 0) {
264  double saveGrowth = table->maxGrowth;
265  table->maxGrowth = table->maxGrowthAlt;
266  result = cuddTreeSifting(table,heuristic);
267  table->maxGrowth = saveGrowth;
268  } else {
269  result = cuddTreeSifting(table,heuristic);
270  }
271 
272 #ifdef DD_STATS
273  (void) fprintf(table->out,"\n");
274  finalSize = table->keys - table->isolated;
275  (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
276  (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
277  ((double)(util_cpu_time() - localTime)/1000.0));
278  (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
280  (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps);
281 #endif
282 
283  if (result == 0)
284  return(0);
285 
286  if (!ddReorderPostprocess(table))
287  return(0);
288 
289  if (table->realign) {
290  if (!cuddZddAlignToBdd(table))
291  return(0);
292  }
293 
294  nextDyn = (table->keys - table->constants.keys + 1) *
295  DD_DYN_RATIO + table->constants.keys;
296  if (table->reorderings < 20 || nextDyn > table->nextDyn)
297  table->nextDyn = nextDyn;
298  else
299  table->nextDyn += 20;
300  if (table->randomizeOrder != 0) {
301  table->nextDyn += Cudd_Random() & table->randomizeOrder;
302  }
303  table->reordered = 1;
304 
305  /* Run hook functions. */
306  hook = table->postReorderingHook;
307  while (hook != NULL) {
308  int res = (hook->f)(table, "BDD", (void *)localTime);
309  if (res == 0) return(0);
310  hook = hook->next;
311  }
312  /* Update cumulative reordering time. */
313  table->reordTime += util_cpu_time() - localTime;
314 
315  return(result);
316 
317 } /* end of Cudd_ReduceHeap */
318 
319 
336 int
338  DdManager * table /* DD manager */,
339  int * permutation /* required variable permutation */)
340 {
341 
342  int result;
343  int i;
344  int identity = 1;
345  int *perm;
346 
347  /* Don't waste time in case of identity permutation. */
348  for (i = 0; i < table->size; i++) {
349  if (permutation[i] != table->invperm[i]) {
350  identity = 0;
351  break;
352  }
353  }
354  if (identity == 1) {
355  return(1);
356  }
357  if (!ddReorderPreprocess(table)) return(0);
358  if (table->keys > table->peakLiveNodes) {
359  table->peakLiveNodes = table->keys;
360  }
361 
362  perm = ALLOC(int, table->size);
363  for (i = 0; i < table->size; i++)
364  perm[permutation[i]] = i;
365  if (!ddCheckPermuation(table,table->tree,perm,permutation)) {
366  FREE(perm);
367  return(0);
368  }
369  if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) {
370  FREE(perm);
371  return(0);
372  }
373  FREE(perm);
374 
375  result = ddShuffle(table,permutation);
376 
377  if (!ddReorderPostprocess(table)) return(0);
378 
379  return(result);
380 
381 } /* end of Cudd_ShuffleHeap */
382 
383 
384 /*---------------------------------------------------------------------------*/
385 /* Definition of internal functions */
386 /*---------------------------------------------------------------------------*/
387 
388 
404 DdNode *
406  DdManager * table)
407 {
408  int i;
409  DdNodePtr *mem;
410  DdNode *list, *node;
411  extern DD_OOMFP MMoutOfMemory;
412  DD_OOMFP saveHandler;
413 
414  if (table->nextFree == NULL) { /* free list is empty */
415  /* Try to allocate a new block. */
416  saveHandler = MMoutOfMemory;
417  MMoutOfMemory = Cudd_OutOfMem;
418  mem = (DdNodePtr *) ALLOC(DdNode, DD_MEM_CHUNK + 1);
419  MMoutOfMemory = saveHandler;
420  if (mem == NULL && table->stash != NULL) {
421  FREE(table->stash);
422  table->stash = NULL;
423  /* Inhibit resizing of tables. */
424  table->maxCacheHard = table->cacheSlots - 1;
425  table->cacheSlack = - (int) (table->cacheSlots + 1);
426  for (i = 0; i < table->size; i++) {
427  table->subtables[i].maxKeys <<= 2;
428  }
429  mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
430  }
431  if (mem == NULL) {
432  /* Out of luck. Call the default handler to do
433  ** whatever it specifies for a failed malloc. If this
434  ** handler returns, then set error code, print
435  ** warning, and return. */
436  (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
437  table->errorCode = CUDD_MEMORY_OUT;
438 #ifdef DD_VERBOSE
439  (void) fprintf(table->err,
440  "cuddDynamicAllocNode: out of memory");
441  (void) fprintf(table->err,"Memory in use = %lu\n",
442  table->memused);
443 #endif
444  return(NULL);
445  } else { /* successful allocation; slice memory */
446  unsigned long offset;
447  table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
448  mem[0] = (DdNode *) table->memoryList;
449  table->memoryList = mem;
450 
451  /* Here we rely on the fact that the size of a DdNode is a
452  ** power of 2 and a multiple of the size of a pointer.
453  ** If we align one node, all the others will be aligned
454  ** as well. */
455  offset = (unsigned long) mem & (sizeof(DdNode) - 1);
456  mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
457 #ifdef DD_DEBUG
458  assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0);
459 #endif
460  list = (DdNode *) mem;
461 
462  i = 1;
463  do {
464  list[i - 1].ref = 0;
465  list[i - 1].next = &list[i];
466  } while (++i < DD_MEM_CHUNK);
467 
468  list[DD_MEM_CHUNK-1].ref = 0;
469  list[DD_MEM_CHUNK - 1].next = NULL;
470 
471  table->nextFree = &list[0];
472  }
473  } /* if free list empty */
474 
475  node = table->nextFree;
476  table->nextFree = node->next;
477  return (node);
478 
479 } /* end of cuddDynamicAllocNode */
480 
481 
501 int
503  DdManager * table,
504  int lower,
505  int upper)
506 {
507  int i;
508  int *var;
509  int size;
510  int x;
511  int result;
512 #ifdef DD_STATS
513  int previousSize;
514 #endif
515 
516  size = table->size;
517 
518  /* Find order in which to sift variables. */
519  var = NULL;
520  entry = ALLOC(int,size);
521  if (entry == NULL) {
522  table->errorCode = CUDD_MEMORY_OUT;
523  goto cuddSiftingOutOfMem;
524  }
525  var = ALLOC(int,size);
526  if (var == NULL) {
527  table->errorCode = CUDD_MEMORY_OUT;
528  goto cuddSiftingOutOfMem;
529  }
530 
531  for (i = 0; i < size; i++) {
532  x = table->perm[i];
533  entry[i] = table->subtables[x].keys;
534  var[i] = i;
535  }
536 
537  qsort((void *)var,size,sizeof(int),(DD_QSFP)ddUniqueCompare);
538 
539  /* Now sift. */
540  for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
541  if (ddTotalNumberSwapping >= table->siftMaxSwap)
542  break;
543  if (util_cpu_time() - table->startTime + table->reordTime
544  > table->timeLimit) {
545  table->autoDyn = 0; /* prevent further reordering */
546  break;
547  }
548  x = table->perm[var[i]];
549 
550  if (x < lower || x > upper || table->subtables[x].bindVar == 1)
551  continue;
552 #ifdef DD_STATS
553  previousSize = table->keys - table->isolated;
554 #endif
555  result = ddSiftingAux(table, x, lower, upper);
556  if (!result) goto cuddSiftingOutOfMem;
557 #ifdef DD_STATS
558  if (table->keys < (unsigned) previousSize + table->isolated) {
559  (void) fprintf(table->out,"-");
560  } else if (table->keys > (unsigned) previousSize + table->isolated) {
561  (void) fprintf(table->out,"+"); /* should never happen */
562  (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
563  } else {
564  (void) fprintf(table->out,"=");
565  }
566  fflush(table->out);
567 #endif
568  }
569 
570  FREE(var);
571  FREE(entry);
572 
573  return(1);
574 
575 cuddSiftingOutOfMem:
576 
577  if (entry != NULL) FREE(entry);
578  if (var != NULL) FREE(var);
579 
580  return(0);
581 
582 } /* end of cuddSifting */
583 
584 
603 int
605  DdManager * table,
606  int lower,
607  int upper,
608  Cudd_ReorderingType heuristic)
609 {
610  int i, j;
611  int max, keys;
612  int nvars;
613  int x, y;
614  int iterate;
615  int previousSize;
616  Move *moves, *move;
617  int pivot;
618  int modulo;
619  int result;
620 
621 #ifdef DD_DEBUG
622  /* Sanity check */
623  assert(lower >= 0 && upper < table->size && lower <= upper);
624 #endif
625 
626  nvars = upper - lower + 1;
627  iterate = nvars;
628 
629  for (i = 0; i < iterate; i++) {
630  if (ddTotalNumberSwapping >= table->siftMaxSwap)
631  break;
632  if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
633  max = -1;
634  for (j = lower; j <= upper; j++) {
635  if ((keys = table->subtables[j].keys) > max) {
636  max = keys;
637  pivot = j;
638  }
639  }
640 
641  modulo = upper - pivot;
642  if (modulo == 0) {
643  y = pivot;
644  } else{
645  y = pivot + 1 + ((int) Cudd_Random() % modulo);
646  }
647 
648  modulo = pivot - lower - 1;
649  if (modulo < 1) {
650  x = lower;
651  } else{
652  do {
653  x = (int) Cudd_Random() % modulo;
654  } while (x == y);
655  }
656  } else {
657  x = ((int) Cudd_Random() % nvars) + lower;
658  do {
659  y = ((int) Cudd_Random() % nvars) + lower;
660  } while (x == y);
661  }
662  previousSize = table->keys - table->isolated;
663  moves = ddSwapAny(table,x,y);
664  if (moves == NULL) goto cuddSwappingOutOfMem;
665  result = ddSiftingBackward(table,previousSize,moves);
666  if (!result) goto cuddSwappingOutOfMem;
667  while (moves != NULL) {
668  move = moves->next;
669  cuddDeallocMove(table, moves);
670  moves = move;
671  }
672 #ifdef DD_STATS
673  if (table->keys < (unsigned) previousSize + table->isolated) {
674  (void) fprintf(table->out,"-");
675  } else if (table->keys > (unsigned) previousSize + table->isolated) {
676  (void) fprintf(table->out,"+"); /* should never happen */
677  } else {
678  (void) fprintf(table->out,"=");
679  }
680  fflush(table->out);
681 #endif
682 #if 0
683  (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n",
684  table->keys - table->isolated);
685 #endif
686  }
687 
688  return(1);
689 
690 cuddSwappingOutOfMem:
691  while (moves != NULL) {
692  move = moves->next;
693  cuddDeallocMove(table, moves);
694  moves = move;
695  }
696 
697  return(0);
698 
699 } /* end of cuddSwapping */
700 
701 
714 int
716  DdManager * table,
717  int x)
718 {
719  return(x+1);
720 
721 } /* end of cuddNextHigh */
722 
723 
736 int
738  DdManager * table,
739  int x)
740 {
741  return(x-1);
742 
743 } /* end of cuddNextLow */
744 
745 
759 int
761  DdManager * table,
762  int x,
763  int y)
764 {
765  DdNodePtr *xlist, *ylist;
766  int xindex, yindex;
767  int xslots, yslots;
768  int xshift, yshift;
769  int oldxkeys, oldykeys;
770  int newxkeys, newykeys;
771  int comple, newcomplement;
772  int i;
773  Cudd_VariableType varType;
774  Cudd_LazyGroupType groupType;
775  int posn;
776  int isolated;
777  DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
778  DdNode *g,*next;
779  DdNodePtr *previousP;
780  DdNode *tmp;
781  DdNode *sentinel = &(table->sentinel);
782  extern DD_OOMFP MMoutOfMemory;
783  DD_OOMFP saveHandler;
784 
785 #ifdef DD_DEBUG
786  int count,idcheck;
787 #endif
788 
789 #ifdef DD_DEBUG
790  assert(x < y);
791  assert(cuddNextHigh(table,x) == y);
792  assert(table->subtables[x].keys != 0);
793  assert(table->subtables[y].keys != 0);
794  assert(table->subtables[x].dead == 0);
795  assert(table->subtables[y].dead == 0);
796 #endif
797 
799 
800  /* Get parameters of x subtable. */
801  xindex = table->invperm[x];
802  xlist = table->subtables[x].nodelist;
803  oldxkeys = table->subtables[x].keys;
804  xslots = table->subtables[x].slots;
805  xshift = table->subtables[x].shift;
806 
807  /* Get parameters of y subtable. */
808  yindex = table->invperm[y];
809  ylist = table->subtables[y].nodelist;
810  oldykeys = table->subtables[y].keys;
811  yslots = table->subtables[y].slots;
812  yshift = table->subtables[y].shift;
813 
814  if (!cuddTestInteract(table,xindex,yindex)) {
815 #ifdef DD_STATS
816  ddTotalNISwaps++;
817 #endif
818  newxkeys = oldxkeys;
819  newykeys = oldykeys;
820  } else {
821  newxkeys = 0;
822  newykeys = oldykeys;
823 
824  /* Check whether the two projection functions involved in this
825  ** swap are isolated. At the end, we'll be able to tell how many
826  ** isolated projection functions are there by checking only these
827  ** two functions again. This is done to eliminate the isolated
828  ** projection functions from the node count.
829  */
830  isolated = - ((table->vars[xindex]->ref == 1) +
831  (table->vars[yindex]->ref == 1));
832 
833  /* The nodes in the x layer that do not depend on
834  ** y will stay there; the others are put in a chain.
835  ** The chain is handled as a LIFO; g points to the beginning.
836  */
837  g = NULL;
838  if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) &&
839  oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) {
840  for (i = 0; i < xslots; i++) {
841  previousP = &(xlist[i]);
842  f = *previousP;
843  while (f != sentinel) {
844  next = f->next;
845  f1 = cuddT(f); f0 = cuddE(f);
846  if (f1->index != (DdHalfWord) yindex &&
847  Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
848  /* stays */
849  newxkeys++;
850  *previousP = f;
851  previousP = &(f->next);
852  } else {
853  f->index = yindex;
854  f->next = g;
855  g = f;
856  }
857  f = next;
858  } /* while there are elements in the collision chain */
859  *previousP = sentinel;
860  } /* for each slot of the x subtable */
861  } else { /* resize xlist */
862  DdNode *h = NULL;
863  DdNodePtr *newxlist;
864  unsigned int newxslots;
865  int newxshift;
866  /* Empty current xlist. Nodes that stay go to list h;
867  ** nodes that move go to list g. */
868  for (i = 0; i < xslots; i++) {
869  f = xlist[i];
870  while (f != sentinel) {
871  next = f->next;
872  f1 = cuddT(f); f0 = cuddE(f);
873  if (f1->index != (DdHalfWord) yindex &&
874  Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
875  /* stays */
876  f->next = h;
877  h = f;
878  newxkeys++;
879  } else {
880  f->index = yindex;
881  f->next = g;
882  g = f;
883  }
884  f = next;
885  } /* while there are elements in the collision chain */
886  } /* for each slot of the x subtable */
887  /* Decide size of new subtable. */
888  newxshift = xshift;
889  newxslots = xslots;
890  while ((unsigned) oldxkeys > DD_MAX_SUBTABLE_DENSITY * newxslots) {
891  newxshift--;
892  newxslots <<= 1;
893  }
894  while ((unsigned) oldxkeys < newxslots &&
895  newxslots > table->initSlots) {
896  newxshift++;
897  newxslots >>= 1;
898  }
899  /* Try to allocate new table. Be ready to back off. */
900  saveHandler = MMoutOfMemory;
901  MMoutOfMemory = Cudd_OutOfMem;
902  newxlist = ALLOC(DdNodePtr, newxslots);
903  MMoutOfMemory = saveHandler;
904  if (newxlist == NULL) {
905  (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i);
906  newxlist = xlist;
907  newxslots = xslots;
908  newxshift = xshift;
909  } else {
910  table->slots += ((int) newxslots - xslots);
911  table->minDead = (unsigned)
912  (table->gcFrac * (double) table->slots);
913  table->cacheSlack = (int)
915  * table->slots) - 2 * (int) table->cacheSlots;
916  table->memused +=
917  ((int) newxslots - xslots) * sizeof(DdNodePtr);
918  FREE(xlist);
919  xslots = newxslots;
920  xshift = newxshift;
921  xlist = newxlist;
922  }
923  /* Initialize new subtable. */
924  for (i = 0; i < xslots; i++) {
925  xlist[i] = sentinel;
926  }
927  /* Move nodes that were parked in list h to their new home. */
928  f = h;
929  while (f != NULL) {
930  next = f->next;
931  f1 = cuddT(f);
932  f0 = cuddE(f);
933  /* Check xlist for pair (f11,f01). */
934  posn = ddHash(f1, f0, xshift);
935  /* For each element tmp in collision list xlist[posn]. */
936  previousP = &(xlist[posn]);
937  tmp = *previousP;
938  while (f1 < cuddT(tmp)) {
939  previousP = &(tmp->next);
940  tmp = *previousP;
941  }
942  while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) {
943  previousP = &(tmp->next);
944  tmp = *previousP;
945  }
946  f->next = *previousP;
947  *previousP = f;
948  f = next;
949  }
950  }
951 
952 #ifdef DD_COUNT
953  table->swapSteps += oldxkeys - newxkeys;
954 #endif
955  /* Take care of the x nodes that must be re-expressed.
956  ** They form a linked list pointed by g. Their index has been
957  ** already changed to yindex.
958  */
959  f = g;
960  while (f != NULL) {
961  next = f->next;
962  /* Find f1, f0, f11, f10, f01, f00. */
963  f1 = cuddT(f);
964 #ifdef DD_DEBUG
965  assert(!(Cudd_IsComplement(f1)));
966 #endif
967  if ((int) f1->index == yindex) {
968  f11 = cuddT(f1); f10 = cuddE(f1);
969  } else {
970  f11 = f10 = f1;
971  }
972 #ifdef DD_DEBUG
973  assert(!(Cudd_IsComplement(f11)));
974 #endif
975  f0 = cuddE(f);
976  comple = Cudd_IsComplement(f0);
977  f0 = Cudd_Regular(f0);
978  if ((int) f0->index == yindex) {
979  f01 = cuddT(f0); f00 = cuddE(f0);
980  } else {
981  f01 = f00 = f0;
982  }
983  if (comple) {
984  f01 = Cudd_Not(f01);
985  f00 = Cudd_Not(f00);
986  }
987  /* Decrease ref count of f1. */
988  cuddSatDec(f1->ref);
989  /* Create the new T child. */
990  if (f11 == f01) {
991  newf1 = f11;
992  cuddSatInc(newf1->ref);
993  } else {
994  /* Check xlist for triple (xindex,f11,f01). */
995  posn = ddHash(f11, f01, xshift);
996  /* For each element newf1 in collision list xlist[posn]. */
997  previousP = &(xlist[posn]);
998  newf1 = *previousP;
999  while (f11 < cuddT(newf1)) {
1000  previousP = &(newf1->next);
1001  newf1 = *previousP;
1002  }
1003  while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) {
1004  previousP = &(newf1->next);
1005  newf1 = *previousP;
1006  }
1007  if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
1008  cuddSatInc(newf1->ref);
1009  } else { /* no match */
1010  newf1 = cuddDynamicAllocNode(table);
1011  if (newf1 == NULL)
1012  goto cuddSwapOutOfMem;
1013  newf1->index = xindex; newf1->ref = 1;
1014  cuddT(newf1) = f11;
1015  cuddE(newf1) = f01;
1016  /* Insert newf1 in the collision list xlist[posn];
1017  ** increase the ref counts of f11 and f01.
1018  */
1019  newxkeys++;
1020  newf1->next = *previousP;
1021  *previousP = newf1;
1022  cuddSatInc(f11->ref);
1023  tmp = Cudd_Regular(f01);
1024  cuddSatInc(tmp->ref);
1025  }
1026  }
1027  cuddT(f) = newf1;
1028 #ifdef DD_DEBUG
1029  assert(!(Cudd_IsComplement(newf1)));
1030 #endif
1031 
1032  /* Do the same for f0, keeping complement dots into account. */
1033  /* Decrease ref count of f0. */
1034  tmp = Cudd_Regular(f0);
1035  cuddSatDec(tmp->ref);
1036  /* Create the new E child. */
1037  if (f10 == f00) {
1038  newf0 = f00;
1039  tmp = Cudd_Regular(newf0);
1040  cuddSatInc(tmp->ref);
1041  } else {
1042  /* make sure f10 is regular */
1043  newcomplement = Cudd_IsComplement(f10);
1044  if (newcomplement) {
1045  f10 = Cudd_Not(f10);
1046  f00 = Cudd_Not(f00);
1047  }
1048  /* Check xlist for triple (xindex,f10,f00). */
1049  posn = ddHash(f10, f00, xshift);
1050  /* For each element newf0 in collision list xlist[posn]. */
1051  previousP = &(xlist[posn]);
1052  newf0 = *previousP;
1053  while (f10 < cuddT(newf0)) {
1054  previousP = &(newf0->next);
1055  newf0 = *previousP;
1056  }
1057  while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) {
1058  previousP = &(newf0->next);
1059  newf0 = *previousP;
1060  }
1061  if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
1062  cuddSatInc(newf0->ref);
1063  } else { /* no match */
1064  newf0 = cuddDynamicAllocNode(table);
1065  if (newf0 == NULL)
1066  goto cuddSwapOutOfMem;
1067  newf0->index = xindex; newf0->ref = 1;
1068  cuddT(newf0) = f10;
1069  cuddE(newf0) = f00;
1070  /* Insert newf0 in the collision list xlist[posn];
1071  ** increase the ref counts of f10 and f00.
1072  */
1073  newxkeys++;
1074  newf0->next = *previousP;
1075  *previousP = newf0;
1076  cuddSatInc(f10->ref);
1077  tmp = Cudd_Regular(f00);
1078  cuddSatInc(tmp->ref);
1079  }
1080  if (newcomplement) {
1081  newf0 = Cudd_Not(newf0);
1082  }
1083  }
1084  cuddE(f) = newf0;
1085 
1086  /* Insert the modified f in ylist.
1087  ** The modified f does not already exists in ylist.
1088  ** (Because of the uniqueness of the cofactors.)
1089  */
1090  posn = ddHash(newf1, newf0, yshift);
1091  newykeys++;
1092  previousP = &(ylist[posn]);
1093  tmp = *previousP;
1094  while (newf1 < cuddT(tmp)) {
1095  previousP = &(tmp->next);
1096  tmp = *previousP;
1097  }
1098  while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
1099  previousP = &(tmp->next);
1100  tmp = *previousP;
1101  }
1102  f->next = *previousP;
1103  *previousP = f;
1104  f = next;
1105  } /* while f != NULL */
1106 
1107  /* GC the y layer. */
1108 
1109  /* For each node f in ylist. */
1110  for (i = 0; i < yslots; i++) {
1111  previousP = &(ylist[i]);
1112  f = *previousP;
1113  while (f != sentinel) {
1114  next = f->next;
1115  if (f->ref == 0) {
1116  tmp = cuddT(f);
1117  cuddSatDec(tmp->ref);
1118  tmp = Cudd_Regular(cuddE(f));
1119  cuddSatDec(tmp->ref);
1120  cuddDeallocNode(table,f);
1121  newykeys--;
1122  } else {
1123  *previousP = f;
1124  previousP = &(f->next);
1125  }
1126  f = next;
1127  } /* while f */
1128  *previousP = sentinel;
1129  } /* for i */
1130 
1131 #ifdef DD_DEBUG
1132 #if 0
1133  (void) fprintf(table->out,"Swapping %d and %d\n",x,y);
1134 #endif
1135  count = 0;
1136  idcheck = 0;
1137  for (i = 0; i < yslots; i++) {
1138  f = ylist[i];
1139  while (f != sentinel) {
1140  count++;
1141  if (f->index != (DdHalfWord) yindex)
1142  idcheck++;
1143  f = f->next;
1144  }
1145  }
1146  if (count != newykeys) {
1147  (void) fprintf(table->out,
1148  "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",
1149  oldykeys,newykeys,count);
1150  }
1151  if (idcheck != 0)
1152  (void) fprintf(table->out,
1153  "Error in id's of ylist\twrong id's = %d\n",
1154  idcheck);
1155  count = 0;
1156  idcheck = 0;
1157  for (i = 0; i < xslots; i++) {
1158  f = xlist[i];
1159  while (f != sentinel) {
1160  count++;
1161  if (f->index != (DdHalfWord) xindex)
1162  idcheck++;
1163  f = f->next;
1164  }
1165  }
1166  if (count != newxkeys) {
1167  (void) fprintf(table->out,
1168  "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",
1169  oldxkeys,newxkeys,count);
1170  }
1171  if (idcheck != 0)
1172  (void) fprintf(table->out,
1173  "Error in id's of xlist\twrong id's = %d\n",
1174  idcheck);
1175 #endif
1176 
1177  isolated += (table->vars[xindex]->ref == 1) +
1178  (table->vars[yindex]->ref == 1);
1179  table->isolated += isolated;
1180  }
1181 
1182  /* Set the appropriate fields in table. */
1183  table->subtables[x].nodelist = ylist;
1184  table->subtables[x].slots = yslots;
1185  table->subtables[x].shift = yshift;
1186  table->subtables[x].keys = newykeys;
1187  table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
1188  i = table->subtables[x].bindVar;
1189  table->subtables[x].bindVar = table->subtables[y].bindVar;
1190  table->subtables[y].bindVar = i;
1191  /* Adjust filds for lazy sifting. */
1192  varType = table->subtables[x].varType;
1193  table->subtables[x].varType = table->subtables[y].varType;
1194  table->subtables[y].varType = varType;
1195  i = table->subtables[x].pairIndex;
1196  table->subtables[x].pairIndex = table->subtables[y].pairIndex;
1197  table->subtables[y].pairIndex = i;
1198  i = table->subtables[x].varHandled;
1199  table->subtables[x].varHandled = table->subtables[y].varHandled;
1200  table->subtables[y].varHandled = i;
1201  groupType = table->subtables[x].varToBeGrouped;
1202  table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped;
1203  table->subtables[y].varToBeGrouped = groupType;
1204 
1205  table->subtables[y].nodelist = xlist;
1206  table->subtables[y].slots = xslots;
1207  table->subtables[y].shift = xshift;
1208  table->subtables[y].keys = newxkeys;
1209  table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
1210 
1211  table->perm[xindex] = y; table->perm[yindex] = x;
1212  table->invperm[x] = yindex; table->invperm[y] = xindex;
1213 
1214  table->keys += newxkeys + newykeys - oldxkeys - oldykeys;
1215 
1216  return(table->keys - table->isolated);
1217 
1218 cuddSwapOutOfMem:
1219  (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n");
1220 
1221  return (0);
1222 
1223 } /* end of cuddSwapInPlace */
1224 
1225 
1249 int
1251  DdManager * table /* DD manager */)
1252 {
1253  int *invperm; /* permutation array */
1254  int M; /* ratio of ZDD variables to BDD variables */
1255  int i; /* loop index */
1256  int result; /* return value */
1257 
1258  /* We assume that a ratio of 0 is OK. */
1259  if (table->size == 0)
1260  return(1);
1261 
1262  M = table->sizeZ / table->size;
1263  /* Check whether the number of ZDD variables is a multiple of the
1264  ** number of BDD variables.
1265  */
1266  if (M * table->size != table->sizeZ)
1267  return(0);
1268  /* Create and initialize the inverse permutation array. */
1269  invperm = ALLOC(int,table->size);
1270  if (invperm == NULL) {
1271  table->errorCode = CUDD_MEMORY_OUT;
1272  return(0);
1273  }
1274  for (i = 0; i < table->sizeZ; i += M) {
1275  int indexZ = table->invpermZ[i];
1276  int index = indexZ / M;
1277  invperm[i / M] = index;
1278  }
1279  /* Eliminate dead nodes. Do not scan the cache again, because we
1280  ** assume that Cudd_zddReduceHeap has already cleared it.
1281  */
1282  cuddGarbageCollect(table,0);
1283 
1284  /* Initialize number of isolated projection functions. */
1285  table->isolated = 0;
1286  for (i = 0; i < table->size; i++) {
1287  if (table->vars[i]->ref == 1) table->isolated++;
1288  }
1289 
1290  /* Initialize the interaction matrix. */
1291  result = cuddInitInteract(table);
1292  if (result == 0) return(0);
1293 
1294  result = ddShuffle(table, invperm);
1295  FREE(invperm);
1296  /* Free interaction matrix. */
1297  FREE(table->interact);
1298  /* Fix the BDD variable group tree. */
1299  bddFixTree(table,table->tree);
1300  return(result);
1301 
1302 } /* end of cuddBddAlignToZdd */
1303 
1304 /*---------------------------------------------------------------------------*/
1305 /* Definition of static functions */
1306 /*---------------------------------------------------------------------------*/
1307 
1308 
1321 static int
1323  int * ptrX,
1324  int * ptrY)
1325 {
1326 #if 0
1327  if (entry[*ptrY] == entry[*ptrX]) {
1328  return((*ptrX) - (*ptrY));
1329  }
1330 #endif
1331  return(entry[*ptrY] - entry[*ptrX]);
1332 
1333 } /* end of ddUniqueCompare */
1334 
1335 
1345 static Move *
1347  DdManager * table,
1348  int x,
1349  int y)
1350 {
1351  Move *move, *moves;
1352  int xRef,yRef;
1353  int xNext,yNext;
1354  int size;
1355  int limitSize;
1356  int tmp;
1357 
1358  if (x >y) {
1359  tmp = x; x = y; y = tmp;
1360  }
1361 
1362  xRef = x; yRef = y;
1363 
1364  xNext = cuddNextHigh(table,x);
1365  yNext = cuddNextLow(table,y);
1366  moves = NULL;
1367  limitSize = table->keys - table->isolated;
1368 
1369  for (;;) {
1370  if ( xNext == yNext) {
1371  size = cuddSwapInPlace(table,x,xNext);
1372  if (size == 0) goto ddSwapAnyOutOfMem;
1373  move = (Move *) cuddDynamicAllocNode(table);
1374  if (move == NULL) goto ddSwapAnyOutOfMem;
1375  move->x = x;
1376  move->y = xNext;
1377  move->size = size;
1378  move->next = moves;
1379  moves = move;
1380 
1381  size = cuddSwapInPlace(table,yNext,y);
1382  if (size == 0) goto ddSwapAnyOutOfMem;
1383  move = (Move *) cuddDynamicAllocNode(table);
1384  if (move == NULL) goto ddSwapAnyOutOfMem;
1385  move->x = yNext;
1386  move->y = y;
1387  move->size = size;
1388  move->next = moves;
1389  moves = move;
1390 
1391  size = cuddSwapInPlace(table,x,xNext);
1392  if (size == 0) goto ddSwapAnyOutOfMem;
1393  move = (Move *) cuddDynamicAllocNode(table);
1394  if (move == NULL) goto ddSwapAnyOutOfMem;
1395  move->x = x;
1396  move->y = xNext;
1397  move->size = size;
1398  move->next = moves;
1399  moves = move;
1400 
1401  tmp = x; x = y; y = tmp;
1402 
1403  } else if (x == yNext) {
1404 
1405  size = cuddSwapInPlace(table,x,xNext);
1406  if (size == 0) goto ddSwapAnyOutOfMem;
1407  move = (Move *) cuddDynamicAllocNode(table);
1408  if (move == NULL) goto ddSwapAnyOutOfMem;
1409  move->x = x;
1410  move->y = xNext;
1411  move->size = size;
1412  move->next = moves;
1413  moves = move;
1414 
1415  tmp = x; x = y; y = tmp;
1416 
1417  } else {
1418  size = cuddSwapInPlace(table,x,xNext);
1419  if (size == 0) goto ddSwapAnyOutOfMem;
1420  move = (Move *) cuddDynamicAllocNode(table);
1421  if (move == NULL) goto ddSwapAnyOutOfMem;
1422  move->x = x;
1423  move->y = xNext;
1424  move->size = size;
1425  move->next = moves;
1426  moves = move;
1427 
1428  size = cuddSwapInPlace(table,yNext,y);
1429  if (size == 0) goto ddSwapAnyOutOfMem;
1430  move = (Move *) cuddDynamicAllocNode(table);
1431  if (move == NULL) goto ddSwapAnyOutOfMem;
1432  move->x = yNext;
1433  move->y = y;
1434  move->size = size;
1435  move->next = moves;
1436  moves = move;
1437 
1438  x = xNext;
1439  y = yNext;
1440  }
1441 
1442  xNext = cuddNextHigh(table,x);
1443  yNext = cuddNextLow(table,y);
1444  if (xNext > yRef) break;
1445 
1446  if ((double) size > table->maxGrowth * (double) limitSize) break;
1447  if (size < limitSize) limitSize = size;
1448  }
1449  if (yNext>=xRef) {
1450  size = cuddSwapInPlace(table,yNext,y);
1451  if (size == 0) goto ddSwapAnyOutOfMem;
1452  move = (Move *) cuddDynamicAllocNode(table);
1453  if (move == NULL) goto ddSwapAnyOutOfMem;
1454  move->x = yNext;
1455  move->y = y;
1456  move->size = size;
1457  move->next = moves;
1458  moves = move;
1459  }
1460 
1461  return(moves);
1462 
1463 ddSwapAnyOutOfMem:
1464  while (moves != NULL) {
1465  move = moves->next;
1466  cuddDeallocMove(table, moves);
1467  moves = move;
1468  }
1469  return(NULL);
1470 
1471 } /* end of ddSwapAny */
1472 
1473 
1486 static int
1488  DdManager * table,
1489  int x,
1490  int xLow,
1491  int xHigh)
1492 {
1493 
1494  Move *move;
1495  Move *moveUp; /* list of up moves */
1496  Move *moveDown; /* list of down moves */
1497  int initialSize;
1498  int result;
1499 
1500  initialSize = table->keys - table->isolated;
1501 
1502  moveDown = NULL;
1503  moveUp = NULL;
1504 
1505  if (x == xLow) {
1506  moveDown = ddSiftingDown(table,x,xHigh);
1507  /* At this point x --> xHigh unless bounding occurred. */
1508  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1509  /* Move backward and stop at best position. */
1510  result = ddSiftingBackward(table,initialSize,moveDown);
1511  if (!result) goto ddSiftingAuxOutOfMem;
1512 
1513  } else if (x == xHigh) {
1514  moveUp = ddSiftingUp(table,x,xLow);
1515  /* At this point x --> xLow unless bounding occurred. */
1516  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1517  /* Move backward and stop at best position. */
1518  result = ddSiftingBackward(table,initialSize,moveUp);
1519  if (!result) goto ddSiftingAuxOutOfMem;
1520 
1521  } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
1522  moveDown = ddSiftingDown(table,x,xHigh);
1523  /* At this point x --> xHigh unless bounding occurred. */
1524  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1525  if (moveDown != NULL) {
1526  x = moveDown->y;
1527  }
1528  moveUp = ddSiftingUp(table,x,xLow);
1529  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1530  /* Move backward and stop at best position */
1531  result = ddSiftingBackward(table,initialSize,moveUp);
1532  if (!result) goto ddSiftingAuxOutOfMem;
1533 
1534  } else { /* must go up first: shorter */
1535  moveUp = ddSiftingUp(table,x,xLow);
1536  /* At this point x --> xLow unless bounding occurred. */
1537  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1538  if (moveUp != NULL) {
1539  x = moveUp->x;
1540  }
1541  moveDown = ddSiftingDown(table,x,xHigh);
1542  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1543  /* Move backward and stop at best position. */
1544  result = ddSiftingBackward(table,initialSize,moveDown);
1545  if (!result) goto ddSiftingAuxOutOfMem;
1546  }
1547 
1548  while (moveDown != NULL) {
1549  move = moveDown->next;
1550  cuddDeallocMove(table, moveDown);
1551  moveDown = move;
1552  }
1553  while (moveUp != NULL) {
1554  move = moveUp->next;
1555  cuddDeallocMove(table, moveUp);
1556  moveUp = move;
1557  }
1558 
1559  return(1);
1560 
1561 ddSiftingAuxOutOfMem:
1562  if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
1563  while (moveDown != NULL) {
1564  move = moveDown->next;
1565  cuddDeallocMove(table, moveDown);
1566  moveDown = move;
1567  }
1568  }
1569  if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
1570  while (moveUp != NULL) {
1571  move = moveUp->next;
1572  cuddDeallocMove(table, moveUp);
1573  moveUp = move;
1574  }
1575  }
1576 
1577  return(0);
1578 
1579 } /* end of ddSiftingAux */
1580 
1581 
1593 static Move *
1595  DdManager * table,
1596  int y,
1597  int xLow)
1598 {
1599  Move *moves;
1600  Move *move;
1601  int x;
1602  int size;
1603  int limitSize;
1604  int xindex, yindex;
1605  int isolated;
1606  int L; /* lower bound on DD size */
1607 #ifdef DD_DEBUG
1608  int checkL;
1609  int z;
1610  int zindex;
1611 #endif
1612 
1613  moves = NULL;
1614  yindex = table->invperm[y];
1615 
1616  /* Initialize the lower bound.
1617  ** The part of the DD below y will not change.
1618  ** The part of the DD above y that does not interact with y will not
1619  ** change. The rest may vanish in the best case, except for
1620  ** the nodes at level xLow, which will not vanish, regardless.
1621  */
1622  limitSize = L = table->keys - table->isolated;
1623  for (x = xLow + 1; x < y; x++) {
1624  xindex = table->invperm[x];
1625  if (cuddTestInteract(table,xindex,yindex)) {
1626  isolated = table->vars[xindex]->ref == 1;
1627  L -= table->subtables[x].keys - isolated;
1628  }
1629  }
1630  isolated = table->vars[yindex]->ref == 1;
1631  L -= table->subtables[y].keys - isolated;
1632 
1633  x = cuddNextLow(table,y);
1634  while (x >= xLow && L <= limitSize) {
1635  xindex = table->invperm[x];
1636 #ifdef DD_DEBUG
1637  checkL = table->keys - table->isolated;
1638  for (z = xLow + 1; z < y; z++) {
1639  zindex = table->invperm[z];
1640  if (cuddTestInteract(table,zindex,yindex)) {
1641  isolated = table->vars[zindex]->ref == 1;
1642  checkL -= table->subtables[z].keys - isolated;
1643  }
1644  }
1645  isolated = table->vars[yindex]->ref == 1;
1646  checkL -= table->subtables[y].keys - isolated;
1647  assert(L == checkL);
1648 #endif
1649  size = cuddSwapInPlace(table,x,y);
1650  if (size == 0) goto ddSiftingUpOutOfMem;
1651  /* Update the lower bound. */
1652  if (cuddTestInteract(table,xindex,yindex)) {
1653  isolated = table->vars[xindex]->ref == 1;
1654  L += table->subtables[y].keys - isolated;
1655  }
1656  move = (Move *) cuddDynamicAllocNode(table);
1657  if (move == NULL) goto ddSiftingUpOutOfMem;
1658  move->x = x;
1659  move->y = y;
1660  move->size = size;
1661  move->next = moves;
1662  moves = move;
1663  if ((double) size > (double) limitSize * table->maxGrowth) break;
1664  if (size < limitSize) limitSize = size;
1665  y = x;
1666  x = cuddNextLow(table,y);
1667  }
1668  return(moves);
1669 
1670 ddSiftingUpOutOfMem:
1671  while (moves != NULL) {
1672  move = moves->next;
1673  cuddDeallocMove(table, moves);
1674  moves = move;
1675  }
1676  return((Move *) CUDD_OUT_OF_MEM);
1677 
1678 } /* end of ddSiftingUp */
1679 
1680 
1693 static Move *
1695  DdManager * table,
1696  int x,
1697  int xHigh)
1698 {
1699  Move *moves;
1700  Move *move;
1701  int y;
1702  int size;
1703  int R; /* upper bound on node decrease */
1704  int limitSize;
1705  int xindex, yindex;
1706  int isolated;
1707 #ifdef DD_DEBUG
1708  int checkR;
1709  int z;
1710  int zindex;
1711 #endif
1712 
1713  moves = NULL;
1714  /* Initialize R */
1715  xindex = table->invperm[x];
1716  limitSize = size = table->keys - table->isolated;
1717  R = 0;
1718  for (y = xHigh; y > x; y--) {
1719  yindex = table->invperm[y];
1720  if (cuddTestInteract(table,xindex,yindex)) {
1721  isolated = table->vars[yindex]->ref == 1;
1722  R += table->subtables[y].keys - isolated;
1723  }
1724  }
1725 
1726  y = cuddNextHigh(table,x);
1727  while (y <= xHigh && size - R < limitSize) {
1728 #ifdef DD_DEBUG
1729  checkR = 0;
1730  for (z = xHigh; z > x; z--) {
1731  zindex = table->invperm[z];
1732  if (cuddTestInteract(table,xindex,zindex)) {
1733  isolated = table->vars[zindex]->ref == 1;
1734  checkR += table->subtables[z].keys - isolated;
1735  }
1736  }
1737  assert(R == checkR);
1738 #endif
1739  /* Update upper bound on node decrease. */
1740  yindex = table->invperm[y];
1741  if (cuddTestInteract(table,xindex,yindex)) {
1742  isolated = table->vars[yindex]->ref == 1;
1743  R -= table->subtables[y].keys - isolated;
1744  }
1745  size = cuddSwapInPlace(table,x,y);
1746  if (size == 0) goto ddSiftingDownOutOfMem;
1747  move = (Move *) cuddDynamicAllocNode(table);
1748  if (move == NULL) goto ddSiftingDownOutOfMem;
1749  move->x = x;
1750  move->y = y;
1751  move->size = size;
1752  move->next = moves;
1753  moves = move;
1754  if ((double) size > (double) limitSize * table->maxGrowth) break;
1755  if (size < limitSize) limitSize = size;
1756  x = y;
1757  y = cuddNextHigh(table,x);
1758  }
1759  return(moves);
1760 
1761 ddSiftingDownOutOfMem:
1762  while (moves != NULL) {
1763  move = moves->next;
1764  cuddDeallocMove(table, moves);
1765  moves = move;
1766  }
1767  return((Move *) CUDD_OUT_OF_MEM);
1768 
1769 } /* end of ddSiftingDown */
1770 
1771 
1785 static int
1787  DdManager * table,
1788  int size,
1789  Move * moves)
1790 {
1791  Move *move;
1792  int res;
1793 
1794  for (move = moves; move != NULL; move = move->next) {
1795  if (move->size < size) {
1796  size = move->size;
1797  }
1798  }
1799 
1800  for (move = moves; move != NULL; move = move->next) {
1801  if (move->size == size) return(1);
1802  res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
1803  if (!res) return(0);
1804  }
1805 
1806  return(1);
1807 
1808 } /* end of ddSiftingBackward */
1809 
1810 
1824 static int
1826  DdManager * table)
1827 {
1828  int i;
1829  int res;
1830 
1831  /* Clear the cache. */
1832  cuddCacheFlush(table);
1833  cuddLocalCacheClearAll(table);
1834 
1835  /* Eliminate dead nodes. Do not scan the cache again. */
1836  cuddGarbageCollect(table,0);
1837 
1838  /* Initialize number of isolated projection functions. */
1839  table->isolated = 0;
1840  for (i = 0; i < table->size; i++) {
1841  if (table->vars[i]->ref == 1) table->isolated++;
1842  }
1843 
1844  /* Initialize the interaction matrix. */
1845  res = cuddInitInteract(table);
1846  if (res == 0) return(0);
1847 
1848  return(1);
1849 
1850 } /* end of ddReorderPreprocess */
1851 
1852 
1862 static int
1864  DdManager * table)
1865 {
1866 
1867 #ifdef DD_VERBOSE
1868  (void) fflush(table->out);
1869 #endif
1870 
1871  /* Free interaction matrix. */
1872  FREE(table->interact);
1873 
1874  return(1);
1875 
1876 } /* end of ddReorderPostprocess */
1877 
1878 
1895 static int
1897  DdManager * table,
1898  int * permutation)
1899 {
1900  int index;
1901  int level;
1902  int position;
1903  int numvars;
1904  int result;
1905 #ifdef DD_STATS
1906  unsigned long localTime;
1907  int initialSize;
1908  int finalSize;
1909  int previousSize;
1910 #endif
1911 
1913 #ifdef DD_STATS
1914  localTime = util_cpu_time();
1915  initialSize = table->keys - table->isolated;
1916  (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
1917  initialSize);
1918  ddTotalNISwaps = 0;
1919 #endif
1920 
1921  numvars = table->size;
1922 
1923  for (level = 0; level < numvars; level++) {
1924  index = permutation[level];
1925  position = table->perm[index];
1926 #ifdef DD_STATS
1927  previousSize = table->keys - table->isolated;
1928 #endif
1929  result = ddSiftUp(table,position,level);
1930  if (!result) return(0);
1931 #ifdef DD_STATS
1932  if (table->keys < (unsigned) previousSize + table->isolated) {
1933  (void) fprintf(table->out,"-");
1934  } else if (table->keys > (unsigned) previousSize + table->isolated) {
1935  (void) fprintf(table->out,"+"); /* should never happen */
1936  } else {
1937  (void) fprintf(table->out,"=");
1938  }
1939  fflush(table->out);
1940 #endif
1941  }
1942 
1943 #ifdef DD_STATS
1944  (void) fprintf(table->out,"\n");
1945  finalSize = table->keys - table->isolated;
1946  (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize);
1947  (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
1948  ((double)(util_cpu_time() - localTime)/1000.0));
1949  (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
1951  (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps);
1952 #endif
1953 
1954  return(1);
1955 
1956 } /* end of ddShuffle */
1957 
1958 
1972 static int
1974  DdManager * table,
1975  int x,
1976  int xLow)
1977 {
1978  int y;
1979  int size;
1980 
1981  y = cuddNextLow(table,x);
1982  while (y >= xLow) {
1983  size = cuddSwapInPlace(table,y,x);
1984  if (size == 0) {
1985  return(0);
1986  }
1987  x = y;
1988  y = cuddNextLow(table,x);
1989  }
1990  return(1);
1991 
1992 } /* end of ddSiftUp */
1993 
1994 
2008 static void
2010  DdManager * table,
2011  MtrNode * treenode)
2012 {
2013  if (treenode == NULL) return;
2014  treenode->low = ((int) treenode->index < table->size) ?
2015  table->perm[treenode->index] : treenode->index;
2016  if (treenode->child != NULL) {
2017  bddFixTree(table, treenode->child);
2018  }
2019  if (treenode->younger != NULL)
2020  bddFixTree(table, treenode->younger);
2021  if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
2022  treenode->parent->low = treenode->low;
2023  treenode->parent->index = treenode->index;
2024  }
2025  return;
2026 
2027 } /* end of bddFixTree */
2028 
2029 
2042 static int
2044  DdManager * table,
2045  MtrNode * treenode,
2046  int * perm,
2047  int * invperm)
2048 {
2049  unsigned int i, size;
2050  int index, level, minLevel, maxLevel, minIndex;
2051 
2052  if (treenode == NULL) return(1);
2053 
2054  minLevel = CUDD_MAXINDEX;
2055  maxLevel = 0;
2056  minIndex = -1;
2057  /* i : level */
2058  for (i = treenode->low; i < treenode->low + treenode->size; i++) {
2059  index = table->invperm[i];
2060  level = perm[index];
2061  if (level < minLevel) {
2062  minLevel = level;
2063  minIndex = index;
2064  }
2065  if (level > maxLevel)
2066  maxLevel = level;
2067  }
2068  size = maxLevel - minLevel + 1;
2069  if (minIndex == -1) return(0);
2070  if (size == treenode->size) {
2071  treenode->low = minLevel;
2072  treenode->index = minIndex;
2073  } else {
2074  return(0);
2075  }
2076 
2077  if (treenode->child != NULL) {
2078  if (!ddUpdateMtrTree(table, treenode->child, perm, invperm))
2079  return(0);
2080  }
2081  if (treenode->younger != NULL) {
2082  if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm))
2083  return(0);
2084  }
2085  return(1);
2086 }
2087 
2088 
2101 static int
2103  DdManager * table,
2104  MtrNode * treenode,
2105  int * perm,
2106  int * invperm)
2107 {
2108  unsigned int i, size;
2109  int index, level, minLevel, maxLevel;
2110 
2111  if (treenode == NULL) return(1);
2112 
2113  minLevel = table->size;
2114  maxLevel = 0;
2115  /* i : level */
2116  for (i = treenode->low; i < treenode->low + treenode->size; i++) {
2117  index = table->invperm[i];
2118  level = perm[index];
2119  if (level < minLevel)
2120  minLevel = level;
2121  if (level > maxLevel)
2122  maxLevel = level;
2123  }
2124  size = maxLevel - minLevel + 1;
2125  if (size != treenode->size)
2126  return(0);
2127 
2128  if (treenode->child != NULL) {
2129  if (!ddCheckPermuation(table, treenode->child, perm, invperm))
2130  return(0);
2131  }
2132  if (treenode->younger != NULL) {
2133  if (!ddCheckPermuation(table, treenode->younger, perm, invperm))
2134  return(0);
2135  }
2136  return(1);
2137 }
static int * entry
Definition: cuddReorder.c:101
DdHalfWord ref
Definition: cudd.h:272
static int ddCheckPermuation(DdManager *table, MtrNode *treenode, int *perm, int *invperm)
Definition: cuddReorder.c:2102
unsigned int keys
Definition: cuddInt.h:314
#define CUDD_OUT_OF_MEM
Definition: cudd.h:91
unsigned short DdHalfWord
Definition: cudd.h:259
#define ddHash(f, g, s)
Definition: cuddInt.h:696
static Move * ddSiftingDown(DdManager *table, int x, int xHigh)
Definition: cuddReorder.c:1694
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2845
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
unsigned long reordTime
Definition: cuddInt.h:434
Cudd_ReorderingType autoMethod
Definition: cuddInt.h:402
unsigned int peakLiveNodes
Definition: cuddInt.h:445
Definition: cudd.h:270
int cuddSwapping(DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
Definition: cuddReorder.c:604
#define Cudd_Not(node)
Definition: cudd.h:354
MtrHalfWord size
Definition: mtr.h:129
#define FREE(obj)
Definition: util.h:80
int siftMaxSwap
Definition: cuddInt.h:396
int(* DD_QSFP)(const void *, const void *)
Definition: cudd.h:313
static Move * ddSwapAny(DdManager *table, int x, int y)
Definition: cuddReorder.c:1346
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:405
DdHook * preReorderingHook
Definition: cuddInt.h:421
unsigned long startTime
Definition: cuddInt.h:426
int * invpermZ
Definition: cuddInt.h:372
int reordCycle
Definition: cuddInt.h:399
#define assert(ex)
Definition: util.h:141
static char rcsid [] DD_UNUSED
Definition: cuddReorder.c:98
int size
Definition: cuddInt.h:345
double gcFrac
Definition: cuddInt.h:359
Definition: cuddInt.h:469
unsigned int maxCacheHard
Definition: cuddInt.h:343
unsigned int slots
Definition: cuddInt.h:352
int cuddInitInteract(DdManager *table)
Definition: cuddInteract.c:234
#define Cudd_Regular(node)
Definition: cudd.h:384
double maxGrowthAlt
Definition: cuddInt.h:398
int realign
Definition: cuddInt.h:404
double maxGrowth
Definition: cuddInt.h:397
FILE * err
Definition: cuddInt.h:424
static int ddSiftingAux(DdManager *table, int x, int xLow, int xHigh)
Definition: cuddReorder.c:1487
static int ddSiftUp(DdManager *table, int x, int xLow)
Definition: cuddReorder.c:1973
int cuddSifting(DdManager *table, int lower, int upper)
Definition: cuddReorder.c:502
int bindVar
Definition: cuddInt.h:318
DdSubtable * subtables
Definition: cuddInt.h:349
DdNode * DdNodePtr
Definition: cuddInt.h:253
struct MtrNode * parent
Definition: mtr.h:131
#define DD_DYN_RATIO
Definition: cuddInt.h:153
MtrNode * tree
Definition: cuddInt.h:408
static void bddFixTree(DdManager *table, MtrNode *treenode)
Definition: cuddReorder.c:2009
int cuddTreeSifting(DdManager *table, Cudd_ReorderingType method)
Definition: cuddGroup.c:271
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:127
int Cudd_ShuffleHeap(DdManager *table, int *permutation)
Definition: cuddReorder.c:337
DD_HFP f
Definition: cuddInt.h:241
void(* DD_OOMFP)(long)
Definition: cudd.h:311
Cudd_VariableType
Definition: cudd.h:249
int ddTotalNumberSwapping
Definition: cuddReorder.c:103
struct DdNode DdNode
Definition: cudd.h:262
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:762
struct MtrNode * younger
Definition: mtr.h:134
unsigned int initSlots
Definition: cuddInt.h:363
unsigned int randomizeOrder
Definition: cuddInt.h:416
Cudd_VariableType varType
Definition: cuddInt.h:320
int reordered
Definition: cuddInt.h:392
unsigned int nextDyn
Definition: cuddInt.h:406
unsigned int dead
Definition: cuddInt.h:355
long Cudd_Random(void)
Definition: cuddUtil.c:2710
unsigned int cacheSlots
Definition: cuddInt.h:337
#define Cudd_IsComplement(node)
Definition: cudd.h:412
void cuddLocalCacheClearAll(DdManager *manager)
Definition: cuddLCache.c:423
DdNode sentinel
Definition: cuddInt.h:328
char * stash
Definition: cuddInt.h:382
MtrHalfWord index
Definition: mtr.h:130
DdHook * postReorderingHook
Definition: cuddInt.h:422
int cuddNextLow(DdManager *table, int x)
Definition: cuddReorder.c:737
unsigned int keys
Definition: cuddInt.h:353
int cuddNextHigh(DdManager *table, int x)
Definition: cuddReorder.c:715
#define ALLOC(type, num)
Definition: util.h:76
static int ddReorderPostprocess(DdManager *table)
Definition: cuddReorder.c:1863
unsigned int dead
Definition: cuddInt.h:316
FILE * out
Definition: cuddInt.h:423
static int numvars
Definition: cuddGenetic.c:107
DdHalfWord x
Definition: cuddInt.h:470
DdNode * next
Definition: cudd.h:273
static int ddUniqueCompare(int *ptrX, int *ptrY)
Definition: cuddReorder.c:1322
Cudd_LazyGroupType varToBeGrouped
Definition: cuddInt.h:323
static int ddUpdateMtrTree(DdManager *table, MtrNode *treenode, int *perm, int *invperm)
Definition: cuddReorder.c:2043
long * interact
Definition: cuddInt.h:377
unsigned int maxKeys
Definition: cuddInt.h:315
DdNode ** nodelist
Definition: cuddInt.h:311
#define ddMin(x, y)
Definition: cuddInt.h:771
MtrHalfWord low
Definition: mtr.h:128
#define DD_MAX_CACHE_TO_SLOTS_RATIO
Definition: cuddInt.h:145
int cacheSlack
Definition: cuddInt.h:342
long util_cpu_time(void)
Definition: cpu_time.c:34
#define cuddT(node)
Definition: cuddInt.h:609
void(* MMoutOfMemory)(long)
Definition: safe_mem.c:32
Definition: mtr.h:126
int varHandled
Definition: cuddInt.h:322
#define cuddDeallocNode(unique, node)
Definition: cuddInt.h:520
int cuddBddAlignToZdd(DdManager *table)
Definition: cuddReorder.c:1250
int Cudd_ReduceHeap(DdManager *table, Cudd_ReorderingType heuristic, int minsize)
Definition: cuddReorder.c:172
static int ddReorderPreprocess(DdManager *table)
Definition: cuddReorder.c:1825
DdNode ** memoryList
Definition: cuddInt.h:380
unsigned long memused
Definition: cuddInt.h:429
int siftMaxVar
Definition: cuddInt.h:395
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:760
static int ddSiftingBackward(DdManager *table, int size, Move *moves)
Definition: cuddReorder.c:1786
DdNode * nextFree
Definition: cuddInt.h:381
void cuddCacheFlush(DdManager *table)
Definition: cuddCache.c:1004
struct DdHook * next
Definition: cuddInt.h:242
int sizeZ
Definition: cuddInt.h:346
DdHalfWord index
Definition: cudd.h:271
unsigned int slots
Definition: cuddInt.h:313
DdHalfWord y
Definition: cuddInt.h:471
unsigned int reorderings
Definition: cuddInt.h:393
DdNode ** vars
Definition: cuddInt.h:373
static int ddShuffle(DdManager *table, int *permutation)
Definition: cuddReorder.c:1896
int pairIndex
Definition: cuddInt.h:321
#define CUDD_MAXINDEX
Definition: cudd.h:108
#define cuddE(node)
Definition: cuddInt.h:625
struct Move * next
Definition: cuddInt.h:474
#define cuddSatDec(x)
Definition: cuddInt.h:849
int cuddZddAlignToBdd(DdManager *table)
Definition: cuddZddReord.c:348
int * invperm
Definition: cuddInt.h:371
DdSubtable constants
Definition: cuddInt.h:351
static int result
Definition: cuddGenetic.c:121
int isolated
Definition: cuddInt.h:368
#define DD_MEM_CHUNK
Definition: cuddInt.h:105
int cuddTestInteract(DdManager *table, int x, int y)
Definition: cuddInteract.c:188
static Move * ddSiftingUp(DdManager *table, int y, int xLow)
Definition: cuddReorder.c:1594
int autoDyn
Definition: cuddInt.h:400
int shift
Definition: cuddInt.h:312
Cudd_ReorderingType
Definition: cudd.h:147
Cudd_LazyGroupType
Definition: cudd.h:234
struct MtrNode * child
Definition: mtr.h:132
int * perm
Definition: cuddInt.h:369
unsigned long timeLimit
Definition: cuddInt.h:427
int size
Definition: cuddInt.h:473
Cudd_ErrorType errorCode
Definition: cuddInt.h:425
unsigned int minDead
Definition: cuddInt.h:358
#define cuddSatInc(x)
Definition: cuddInt.h:831
if(DEFINED IN_SOURCE_BUILD) set(LLVM_LINK_COMPONENTS BitWriter Core IPO IrReader InstCombine Instrumentation Target Linker Analysis ScalarOpts Support Svf Cudd) add_llvm_tool(dvf dda.cpp) else() add_executable(dvf dda.cpp) target_link_libraries(dvf Svf Cudd $
Definition: CMakeLists.txt:2