SVF
cuddZddReord.c
Go to the documentation of this file.
1 
76 #include "CUDD/util.h"
77 #include "CUDD/cuddInt.h"
78 
79 /*---------------------------------------------------------------------------*/
80 /* Constant declarations */
81 /*---------------------------------------------------------------------------*/
82 
83 #define DD_MAX_SUBTABLE_SPARSITY 8
84 #define DD_SHRINK_FACTOR 2
85 
86 /*---------------------------------------------------------------------------*/
87 /* Stucture declarations */
88 /*---------------------------------------------------------------------------*/
89 
90 
91 /*---------------------------------------------------------------------------*/
92 /* Type declarations */
93 /*---------------------------------------------------------------------------*/
94 
95 
96 /*---------------------------------------------------------------------------*/
97 /* Variable declarations */
98 /*---------------------------------------------------------------------------*/
99 
100 #ifndef lint
101 static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.49 2012/02/05 01:07:19 fabio Exp $";
102 #endif
103 
105 
107 
108 static DdNode *empty;
109 
110 
111 /*---------------------------------------------------------------------------*/
112 /* Macro declarations */
113 /*---------------------------------------------------------------------------*/
114 
115 
118 /*---------------------------------------------------------------------------*/
119 /* Static function prototypes */
120 /*---------------------------------------------------------------------------*/
121 
122 static Move * zddSwapAny (DdManager *table, int x, int y);
123 static int cuddZddSiftingAux (DdManager *table, int x, int x_low, int x_high);
124 static Move * cuddZddSiftingUp (DdManager *table, int x, int x_low, int initial_size);
125 static Move * cuddZddSiftingDown (DdManager *table, int x, int x_high, int initial_size);
126 static int cuddZddSiftingBackward (DdManager *table, Move *moves, int size);
127 static void zddReorderPreprocess (DdManager *table);
128 static int zddReorderPostprocess (DdManager *table);
129 static int zddShuffle (DdManager *table, int *permutation);
130 static int zddSiftUp (DdManager *table, int x, int xLow);
131 static void zddFixTree (DdManager *table, MtrNode *treenode);
132 
136 /*---------------------------------------------------------------------------*/
137 /* Definition of exported functions */
138 /*---------------------------------------------------------------------------*/
139 
140 
166 int
168  DdManager * table /* DD manager */,
169  Cudd_ReorderingType heuristic /* method used for reordering */,
170  int minsize /* bound below which no reordering occurs */)
171 {
172  DdHook *hook;
173  int result;
174  unsigned int nextDyn;
175 #ifdef DD_STATS
176  unsigned int initialSize;
177  unsigned int finalSize;
178 #endif
179  unsigned long localTime;
180 
181  /* Don't reorder if there are too many dead nodes. */
182  if (table->keysZ - table->deadZ < (unsigned) minsize)
183  return(1);
184 
185  if (heuristic == CUDD_REORDER_SAME) {
186  heuristic = table->autoMethodZ;
187  }
188  if (heuristic == CUDD_REORDER_NONE) {
189  return(1);
190  }
191 
192  /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore
193  ** we count it.
194  */
195  table->reorderings++;
196  empty = table->zero;
197 
198  localTime = util_cpu_time();
199 
200  /* Run the hook functions. */
201  hook = table->preReorderingHook;
202  while (hook != NULL) {
203  int res = (hook->f)(table, "ZDD", (void *)heuristic);
204  if (res == 0) return(0);
205  hook = hook->next;
206  }
207 
208  /* Clear the cache and collect garbage. */
209  zddReorderPreprocess(table);
211 
212 #ifdef DD_STATS
213  initialSize = table->keysZ;
214 
215  switch(heuristic) {
216  case CUDD_REORDER_RANDOM:
218  (void) fprintf(table->out,"#:I_RANDOM ");
219  break;
220  case CUDD_REORDER_SIFT:
224  (void) fprintf(table->out,"#:I_SIFTING ");
225  break;
226  case CUDD_REORDER_LINEAR:
228  (void) fprintf(table->out,"#:I_LINSIFT ");
229  break;
230  default:
231  (void) fprintf(table->err,"Unsupported ZDD reordering method\n");
232  return(0);
233  }
234  (void) fprintf(table->out,"%8d: initial size",initialSize);
235 #endif
236 
237  result = cuddZddTreeSifting(table,heuristic);
238 
239 #ifdef DD_STATS
240  (void) fprintf(table->out,"\n");
241  finalSize = table->keysZ;
242  (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
243  (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
244  ((double)(util_cpu_time() - localTime)/1000.0));
245  (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
247 #endif
248 
249  if (result == 0)
250  return(0);
251 
252  if (!zddReorderPostprocess(table))
253  return(0);
254 
255  if (table->realignZ) {
256  if (!cuddBddAlignToZdd(table))
257  return(0);
258  }
259 
260  nextDyn = table->keysZ * DD_DYN_RATIO;
261  if (table->reorderings < 20 || nextDyn > table->nextDyn)
262  table->nextDyn = nextDyn;
263  else
264  table->nextDyn += 20;
265 
266  table->reordered = 1;
267 
268  /* Run hook functions. */
269  hook = table->postReorderingHook;
270  while (hook != NULL) {
271  int res = (hook->f)(table, "ZDD", (void *)localTime);
272  if (res == 0) return(0);
273  hook = hook->next;
274  }
275  /* Update cumulative reordering time. */
276  table->reordTime += util_cpu_time() - localTime;
277 
278  return(result);
279 
280 } /* end of Cudd_zddReduceHeap */
281 
282 
299 int
301  DdManager * table /* DD manager */,
302  int * permutation /* required variable permutation */)
303 {
304 
305  int result;
306 
307  empty = table->zero;
308  zddReorderPreprocess(table);
309 
310  result = zddShuffle(table,permutation);
311 
312  if (!zddReorderPostprocess(table)) return(0);
313 
314  return(result);
315 
316 } /* end of Cudd_zddShuffleHeap */
317 
318 
319 /*---------------------------------------------------------------------------*/
320 /* Definition of internal functions */
321 /*---------------------------------------------------------------------------*/
322 
323 
347 int
349  DdManager * table /* DD manager */)
350 {
351  int *invpermZ; /* permutation array */
352  int M; /* ratio of ZDD variables to BDD variables */
353  int i,j; /* loop indices */
354  int result; /* return value */
355 
356  /* We assume that a ratio of 0 is OK. */
357  if (table->sizeZ == 0)
358  return(1);
359 
360  empty = table->zero;
361  M = table->sizeZ / table->size;
362  /* Check whether the number of ZDD variables is a multiple of the
363  ** number of BDD variables.
364  */
365  if (M * table->size != table->sizeZ)
366  return(0);
367  /* Create and initialize the inverse permutation array. */
368  invpermZ = ALLOC(int,table->sizeZ);
369  if (invpermZ == NULL) {
370  table->errorCode = CUDD_MEMORY_OUT;
371  return(0);
372  }
373  for (i = 0; i < table->size; i++) {
374  int index = table->invperm[i];
375  int indexZ = index * M;
376  int levelZ = table->permZ[indexZ];
377  levelZ = (levelZ / M) * M;
378  for (j = 0; j < M; j++) {
379  invpermZ[M * i + j] = table->invpermZ[levelZ + j];
380  }
381  }
382  /* Eliminate dead nodes. Do not scan the cache again, because we
383  ** assume that Cudd_ReduceHeap has already cleared it.
384  */
385  cuddGarbageCollect(table,0);
386 
387  result = zddShuffle(table, invpermZ);
388  FREE(invpermZ);
389  /* Fix the ZDD variable group tree. */
390  zddFixTree(table,table->treeZ);
391  return(result);
392 
393 } /* end of cuddZddAlignToBdd */
394 
395 
408 int
410  DdManager * table,
411  int x)
412 {
413  return(x + 1);
414 
415 } /* end of cuddZddNextHigh */
416 
417 
430 int
432  DdManager * table,
433  int x)
434 {
435  return(x - 1);
436 
437 } /* end of cuddZddNextLow */
438 
439 
454 int
456  int * ptr_x,
457  int * ptr_y)
458 {
459  return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]);
460 
461 } /* end of cuddZddUniqueCompare */
462 
463 
479 int
481  DdManager * table,
482  int x,
483  int y)
484 {
485  DdNodePtr *xlist, *ylist;
486  int xindex, yindex;
487  int xslots, yslots;
488  int xshift, yshift;
489  int oldxkeys, oldykeys;
490  int newxkeys, newykeys;
491  int i;
492  int posn;
493  DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00;
494  DdNode *newf1, *newf0, *next;
495  DdNodePtr g, *lastP, *previousP;
496 
497 #ifdef DD_DEBUG
498  assert(x < y);
499  assert(cuddZddNextHigh(table,x) == y);
500  assert(table->subtableZ[x].keys != 0);
501  assert(table->subtableZ[y].keys != 0);
502  assert(table->subtableZ[x].dead == 0);
503  assert(table->subtableZ[y].dead == 0);
504 #endif
505 
507 
508  /* Get parameters of x subtable. */
509  xindex = table->invpermZ[x];
510  xlist = table->subtableZ[x].nodelist;
511  oldxkeys = table->subtableZ[x].keys;
512  xslots = table->subtableZ[x].slots;
513  xshift = table->subtableZ[x].shift;
514  newxkeys = 0;
515 
516  yindex = table->invpermZ[y];
517  ylist = table->subtableZ[y].nodelist;
518  oldykeys = table->subtableZ[y].keys;
519  yslots = table->subtableZ[y].slots;
520  yshift = table->subtableZ[y].shift;
521  newykeys = oldykeys;
522 
523  /* The nodes in the x layer that don't depend on y directly
524  ** will stay there; the others are put in a chain.
525  ** The chain is handled as a FIFO; g points to the beginning and
526  ** last points to the end.
527  */
528 
529  g = NULL;
530  lastP = &g;
531  for (i = 0; i < xslots; i++) {
532  previousP = &(xlist[i]);
533  f = *previousP;
534  while (f != NULL) {
535  next = f->next;
536  f1 = cuddT(f); f0 = cuddE(f);
537  if ((f1->index != (DdHalfWord) yindex) &&
538  (f0->index != (DdHalfWord) yindex)) { /* stays */
539  newxkeys++;
540  *previousP = f;
541  previousP = &(f->next);
542  } else {
543  f->index = yindex;
544  *lastP = f;
545  lastP = &(f->next);
546  }
547  f = next;
548  } /* while there are elements in the collision chain */
549  *previousP = NULL;
550  } /* for each slot of the x subtable */
551  *lastP = NULL;
552 
553 
554 #ifdef DD_COUNT
555  table->swapSteps += oldxkeys - newxkeys;
556 #endif
557  /* Take care of the x nodes that must be re-expressed.
558  ** They form a linked list pointed by g. Their index has been
559  ** changed to yindex already.
560  */
561  f = g;
562  while (f != NULL) {
563  next = f->next;
564  /* Find f1, f0, f11, f10, f01, f00. */
565  f1 = cuddT(f);
566  if ((int) f1->index == yindex) {
567  f11 = cuddT(f1); f10 = cuddE(f1);
568  } else {
569  f11 = empty; f10 = f1;
570  }
571  f0 = cuddE(f);
572  if ((int) f0->index == yindex) {
573  f01 = cuddT(f0); f00 = cuddE(f0);
574  } else {
575  f01 = empty; f00 = f0;
576  }
577 
578  /* Decrease ref count of f1. */
579  cuddSatDec(f1->ref);
580  /* Create the new T child. */
581  if (f11 == empty) {
582  if (f01 != empty) {
583  newf1 = f01;
584  cuddSatInc(newf1->ref);
585  }
586  /* else case was already handled when finding nodes
587  ** with both children below level y
588  */
589  } else {
590  /* Check xlist for triple (xindex, f11, f01). */
591  posn = ddHash(f11, f01, xshift);
592  /* For each element newf1 in collision list xlist[posn]. */
593  newf1 = xlist[posn];
594  while (newf1 != NULL) {
595  if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
596  cuddSatInc(newf1->ref);
597  break; /* match */
598  }
599  newf1 = newf1->next;
600  } /* while newf1 */
601  if (newf1 == NULL) { /* no match */
602  newf1 = cuddDynamicAllocNode(table);
603  if (newf1 == NULL)
604  goto zddSwapOutOfMem;
605  newf1->index = xindex; newf1->ref = 1;
606  cuddT(newf1) = f11;
607  cuddE(newf1) = f01;
608  /* Insert newf1 in the collision list xlist[pos];
609  ** increase the ref counts of f11 and f01
610  */
611  newxkeys++;
612  newf1->next = xlist[posn];
613  xlist[posn] = newf1;
614  cuddSatInc(f11->ref);
615  cuddSatInc(f01->ref);
616  }
617  }
618  cuddT(f) = newf1;
619 
620  /* Do the same for f0. */
621  /* Decrease ref count of f0. */
622  cuddSatDec(f0->ref);
623  /* Create the new E child. */
624  if (f10 == empty) {
625  newf0 = f00;
626  cuddSatInc(newf0->ref);
627  } else {
628  /* Check xlist for triple (xindex, f10, f00). */
629  posn = ddHash(f10, f00, xshift);
630  /* For each element newf0 in collision list xlist[posn]. */
631  newf0 = xlist[posn];
632  while (newf0 != NULL) {
633  if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
634  cuddSatInc(newf0->ref);
635  break; /* match */
636  }
637  newf0 = newf0->next;
638  } /* while newf0 */
639  if (newf0 == NULL) { /* no match */
640  newf0 = cuddDynamicAllocNode(table);
641  if (newf0 == NULL)
642  goto zddSwapOutOfMem;
643  newf0->index = xindex; newf0->ref = 1;
644  cuddT(newf0) = f10; cuddE(newf0) = f00;
645  /* Insert newf0 in the collision list xlist[posn];
646  ** increase the ref counts of f10 and f00.
647  */
648  newxkeys++;
649  newf0->next = xlist[posn];
650  xlist[posn] = newf0;
651  cuddSatInc(f10->ref);
652  cuddSatInc(f00->ref);
653  }
654  }
655  cuddE(f) = newf0;
656 
657  /* Insert the modified f in ylist.
658  ** The modified f does not already exists in ylist.
659  ** (Because of the uniqueness of the cofactors.)
660  */
661  posn = ddHash(newf1, newf0, yshift);
662  newykeys++;
663  f->next = ylist[posn];
664  ylist[posn] = f;
665  f = next;
666  } /* while f != NULL */
667 
668  /* GC the y layer. */
669 
670  /* For each node f in ylist. */
671  for (i = 0; i < yslots; i++) {
672  previousP = &(ylist[i]);
673  f = *previousP;
674  while (f != NULL) {
675  next = f->next;
676  if (f->ref == 0) {
677  cuddSatDec(cuddT(f)->ref);
678  cuddSatDec(cuddE(f)->ref);
679  cuddDeallocNode(table, f);
680  newykeys--;
681  } else {
682  *previousP = f;
683  previousP = &(f->next);
684  }
685  f = next;
686  } /* while f */
687  *previousP = NULL;
688  } /* for i */
689 
690  /* Set the appropriate fields in table. */
691  table->subtableZ[x].nodelist = ylist;
692  table->subtableZ[x].slots = yslots;
693  table->subtableZ[x].shift = yshift;
694  table->subtableZ[x].keys = newykeys;
695  table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
696 
697  table->subtableZ[y].nodelist = xlist;
698  table->subtableZ[y].slots = xslots;
699  table->subtableZ[y].shift = xshift;
700  table->subtableZ[y].keys = newxkeys;
701  table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
702 
703  table->permZ[xindex] = y; table->permZ[yindex] = x;
704  table->invpermZ[x] = yindex; table->invpermZ[y] = xindex;
705 
706  table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
707 
708  /* Update univ section; univ[x] remains the same. */
709  table->univ[y] = cuddT(table->univ[x]);
710 
711  return (table->keysZ);
712 
713 zddSwapOutOfMem:
714  (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
715 
716  return (0);
717 
718 } /* end of cuddZddSwapInPlace */
719 
720 
741 int
743  DdManager * table,
744  int lower,
745  int upper,
746  Cudd_ReorderingType heuristic)
747 {
748  int i, j;
749  int max, keys;
750  int nvars;
751  int x, y;
752  int iterate;
753  int previousSize;
754  Move *moves, *move;
755  int pivot;
756  int modulo;
757  int result;
758 
759 #ifdef DD_DEBUG
760  /* Sanity check */
761  assert(lower >= 0 && upper < table->sizeZ && lower <= upper);
762 #endif
763 
764  nvars = upper - lower + 1;
765  iterate = nvars;
766 
767  for (i = 0; i < iterate; i++) {
768  if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
769  /* Find pivot <= id with maximum keys. */
770  for (max = -1, j = lower; j <= upper; j++) {
771  if ((keys = table->subtableZ[j].keys) > max) {
772  max = keys;
773  pivot = j;
774  }
775  }
776 
777  modulo = upper - pivot;
778  if (modulo == 0) {
779  y = pivot; /* y = nvars-1 */
780  } else {
781  /* y = random # from {pivot+1 .. nvars-1} */
782  y = pivot + 1 + (int) (Cudd_Random() % modulo);
783  }
784 
785  modulo = pivot - lower - 1;
786  if (modulo < 1) { /* if pivot = 1 or 0 */
787  x = lower;
788  } else {
789  do { /* x = random # from {0 .. pivot-2} */
790  x = (int) Cudd_Random() % modulo;
791  } while (x == y);
792  /* Is this condition really needed, since x and y
793  are in regions separated by pivot? */
794  }
795  } else {
796  x = (int) (Cudd_Random() % nvars) + lower;
797  do {
798  y = (int) (Cudd_Random() % nvars) + lower;
799  } while (x == y);
800  }
801 
802  previousSize = table->keysZ;
803  moves = zddSwapAny(table, x, y);
804  if (moves == NULL)
805  goto cuddZddSwappingOutOfMem;
806 
807  result = cuddZddSiftingBackward(table, moves, previousSize);
808  if (!result)
809  goto cuddZddSwappingOutOfMem;
810 
811  while (moves != NULL) {
812  move = moves->next;
813  cuddDeallocMove(table, moves);
814  moves = move;
815  }
816 #ifdef DD_STATS
817  if (table->keysZ < (unsigned) previousSize) {
818  (void) fprintf(table->out,"-");
819  } else if (table->keysZ > (unsigned) previousSize) {
820  (void) fprintf(table->out,"+"); /* should never happen */
821  } else {
822  (void) fprintf(table->out,"=");
823  }
824  fflush(table->out);
825 #endif
826  }
827 
828  return(1);
829 
830 cuddZddSwappingOutOfMem:
831  while (moves != NULL) {
832  move = moves->next;
833  cuddDeallocMove(table, moves);
834  moves = move;
835  }
836  return(0);
837 
838 } /* end of cuddZddSwapping */
839 
840 
862 int
864  DdManager * table,
865  int lower,
866  int upper)
867 {
868  int i;
869  int *var;
870  int size;
871  int x;
872  int result;
873 #ifdef DD_STATS
874  int previousSize;
875 #endif
876 
877  size = table->sizeZ;
878 
879  /* Find order in which to sift variables. */
880  var = NULL;
881  zdd_entry = ALLOC(int, size);
882  if (zdd_entry == NULL) {
883  table->errorCode = CUDD_MEMORY_OUT;
884  goto cuddZddSiftingOutOfMem;
885  }
886  var = ALLOC(int, size);
887  if (var == NULL) {
888  table->errorCode = CUDD_MEMORY_OUT;
889  goto cuddZddSiftingOutOfMem;
890  }
891 
892  for (i = 0; i < size; i++) {
893  x = table->permZ[i];
894  zdd_entry[i] = table->subtableZ[x].keys;
895  var[i] = i;
896  }
897 
898  qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
899 
900  /* Now sift. */
901  for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
902  if (zddTotalNumberSwapping >= table->siftMaxSwap)
903  break;
904  if (util_cpu_time() - table->startTime > table->timeLimit) {
905  table->autoDynZ = 0; /* prevent further reordering */
906  break;
907  }
908  x = table->permZ[var[i]];
909  if (x < lower || x > upper) continue;
910 #ifdef DD_STATS
911  previousSize = table->keysZ;
912 #endif
913  result = cuddZddSiftingAux(table, x, lower, upper);
914  if (!result)
915  goto cuddZddSiftingOutOfMem;
916 #ifdef DD_STATS
917  if (table->keysZ < (unsigned) previousSize) {
918  (void) fprintf(table->out,"-");
919  } else if (table->keysZ > (unsigned) previousSize) {
920  (void) fprintf(table->out,"+"); /* should never happen */
921  (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
922  } else {
923  (void) fprintf(table->out,"=");
924  }
925  fflush(table->out);
926 #endif
927  }
928 
929  FREE(var);
930  FREE(zdd_entry);
931 
932  return(1);
933 
934 cuddZddSiftingOutOfMem:
935 
936  if (zdd_entry != NULL) FREE(zdd_entry);
937  if (var != NULL) FREE(var);
938 
939  return(0);
940 
941 } /* end of cuddZddSifting */
942 
943 
944 /*---------------------------------------------------------------------------*/
945 /* Definition of static functions */
946 /*---------------------------------------------------------------------------*/
947 
948 
960 static Move *
962  DdManager * table,
963  int x,
964  int y)
965 {
966  Move *move, *moves;
967  int tmp, size;
968  int x_ref, y_ref;
969  int x_next, y_next;
970  int limit_size;
971 
972  if (x > y) { /* make x precede y */
973  tmp = x; x = y; y = tmp;
974  }
975 
976  x_ref = x; y_ref = y;
977 
978  x_next = cuddZddNextHigh(table, x);
979  y_next = cuddZddNextLow(table, y);
980  moves = NULL;
981  limit_size = table->keysZ;
982 
983  for (;;) {
984  if (x_next == y_next) { /* x < x_next = y_next < y */
985  size = cuddZddSwapInPlace(table, x, x_next);
986  if (size == 0)
987  goto zddSwapAnyOutOfMem;
988  move = (Move *) cuddDynamicAllocNode(table);
989  if (move == NULL)
990  goto zddSwapAnyOutOfMem;
991  move->x = x;
992  move->y = x_next;
993  move->size = size;
994  move->next = moves;
995  moves = move;
996 
997  size = cuddZddSwapInPlace(table, y_next, y);
998  if (size == 0)
999  goto zddSwapAnyOutOfMem;
1000  move = (Move *)cuddDynamicAllocNode(table);
1001  if (move == NULL)
1002  goto zddSwapAnyOutOfMem;
1003  move->x = y_next;
1004  move->y = y;
1005  move->size = size;
1006  move->next = moves;
1007  moves = move;
1008 
1009  size = cuddZddSwapInPlace(table, x, x_next);
1010  if (size == 0)
1011  goto zddSwapAnyOutOfMem;
1012  move = (Move *)cuddDynamicAllocNode(table);
1013  if (move == NULL)
1014  goto zddSwapAnyOutOfMem;
1015  move->x = x;
1016  move->y = x_next;
1017  move->size = size;
1018  move->next = moves;
1019  moves = move;
1020 
1021  tmp = x; x = y; y = tmp;
1022 
1023  } else if (x == y_next) { /* x = y_next < y = x_next */
1024  size = cuddZddSwapInPlace(table, x, x_next);
1025  if (size == 0)
1026  goto zddSwapAnyOutOfMem;
1027  move = (Move *)cuddDynamicAllocNode(table);
1028  if (move == NULL)
1029  goto zddSwapAnyOutOfMem;
1030  move->x = x;
1031  move->y = x_next;
1032  move->size = size;
1033  move->next = moves;
1034  moves = move;
1035 
1036  tmp = x; x = y; y = tmp;
1037  } else {
1038  size = cuddZddSwapInPlace(table, x, x_next);
1039  if (size == 0)
1040  goto zddSwapAnyOutOfMem;
1041  move = (Move *)cuddDynamicAllocNode(table);
1042  if (move == NULL)
1043  goto zddSwapAnyOutOfMem;
1044  move->x = x;
1045  move->y = x_next;
1046  move->size = size;
1047  move->next = moves;
1048  moves = move;
1049 
1050  size = cuddZddSwapInPlace(table, y_next, y);
1051  if (size == 0)
1052  goto zddSwapAnyOutOfMem;
1053  move = (Move *)cuddDynamicAllocNode(table);
1054  if (move == NULL)
1055  goto zddSwapAnyOutOfMem;
1056  move->x = y_next;
1057  move->y = y;
1058  move->size = size;
1059  move->next = moves;
1060  moves = move;
1061 
1062  x = x_next; y = y_next;
1063  }
1064 
1065  x_next = cuddZddNextHigh(table, x);
1066  y_next = cuddZddNextLow(table, y);
1067  if (x_next > y_ref)
1068  break; /* if x == y_ref */
1069 
1070  if ((double) size > table->maxGrowth * (double) limit_size)
1071  break;
1072  if (size < limit_size)
1073  limit_size = size;
1074  }
1075  if (y_next >= x_ref) {
1076  size = cuddZddSwapInPlace(table, y_next, y);
1077  if (size == 0)
1078  goto zddSwapAnyOutOfMem;
1079  move = (Move *)cuddDynamicAllocNode(table);
1080  if (move == NULL)
1081  goto zddSwapAnyOutOfMem;
1082  move->x = y_next;
1083  move->y = y;
1084  move->size = size;
1085  move->next = moves;
1086  moves = move;
1087  }
1088 
1089  return(moves);
1090 
1091 zddSwapAnyOutOfMem:
1092  while (moves != NULL) {
1093  move = moves->next;
1094  cuddDeallocMove(table, moves);
1095  moves = move;
1096  }
1097  return(NULL);
1098 
1099 } /* end of zddSwapAny */
1100 
1101 
1116 static int
1118  DdManager * table,
1119  int x,
1120  int x_low,
1121  int x_high)
1122 {
1123  Move *move;
1124  Move *moveUp; /* list of up move */
1125  Move *moveDown; /* list of down move */
1126 
1127  int initial_size;
1128  int result;
1129 
1130  initial_size = table->keysZ;
1131 
1132 #ifdef DD_DEBUG
1133  assert(table->subtableZ[x].keys > 0);
1134 #endif
1135 
1136  moveDown = NULL;
1137  moveUp = NULL;
1138 
1139  if (x == x_low) {
1140  moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
1141  /* after that point x --> x_high */
1142  if (moveDown == NULL)
1143  goto cuddZddSiftingAuxOutOfMem;
1144  result = cuddZddSiftingBackward(table, moveDown,
1145  initial_size);
1146  /* move backward and stop at best position */
1147  if (!result)
1148  goto cuddZddSiftingAuxOutOfMem;
1149 
1150  }
1151  else if (x == x_high) {
1152  moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
1153  /* after that point x --> x_low */
1154  if (moveUp == NULL)
1155  goto cuddZddSiftingAuxOutOfMem;
1156  result = cuddZddSiftingBackward(table, moveUp, initial_size);
1157  /* move backward and stop at best position */
1158  if (!result)
1159  goto cuddZddSiftingAuxOutOfMem;
1160  }
1161  else if ((x - x_low) > (x_high - x)) {
1162  /* must go down first:shorter */
1163  moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
1164  /* after that point x --> x_high */
1165  if (moveDown == NULL)
1166  goto cuddZddSiftingAuxOutOfMem;
1167  moveUp = cuddZddSiftingUp(table, moveDown->y, x_low,
1168  initial_size);
1169  if (moveUp == NULL)
1170  goto cuddZddSiftingAuxOutOfMem;
1171  result = cuddZddSiftingBackward(table, moveUp, initial_size);
1172  /* move backward and stop at best position */
1173  if (!result)
1174  goto cuddZddSiftingAuxOutOfMem;
1175  }
1176  else {
1177  moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
1178  /* after that point x --> x_high */
1179  if (moveUp == NULL)
1180  goto cuddZddSiftingAuxOutOfMem;
1181  moveDown = cuddZddSiftingDown(table, moveUp->x, x_high,
1182  initial_size);
1183  /* then move up */
1184  if (moveDown == NULL)
1185  goto cuddZddSiftingAuxOutOfMem;
1186  result = cuddZddSiftingBackward(table, moveDown,
1187  initial_size);
1188  /* move backward and stop at best position */
1189  if (!result)
1190  goto cuddZddSiftingAuxOutOfMem;
1191  }
1192 
1193  while (moveDown != NULL) {
1194  move = moveDown->next;
1195  cuddDeallocMove(table, moveDown);
1196  moveDown = move;
1197  }
1198  while (moveUp != NULL) {
1199  move = moveUp->next;
1200  cuddDeallocMove(table, moveUp);
1201  moveUp = move;
1202  }
1203 
1204  return(1);
1205 
1206 cuddZddSiftingAuxOutOfMem:
1207  while (moveDown != NULL) {
1208  move = moveDown->next;
1209  cuddDeallocMove(table, moveDown);
1210  moveDown = move;
1211  }
1212  while (moveUp != NULL) {
1213  move = moveUp->next;
1214  cuddDeallocMove(table, moveUp);
1215  moveUp = move;
1216  }
1217 
1218  return(0);
1219 
1220 } /* end of cuddZddSiftingAux */
1221 
1222 
1236 static Move *
1238  DdManager * table,
1239  int x,
1240  int x_low,
1241  int initial_size)
1242 {
1243  Move *moves;
1244  Move *move;
1245  int y;
1246  int size;
1247  int limit_size = initial_size;
1248 
1249  moves = NULL;
1250  y = cuddZddNextLow(table, x);
1251  while (y >= x_low) {
1252  size = cuddZddSwapInPlace(table, y, x);
1253  if (size == 0)
1254  goto cuddZddSiftingUpOutOfMem;
1255  move = (Move *)cuddDynamicAllocNode(table);
1256  if (move == NULL)
1257  goto cuddZddSiftingUpOutOfMem;
1258  move->x = y;
1259  move->y = x;
1260  move->size = size;
1261  move->next = moves;
1262  moves = move;
1263 
1264  if ((double)size > (double)limit_size * table->maxGrowth)
1265  break;
1266  if (size < limit_size)
1267  limit_size = size;
1268 
1269  x = y;
1270  y = cuddZddNextLow(table, x);
1271  }
1272  return(moves);
1273 
1274 cuddZddSiftingUpOutOfMem:
1275  while (moves != NULL) {
1276  move = moves->next;
1277  cuddDeallocMove(table, moves);
1278  moves = move;
1279  }
1280  return(NULL);
1281 
1282 } /* end of cuddZddSiftingUp */
1283 
1284 
1299 static Move *
1301  DdManager * table,
1302  int x,
1303  int x_high,
1304  int initial_size)
1305 {
1306  Move *moves;
1307  Move *move;
1308  int y;
1309  int size;
1310  int limit_size = initial_size;
1311 
1312  moves = NULL;
1313  y = cuddZddNextHigh(table, x);
1314  while (y <= x_high) {
1315  size = cuddZddSwapInPlace(table, x, y);
1316  if (size == 0)
1317  goto cuddZddSiftingDownOutOfMem;
1318  move = (Move *)cuddDynamicAllocNode(table);
1319  if (move == NULL)
1320  goto cuddZddSiftingDownOutOfMem;
1321  move->x = x;
1322  move->y = y;
1323  move->size = size;
1324  move->next = moves;
1325  moves = move;
1326 
1327  if ((double)size > (double)limit_size * table->maxGrowth)
1328  break;
1329  if (size < limit_size)
1330  limit_size = size;
1331 
1332  x = y;
1333  y = cuddZddNextHigh(table, x);
1334  }
1335  return(moves);
1336 
1337 cuddZddSiftingDownOutOfMem:
1338  while (moves != NULL) {
1339  move = moves->next;
1340  cuddDeallocMove(table, moves);
1341  moves = move;
1342  }
1343  return(NULL);
1344 
1345 } /* end of cuddZddSiftingDown */
1346 
1347 
1363 static int
1365  DdManager * table,
1366  Move * moves,
1367  int size)
1368 {
1369  int i;
1370  int i_best;
1371  Move *move;
1372  int res;
1373 
1374  /* Find the minimum size among moves. */
1375  i_best = -1;
1376  for (move = moves, i = 0; move != NULL; move = move->next, i++) {
1377  if (move->size < size) {
1378  i_best = i;
1379  size = move->size;
1380  }
1381  }
1382 
1383  for (move = moves, i = 0; move != NULL; move = move->next, i++) {
1384  if (i == i_best)
1385  break;
1386  res = cuddZddSwapInPlace(table, move->x, move->y);
1387  if (!res)
1388  return(0);
1389  if (i_best == -1 && res == size)
1390  break;
1391  }
1392 
1393  return(1);
1394 
1395 } /* end of cuddZddSiftingBackward */
1396 
1397 
1409 static void
1411  DdManager * table)
1412 {
1413 
1414  /* Clear the cache. */
1415  cuddCacheFlush(table);
1416 
1417  /* Eliminate dead nodes. Do not scan the cache again. */
1418  cuddGarbageCollect(table,0);
1419 
1420  return;
1421 
1422 } /* end of ddReorderPreprocess */
1423 
1424 
1438 static int
1440  DdManager * table)
1441 {
1442  int i, j, posn;
1443  DdNodePtr *nodelist, *oldnodelist;
1444  DdNode *node, *next;
1445  unsigned int slots, oldslots;
1446  extern DD_OOMFP MMoutOfMemory;
1447  DD_OOMFP saveHandler;
1448 
1449 #ifdef DD_VERBOSE
1450  (void) fflush(table->out);
1451 #endif
1452 
1453  /* If we have very many reclaimed nodes, we do not want to shrink
1454  ** the subtables, because this will lead to more garbage
1455  ** collections. More garbage collections mean shorter mean life for
1456  ** nodes with zero reference count; hence lower probability of finding
1457  ** a result in the cache.
1458  */
1459  if (table->reclaimed > table->allocated * 0.5) return(1);
1460 
1461  /* Resize subtables. */
1462  for (i = 0; i < table->sizeZ; i++) {
1463  int shift;
1464  oldslots = table->subtableZ[i].slots;
1465  if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY ||
1466  oldslots <= table->initSlots) continue;
1467  oldnodelist = table->subtableZ[i].nodelist;
1468  slots = oldslots >> 1;
1469  saveHandler = MMoutOfMemory;
1470  MMoutOfMemory = Cudd_OutOfMem;
1471  nodelist = ALLOC(DdNodePtr, slots);
1472  MMoutOfMemory = saveHandler;
1473  if (nodelist == NULL) {
1474  return(1);
1475  }
1476  table->subtableZ[i].nodelist = nodelist;
1477  table->subtableZ[i].slots = slots;
1478  table->subtableZ[i].shift++;
1479  table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
1480 #ifdef DD_VERBOSE
1481  (void) fprintf(table->err,
1482  "shrunk layer %d (%d keys) from %d to %d slots\n",
1483  i, table->subtableZ[i].keys, oldslots, slots);
1484 #endif
1485 
1486  for (j = 0; (unsigned) j < slots; j++) {
1487  nodelist[j] = NULL;
1488  }
1489  shift = table->subtableZ[i].shift;
1490  for (j = 0; (unsigned) j < oldslots; j++) {
1491  node = oldnodelist[j];
1492  while (node != NULL) {
1493  next = node->next;
1494  posn = ddHash(cuddT(node), cuddE(node), shift);
1495  node->next = nodelist[posn];
1496  nodelist[posn] = node;
1497  node = next;
1498  }
1499  }
1500  FREE(oldnodelist);
1501 
1502  table->memused += (slots - oldslots) * sizeof(DdNode *);
1503  table->slots += slots - oldslots;
1504  table->minDead = (unsigned) (table->gcFrac * (double) table->slots);
1505  table->cacheSlack = (int) ddMin(table->maxCacheHard,
1507  2 * (int) table->cacheSlots;
1508  }
1509  /* We don't look at the constant subtable, because it is not
1510  ** affected by reordering.
1511  */
1512 
1513  return(1);
1514 
1515 } /* end of zddReorderPostprocess */
1516 
1517 
1533 static int
1535  DdManager * table,
1536  int * permutation)
1537 {
1538  int index;
1539  int level;
1540  int position;
1541  int numvars;
1542  int result;
1543 #ifdef DD_STATS
1544  unsigned long localTime;
1545  int initialSize;
1546  int finalSize;
1547  int previousSize;
1548 #endif
1549 
1551 #ifdef DD_STATS
1552  localTime = util_cpu_time();
1553  initialSize = table->keysZ;
1554  (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
1555  initialSize);
1556 #endif
1557 
1558  numvars = table->sizeZ;
1559 
1560  for (level = 0; level < numvars; level++) {
1561  index = permutation[level];
1562  position = table->permZ[index];
1563 #ifdef DD_STATS
1564  previousSize = table->keysZ;
1565 #endif
1566  result = zddSiftUp(table,position,level);
1567  if (!result) return(0);
1568 #ifdef DD_STATS
1569  if (table->keysZ < (unsigned) previousSize) {
1570  (void) fprintf(table->out,"-");
1571  } else if (table->keysZ > (unsigned) previousSize) {
1572  (void) fprintf(table->out,"+"); /* should never happen */
1573  } else {
1574  (void) fprintf(table->out,"=");
1575  }
1576  fflush(table->out);
1577 #endif
1578  }
1579 
1580 #ifdef DD_STATS
1581  (void) fprintf(table->out,"\n");
1582  finalSize = table->keysZ;
1583  (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize);
1584  (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
1585  ((double)(util_cpu_time() - localTime)/1000.0));
1586  (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
1588 #endif
1589 
1590  return(1);
1591 
1592 } /* end of zddShuffle */
1593 
1594 
1608 static int
1610  DdManager * table,
1611  int x,
1612  int xLow)
1613 {
1614  int y;
1615  int size;
1616 
1617  y = cuddZddNextLow(table,x);
1618  while (y >= xLow) {
1619  size = cuddZddSwapInPlace(table,y,x);
1620  if (size == 0) {
1621  return(0);
1622  }
1623  x = y;
1624  y = cuddZddNextLow(table,x);
1625  }
1626  return(1);
1627 
1628 } /* end of zddSiftUp */
1629 
1630 
1644 static void
1646  DdManager * table,
1647  MtrNode * treenode)
1648 {
1649  if (treenode == NULL) return;
1650  treenode->low = ((int) treenode->index < table->sizeZ) ?
1651  table->permZ[treenode->index] : treenode->index;
1652  if (treenode->child != NULL) {
1653  zddFixTree(table, treenode->child);
1654  }
1655  if (treenode->younger != NULL)
1656  zddFixTree(table, treenode->younger);
1657  if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
1658  treenode->parent->low = treenode->low;
1659  treenode->parent->index = treenode->index;
1660  }
1661  return;
1662 
1663 } /* end of zddFixTree */
1664 
DdHalfWord ref
Definition: cudd.h:272
static Move * cuddZddSiftingUp(DdManager *table, int x, int x_low, int initial_size)
unsigned int keys
Definition: cuddInt.h:314
unsigned short DdHalfWord
Definition: cudd.h:259
int cuddZddSwapping(DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
Definition: cuddZddReord.c:742
#define ddHash(f, g, s)
Definition: cuddInt.h:696
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2845
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
unsigned long reordTime
Definition: cuddInt.h:434
static char rcsid [] DD_UNUSED
Definition: cuddZddReord.c:101
double allocated
Definition: cuddInt.h:365
Definition: cudd.h:270
unsigned int deadZ
Definition: cuddInt.h:356
#define FREE(obj)
Definition: util.h:80
int siftMaxSwap
Definition: cuddInt.h:396
int(* DD_QSFP)(const void *, const void *)
Definition: cudd.h:313
DdHook * preReorderingHook
Definition: cuddInt.h:421
unsigned long startTime
Definition: cuddInt.h:426
int * invpermZ
Definition: cuddInt.h:372
static Move * cuddZddSiftingDown(DdManager *table, int x, int x_high, int initial_size)
#define assert(ex)
Definition: util.h:141
static void zddReorderPreprocess(DdManager *table)
int size
Definition: cuddInt.h:345
double gcFrac
Definition: cuddInt.h:359
Definition: cuddInt.h:469
unsigned int maxCacheHard
Definition: cuddInt.h:343
int cuddZddNextHigh(DdManager *table, int x)
Definition: cuddZddReord.c:409
unsigned int slots
Definition: cuddInt.h:352
DdNode * zero
Definition: cuddInt.h:330
double maxGrowth
Definition: cuddInt.h:397
FILE * err
Definition: cuddInt.h:424
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:480
Cudd_ReorderingType autoMethodZ
Definition: cuddInt.h:403
int * permZ
Definition: cuddInt.h:370
struct MtrNode * parent
Definition: mtr.h:131
#define DD_DYN_RATIO
Definition: cuddInt.h:153
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:127
DD_HFP f
Definition: cuddInt.h:241
void(* DD_OOMFP)(long)
Definition: cudd.h:311
int cuddZddNextLow(DdManager *table, int x)
Definition: cuddZddReord.c:431
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:762
static DdNode * empty
Definition: cuddZddReord.c:108
struct MtrNode * younger
Definition: mtr.h:134
#define DD_MAX_SUBTABLE_SPARSITY
Definition: cuddZddReord.c:83
int reordered
Definition: cuddInt.h:392
unsigned int nextDyn
Definition: cuddInt.h:406
long Cudd_Random(void)
Definition: cuddUtil.c:2710
unsigned int cacheSlots
Definition: cuddInt.h:337
static int cuddZddSiftingAux(DdManager *table, int x, int x_low, int x_high)
MtrHalfWord index
Definition: mtr.h:130
DdHook * postReorderingHook
Definition: cuddInt.h:422
int zddTotalNumberSwapping
Definition: cuddZddReord.c:106
#define ALLOC(type, num)
Definition: util.h:76
unsigned int dead
Definition: cuddInt.h:316
FILE * out
Definition: cuddInt.h:423
static int numvars
Definition: cuddGenetic.c:107
int realignZ
Definition: cuddInt.h:405
DdHalfWord x
Definition: cuddInt.h:470
DdNode * next
Definition: cudd.h:273
int cuddZddSifting(DdManager *table, int lower, int upper)
Definition: cuddZddReord.c:863
unsigned int maxKeys
Definition: cuddInt.h:315
static Move * zddSwapAny(DdManager *table, int x, int y)
Definition: cuddZddReord.c:961
static int zddReorderPostprocess(DdManager *table)
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 cuddZddUniqueCompare(int *ptr_x, int *ptr_y)
Definition: cuddZddReord.c:455
int cacheSlack
Definition: cuddInt.h:342
long util_cpu_time(void)
Definition: cpu_time.c:34
#define cuddT(node)
Definition: cuddInt.h:609
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:405
static int zddSiftUp(DdManager *table, int x, int xLow)
void(* MMoutOfMemory)(long)
Definition: safe_mem.c:32
Definition: mtr.h:126
#define cuddDeallocNode(unique, node)
Definition: cuddInt.h:520
int cuddZddAlignToBdd(DdManager *table)
Definition: cuddZddReord.c:348
unsigned long memused
Definition: cuddInt.h:429
int siftMaxVar
Definition: cuddInt.h:395
static int cuddZddSiftingBackward(DdManager *table, Move *moves, int size)
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
int cuddZddTreeSifting(DdManager *table, Cudd_ReorderingType method)
Definition: cuddZddGroup.c:228
MtrNode * treeZ
Definition: cuddInt.h:409
int autoDynZ
Definition: cuddInt.h:401
#define cuddE(node)
Definition: cuddInt.h:625
struct Move * next
Definition: cuddInt.h:474
#define cuddSatDec(x)
Definition: cuddInt.h:849
int * invperm
Definition: cuddInt.h:371
static int result
Definition: cuddGenetic.c:121
static void zddFixTree(DdManager *table, MtrNode *treenode)
int cuddBddAlignToZdd(DdManager *table)
Definition: cuddReorder.c:1250
int shift
Definition: cuddInt.h:312
static int zddShuffle(DdManager *table, int *permutation)
unsigned int keysZ
Definition: cuddInt.h:354
int * zdd_entry
Definition: cuddZddReord.c:104
Cudd_ReorderingType
Definition: cudd.h:147
int Cudd_zddShuffleHeap(DdManager *table, int *permutation)
Definition: cuddZddReord.c:300
struct MtrNode * child
Definition: mtr.h:132
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
double reclaimed
Definition: cuddInt.h:367
DdSubtable * subtableZ
Definition: cuddInt.h:350
DdNode ** univ
Definition: cuddInt.h:375
int Cudd_zddReduceHeap(DdManager *table, Cudd_ReorderingType heuristic, int minsize)
Definition: cuddZddReord.c:167