SVF
cuddZddGroup.c
Go to the documentation of this file.
1 
70 #include "CUDD/util.h"
71 #include "CUDD/cuddInt.h"
72 
73 /*---------------------------------------------------------------------------*/
74 /* Constant declarations */
75 /*---------------------------------------------------------------------------*/
76 
77 /*---------------------------------------------------------------------------*/
78 /* Stucture declarations */
79 /*---------------------------------------------------------------------------*/
80 
81 /*---------------------------------------------------------------------------*/
82 /* Type declarations */
83 /*---------------------------------------------------------------------------*/
84 
85 /*---------------------------------------------------------------------------*/
86 /* Variable declarations */
87 /*---------------------------------------------------------------------------*/
88 
89 #ifndef lint
90 static char rcsid[] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.22 2012/02/05 01:07:19 fabio Exp $";
91 #endif
92 
93 static int *entry;
94 extern int zddTotalNumberSwapping;
95 #ifdef DD_STATS
96 static int extsymmcalls;
97 static int extsymm;
98 static int secdiffcalls;
99 static int secdiff;
100 static int secdiffmisfire;
101 #endif
102 #ifdef DD_DEBUG
103 static int pr = 0; /* flag to enable printing while debugging */
104  /* by depositing a 1 into it */
105 #endif
106 
107 /*---------------------------------------------------------------------------*/
108 /* Macro declarations */
109 /*---------------------------------------------------------------------------*/
110 
113 /*---------------------------------------------------------------------------*/
114 /* Static function prototypes */
115 /*---------------------------------------------------------------------------*/
116 
117 static int zddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
118 #ifdef DD_STATS
119 static int zddCountInternalMtrNodes (DdManager *table, MtrNode *treenode);
120 #endif
121 static int zddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
122 static void zddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper);
123 static int zddUniqueCompareGroup (int *ptrX, int *ptrY);
124 static int zddGroupSifting (DdManager *table, int lower, int upper);
125 static int zddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh);
126 static int zddGroupSiftingUp (DdManager *table, int y, int xLow, Move **moves);
127 static int zddGroupSiftingDown (DdManager *table, int x, int xHigh, Move **moves);
128 static int zddGroupMove (DdManager *table, int x, int y, Move **moves);
129 static int zddGroupMoveBackward (DdManager *table, int x, int y);
130 static int zddGroupSiftingBackward (DdManager *table, Move *moves, int size);
131 static void zddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high);
132 
136 /*---------------------------------------------------------------------------*/
137 /* Definition of exported functions */
138 /*---------------------------------------------------------------------------*/
139 
140 
158 MtrNode *
160  DdManager * dd /* manager */,
161  unsigned int low /* index of the first group variable */,
162  unsigned int size /* number of variables in the group */,
163  unsigned int type /* MTR_DEFAULT or MTR_FIXED */)
164 {
165  MtrNode *group;
166  MtrNode *tree;
167  unsigned int level;
168 
169  /* If the variable does not exist yet, the position is assumed to be
170  ** the same as the index. Therefore, applications that rely on
171  ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new
172  ** variables have to create the variables before they group them.
173  */
174  level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low;
175 
176  if (level + size - 1> (int) MTR_MAXHIGH)
177  return(NULL);
178 
179  /* If the tree does not exist yet, create it. */
180  tree = dd->treeZ;
181  if (tree == NULL) {
182  dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ);
183  if (tree == NULL)
184  return(NULL);
185  tree->index = dd->invpermZ[0];
186  }
187 
188  /* Extend the upper bound of the tree if necessary. This allows the
189  ** application to create groups even before the variables are created.
190  */
191  tree->size = ddMax(tree->size, level + size);
192 
193  /* Create the group. */
194  group = Mtr_MakeGroup(tree, level, size, type);
195  if (group == NULL)
196  return(NULL);
197 
198  /* Initialize the index field to the index of the variable currently
199  ** in position low. This field will be updated by the reordering
200  ** procedure to provide a handle to the group once it has been moved.
201  */
202  group->index = (MtrHalfWord) low;
203 
204  return(group);
205 
206 } /* end of Cudd_MakeZddTreeNode */
207 
208 
209 /*---------------------------------------------------------------------------*/
210 /* Definition of internal functions */
211 /*---------------------------------------------------------------------------*/
212 
213 
227 int
229  DdManager * table /* DD table */,
230  Cudd_ReorderingType method /* reordering method for the groups of leaves */)
231 {
232  int i;
233  int nvars;
234  int result;
235  int tempTree;
236 
237  /* If no tree is provided we create a temporary one in which all
238  ** variables are in a single group. After reordering this tree is
239  ** destroyed.
240  */
241  tempTree = table->treeZ == NULL;
242  if (tempTree) {
243  table->treeZ = Mtr_InitGroupTree(0,table->sizeZ);
244  table->treeZ->index = table->invpermZ[0];
245  }
246  nvars = table->sizeZ;
247 
248 #ifdef DD_DEBUG
249  if (pr > 0 && !tempTree)
250  (void) fprintf(table->out,"cuddZddTreeSifting:");
251  Mtr_PrintGroups(table->treeZ,pr <= 0);
252 #endif
253 #if 0
254  /* Debugging code. */
255  if (table->tree && table->treeZ) {
256  (void) fprintf(table->out,"\n");
257  Mtr_PrintGroups(table->tree, 0);
258  cuddPrintVarGroups(table,table->tree,0,0);
259  for (i = 0; i < table->size; i++) {
260  (void) fprintf(table->out,"%s%d",
261  (i == 0) ? "" : ",", table->invperm[i]);
262  }
263  (void) fprintf(table->out,"\n");
264  for (i = 0; i < table->size; i++) {
265  (void) fprintf(table->out,"%s%d",
266  (i == 0) ? "" : ",", table->perm[i]);
267  }
268  (void) fprintf(table->out,"\n\n");
269  Mtr_PrintGroups(table->treeZ,0);
270  cuddPrintVarGroups(table,table->treeZ,1,0);
271  for (i = 0; i < table->sizeZ; i++) {
272  (void) fprintf(table->out,"%s%d",
273  (i == 0) ? "" : ",", table->invpermZ[i]);
274  }
275  (void) fprintf(table->out,"\n");
276  for (i = 0; i < table->sizeZ; i++) {
277  (void) fprintf(table->out,"%s%d",
278  (i == 0) ? "" : ",", table->permZ[i]);
279  }
280  (void) fprintf(table->out,"\n");
281  }
282  /* End of debugging code. */
283 #endif
284 #ifdef DD_STATS
285  extsymmcalls = 0;
286  extsymm = 0;
287  secdiffcalls = 0;
288  secdiff = 0;
289  secdiffmisfire = 0;
290 
291  (void) fprintf(table->out,"\n");
292  if (!tempTree)
293  (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n",
294  zddCountInternalMtrNodes(table,table->treeZ));
295 #endif
296 
297  /* Initialize the group of each subtable to itself. Initially
298  ** there are no groups. Groups are created according to the tree
299  ** structure in postorder fashion.
300  */
301  for (i = 0; i < nvars; i++)
302  table->subtableZ[i].next = i;
303 
304  /* Reorder. */
305  result = zddTreeSiftingAux(table, table->treeZ, method);
306 
307 #ifdef DD_STATS /* print stats */
308  if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
309  (table->groupcheck == CUDD_GROUP_CHECK7 ||
310  table->groupcheck == CUDD_GROUP_CHECK5)) {
311  (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
312  (void) fprintf(table->out,"extsymm = %d",extsymm);
313  }
314  if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
315  table->groupcheck == CUDD_GROUP_CHECK7) {
316  (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
317  (void) fprintf(table->out,"secdiff = %d\n",secdiff);
318  (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
319  }
320 #endif
321 
322  if (tempTree)
323  Cudd_FreeZddTree(table);
324  return(result);
325 
326 } /* end of cuddZddTreeSifting */
327 
328 
329 /*---------------------------------------------------------------------------*/
330 /* Definition of static functions */
331 /*---------------------------------------------------------------------------*/
332 
333 
344 static int
346  DdManager * table,
347  MtrNode * treenode,
348  Cudd_ReorderingType method)
349 {
350  MtrNode *auxnode;
351  int res;
352 
353 #ifdef DD_DEBUG
354  Mtr_PrintGroups(treenode,1);
355 #endif
356 
357  auxnode = treenode;
358  while (auxnode != NULL) {
359  if (auxnode->child != NULL) {
360  if (!zddTreeSiftingAux(table, auxnode->child, method))
361  return(0);
362  res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
363  if (res == 0)
364  return(0);
365  } else if (auxnode->size > 1) {
366  if (!zddReorderChildren(table, auxnode, method))
367  return(0);
368  }
369  auxnode = auxnode->younger;
370  }
371 
372  return(1);
373 
374 } /* end of zddTreeSiftingAux */
375 
376 
377 #ifdef DD_STATS
378 
388 static int
389 zddCountInternalMtrNodes(
390  DdManager * table,
391  MtrNode * treenode)
392 {
393  MtrNode *auxnode;
394  int count,nodeCount;
395 
396 
397  nodeCount = 0;
398  auxnode = treenode;
399  while (auxnode != NULL) {
400  if (!(MTR_TEST(auxnode,MTR_TERMINAL))) {
401  nodeCount++;
402  count = zddCountInternalMtrNodes(table,auxnode->child);
403  nodeCount += count;
404  }
405  auxnode = auxnode->younger;
406  }
407 
408  return(nodeCount);
409 
410 } /* end of zddCountInternalMtrNodes */
411 #endif
412 
413 
428 static int
430  DdManager * table,
431  MtrNode * treenode,
432  Cudd_ReorderingType method)
433 {
434  int lower;
435  int upper;
436  int result;
437  unsigned int initialSize;
438 
439  zddFindNodeHiLo(table,treenode,&lower,&upper);
440  /* If upper == -1 these variables do not exist yet. */
441  if (upper == -1)
442  return(1);
443 
444  if (treenode->flags == MTR_FIXED) {
445  result = 1;
446  } else {
447 #ifdef DD_STATS
448  (void) fprintf(table->out," ");
449 #endif
450  switch (method) {
451  case CUDD_REORDER_RANDOM:
453  result = cuddZddSwapping(table,lower,upper,method);
454  break;
455  case CUDD_REORDER_SIFT:
456  result = cuddZddSifting(table,lower,upper);
457  break;
459  do {
460  initialSize = table->keysZ;
461  result = cuddZddSifting(table,lower,upper);
462  if (initialSize <= table->keysZ)
463  break;
464 #ifdef DD_STATS
465  else
466  (void) fprintf(table->out,"\n");
467 #endif
468  } while (result != 0);
469  break;
471  result = cuddZddSymmSifting(table,lower,upper);
472  break;
474  result = cuddZddSymmSiftingConv(table,lower,upper);
475  break;
477  result = zddGroupSifting(table,lower,upper);
478  break;
479  case CUDD_REORDER_LINEAR:
480  result = cuddZddLinearSifting(table,lower,upper);
481  break;
483  do {
484  initialSize = table->keysZ;
485  result = cuddZddLinearSifting(table,lower,upper);
486  if (initialSize <= table->keysZ)
487  break;
488 #ifdef DD_STATS
489  else
490  (void) fprintf(table->out,"\n");
491 #endif
492  } while (result != 0);
493  break;
494  default:
495  return(0);
496  }
497  }
498 
499  /* Create a single group for all the variables that were sifted,
500  ** so that they will be treated as a single block by successive
501  ** invocations of zddGroupSifting.
502  */
503  zddMergeGroups(table,treenode,lower,upper);
504 
505 #ifdef DD_DEBUG
506  if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:");
507 #endif
508 
509  return(result);
510 
511 } /* end of zddReorderChildren */
512 
513 
529 static void
531  DdManager * table,
532  MtrNode * treenode,
533  int * lower,
534  int * upper)
535 {
536  int low;
537  int high;
538 
539  /* Check whether no variables in this group already exist.
540  ** If so, return immediately. The calling procedure will know from
541  ** the values of upper that no reordering is needed.
542  */
543  if ((int) treenode->low >= table->sizeZ) {
544  *lower = table->sizeZ;
545  *upper = -1;
546  return;
547  }
548 
549  *lower = low = (unsigned int) table->permZ[treenode->index];
550  high = (int) (low + treenode->size - 1);
551 
552  if (high >= table->sizeZ) {
553  /* This is the case of a partially existing group. The aim is to
554  ** reorder as many variables as safely possible. If the tree
555  ** node is terminal, we just reorder the subset of the group
556  ** that is currently in existence. If the group has
557  ** subgroups, then we only reorder those subgroups that are
558  ** fully instantiated. This way we avoid breaking up a group.
559  */
560  MtrNode *auxnode = treenode->child;
561  if (auxnode == NULL) {
562  *upper = (unsigned int) table->sizeZ - 1;
563  } else {
564  /* Search the subgroup that strands the table->sizeZ line.
565  ** If the first group starts at 0 and goes past table->sizeZ
566  ** upper will get -1, thus correctly signaling that no reordering
567  ** should take place.
568  */
569  while (auxnode != NULL) {
570  int thisLower = table->permZ[auxnode->low];
571  int thisUpper = thisLower + auxnode->size - 1;
572  if (thisUpper >= table->sizeZ && thisLower < table->sizeZ)
573  *upper = (unsigned int) thisLower - 1;
574  auxnode = auxnode->younger;
575  }
576  }
577  } else {
578  /* Normal case: All the variables of the group exist. */
579  *upper = (unsigned int) high;
580  }
581 
582 #ifdef DD_DEBUG
583  /* Make sure that all variables in group are contiguous. */
584  assert(treenode->size >= *upper - *lower + 1);
585 #endif
586 
587  return;
588 
589 } /* end of zddFindNodeHiLo */
590 
591 
604 static int
606  int * ptrX,
607  int * ptrY)
608 {
609 #if 0
610  if (entry[*ptrY] == entry[*ptrX]) {
611  return((*ptrX) - (*ptrY));
612  }
613 #endif
614  return(entry[*ptrY] - entry[*ptrX]);
615 
616 } /* end of zddUniqueCompareGroup */
617 
618 
632 static int
634  DdManager * table,
635  int lower,
636  int upper)
637 {
638  int *var;
639  int i,j,x,xInit;
640  int nvars;
641  int classes;
642  int result;
643  int *sifted;
644 #ifdef DD_STATS
645  unsigned previousSize;
646 #endif
647  int xindex;
648 
649  nvars = table->sizeZ;
650 
651  /* Order variables to sift. */
652  entry = NULL;
653  sifted = NULL;
654  var = ALLOC(int,nvars);
655  if (var == NULL) {
656  table->errorCode = CUDD_MEMORY_OUT;
657  goto zddGroupSiftingOutOfMem;
658  }
659  entry = ALLOC(int,nvars);
660  if (entry == NULL) {
661  table->errorCode = CUDD_MEMORY_OUT;
662  goto zddGroupSiftingOutOfMem;
663  }
664  sifted = ALLOC(int,nvars);
665  if (sifted == NULL) {
666  table->errorCode = CUDD_MEMORY_OUT;
667  goto zddGroupSiftingOutOfMem;
668  }
669 
670  /* Here we consider only one representative for each group. */
671  for (i = 0, classes = 0; i < nvars; i++) {
672  sifted[i] = 0;
673  x = table->permZ[i];
674  if ((unsigned) x >= table->subtableZ[x].next) {
675  entry[i] = table->subtableZ[x].keys;
676  var[classes] = i;
677  classes++;
678  }
679  }
680 
681  qsort((void *)var,classes,sizeof(int),(DD_QSFP)zddUniqueCompareGroup);
682 
683  /* Now sift. */
684  for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
685  if (zddTotalNumberSwapping >= table->siftMaxSwap)
686  break;
687  if (util_cpu_time() - table->startTime > table->timeLimit) {
688  table->autoDynZ = 0; /* prevent further reordering */
689  break;
690  }
691  xindex = var[i];
692  if (sifted[xindex] == 1) /* variable already sifted as part of group */
693  continue;
694  x = table->permZ[xindex]; /* find current level of this variable */
695  if (x < lower || x > upper)
696  continue;
697 #ifdef DD_STATS
698  previousSize = table->keysZ;
699 #endif
700 #ifdef DD_DEBUG
701  /* x is bottom of group */
702  assert((unsigned) x >= table->subtableZ[x].next);
703 #endif
704  result = zddGroupSiftingAux(table,x,lower,upper);
705  if (!result) goto zddGroupSiftingOutOfMem;
706 
707 #ifdef DD_STATS
708  if (table->keysZ < previousSize) {
709  (void) fprintf(table->out,"-");
710  } else if (table->keysZ > previousSize) {
711  (void) fprintf(table->out,"+");
712  } else {
713  (void) fprintf(table->out,"=");
714  }
715  fflush(table->out);
716 #endif
717 
718  /* Mark variables in the group just sifted. */
719  x = table->permZ[xindex];
720  if ((unsigned) x != table->subtableZ[x].next) {
721  xInit = x;
722  do {
723  j = table->invpermZ[x];
724  sifted[j] = 1;
725  x = table->subtableZ[x].next;
726  } while (x != xInit);
727  }
728 
729 #ifdef DD_DEBUG
730  if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:");
731 #endif
732  } /* for */
733 
734  FREE(sifted);
735  FREE(var);
736  FREE(entry);
737 
738  return(1);
739 
740 zddGroupSiftingOutOfMem:
741  if (entry != NULL) FREE(entry);
742  if (var != NULL) FREE(var);
743  if (sifted != NULL) FREE(sifted);
744 
745  return(0);
746 
747 } /* end of zddGroupSifting */
748 
749 
765 static int
767  DdManager * table,
768  int x,
769  int xLow,
770  int xHigh)
771 {
772  Move *move;
773  Move *moves; /* list of moves */
774  int initialSize;
775  int result;
776 
777 
778 #ifdef DD_DEBUG
779  if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh);
780  assert((unsigned) x >= table->subtableZ[x].next); /* x is bottom of group */
781 #endif
782 
783  initialSize = table->keysZ;
784  moves = NULL;
785 
786  if (x == xLow) { /* Sift down */
787 #ifdef DD_DEBUG
788  /* x must be a singleton */
789  assert((unsigned) x == table->subtableZ[x].next);
790 #endif
791  if (x == xHigh) return(1); /* just one variable */
792 
793  if (!zddGroupSiftingDown(table,x,xHigh,&moves))
794  goto zddGroupSiftingAuxOutOfMem;
795  /* at this point x == xHigh, unless early term */
796 
797  /* move backward and stop at best position */
798  result = zddGroupSiftingBackward(table,moves,initialSize);
799 #ifdef DD_DEBUG
800  assert(table->keysZ <= (unsigned) initialSize);
801 #endif
802  if (!result) goto zddGroupSiftingAuxOutOfMem;
803 
804  } else if (cuddZddNextHigh(table,x) > xHigh) { /* Sift up */
805 #ifdef DD_DEBUG
806  /* x is bottom of group */
807  assert((unsigned) x >= table->subtableZ[x].next);
808 #endif
809  /* Find top of x's group */
810  x = table->subtableZ[x].next;
811 
812  if (!zddGroupSiftingUp(table,x,xLow,&moves))
813  goto zddGroupSiftingAuxOutOfMem;
814  /* at this point x == xLow, unless early term */
815 
816  /* move backward and stop at best position */
817  result = zddGroupSiftingBackward(table,moves,initialSize);
818 #ifdef DD_DEBUG
819  assert(table->keysZ <= (unsigned) initialSize);
820 #endif
821  if (!result) goto zddGroupSiftingAuxOutOfMem;
822 
823  } else if (x - xLow > xHigh - x) { /* must go down first: shorter */
824  if (!zddGroupSiftingDown(table,x,xHigh,&moves))
825  goto zddGroupSiftingAuxOutOfMem;
826  /* at this point x == xHigh, unless early term */
827 
828  /* Find top of group */
829  if (moves) {
830  x = moves->y;
831  }
832  while ((unsigned) x < table->subtableZ[x].next)
833  x = table->subtableZ[x].next;
834  x = table->subtableZ[x].next;
835 #ifdef DD_DEBUG
836  /* x should be the top of a group */
837  assert((unsigned) x <= table->subtableZ[x].next);
838 #endif
839 
840  if (!zddGroupSiftingUp(table,x,xLow,&moves))
841  goto zddGroupSiftingAuxOutOfMem;
842 
843  /* move backward and stop at best position */
844  result = zddGroupSiftingBackward(table,moves,initialSize);
845 #ifdef DD_DEBUG
846  assert(table->keysZ <= (unsigned) initialSize);
847 #endif
848  if (!result) goto zddGroupSiftingAuxOutOfMem;
849 
850  } else { /* moving up first: shorter */
851  /* Find top of x's group */
852  x = table->subtableZ[x].next;
853 
854  if (!zddGroupSiftingUp(table,x,xLow,&moves))
855  goto zddGroupSiftingAuxOutOfMem;
856  /* at this point x == xHigh, unless early term */
857 
858  if (moves) {
859  x = moves->x;
860  }
861  while ((unsigned) x < table->subtableZ[x].next)
862  x = table->subtableZ[x].next;
863 #ifdef DD_DEBUG
864  /* x is bottom of a group */
865  assert((unsigned) x >= table->subtableZ[x].next);
866 #endif
867 
868  if (!zddGroupSiftingDown(table,x,xHigh,&moves))
869  goto zddGroupSiftingAuxOutOfMem;
870 
871  /* move backward and stop at best position */
872  result = zddGroupSiftingBackward(table,moves,initialSize);
873 #ifdef DD_DEBUG
874  assert(table->keysZ <= (unsigned) initialSize);
875 #endif
876  if (!result) goto zddGroupSiftingAuxOutOfMem;
877  }
878 
879  while (moves != NULL) {
880  move = moves->next;
881  cuddDeallocMove(table, moves);
882  moves = move;
883  }
884 
885  return(1);
886 
887 zddGroupSiftingAuxOutOfMem:
888  while (moves != NULL) {
889  move = moves->next;
890  cuddDeallocMove(table, moves);
891  moves = move;
892  }
893 
894  return(0);
895 
896 } /* end of zddGroupSiftingAux */
897 
898 
914 static int
916  DdManager * table,
917  int y,
918  int xLow,
919  Move ** moves)
920 {
921  Move *move;
922  int x;
923  int size;
924  int gxtop;
925  int limitSize;
926 
927  limitSize = table->keysZ;
928 
929  x = cuddZddNextLow(table,y);
930  while (x >= xLow) {
931  gxtop = table->subtableZ[x].next;
932  if (table->subtableZ[x].next == (unsigned) x &&
933  table->subtableZ[y].next == (unsigned) y) {
934  /* x and y are self groups */
935  size = cuddZddSwapInPlace(table,x,y);
936 #ifdef DD_DEBUG
937  assert(table->subtableZ[x].next == (unsigned) x);
938  assert(table->subtableZ[y].next == (unsigned) y);
939 #endif
940  if (size == 0) goto zddGroupSiftingUpOutOfMem;
941  move = (Move *)cuddDynamicAllocNode(table);
942  if (move == NULL) goto zddGroupSiftingUpOutOfMem;
943  move->x = x;
944  move->y = y;
945  move->flags = MTR_DEFAULT;
946  move->size = size;
947  move->next = *moves;
948  *moves = move;
949 
950 #ifdef DD_DEBUG
951  if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n");
952 #endif
953  if ((double) size > (double) limitSize * table->maxGrowth)
954  return(1);
955  if (size < limitSize) limitSize = size;
956  } else { /* group move */
957  size = zddGroupMove(table,x,y,moves);
958  if (size == 0) goto zddGroupSiftingUpOutOfMem;
959  if ((double) size > (double) limitSize * table->maxGrowth)
960  return(1);
961  if (size < limitSize) limitSize = size;
962  }
963  y = gxtop;
964  x = cuddZddNextLow(table,y);
965  }
966 
967  return(1);
968 
969 zddGroupSiftingUpOutOfMem:
970  while (*moves != NULL) {
971  move = (*moves)->next;
972  cuddDeallocMove(table, *moves);
973  *moves = move;
974  }
975  return(0);
976 
977 } /* end of zddGroupSiftingUp */
978 
979 
991 static int
993  DdManager * table,
994  int x,
995  int xHigh,
996  Move ** moves)
997 {
998  Move *move;
999  int y;
1000  int size;
1001  int limitSize;
1002  int gybot;
1003 
1004 
1005  /* Initialize R */
1006  limitSize = size = table->keysZ;
1007  y = cuddZddNextHigh(table,x);
1008  while (y <= xHigh) {
1009  /* Find bottom of y group. */
1010  gybot = table->subtableZ[y].next;
1011  while (table->subtableZ[gybot].next != (unsigned) y)
1012  gybot = table->subtableZ[gybot].next;
1013 
1014  if (table->subtableZ[x].next == (unsigned) x &&
1015  table->subtableZ[y].next == (unsigned) y) {
1016  /* x and y are self groups */
1017  size = cuddZddSwapInPlace(table,x,y);
1018 #ifdef DD_DEBUG
1019  assert(table->subtableZ[x].next == (unsigned) x);
1020  assert(table->subtableZ[y].next == (unsigned) y);
1021 #endif
1022  if (size == 0) goto zddGroupSiftingDownOutOfMem;
1023 
1024  /* Record move. */
1025  move = (Move *) cuddDynamicAllocNode(table);
1026  if (move == NULL) goto zddGroupSiftingDownOutOfMem;
1027  move->x = x;
1028  move->y = y;
1029  move->flags = MTR_DEFAULT;
1030  move->size = size;
1031  move->next = *moves;
1032  *moves = move;
1033 
1034 #ifdef DD_DEBUG
1035  if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n");
1036 #endif
1037  if ((double) size > (double) limitSize * table->maxGrowth)
1038  return(1);
1039  if (size < limitSize) limitSize = size;
1040  x = y;
1041  y = cuddZddNextHigh(table,x);
1042  } else { /* Group move */
1043  size = zddGroupMove(table,x,y,moves);
1044  if (size == 0) goto zddGroupSiftingDownOutOfMem;
1045  if ((double) size > (double) limitSize * table->maxGrowth)
1046  return(1);
1047  if (size < limitSize) limitSize = size;
1048  }
1049  x = gybot;
1050  y = cuddZddNextHigh(table,x);
1051  }
1052 
1053  return(1);
1054 
1055 zddGroupSiftingDownOutOfMem:
1056  while (*moves != NULL) {
1057  move = (*moves)->next;
1058  cuddDeallocMove(table, *moves);
1059  *moves = move;
1060  }
1061 
1062  return(0);
1063 
1064 } /* end of zddGroupSiftingDown */
1065 
1066 
1077 static int
1079  DdManager * table,
1080  int x,
1081  int y,
1082  Move ** moves)
1083 {
1084  Move *move;
1085  int size;
1086  int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
1087  int swapx,swapy;
1088 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
1089  int initialSize,bestSize;
1090 #endif
1091 
1092 #ifdef DD_DEBUG
1093  /* We assume that x < y */
1094  assert(x < y);
1095 #endif
1096  /* Find top, bottom, and size for the two groups. */
1097  xbot = x;
1098  xtop = table->subtableZ[x].next;
1099  xsize = xbot - xtop + 1;
1100  ybot = y;
1101  while ((unsigned) ybot < table->subtableZ[ybot].next)
1102  ybot = table->subtableZ[ybot].next;
1103  ytop = y;
1104  ysize = ybot - ytop + 1;
1105 
1106 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
1107  initialSize = bestSize = table->keysZ;
1108 #endif
1109  /* Sift the variables of the second group up through the first group */
1110  for (i = 1; i <= ysize; i++) {
1111  for (j = 1; j <= xsize; j++) {
1112  size = cuddZddSwapInPlace(table,x,y);
1113  if (size == 0) goto zddGroupMoveOutOfMem;
1114 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
1115  if (size < bestSize)
1116  bestSize = size;
1117 #endif
1118  swapx = x; swapy = y;
1119  y = x;
1120  x = cuddZddNextLow(table,y);
1121  }
1122  y = ytop + i;
1123  x = cuddZddNextLow(table,y);
1124  }
1125 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
1126  if ((bestSize < initialSize) && (bestSize < size))
1127  (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size);
1128 #endif
1129 
1130  /* fix groups */
1131  y = xtop; /* ytop is now where xtop used to be */
1132  for (i = 0; i < ysize - 1; i++) {
1133  table->subtableZ[y].next = cuddZddNextHigh(table,y);
1134  y = cuddZddNextHigh(table,y);
1135  }
1136  table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
1137  /* it to top of its group */
1138  x = cuddZddNextHigh(table,y);
1139  newxtop = x;
1140  for (i = 0; i < xsize - 1; i++) {
1141  table->subtableZ[x].next = cuddZddNextHigh(table,x);
1142  x = cuddZddNextHigh(table,x);
1143  }
1144  table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
1145  /* it to top of its group */
1146 #ifdef DD_DEBUG
1147  if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n");
1148 #endif
1149 
1150  /* Store group move */
1151  move = (Move *) cuddDynamicAllocNode(table);
1152  if (move == NULL) goto zddGroupMoveOutOfMem;
1153  move->x = swapx;
1154  move->y = swapy;
1155  move->flags = MTR_DEFAULT;
1156  move->size = table->keysZ;
1157  move->next = *moves;
1158  *moves = move;
1159 
1160  return(table->keysZ);
1161 
1162 zddGroupMoveOutOfMem:
1163  while (*moves != NULL) {
1164  move = (*moves)->next;
1165  cuddDeallocMove(table, *moves);
1166  *moves = move;
1167  }
1168  return(0);
1169 
1170 } /* end of zddGroupMove */
1171 
1172 
1183 static int
1185  DdManager * table,
1186  int x,
1187  int y)
1188 {
1189  int size;
1190  int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
1191 
1192 
1193 #ifdef DD_DEBUG
1194  /* We assume that x < y */
1195  assert(x < y);
1196 #endif
1197 
1198  /* Find top, bottom, and size for the two groups. */
1199  xbot = x;
1200  xtop = table->subtableZ[x].next;
1201  xsize = xbot - xtop + 1;
1202  ybot = y;
1203  while ((unsigned) ybot < table->subtableZ[ybot].next)
1204  ybot = table->subtableZ[ybot].next;
1205  ytop = y;
1206  ysize = ybot - ytop + 1;
1207 
1208  /* Sift the variables of the second group up through the first group */
1209  for (i = 1; i <= ysize; i++) {
1210  for (j = 1; j <= xsize; j++) {
1211  size = cuddZddSwapInPlace(table,x,y);
1212  if (size == 0)
1213  return(0);
1214  y = x;
1215  x = cuddZddNextLow(table,y);
1216  }
1217  y = ytop + i;
1218  x = cuddZddNextLow(table,y);
1219  }
1220 
1221  /* fix groups */
1222  y = xtop;
1223  for (i = 0; i < ysize - 1; i++) {
1224  table->subtableZ[y].next = cuddZddNextHigh(table,y);
1225  y = cuddZddNextHigh(table,y);
1226  }
1227  table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
1228  /* to its top */
1229  x = cuddZddNextHigh(table,y);
1230  newxtop = x;
1231  for (i = 0; i < xsize - 1; i++) {
1232  table->subtableZ[x].next = cuddZddNextHigh(table,x);
1233  x = cuddZddNextHigh(table,x);
1234  }
1235  table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
1236  /* to its top */
1237 #ifdef DD_DEBUG
1238  if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n");
1239 #endif
1240 
1241  return(1);
1242 
1243 } /* end of zddGroupMoveBackward */
1244 
1245 
1257 static int
1259  DdManager * table,
1260  Move * moves,
1261  int size)
1262 {
1263  Move *move;
1264  int res;
1265 
1266 
1267  for (move = moves; move != NULL; move = move->next) {
1268  if (move->size < size) {
1269  size = move->size;
1270  }
1271  }
1272 
1273  for (move = moves; move != NULL; move = move->next) {
1274  if (move->size == size) return(1);
1275  if ((table->subtableZ[move->x].next == move->x) &&
1276  (table->subtableZ[move->y].next == move->y)) {
1277  res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
1278  if (!res) return(0);
1279 #ifdef DD_DEBUG
1280  if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n");
1281  assert(table->subtableZ[move->x].next == move->x);
1282  assert(table->subtableZ[move->y].next == move->y);
1283 #endif
1284  } else { /* Group move necessary */
1285  res = zddGroupMoveBackward(table,(int)move->x,(int)move->y);
1286  if (!res) return(0);
1287  }
1288  }
1289 
1290  return(1);
1291 
1292 } /* end of zddGroupSiftingBackward */
1293 
1294 
1305 static void
1307  DdManager * table,
1308  MtrNode * treenode,
1309  int low,
1310  int high)
1311 {
1312  int i;
1313  MtrNode *auxnode;
1314  int saveindex;
1315  int newindex;
1316 
1317  /* Merge all variables from low to high in one group, unless
1318  ** this is the topmost group. In such a case we do not merge lest
1319  ** we lose the symmetry information. */
1320  if (treenode != table->treeZ) {
1321  for (i = low; i < high; i++)
1322  table->subtableZ[i].next = i+1;
1323  table->subtableZ[high].next = low;
1324  }
1325 
1326  /* Adjust the index fields of the tree nodes. If a node is the
1327  ** first child of its parent, then the parent may also need adjustment. */
1328  saveindex = treenode->index;
1329  newindex = table->invpermZ[low];
1330  auxnode = treenode;
1331  do {
1332  auxnode->index = newindex;
1333  if (auxnode->parent == NULL ||
1334  (int) auxnode->parent->index != saveindex)
1335  break;
1336  auxnode = auxnode->parent;
1337  } while (1);
1338  return;
1339 
1340 } /* end of zddMergeGroups */
#define MTR_MAXHIGH
Definition: mtr.h:107
#define MTR_TERMINAL
Definition: mtr.h:95
Cudd_AggregationType groupcheck
Definition: cuddInt.h:410
unsigned int keys
Definition: cuddInt.h:314
MtrHalfWord flags
Definition: mtr.h:127
static int zddGroupMove(DdManager *table, int x, int y, Move **moves)
unsigned short MtrHalfWord
Definition: mtr.h:123
int zddTotalNumberSwapping
Definition: cuddZddReord.c:106
static int zddGroupSifting(DdManager *table, int lower, int upper)
Definition: cuddZddGroup.c:633
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
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
unsigned long startTime
Definition: cuddInt.h:426
int * invpermZ
Definition: cuddInt.h:372
#define assert(ex)
Definition: util.h:141
static int zddReorderChildren(DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
Definition: cuddZddGroup.c:429
int size
Definition: cuddInt.h:345
Definition: cuddInt.h:469
static int * entry
Definition: cuddZddGroup.c:93
double maxGrowth
Definition: cuddInt.h:397
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:480
#define MTR_FIXED
Definition: mtr.h:97
static void zddFindNodeHiLo(DdManager *table, MtrNode *treenode, int *lower, int *upper)
Definition: cuddZddGroup.c:530
int * permZ
Definition: cuddInt.h:370
struct MtrNode * parent
Definition: mtr.h:131
void cuddPrintVarGroups(DdManager *dd, MtrNode *root, int zdd, int silent)
Definition: cuddCheck.c:749
static int zddGroupSiftingUp(DdManager *table, int y, int xLow, Move **moves)
Definition: cuddZddGroup.c:915
#define MTR_DEFAULT
Definition: mtr.h:94
MtrNode * tree
Definition: cuddInt.h:408
#define MTR_TEST(node, flag)
Definition: mtr.h:150
struct MtrNode * younger
Definition: mtr.h:134
int cuddZddSymmSiftingConv(DdManager *table, int lower, int upper)
Definition: cuddZddSymm.c:423
int cuddZddLinearSifting(DdManager *table, int lower, int upper)
Definition: cuddZddLin.c:152
MtrHalfWord index
Definition: mtr.h:130
static int zddGroupSiftingBackward(DdManager *table, Move *moves, int size)
#define ALLOC(type, num)
Definition: util.h:76
FILE * out
Definition: cuddInt.h:423
unsigned int flags
Definition: cuddInt.h:472
DdHalfWord x
Definition: cuddInt.h:470
static int zddUniqueCompareGroup(int *ptrX, int *ptrY)
Definition: cuddZddGroup.c:605
#define ddMax(x, y)
Definition: cuddInt.h:785
MtrNode * Cudd_MakeZddTreeNode(DdManager *dd, unsigned int low, unsigned int size, unsigned int type)
Definition: cuddZddGroup.c:159
static int zddGroupSiftingDown(DdManager *table, int x, int xHigh, Move **moves)
Definition: cuddZddGroup.c:992
int cuddZddSifting(DdManager *table, int lower, int upper)
Definition: cuddZddReord.c:863
#define ddMin(x, y)
Definition: cuddInt.h:771
int cuddZddNextHigh(DdManager *table, int x)
Definition: cuddZddReord.c:409
MtrHalfWord low
Definition: mtr.h:128
long util_cpu_time(void)
Definition: cpu_time.c:34
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:405
Definition: mtr.h:126
static char rcsid [] DD_UNUSED
Definition: cuddZddGroup.c:90
void Mtr_PrintGroups(MtrNode *root, int silent)
Definition: mtrGroup.c:595
int siftMaxVar
Definition: cuddInt.h:395
int cuddZddSymmSifting(DdManager *table, int lower, int upper)
Definition: cuddZddSymm.c:298
static int zddGroupSiftingAux(DdManager *table, int x, int xLow, int xHigh)
Definition: cuddZddGroup.c:766
MtrNode * Mtr_InitGroupTree(int lower, int size)
Definition: mtrGroup.c:120
int sizeZ
Definition: cuddInt.h:346
int cuddZddTreeSifting(DdManager *table, Cudd_ReorderingType method)
Definition: cuddZddGroup.c:228
DdHalfWord y
Definition: cuddInt.h:471
unsigned int next
Definition: cuddInt.h:317
int cuddZddSwapping(DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
Definition: cuddZddReord.c:742
MtrNode * treeZ
Definition: cuddInt.h:409
int autoDynZ
Definition: cuddInt.h:401
static int zddTreeSiftingAux(DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
Definition: cuddZddGroup.c:345
struct Move * next
Definition: cuddInt.h:474
int * invperm
Definition: cuddInt.h:371
static int result
Definition: cuddGenetic.c:121
void Cudd_FreeZddTree(DdManager *dd)
Definition: cuddAPI.c:2534
static void zddMergeGroups(DdManager *table, MtrNode *treenode, int low, int high)
MtrNode * Mtr_MakeGroup(MtrNode *root, unsigned int low, unsigned int high, unsigned int flags)
Definition: mtrGroup.c:156
static int zddGroupMoveBackward(DdManager *table, int x, int y)
unsigned int keysZ
Definition: cuddInt.h:354
Cudd_ReorderingType
Definition: cudd.h:147
struct MtrNode * child
Definition: mtr.h:132
int * perm
Definition: cuddInt.h:369
unsigned long timeLimit
Definition: cuddInt.h:427
int cuddZddNextLow(DdManager *table, int x)
Definition: cuddZddReord.c:431
int size
Definition: cuddInt.h:473
Cudd_ErrorType errorCode
Definition: cuddInt.h:425
DdSubtable * subtableZ
Definition: cuddInt.h:350