abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cuddReorder.c
Go to the documentation of this file.
1 /**CFile***********************************************************************
2 
3  FileName [cuddReorder.c]
4 
5  PackageName [cudd]
6 
7  Synopsis [Functions for dynamic variable reordering.]
8 
9  Description [External procedures included in this file:
10  <ul>
11  <li> Cudd_ReduceHeap()
12  <li> Cudd_ShuffleHeap()
13  </ul>
14  Internal procedures included in this module:
15  <ul>
16  <li> cuddDynamicAllocNode()
17  <li> cuddSifting()
18  <li> cuddSwapping()
19  <li> cuddNextHigh()
20  <li> cuddNextLow()
21  <li> cuddSwapInPlace()
22  <li> cuddBddAlignToZdd()
23  </ul>
24  Static procedures included in this module:
25  <ul>
26  <li> ddUniqueCompare()
27  <li> ddSwapAny()
28  <li> ddSiftingAux()
29  <li> ddSiftingUp()
30  <li> ddSiftingDown()
31  <li> ddSiftingBackward()
32  <li> ddReorderPreprocess()
33  <li> ddReorderPostprocess()
34  <li> ddShuffle()
35  <li> ddSiftUp()
36  <li> bddFixTree()
37  </ul>]
38 
39  Author [Shipra Panda, Bernard Plessier, Fabio Somenzi]
40 
41  Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
42 
43  All rights reserved.
44 
45  Redistribution and use in source and binary forms, with or without
46  modification, are permitted provided that the following conditions
47  are met:
48 
49  Redistributions of source code must retain the above copyright
50  notice, this list of conditions and the following disclaimer.
51 
52  Redistributions in binary form must reproduce the above copyright
53  notice, this list of conditions and the following disclaimer in the
54  documentation and/or other materials provided with the distribution.
55 
56  Neither the name of the University of Colorado nor the names of its
57  contributors may be used to endorse or promote products derived from
58  this software without specific prior written permission.
59 
60  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
61  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
62  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
63  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
64  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
65  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
66  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
67  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
68  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
70  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
71  POSSIBILITY OF SUCH DAMAGE.]
72 
73 ******************************************************************************/
74 
75 #include "misc/util/util_hack.h"
76 #include "cuddInt.h"
77 
79 
80 
81 
82 /*---------------------------------------------------------------------------*/
83 /* Constant declarations */
84 /*---------------------------------------------------------------------------*/
85 
86 #define DD_MAX_SUBTABLE_SPARSITY 8
87 #define DD_SHRINK_FACTOR 2
88 
89 /*---------------------------------------------------------------------------*/
90 /* Stucture declarations */
91 /*---------------------------------------------------------------------------*/
92 
93 /*---------------------------------------------------------------------------*/
94 /* Type declarations */
95 /*---------------------------------------------------------------------------*/
96 
97 /*---------------------------------------------------------------------------*/
98 /* Variable declarations */
99 /*---------------------------------------------------------------------------*/
100 
101 #ifndef lint
102 static char rcsid[] DD_UNUSED = "$Id: cuddReorder.c,v 1.69 2009/02/21 18:24:10 fabio Exp $";
103 #endif
104 
105 static int *entry;
106 
108 #ifdef DD_STATS
109 int ddTotalNISwaps;
110 #endif
111 
112 /*---------------------------------------------------------------------------*/
113 /* Macro declarations */
114 /*---------------------------------------------------------------------------*/
115 
116 /**AutomaticStart*************************************************************/
117 
118 /*---------------------------------------------------------------------------*/
119 /* Static function prototypes */
120 /*---------------------------------------------------------------------------*/
121 
122 static int ddUniqueCompare (int *ptrX, int *ptrY);
123 static Move * ddSwapAny (DdManager *table, int x, int y);
124 static int ddSiftingAux (DdManager *table, int x, int xLow, int xHigh);
125 static Move * ddSiftingUp (DdManager *table, int y, int xLow);
126 static Move * ddSiftingDown (DdManager *table, int x, int xHigh);
127 static int ddSiftingBackward (DdManager *table, int size, Move *moves);
128 static int ddReorderPreprocess (DdManager *table);
129 static int ddReorderPostprocess (DdManager *table);
130 static int ddShuffle (DdManager *table, int *permutation);
131 static int ddSiftUp (DdManager *table, int x, int xLow);
132 static void bddFixTree (DdManager *table, MtrNode *treenode);
133 static int ddUpdateMtrTree (DdManager *table, MtrNode *treenode, int *perm, int *invperm);
134 static int ddCheckPermuation (DdManager *table, MtrNode *treenode, int *perm, int *invperm);
135 
136 /**AutomaticEnd***************************************************************/
137 
138 
139 /*---------------------------------------------------------------------------*/
140 /* Definition of exported functions */
141 /*---------------------------------------------------------------------------*/
142 
143 
144 /**Function********************************************************************
145 
146  Synopsis [Main dynamic reordering routine.]
147 
148  Description [Main dynamic reordering routine.
149  Calls one of the possible reordering procedures:
150  <ul>
151  <li>Swapping
152  <li>Sifting
153  <li>Symmetric Sifting
154  <li>Group Sifting
155  <li>Window Permutation
156  <li>Simulated Annealing
157  <li>Genetic Algorithm
158  <li>Dynamic Programming (exact)
159  </ul>
160 
161  For sifting, symmetric sifting, group sifting, and window
162  permutation it is possible to request reordering to convergence.<p>
163 
164  The core of all methods is the reordering procedure
165  cuddSwapInPlace() which swaps two adjacent variables and is based
166  on Rudell's paper.
167  Returns 1 in case of success; 0 otherwise. In the case of symmetric
168  sifting (with and without convergence) returns 1 plus the number of
169  symmetric variables, in case of success.]
170 
171  SideEffects [Changes the variable order for all diagrams and clears
172  the cache.]
173 
174 ******************************************************************************/
175 int
177  DdManager * table /* DD manager */,
178  Cudd_ReorderingType heuristic /* method used for reordering */,
179  int minsize /* bound below which no reordering occurs */)
180 {
181  DdHook *hook;
182  int result;
183  unsigned int nextDyn;
184 #ifdef DD_STATS
185  unsigned int initialSize;
186  unsigned int finalSize;
187 #endif
188  long localTime;
189 
190  /* Don't reorder if there are too many dead nodes. */
191  if (table->keys - table->dead < (unsigned) minsize)
192  return(1);
193 
194  if (heuristic == CUDD_REORDER_SAME) {
195  heuristic = table->autoMethod;
196  }
197  if (heuristic == CUDD_REORDER_NONE) {
198  return(1);
199  }
200 
201  /* This call to Cudd_ReduceHeap does initiate reordering. Therefore
202  ** we count it.
203  */
204  table->reorderings++;
205 
206  localTime = util_cpu_time();
207 
208  /* Run the hook functions. */
209  hook = table->preReorderingHook;
210  while (hook != NULL) {
211  int res = (hook->f)(table, "BDD", (void *)heuristic);
212  if (res == 0) return(0);
213  hook = hook->next;
214  }
215 
216  if (!ddReorderPreprocess(table)) return(0);
218 
219  if (table->keys > table->peakLiveNodes) {
220  table->peakLiveNodes = table->keys;
221  }
222 #ifdef DD_STATS
223  initialSize = table->keys - table->isolated;
224  ddTotalNISwaps = 0;
225 
226  switch(heuristic) {
227  case CUDD_REORDER_RANDOM:
229  (void) fprintf(table->out,"#:I_RANDOM ");
230  break;
231  case CUDD_REORDER_SIFT:
237  (void) fprintf(table->out,"#:I_SIFTING ");
238  break;
245  (void) fprintf(table->out,"#:I_WINDOW ");
246  break;
248  (void) fprintf(table->out,"#:I_ANNEAL ");
249  break;
251  (void) fprintf(table->out,"#:I_GENETIC ");
252  break;
253  case CUDD_REORDER_LINEAR:
255  (void) fprintf(table->out,"#:I_LINSIFT ");
256  break;
257  case CUDD_REORDER_EXACT:
258  (void) fprintf(table->out,"#:I_EXACT ");
259  break;
260  default:
261  return(0);
262  }
263  (void) fprintf(table->out,"%8d: initial size",initialSize);
264 #endif
265 
266  /* See if we should use alternate threshold for maximum growth. */
267  if (table->reordCycle && table->reorderings % table->reordCycle == 0) {
268  double saveGrowth = table->maxGrowth;
269  table->maxGrowth = table->maxGrowthAlt;
270  result = cuddTreeSifting(table,heuristic);
271  table->maxGrowth = saveGrowth;
272  } else {
273  result = cuddTreeSifting(table,heuristic);
274  }
275 
276 #ifdef DD_STATS
277  (void) fprintf(table->out,"\n");
278  finalSize = table->keys - table->isolated;
279  (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
280  (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
281  ((double)(util_cpu_time() - localTime)/1000.0));
282  (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
284  (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps);
285 #endif
286 
287  if (result == 0)
288  return(0);
289 
290  if (!ddReorderPostprocess(table))
291  return(0);
292 
293  if (table->realign) {
294  if (!cuddZddAlignToBdd(table))
295  return(0);
296  }
297 
298  nextDyn = (table->keys - table->constants.keys + 1) *
299  DD_DYN_RATIO + table->constants.keys;
300  if (table->reorderings < 20 || nextDyn > table->nextDyn)
301  table->nextDyn = nextDyn;
302  else
303  table->nextDyn += 20;
304  table->reordered = 1;
305 
306  /* Run hook functions. */
307  hook = table->postReorderingHook;
308  while (hook != NULL) {
309  int res = (hook->f)(table, "BDD", (void *)localTime);
310  if (res == 0) return(0);
311  hook = hook->next;
312  }
313  /* Update cumulative reordering time. */
314  table->reordTime += util_cpu_time() - localTime;
315 
316  return(result);
317 
318 } /* end of Cudd_ReduceHeap */
319 
320 
321 /**Function********************************************************************
322 
323  Synopsis [Reorders variables according to given permutation.]
324 
325  Description [Reorders variables according to given permutation.
326  The i-th entry of the permutation array contains the index of the variable
327  that should be brought to the i-th level. The size of the array should be
328  equal or greater to the number of variables currently in use.
329  Returns 1 in case of success; 0 otherwise.]
330 
331  SideEffects [Changes the variable order for all diagrams and clears
332  the cache.]
333 
334  SeeAlso [Cudd_ReduceHeap]
335 
336 ******************************************************************************/
337 int
339  DdManager * table /* DD manager */,
340  int * permutation /* required variable permutation */)
341 {
342 
343  int result;
344  int i;
345  int identity = 1;
346  int *perm;
347 
348  /* Don't waste time in case of identity permutation. */
349  for (i = 0; i < table->size; i++) {
350  if (permutation[i] != table->invperm[i]) {
351  identity = 0;
352  break;
353  }
354  }
355  if (identity == 1) {
356  return(1);
357  }
358  if (!ddReorderPreprocess(table)) return(0);
359  if (table->keys > table->peakLiveNodes) {
360  table->peakLiveNodes = table->keys;
361  }
362 
363  perm = ABC_ALLOC(int, table->size);
364  for (i = 0; i < table->size; i++)
365  perm[permutation[i]] = i;
366  if (!ddCheckPermuation(table,table->tree,perm,permutation)) {
367  ABC_FREE(perm);
368  return(0);
369  }
370  if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) {
371  ABC_FREE(perm);
372  return(0);
373  }
374  ABC_FREE(perm);
375 
376  result = ddShuffle(table,permutation);
377 
378  if (!ddReorderPostprocess(table)) return(0);
379 
380  return(result);
381 
382 } /* end of Cudd_ShuffleHeap */
383 
384 
385 /*---------------------------------------------------------------------------*/
386 /* Definition of internal functions */
387 /*---------------------------------------------------------------------------*/
388 
389 
390 /**Function********************************************************************
391 
392  Synopsis [Dynamically allocates a Node.]
393 
394  Description [Dynamically allocates a Node. This procedure is similar
395  to cuddAllocNode in Cudd_Table.c, but it does not attempt garbage
396  collection, because during reordering there are no dead nodes.
397  Returns a pointer to a new node if successful; NULL is memory is
398  full.]
399 
400  SideEffects [None]
401 
402  SeeAlso [cuddAllocNode]
403 
404 ******************************************************************************/
405 DdNode *
407  DdManager * table)
408 {
409  int i;
410  DdNodePtr *mem;
411  DdNode *list, *node;
412  extern DD_OOMFP MMoutOfMemory;
413  DD_OOMFP saveHandler;
414 
415  if (table->nextFree == NULL) { /* free list is empty */
416  /* Try to allocate a new block. */
417  saveHandler = MMoutOfMemory;
418  MMoutOfMemory = Cudd_OutOfMem;
419 // mem = (DdNodePtr *) ABC_ALLOC(DdNode, DD_MEM_CHUNK + 1);
420  mem = (DdNodePtr *) ABC_ALLOC(DdNode, DD_MEM_CHUNK + 2);
421  MMoutOfMemory = saveHandler;
422  if (mem == NULL && table->stash != NULL) {
423  ABC_FREE(table->stash);
424  table->stash = NULL;
425  /* Inhibit resizing of tables. */
426  table->maxCacheHard = table->cacheSlots - 1;
427  table->cacheSlack = - (int) (table->cacheSlots + 1);
428  for (i = 0; i < table->size; i++) {
429  table->subtables[i].maxKeys <<= 2;
430  }
431 // mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 1);
432  mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 2);
433  }
434  if (mem == NULL) {
435  /* Out of luck. Call the default handler to do
436  ** whatever it specifies for a failed malloc. If this
437  ** handler returns, then set error code, print
438  ** warning, and return. */
439  (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
440  table->errorCode = CUDD_MEMORY_OUT;
441 #ifdef DD_VERBOSE
442  (void) fprintf(table->err,
443  "cuddDynamicAllocNode: out of memory");
444  (void) fprintf(table->err,"Memory in use = %lu\n",
445  table->memused);
446 #endif
447  return(NULL);
448  } else { /* successful allocation; slice memory */
449  unsigned long offset;
450  table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
451  mem[0] = (DdNode *) table->memoryList;
452  table->memoryList = mem;
453 
454  /* Here we rely on the fact that the size of a DdNode is a
455  ** power of 2 and a multiple of the size of a pointer.
456  ** If we align one node, all the others will be aligned
457  ** as well. */
458 // offset = (unsigned long) mem & (sizeof(DdNode) - 1);
459 // mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
460  offset = (unsigned long) mem & (32 - 1);
461  mem += (32 - offset) / sizeof(DdNodePtr);
462 #ifdef DD_DEBUG
463 // assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0);
464  assert(((unsigned long) mem & (32 - 1)) == 0);
465 #endif
466  list = (DdNode *) mem;
467 
468  i = 1;
469  do {
470  list[i - 1].ref = 0;
471  list[i - 1].next = &list[i];
472  } while (++i < DD_MEM_CHUNK);
473 
474  list[DD_MEM_CHUNK-1].ref = 0;
475  list[DD_MEM_CHUNK - 1].next = NULL;
476 
477  table->nextFree = &list[0];
478  }
479  } /* if free list empty */
480 
481  node = table->nextFree;
482  table->nextFree = node->next;
483  return (node);
484 
485 } /* end of cuddDynamicAllocNode */
486 
487 
488 /**Function********************************************************************
489 
490  Synopsis [Implementation of Rudell's sifting algorithm.]
491 
492  Description [Implementation of Rudell's sifting algorithm.
493  Assumes that no dead nodes are present.
494  <ol>
495  <li> Order all the variables according to the number of entries
496  in each unique table.
497  <li> Sift the variable up and down, remembering each time the
498  total size of the DD heap.
499  <li> Select the best permutation.
500  <li> Repeat 3 and 4 for all variables.
501  </ol>
502  Returns 1 if successful; 0 otherwise.]
503 
504  SideEffects [None]
505 
506 ******************************************************************************/
507 int
509  DdManager * table,
510  int lower,
511  int upper)
512 {
513  int i;
514  int *var;
515  int size;
516  int x;
517  int result;
518 #ifdef DD_STATS
519  int previousSize;
520 #endif
521 
522  size = table->size;
523 
524  /* Find order in which to sift variables. */
525  var = NULL;
526  entry = ABC_ALLOC(int,size);
527  if (entry == NULL) {
528  table->errorCode = CUDD_MEMORY_OUT;
529  goto cuddSiftingOutOfMem;
530  }
531  var = ABC_ALLOC(int,size);
532  if (var == NULL) {
533  table->errorCode = CUDD_MEMORY_OUT;
534  goto cuddSiftingOutOfMem;
535  }
536 
537  for (i = 0; i < size; i++) {
538  x = table->perm[i];
539  entry[i] = table->subtables[x].keys;
540  var[i] = i;
541  }
542 
543  qsort((void *)var,size,sizeof(int),(DD_QSFP)ddUniqueCompare);
544 
545  /* Now sift. */
546  for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
547  if (ddTotalNumberSwapping >= table->siftMaxSwap)
548  break;
549  x = table->perm[var[i]];
550 
551  if (x < lower || x > upper || table->subtables[x].bindVar == 1)
552  continue;
553 #ifdef DD_STATS
554  previousSize = table->keys - table->isolated;
555 #endif
556  result = ddSiftingAux(table, x, lower, upper);
557  if (!result) goto cuddSiftingOutOfMem;
558 #ifdef DD_STATS
559  if (table->keys < (unsigned) previousSize + table->isolated) {
560  (void) fprintf(table->out,"-");
561  } else if (table->keys > (unsigned) previousSize + table->isolated) {
562  (void) fprintf(table->out,"+"); /* should never happen */
563  (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
564  } else {
565  (void) fprintf(table->out,"=");
566  }
567  fflush(table->out);
568 #endif
569  }
570 
571  ABC_FREE(var);
572  ABC_FREE(entry);
573 
574  return(1);
575 
576 cuddSiftingOutOfMem:
577 
578  if (entry != NULL) ABC_FREE(entry);
579  if (var != NULL) ABC_FREE(var);
580 
581  return(0);
582 
583 } /* end of cuddSifting */
584 
585 
586 /**Function********************************************************************
587 
588  Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.]
589 
590  Description [Implementation of Plessier's algorithm that reorders
591  variables by a sequence of (non-adjacent) swaps.
592  <ol>
593  <li> Select two variables (RANDOM or HEURISTIC).
594  <li> Permute these variables.
595  <li> If the nodes have decreased accept the permutation.
596  <li> Otherwise reconstruct the original heap.
597  <li> Loop.
598  </ol>
599  Returns 1 in case of success; 0 otherwise.]
600 
601  SideEffects [None]
602 
603 ******************************************************************************/
604 int
606  DdManager * table,
607  int lower,
608  int upper,
609  Cudd_ReorderingType heuristic)
610 {
611  int i, j;
612  int max, keys;
613  int nvars;
614  int x, y;
615  int iterate;
616  int previousSize;
617  Move *moves, *move;
618  int pivot = -1;
619  int modulo;
620  int result;
621 
622 #ifdef DD_DEBUG
623  /* Sanity check */
624  assert(lower >= 0 && upper < table->size && lower <= upper);
625 #endif
626 
627  nvars = upper - lower + 1;
628  iterate = nvars;
629 
630  for (i = 0; i < iterate; i++) {
631  if (ddTotalNumberSwapping >= table->siftMaxSwap)
632  break;
633  if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
634  max = -1;
635  for (j = lower; j <= upper; j++) {
636  if ((keys = table->subtables[j].keys) > max) {
637  max = keys;
638  pivot = j;
639  }
640  }
641 
642  modulo = upper - pivot;
643  if (modulo == 0) {
644  y = pivot;
645  } else{
646  y = pivot + 1 + ((int) Cudd_Random() % modulo);
647  }
648 
649  modulo = pivot - lower - 1;
650  if (modulo < 1) {
651  x = lower;
652  } else{
653  do {
654  x = (int) Cudd_Random() % modulo;
655  } while (x == y);
656  }
657  } else {
658  x = ((int) Cudd_Random() % nvars) + lower;
659  do {
660  y = ((int) Cudd_Random() % nvars) + lower;
661  } while (x == y);
662  }
663  previousSize = table->keys - table->isolated;
664  moves = ddSwapAny(table,x,y);
665  if (moves == NULL) goto cuddSwappingOutOfMem;
666  result = ddSiftingBackward(table,previousSize,moves);
667  if (!result) goto cuddSwappingOutOfMem;
668  while (moves != NULL) {
669  move = moves->next;
670  cuddDeallocMove(table, moves);
671  moves = move;
672  }
673 #ifdef DD_STATS
674  if (table->keys < (unsigned) previousSize + table->isolated) {
675  (void) fprintf(table->out,"-");
676  } else if (table->keys > (unsigned) previousSize + table->isolated) {
677  (void) fprintf(table->out,"+"); /* should never happen */
678  } else {
679  (void) fprintf(table->out,"=");
680  }
681  fflush(table->out);
682 #endif
683 #if 0
684  (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n",
685  table->keys - table->isolated);
686 #endif
687  }
688 
689  return(1);
690 
691 cuddSwappingOutOfMem:
692  while (moves != NULL) {
693  move = moves->next;
694  cuddDeallocMove(table, moves);
695  moves = move;
696  }
697 
698  return(0);
699 
700 } /* end of cuddSwapping */
701 
702 
703 /**Function********************************************************************
704 
705  Synopsis [Finds the next subtable with a larger index.]
706 
707  Description [Finds the next subtable with a larger index. Returns the
708  index.]
709 
710  SideEffects [None]
711 
712  SeeAlso [cuddNextLow]
713 
714 ******************************************************************************/
715 int
717  DdManager * table,
718  int x)
719 {
720  return(x+1);
721 
722 } /* end of cuddNextHigh */
723 
724 
725 /**Function********************************************************************
726 
727  Synopsis [Finds the next subtable with a smaller index.]
728 
729  Description [Finds the next subtable with a smaller index. Returns the
730  index.]
731 
732  SideEffects [None]
733 
734  SeeAlso [cuddNextHigh]
735 
736 ******************************************************************************/
737 int
739  DdManager * table,
740  int x)
741 {
742  return(x-1);
743 
744 } /* end of cuddNextLow */
745 
746 
747 /**Function********************************************************************
748 
749  Synopsis [Swaps two adjacent variables.]
750 
751  Description [Swaps two adjacent variables. It assumes that no dead
752  nodes are present on entry to this procedure. The procedure then
753  guarantees that no dead nodes will be present when it terminates.
754  cuddSwapInPlace assumes that x &lt; y. Returns the number of keys in
755  the table if successful; 0 otherwise.]
756 
757  SideEffects [None]
758 
759 ******************************************************************************/
760 int
762  DdManager * table,
763  int x,
764  int y)
765 {
766  DdNodePtr *xlist, *ylist;
767  int xindex, yindex;
768  int xslots, yslots;
769  int xshift, yshift;
770  int oldxkeys, oldykeys;
771  int newxkeys, newykeys;
772  int comple, newcomplement;
773  int i;
774  Cudd_VariableType varType;
775  Cudd_LazyGroupType groupType;
776  int posn;
777  int isolated;
778  DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
779  DdNode *g,*next;
780  DdNodePtr *previousP;
781  DdNode *tmp;
782  DdNode *sentinel = &(table->sentinel);
783  extern DD_OOMFP MMoutOfMemory;
784  DD_OOMFP saveHandler;
785 
786 #ifdef DD_DEBUG
787  int count,idcheck;
788 #endif
789 
790 #ifdef DD_DEBUG
791  assert(x < y);
792  assert(cuddNextHigh(table,x) == y);
793  assert(table->subtables[x].keys != 0);
794  assert(table->subtables[y].keys != 0);
795  assert(table->subtables[x].dead == 0);
796  assert(table->subtables[y].dead == 0);
797 #endif
798 
800 
801  /* Get parameters of x subtable. */
802  xindex = table->invperm[x];
803  xlist = table->subtables[x].nodelist;
804  oldxkeys = table->subtables[x].keys;
805  xslots = table->subtables[x].slots;
806  xshift = table->subtables[x].shift;
807 
808  /* Get parameters of y subtable. */
809  yindex = table->invperm[y];
810  ylist = table->subtables[y].nodelist;
811  oldykeys = table->subtables[y].keys;
812  yslots = table->subtables[y].slots;
813  yshift = table->subtables[y].shift;
814 
815  if (!cuddTestInteract(table,xindex,yindex)) {
816 #ifdef DD_STATS
817  ddTotalNISwaps++;
818 #endif
819  newxkeys = oldxkeys;
820  newykeys = oldykeys;
821  } else {
822  newxkeys = 0;
823  newykeys = oldykeys;
824 
825  /* Check whether the two projection functions involved in this
826  ** swap are isolated. At the end, we'll be able to tell how many
827  ** isolated projection functions are there by checking only these
828  ** two functions again. This is done to eliminate the isolated
829  ** projection functions from the node count.
830  */
831  isolated = - ((table->vars[xindex]->ref == 1) +
832  (table->vars[yindex]->ref == 1));
833 
834  /* The nodes in the x layer that do not depend on
835  ** y will stay there; the others are put in a chain.
836  ** The chain is handled as a LIFO; g points to the beginning.
837  */
838  g = NULL;
839  if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) &&
840  oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) {
841  for (i = 0; i < xslots; i++) {
842  previousP = &(xlist[i]);
843  f = *previousP;
844  while (f != sentinel) {
845  next = f->next;
846  f1 = cuddT(f); f0 = cuddE(f);
847  if (f1->index != (DdHalfWord) yindex &&
848  Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
849  /* stays */
850  newxkeys++;
851  *previousP = f;
852  previousP = &(f->next);
853  } else {
854  f->index = yindex;
855  f->next = g;
856  g = f;
857  }
858  f = next;
859  } /* while there are elements in the collision chain */
860  *previousP = sentinel;
861  } /* for each slot of the x subtable */
862  } else { /* resize xlist */
863  DdNode *h = NULL;
864  DdNodePtr *newxlist;
865  unsigned int newxslots;
866  int newxshift;
867  /* Empty current xlist. Nodes that stay go to list h;
868  ** nodes that move go to list g. */
869  for (i = 0; i < xslots; i++) {
870  f = xlist[i];
871  while (f != sentinel) {
872  next = f->next;
873  f1 = cuddT(f); f0 = cuddE(f);
874  if (f1->index != (DdHalfWord) yindex &&
875  Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
876  /* stays */
877  f->next = h;
878  h = f;
879  newxkeys++;
880  } else {
881  f->index = yindex;
882  f->next = g;
883  g = f;
884  }
885  f = next;
886  } /* while there are elements in the collision chain */
887  } /* for each slot of the x subtable */
888  /* Decide size of new subtable. */
889  newxshift = xshift;
890  newxslots = xslots;
891  while ((unsigned) oldxkeys > DD_MAX_SUBTABLE_DENSITY * newxslots) {
892  newxshift--;
893  newxslots <<= 1;
894  }
895  while ((unsigned) oldxkeys < newxslots &&
896  newxslots > table->initSlots) {
897  newxshift++;
898  newxslots >>= 1;
899  }
900  /* Try to allocate new table. Be ready to back off. */
901  saveHandler = MMoutOfMemory;
902  MMoutOfMemory = Cudd_OutOfMem;
903  newxlist = ABC_ALLOC(DdNodePtr, newxslots);
904  MMoutOfMemory = saveHandler;
905  if (newxlist == NULL) {
906  (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i);
907  newxlist = xlist;
908  newxslots = xslots;
909  newxshift = xshift;
910  } else {
911  table->slots += ((int) newxslots - xslots);
912  table->minDead = (unsigned)
913  (table->gcFrac * (double) table->slots);
914  table->cacheSlack = (int)
916  * table->slots) - 2 * (int) table->cacheSlots;
917  table->memused +=
918  ((int) newxslots - xslots) * sizeof(DdNodePtr);
919  ABC_FREE(xlist);
920  xslots = newxslots;
921  xshift = newxshift;
922  xlist = newxlist;
923  }
924  /* Initialize new subtable. */
925  for (i = 0; i < xslots; i++) {
926  xlist[i] = sentinel;
927  }
928  /* Move nodes that were parked in list h to their new home. */
929  f = h;
930  while (f != NULL) {
931  next = f->next;
932  f1 = cuddT(f);
933  f0 = cuddE(f);
934  /* Check xlist for pair (f11,f01). */
935  posn = ddHash(cuddF2L(f1), cuddF2L(f0), xshift);
936  /* For each element tmp in collision list xlist[posn]. */
937  previousP = &(xlist[posn]);
938  tmp = *previousP;
939  while (f1 < cuddT(tmp)) {
940  previousP = &(tmp->next);
941  tmp = *previousP;
942  }
943  while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) {
944  previousP = &(tmp->next);
945  tmp = *previousP;
946  }
947  f->next = *previousP;
948  *previousP = f;
949  f = next;
950  }
951  }
952 
953 #ifdef DD_COUNT
954  table->swapSteps += oldxkeys - newxkeys;
955 #endif
956  /* Take care of the x nodes that must be re-expressed.
957  ** They form a linked list pointed by g. Their index has been
958  ** already changed to yindex.
959  */
960  f = g;
961  while (f != NULL) {
962  next = f->next;
963  /* Find f1, f0, f11, f10, f01, f00. */
964  f1 = cuddT(f);
965 #ifdef DD_DEBUG
966  assert(!(Cudd_IsComplement(f1)));
967 #endif
968  if ((int) f1->index == yindex) {
969  f11 = cuddT(f1); f10 = cuddE(f1);
970  } else {
971  f11 = f10 = f1;
972  }
973 #ifdef DD_DEBUG
974  assert(!(Cudd_IsComplement(f11)));
975 #endif
976  f0 = cuddE(f);
977  comple = Cudd_IsComplement(f0);
978  f0 = Cudd_Regular(f0);
979  if ((int) f0->index == yindex) {
980  f01 = cuddT(f0); f00 = cuddE(f0);
981  } else {
982  f01 = f00 = f0;
983  }
984  if (comple) {
985  f01 = Cudd_Not(f01);
986  f00 = Cudd_Not(f00);
987  }
988  /* Decrease ref count of f1. */
989  cuddSatDec(f1->ref);
990  /* Create the new T child. */
991  if (f11 == f01) {
992  newf1 = f11;
993  cuddSatInc(newf1->ref);
994  } else {
995  /* Check xlist for triple (xindex,f11,f01). */
996  posn = ddHash(cuddF2L(f11), cuddF2L(f01), xshift);
997  /* For each element newf1 in collision list xlist[posn]. */
998  previousP = &(xlist[posn]);
999  newf1 = *previousP;
1000  while (f11 < cuddT(newf1)) {
1001  previousP = &(newf1->next);
1002  newf1 = *previousP;
1003  }
1004  while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) {
1005  previousP = &(newf1->next);
1006  newf1 = *previousP;
1007  }
1008  if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
1009  cuddSatInc(newf1->ref);
1010  } else { /* no match */
1011  newf1 = cuddDynamicAllocNode(table);
1012  if (newf1 == NULL)
1013  goto cuddSwapOutOfMem;
1014  newf1->index = xindex; newf1->ref = 1;
1015  cuddT(newf1) = f11;
1016  cuddE(newf1) = f01;
1017  /* Insert newf1 in the collision list xlist[posn];
1018  ** increase the ref counts of f11 and f01.
1019  */
1020  newxkeys++;
1021  newf1->next = *previousP;
1022  *previousP = newf1;
1023  cuddSatInc(f11->ref);
1024  tmp = Cudd_Regular(f01);
1025  cuddSatInc(tmp->ref);
1026  }
1027  }
1028  cuddT(f) = newf1;
1029 #ifdef DD_DEBUG
1030  assert(!(Cudd_IsComplement(newf1)));
1031 #endif
1032 
1033  /* Do the same for f0, keeping complement dots into account. */
1034  /* Decrease ref count of f0. */
1035  tmp = Cudd_Regular(f0);
1036  cuddSatDec(tmp->ref);
1037  /* Create the new E child. */
1038  if (f10 == f00) {
1039  newf0 = f00;
1040  tmp = Cudd_Regular(newf0);
1041  cuddSatInc(tmp->ref);
1042  } else {
1043  /* make sure f10 is regular */
1044  newcomplement = Cudd_IsComplement(f10);
1045  if (newcomplement) {
1046  f10 = Cudd_Not(f10);
1047  f00 = Cudd_Not(f00);
1048  }
1049  /* Check xlist for triple (xindex,f10,f00). */
1050  posn = ddHash(cuddF2L(f10), cuddF2L(f00), xshift);
1051  /* For each element newf0 in collision list xlist[posn]. */
1052  previousP = &(xlist[posn]);
1053  newf0 = *previousP;
1054  while (f10 < cuddT(newf0)) {
1055  previousP = &(newf0->next);
1056  newf0 = *previousP;
1057  }
1058  while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) {
1059  previousP = &(newf0->next);
1060  newf0 = *previousP;
1061  }
1062  if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
1063  cuddSatInc(newf0->ref);
1064  } else { /* no match */
1065  newf0 = cuddDynamicAllocNode(table);
1066  if (newf0 == NULL)
1067  goto cuddSwapOutOfMem;
1068  newf0->index = xindex; newf0->ref = 1;
1069  cuddT(newf0) = f10;
1070  cuddE(newf0) = f00;
1071  /* Insert newf0 in the collision list xlist[posn];
1072  ** increase the ref counts of f10 and f00.
1073  */
1074  newxkeys++;
1075  newf0->next = *previousP;
1076  *previousP = newf0;
1077  cuddSatInc(f10->ref);
1078  tmp = Cudd_Regular(f00);
1079  cuddSatInc(tmp->ref);
1080  }
1081  if (newcomplement) {
1082  newf0 = Cudd_Not(newf0);
1083  }
1084  }
1085  cuddE(f) = newf0;
1086 
1087  /* Insert the modified f in ylist.
1088  ** The modified f does not already exists in ylist.
1089  ** (Because of the uniqueness of the cofactors.)
1090  */
1091  posn = ddHash(cuddF2L(newf1), cuddF2L(newf0), yshift);
1092  newykeys++;
1093  previousP = &(ylist[posn]);
1094  tmp = *previousP;
1095  while (newf1 < cuddT(tmp)) {
1096  previousP = &(tmp->next);
1097  tmp = *previousP;
1098  }
1099  while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
1100  previousP = &(tmp->next);
1101  tmp = *previousP;
1102  }
1103  f->next = *previousP;
1104  *previousP = f;
1105  f = next;
1106  } /* while f != NULL */
1107 
1108  /* GC the y layer. */
1109 
1110  /* For each node f in ylist. */
1111  for (i = 0; i < yslots; i++) {
1112  previousP = &(ylist[i]);
1113  f = *previousP;
1114  while (f != sentinel) {
1115  next = f->next;
1116  if (f->ref == 0) {
1117  tmp = cuddT(f);
1118  cuddSatDec(tmp->ref);
1119  tmp = Cudd_Regular(cuddE(f));
1120  cuddSatDec(tmp->ref);
1121  cuddDeallocNode(table,f);
1122  newykeys--;
1123  } else {
1124  *previousP = f;
1125  previousP = &(f->next);
1126  }
1127  f = next;
1128  } /* while f */
1129  *previousP = sentinel;
1130  } /* for i */
1131 
1132 #ifdef DD_DEBUG
1133 #if 0
1134  (void) fprintf(table->out,"Swapping %d and %d\n",x,y);
1135 #endif
1136  count = 0;
1137  idcheck = 0;
1138  for (i = 0; i < yslots; i++) {
1139  f = ylist[i];
1140  while (f != sentinel) {
1141  count++;
1142  if (f->index != (DdHalfWord) yindex)
1143  idcheck++;
1144  f = f->next;
1145  }
1146  }
1147  if (count != newykeys) {
1148  (void) fprintf(table->out,
1149  "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",
1150  oldykeys,newykeys,count);
1151  }
1152  if (idcheck != 0)
1153  (void) fprintf(table->out,
1154  "Error in id's of ylist\twrong id's = %d\n",
1155  idcheck);
1156  count = 0;
1157  idcheck = 0;
1158  for (i = 0; i < xslots; i++) {
1159  f = xlist[i];
1160  while (f != sentinel) {
1161  count++;
1162  if (f->index != (DdHalfWord) xindex)
1163  idcheck++;
1164  f = f->next;
1165  }
1166  }
1167  if (count != newxkeys) {
1168  (void) fprintf(table->out,
1169  "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",
1170  oldxkeys,newxkeys,count);
1171  }
1172  if (idcheck != 0)
1173  (void) fprintf(table->out,
1174  "Error in id's of xlist\twrong id's = %d\n",
1175  idcheck);
1176 #endif
1177 
1178  isolated += (table->vars[xindex]->ref == 1) +
1179  (table->vars[yindex]->ref == 1);
1180  table->isolated += isolated;
1181  }
1182 
1183  /* Set the appropriate fields in table. */
1184  table->subtables[x].nodelist = ylist;
1185  table->subtables[x].slots = yslots;
1186  table->subtables[x].shift = yshift;
1187  table->subtables[x].keys = newykeys;
1188  table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
1189  i = table->subtables[x].bindVar;
1190  table->subtables[x].bindVar = table->subtables[y].bindVar;
1191  table->subtables[y].bindVar = i;
1192  /* Adjust filds for lazy sifting. */
1193  varType = table->subtables[x].varType;
1194  table->subtables[x].varType = table->subtables[y].varType;
1195  table->subtables[y].varType = varType;
1196  i = table->subtables[x].pairIndex;
1197  table->subtables[x].pairIndex = table->subtables[y].pairIndex;
1198  table->subtables[y].pairIndex = i;
1199  i = table->subtables[x].varHandled;
1200  table->subtables[x].varHandled = table->subtables[y].varHandled;
1201  table->subtables[y].varHandled = i;
1202  groupType = table->subtables[x].varToBeGrouped;
1203  table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped;
1204  table->subtables[y].varToBeGrouped = groupType;
1205 
1206  table->subtables[y].nodelist = xlist;
1207  table->subtables[y].slots = xslots;
1208  table->subtables[y].shift = xshift;
1209  table->subtables[y].keys = newxkeys;
1210  table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
1211 
1212  table->perm[xindex] = y; table->perm[yindex] = x;
1213  table->invperm[x] = yindex; table->invperm[y] = xindex;
1214 
1215  table->keys += newxkeys + newykeys - oldxkeys - oldykeys;
1216 
1217  return(table->keys - table->isolated);
1218 
1219 cuddSwapOutOfMem:
1220  (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n");
1221 
1222  return (0);
1223 
1224 } /* end of cuddSwapInPlace */
1225 
1226 
1227 /**Function********************************************************************
1228 
1229  Synopsis [Reorders BDD variables according to the order of the ZDD
1230  variables.]
1231 
1232  Description [Reorders BDD variables according to the order of the
1233  ZDD variables. This function can be called at the end of ZDD
1234  reordering to insure that the order of the BDD variables is
1235  consistent with the order of the ZDD variables. The number of ZDD
1236  variables must be a multiple of the number of BDD variables. Let
1237  <code>M</code> be the ratio of the two numbers. cuddBddAlignToZdd
1238  then considers the ZDD variables from <code>M*i</code> to
1239  <code>(M+1)*i-1</code> as corresponding to BDD variable
1240  <code>i</code>. This function should be normally called from
1241  Cudd_zddReduceHeap, which clears the cache. Returns 1 in case of
1242  success; 0 otherwise.]
1243 
1244  SideEffects [Changes the BDD variable order for all diagrams and performs
1245  garbage collection of the BDD unique table.]
1246 
1247  SeeAlso [Cudd_ShuffleHeap Cudd_zddReduceHeap]
1248 
1249 ******************************************************************************/
1250 int
1252  DdManager * table /* DD manager */)
1253 {
1254  int *invperm; /* permutation array */
1255  int M; /* ratio of ZDD variables to BDD variables */
1256  int i; /* loop index */
1257  int result; /* return value */
1258 
1259  /* We assume that a ratio of 0 is OK. */
1260  if (table->size == 0)
1261  return(1);
1262 
1263  M = table->sizeZ / table->size;
1264  /* Check whether the number of ZDD variables is a multiple of the
1265  ** number of BDD variables.
1266  */
1267  if (M * table->size != table->sizeZ)
1268  return(0);
1269  /* Create and initialize the inverse permutation array. */
1270  invperm = ABC_ALLOC(int,table->size);
1271  if (invperm == NULL) {
1272  table->errorCode = CUDD_MEMORY_OUT;
1273  return(0);
1274  }
1275  for (i = 0; i < table->sizeZ; i += M) {
1276  int indexZ = table->invpermZ[i];
1277  int index = indexZ / M;
1278  invperm[i / M] = index;
1279  }
1280  /* Eliminate dead nodes. Do not scan the cache again, because we
1281  ** assume that Cudd_zddReduceHeap has already cleared it.
1282  */
1283  cuddGarbageCollect(table,0);
1284 
1285  /* Initialize number of isolated projection functions. */
1286  table->isolated = 0;
1287  for (i = 0; i < table->size; i++) {
1288  if (table->vars[i]->ref == 1) table->isolated++;
1289  }
1290 
1291  /* Initialize the interaction matrix. */
1292  result = cuddInitInteract(table);
1293  if (result == 0) return(0);
1294 
1295  result = ddShuffle(table, invperm);
1296  ABC_FREE(invperm);
1297  /* Free interaction matrix. */
1298  ABC_FREE(table->interact);
1299  /* Fix the BDD variable group tree. */
1300  bddFixTree(table,table->tree);
1301  return(result);
1302 
1303 } /* end of cuddBddAlignToZdd */
1304 
1305 /*---------------------------------------------------------------------------*/
1306 /* Definition of static functions */
1307 /*---------------------------------------------------------------------------*/
1308 
1309 
1310 /**Function********************************************************************
1311 
1312  Synopsis [Comparison function used by qsort.]
1313 
1314  Description [Comparison function used by qsort to order the
1315  variables according to the number of keys in the subtables.
1316  Returns the difference in number of keys between the two
1317  variables being compared.]
1318 
1319  SideEffects [None]
1320 
1321 ******************************************************************************/
1322 static int
1324  int * ptrX,
1325  int * ptrY)
1326 {
1327 #if 0
1328  if (entry[*ptrY] == entry[*ptrX]) {
1329  return((*ptrX) - (*ptrY));
1330  }
1331 #endif
1332  return(entry[*ptrY] - entry[*ptrX]);
1333 
1334 } /* end of ddUniqueCompare */
1335 
1336 
1337 /**Function********************************************************************
1338 
1339  Synopsis [Swaps any two variables.]
1340 
1341  Description [Swaps any two variables. Returns the set of moves.]
1342 
1343  SideEffects [None]
1344 
1345 ******************************************************************************/
1346 static Move *
1348  DdManager * table,
1349  int x,
1350  int y)
1351 {
1352  Move *move, *moves;
1353  int xRef,yRef;
1354  int xNext,yNext;
1355  int size;
1356  int limitSize;
1357  int tmp;
1358 
1359  if (x >y) {
1360  tmp = x; x = y; y = tmp;
1361  }
1362 
1363  xRef = x; yRef = y;
1364 
1365  xNext = cuddNextHigh(table,x);
1366  yNext = cuddNextLow(table,y);
1367  moves = NULL;
1368  limitSize = table->keys - table->isolated;
1369 
1370  for (;;) {
1371  if ( xNext == yNext) {
1372  size = cuddSwapInPlace(table,x,xNext);
1373  if (size == 0) goto ddSwapAnyOutOfMem;
1374  move = (Move *) cuddDynamicAllocNode(table);
1375  if (move == NULL) goto ddSwapAnyOutOfMem;
1376  move->x = x;
1377  move->y = xNext;
1378  move->size = size;
1379  move->next = moves;
1380  moves = move;
1381 
1382  size = cuddSwapInPlace(table,yNext,y);
1383  if (size == 0) goto ddSwapAnyOutOfMem;
1384  move = (Move *) cuddDynamicAllocNode(table);
1385  if (move == NULL) goto ddSwapAnyOutOfMem;
1386  move->x = yNext;
1387  move->y = y;
1388  move->size = size;
1389  move->next = moves;
1390  moves = move;
1391 
1392  size = cuddSwapInPlace(table,x,xNext);
1393  if (size == 0) goto ddSwapAnyOutOfMem;
1394  move = (Move *) cuddDynamicAllocNode(table);
1395  if (move == NULL) goto ddSwapAnyOutOfMem;
1396  move->x = x;
1397  move->y = xNext;
1398  move->size = size;
1399  move->next = moves;
1400  moves = move;
1401 
1402  tmp = x; x = y; y = tmp;
1403 
1404  } else if (x == yNext) {
1405 
1406  size = cuddSwapInPlace(table,x,xNext);
1407  if (size == 0) goto ddSwapAnyOutOfMem;
1408  move = (Move *) cuddDynamicAllocNode(table);
1409  if (move == NULL) goto ddSwapAnyOutOfMem;
1410  move->x = x;
1411  move->y = xNext;
1412  move->size = size;
1413  move->next = moves;
1414  moves = move;
1415 
1416  tmp = x; x = y; y = tmp;
1417 
1418  } else {
1419  size = cuddSwapInPlace(table,x,xNext);
1420  if (size == 0) goto ddSwapAnyOutOfMem;
1421  move = (Move *) cuddDynamicAllocNode(table);
1422  if (move == NULL) goto ddSwapAnyOutOfMem;
1423  move->x = x;
1424  move->y = xNext;
1425  move->size = size;
1426  move->next = moves;
1427  moves = move;
1428 
1429  size = cuddSwapInPlace(table,yNext,y);
1430  if (size == 0) goto ddSwapAnyOutOfMem;
1431  move = (Move *) cuddDynamicAllocNode(table);
1432  if (move == NULL) goto ddSwapAnyOutOfMem;
1433  move->x = yNext;
1434  move->y = y;
1435  move->size = size;
1436  move->next = moves;
1437  moves = move;
1438 
1439  x = xNext;
1440  y = yNext;
1441  }
1442 
1443  xNext = cuddNextHigh(table,x);
1444  yNext = cuddNextLow(table,y);
1445  if (xNext > yRef) break;
1446 
1447  if ((double) size > table->maxGrowth * (double) limitSize) break;
1448  if (size < limitSize) limitSize = size;
1449  }
1450  if (yNext>=xRef) {
1451  size = cuddSwapInPlace(table,yNext,y);
1452  if (size == 0) goto ddSwapAnyOutOfMem;
1453  move = (Move *) cuddDynamicAllocNode(table);
1454  if (move == NULL) goto ddSwapAnyOutOfMem;
1455  move->x = yNext;
1456  move->y = y;
1457  move->size = size;
1458  move->next = moves;
1459  moves = move;
1460  }
1461 
1462  return(moves);
1463 
1464 ddSwapAnyOutOfMem:
1465  while (moves != NULL) {
1466  move = moves->next;
1467  cuddDeallocMove(table, moves);
1468  moves = move;
1469  }
1470  return(NULL);
1471 
1472 } /* end of ddSwapAny */
1473 
1474 
1475 /**Function********************************************************************
1476 
1477  Synopsis [Given xLow <= x <= xHigh moves x up and down between the
1478  boundaries.]
1479 
1480  Description [Given xLow <= x <= xHigh moves x up and down between the
1481  boundaries. Finds the best position and does the required changes.
1482  Returns 1 if successful; 0 otherwise.]
1483 
1484  SideEffects [None]
1485 
1486 ******************************************************************************/
1487 static int
1489  DdManager * table,
1490  int x,
1491  int xLow,
1492  int xHigh)
1493 {
1494 
1495  Move *move;
1496  Move *moveUp; /* list of up moves */
1497  Move *moveDown; /* list of down moves */
1498  int initialSize;
1499  int result;
1500 
1501  initialSize = table->keys - table->isolated;
1502 
1503  moveDown = NULL;
1504  moveUp = NULL;
1505 
1506  if (x == xLow) {
1507  moveDown = ddSiftingDown(table,x,xHigh);
1508  /* At this point x --> xHigh unless bounding occurred. */
1509  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1510  /* Move backward and stop at best position. */
1511  result = ddSiftingBackward(table,initialSize,moveDown);
1512  if (!result) goto ddSiftingAuxOutOfMem;
1513 
1514  } else if (x == xHigh) {
1515  moveUp = ddSiftingUp(table,x,xLow);
1516  /* At this point x --> xLow unless bounding occurred. */
1517  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1518  /* Move backward and stop at best position. */
1519  result = ddSiftingBackward(table,initialSize,moveUp);
1520  if (!result) goto ddSiftingAuxOutOfMem;
1521 
1522  } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
1523  moveDown = ddSiftingDown(table,x,xHigh);
1524  /* At this point x --> xHigh unless bounding occurred. */
1525  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1526  if (moveDown != NULL) {
1527  x = moveDown->y;
1528  }
1529  moveUp = ddSiftingUp(table,x,xLow);
1530  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1531  /* Move backward and stop at best position */
1532  result = ddSiftingBackward(table,initialSize,moveUp);
1533  if (!result) goto ddSiftingAuxOutOfMem;
1534 
1535  } else { /* must go up first: shorter */
1536  moveUp = ddSiftingUp(table,x,xLow);
1537  /* At this point x --> xLow unless bounding occurred. */
1538  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1539  if (moveUp != NULL) {
1540  x = moveUp->x;
1541  }
1542  moveDown = ddSiftingDown(table,x,xHigh);
1543  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1544  /* Move backward and stop at best position. */
1545  result = ddSiftingBackward(table,initialSize,moveDown);
1546  if (!result) goto ddSiftingAuxOutOfMem;
1547  }
1548 
1549  while (moveDown != NULL) {
1550  move = moveDown->next;
1551  cuddDeallocMove(table, moveDown);
1552  moveDown = move;
1553  }
1554  while (moveUp != NULL) {
1555  move = moveUp->next;
1556  cuddDeallocMove(table, moveUp);
1557  moveUp = move;
1558  }
1559 
1560  return(1);
1561 
1562 ddSiftingAuxOutOfMem:
1563  if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
1564  while (moveDown != NULL) {
1565  move = moveDown->next;
1566  cuddDeallocMove(table, moveDown);
1567  moveDown = move;
1568  }
1569  }
1570  if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
1571  while (moveUp != NULL) {
1572  move = moveUp->next;
1573  cuddDeallocMove(table, moveUp);
1574  moveUp = move;
1575  }
1576  }
1577 
1578  return(0);
1579 
1580 } /* end of ddSiftingAux */
1581 
1582 
1583 /**Function********************************************************************
1584 
1585  Synopsis [Sifts a variable up.]
1586 
1587  Description [Sifts a variable up. Moves y up until either it reaches
1588  the bound (xLow) or the size of the DD heap increases too much.
1589  Returns the set of moves in case of success; NULL if memory is full.]
1590 
1591  SideEffects [None]
1592 
1593 ******************************************************************************/
1594 static Move *
1596  DdManager * table,
1597  int y,
1598  int xLow)
1599 {
1600  Move *moves;
1601  Move *move;
1602  int x;
1603  int size;
1604  int limitSize;
1605  int xindex, yindex;
1606  int isolated;
1607  int L; /* lower bound on DD size */
1608 #ifdef DD_DEBUG
1609  int checkL;
1610  int z;
1611  int zindex;
1612 #endif
1613 
1614  moves = NULL;
1615  yindex = table->invperm[y];
1616 
1617  /* Initialize the lower bound.
1618  ** The part of the DD below y will not change.
1619  ** The part of the DD above y that does not interact with y will not
1620  ** change. The rest may vanish in the best case, except for
1621  ** the nodes at level xLow, which will not vanish, regardless.
1622  */
1623  limitSize = L = table->keys - table->isolated;
1624  for (x = xLow + 1; x < y; x++) {
1625  xindex = table->invperm[x];
1626  if (cuddTestInteract(table,xindex,yindex)) {
1627  isolated = table->vars[xindex]->ref == 1;
1628  L -= table->subtables[x].keys - isolated;
1629  }
1630  }
1631  isolated = table->vars[yindex]->ref == 1;
1632  L -= table->subtables[y].keys - isolated;
1633 
1634  x = cuddNextLow(table,y);
1635  while (x >= xLow && L <= limitSize) {
1636  xindex = table->invperm[x];
1637 #ifdef DD_DEBUG
1638  checkL = table->keys - table->isolated;
1639  for (z = xLow + 1; z < y; z++) {
1640  zindex = table->invperm[z];
1641  if (cuddTestInteract(table,zindex,yindex)) {
1642  isolated = table->vars[zindex]->ref == 1;
1643  checkL -= table->subtables[z].keys - isolated;
1644  }
1645  }
1646  isolated = table->vars[yindex]->ref == 1;
1647  checkL -= table->subtables[y].keys - isolated;
1648  assert(L == checkL);
1649 #endif
1650  size = cuddSwapInPlace(table,x,y);
1651  if (size == 0) goto ddSiftingUpOutOfMem;
1652  /* Update the lower bound. */
1653  if (cuddTestInteract(table,xindex,yindex)) {
1654  isolated = table->vars[xindex]->ref == 1;
1655  L += table->subtables[y].keys - isolated;
1656  }
1657  move = (Move *) cuddDynamicAllocNode(table);
1658  if (move == NULL) goto ddSiftingUpOutOfMem;
1659  move->x = x;
1660  move->y = y;
1661  move->size = size;
1662  move->next = moves;
1663  moves = move;
1664  if ((double) size > (double) limitSize * table->maxGrowth) break;
1665  if (size < limitSize) limitSize = size;
1666  y = x;
1667  x = cuddNextLow(table,y);
1668  }
1669  return(moves);
1670 
1671 ddSiftingUpOutOfMem:
1672  while (moves != NULL) {
1673  move = moves->next;
1674  cuddDeallocMove(table, moves);
1675  moves = move;
1676  }
1677  return((Move *) CUDD_OUT_OF_MEM);
1678 
1679 } /* end of ddSiftingUp */
1680 
1681 
1682 /**Function********************************************************************
1683 
1684  Synopsis [Sifts a variable down.]
1685 
1686  Description [Sifts a variable down. Moves x down until either it
1687  reaches the bound (xHigh) or the size of the DD heap increases too
1688  much. Returns the set of moves in case of success; NULL if memory is
1689  full.]
1690 
1691  SideEffects [None]
1692 
1693 ******************************************************************************/
1694 static Move *
1696  DdManager * table,
1697  int x,
1698  int xHigh)
1699 {
1700  Move *moves;
1701  Move *move;
1702  int y;
1703  int size;
1704  int R; /* upper bound on node decrease */
1705  int limitSize;
1706  int xindex, yindex;
1707  int isolated;
1708 #ifdef DD_DEBUG
1709  int checkR;
1710  int z;
1711  int zindex;
1712 #endif
1713 
1714  moves = NULL;
1715  /* Initialize R */
1716  xindex = table->invperm[x];
1717  limitSize = size = table->keys - table->isolated;
1718  R = 0;
1719  for (y = xHigh; y > x; y--) {
1720  yindex = table->invperm[y];
1721  if (cuddTestInteract(table,xindex,yindex)) {
1722  isolated = table->vars[yindex]->ref == 1;
1723  R += table->subtables[y].keys - isolated;
1724  }
1725  }
1726 
1727  y = cuddNextHigh(table,x);
1728  while (y <= xHigh && size - R < limitSize) {
1729 #ifdef DD_DEBUG
1730  checkR = 0;
1731  for (z = xHigh; z > x; z--) {
1732  zindex = table->invperm[z];
1733  if (cuddTestInteract(table,xindex,zindex)) {
1734  isolated = table->vars[zindex]->ref == 1;
1735  checkR += table->subtables[z].keys - isolated;
1736  }
1737  }
1738  assert(R == checkR);
1739 #endif
1740  /* Update upper bound on node decrease. */
1741  yindex = table->invperm[y];
1742  if (cuddTestInteract(table,xindex,yindex)) {
1743  isolated = table->vars[yindex]->ref == 1;
1744  R -= table->subtables[y].keys - isolated;
1745  }
1746  size = cuddSwapInPlace(table,x,y);
1747  if (size == 0) goto ddSiftingDownOutOfMem;
1748  move = (Move *) cuddDynamicAllocNode(table);
1749  if (move == NULL) goto ddSiftingDownOutOfMem;
1750  move->x = x;
1751  move->y = y;
1752  move->size = size;
1753  move->next = moves;
1754  moves = move;
1755  if ((double) size > (double) limitSize * table->maxGrowth) break;
1756  if (size < limitSize) limitSize = size;
1757  x = y;
1758  y = cuddNextHigh(table,x);
1759  }
1760  return(moves);
1761 
1762 ddSiftingDownOutOfMem:
1763  while (moves != NULL) {
1764  move = moves->next;
1765  cuddDeallocMove(table, moves);
1766  moves = move;
1767  }
1768  return((Move *) CUDD_OUT_OF_MEM);
1769 
1770 } /* end of ddSiftingDown */
1771 
1772 
1773 /**Function********************************************************************
1774 
1775  Synopsis [Given a set of moves, returns the DD heap to the position
1776  giving the minimum size.]
1777 
1778  Description [Given a set of moves, returns the DD heap to the
1779  position giving the minimum size. In case of ties, returns to the
1780  closest position giving the minimum size. Returns 1 in case of
1781  success; 0 otherwise.]
1782 
1783  SideEffects [None]
1784 
1785 ******************************************************************************/
1786 static int
1788  DdManager * table,
1789  int size,
1790  Move * moves)
1791 {
1792  Move *move;
1793  int res;
1794 
1795  for (move = moves; move != NULL; move = move->next) {
1796  if (move->size < size) {
1797  size = move->size;
1798  }
1799  }
1800 
1801  for (move = moves; move != NULL; move = move->next) {
1802  if (move->size == size) return(1);
1803  res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
1804  if (!res) return(0);
1805  }
1806 
1807  return(1);
1808 
1809 } /* end of ddSiftingBackward */
1810 
1811 
1812 /**Function********************************************************************
1813 
1814  Synopsis [Prepares the DD heap for dynamic reordering.]
1815 
1816  Description [Prepares the DD heap for dynamic reordering. Does
1817  garbage collection, to guarantee that there are no dead nodes;
1818  clears the cache, which is invalidated by dynamic reordering; initializes
1819  the number of isolated projection functions; and initializes the
1820  interaction matrix. Returns 1 in case of success; 0 otherwise.]
1821 
1822  SideEffects [None]
1823 
1824 ******************************************************************************/
1825 static int
1827  DdManager * table)
1828 {
1829  int i;
1830  int res;
1831 
1832  /* Clear the cache. */
1833  cuddCacheFlush(table);
1834  cuddLocalCacheClearAll(table);
1835 
1836  /* Eliminate dead nodes. Do not scan the cache again. */
1837  cuddGarbageCollect(table,0);
1838 
1839  /* Initialize number of isolated projection functions. */
1840  table->isolated = 0;
1841  for (i = 0; i < table->size; i++) {
1842  if (table->vars[i]->ref == 1) table->isolated++;
1843  }
1844 
1845  /* Initialize the interaction matrix. */
1846  res = cuddInitInteract(table);
1847  if (res == 0) return(0);
1848 
1849  return(1);
1850 
1851 } /* end of ddReorderPreprocess */
1852 
1853 
1854 /**Function********************************************************************
1855 
1856  Synopsis [Cleans up at the end of reordering.]
1857 
1858  Description []
1859 
1860  SideEffects [None]
1861 
1862 ******************************************************************************/
1863 static int
1865  DdManager * table)
1866 {
1867 
1868 #ifdef DD_VERBOSE
1869  (void) fflush(table->out);
1870 #endif
1871 
1872  /* Free interaction matrix. */
1873  ABC_FREE(table->interact);
1874 
1875  return(1);
1876 
1877 } /* end of ddReorderPostprocess */
1878 
1879 
1880 /**Function********************************************************************
1881 
1882  Synopsis [Reorders variables according to a given permutation.]
1883 
1884  Description [Reorders variables according to a given permutation.
1885  The i-th permutation array contains the index of the variable that
1886  should be brought to the i-th level. ddShuffle assumes that no
1887  dead nodes are present and that the interaction matrix is properly
1888  initialized. The reordering is achieved by a series of upward sifts.
1889  Returns 1 if successful; 0 otherwise.]
1890 
1891  SideEffects [None]
1892 
1893  SeeAlso []
1894 
1895 ******************************************************************************/
1896 static int
1898  DdManager * table,
1899  int * permutation)
1900 {
1901  int index;
1902  int level;
1903  int position;
1904  int numvars;
1905  int result;
1906 #ifdef DD_STATS
1907  long localTime;
1908  int initialSize;
1909  int finalSize;
1910  int previousSize;
1911 #endif
1912 
1914 #ifdef DD_STATS
1915  localTime = util_cpu_time();
1916  initialSize = table->keys - table->isolated;
1917  (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
1918  initialSize);
1919  ddTotalNISwaps = 0;
1920 #endif
1921 
1922  numvars = table->size;
1923 
1924  for (level = 0; level < numvars; level++) {
1925  index = permutation[level];
1926  position = table->perm[index];
1927 #ifdef DD_STATS
1928  previousSize = table->keys - table->isolated;
1929 #endif
1930  result = ddSiftUp(table,position,level);
1931  if (!result) return(0);
1932 #ifdef DD_STATS
1933  if (table->keys < (unsigned) previousSize + table->isolated) {
1934  (void) fprintf(table->out,"-");
1935  } else if (table->keys > (unsigned) previousSize + table->isolated) {
1936  (void) fprintf(table->out,"+"); /* should never happen */
1937  } else {
1938  (void) fprintf(table->out,"=");
1939  }
1940  fflush(table->out);
1941 #endif
1942  }
1943 
1944 #ifdef DD_STATS
1945  (void) fprintf(table->out,"\n");
1946  finalSize = table->keys - table->isolated;
1947  (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize);
1948  (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
1949  ((double)(util_cpu_time() - localTime)/1000.0));
1950  (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
1952  (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps);
1953 #endif
1954 
1955  return(1);
1956 
1957 } /* end of ddShuffle */
1958 
1959 
1960 /**Function********************************************************************
1961 
1962  Synopsis [Moves one variable up.]
1963 
1964  Description [Takes a variable from position x and sifts it up to
1965  position xLow; xLow should be less than or equal to x.
1966  Returns 1 if successful; 0 otherwise]
1967 
1968  SideEffects [None]
1969 
1970  SeeAlso []
1971 
1972 ******************************************************************************/
1973 static int
1975  DdManager * table,
1976  int x,
1977  int xLow)
1978 {
1979  int y;
1980  int size;
1981 
1982  y = cuddNextLow(table,x);
1983  while (y >= xLow) {
1984  size = cuddSwapInPlace(table,y,x);
1985  if (size == 0) {
1986  return(0);
1987  }
1988  x = y;
1989  y = cuddNextLow(table,x);
1990  }
1991  return(1);
1992 
1993 } /* end of ddSiftUp */
1994 
1995 
1996 /**Function********************************************************************
1997 
1998  Synopsis [Fixes the BDD variable group tree after a shuffle.]
1999 
2000  Description [Fixes the BDD variable group tree after a
2001  shuffle. Assumes that the order of the variables in a terminal node
2002  has not been changed.]
2003 
2004  SideEffects [Changes the BDD variable group tree.]
2005 
2006  SeeAlso []
2007 
2008 ******************************************************************************/
2009 static void
2011  DdManager * table,
2012  MtrNode * treenode)
2013 {
2014  if (treenode == NULL) return;
2015  treenode->low = ((int) treenode->index < table->size) ?
2016  table->perm[treenode->index] : treenode->index;
2017  if (treenode->child != NULL) {
2018  bddFixTree(table, treenode->child);
2019  }
2020  if (treenode->younger != NULL)
2021  bddFixTree(table, treenode->younger);
2022  if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
2023  treenode->parent->low = treenode->low;
2024  treenode->parent->index = treenode->index;
2025  }
2026  return;
2027 
2028 } /* end of bddFixTree */
2029 
2030 
2031 /**Function********************************************************************
2032 
2033  Synopsis [Updates the BDD variable group tree before a shuffle.]
2034 
2035  Description [Updates the BDD variable group tree before a shuffle.
2036  Returns 1 if successful; 0 otherwise.]
2037 
2038  SideEffects [Changes the BDD variable group tree.]
2039 
2040  SeeAlso []
2041 
2042 ******************************************************************************/
2043 static int
2045  DdManager * table,
2046  MtrNode * treenode,
2047  int * perm,
2048  int * invperm)
2049 {
2050  int i, size;
2051  int index, level, minLevel, maxLevel, minIndex;
2052 
2053  if (treenode == NULL) return(1);
2054 
2055  minLevel = CUDD_MAXINDEX;
2056  maxLevel = 0;
2057  minIndex = -1;
2058  /* i : level */
2059  for (i = treenode->low; i < treenode->low + treenode->size; i++) {
2060  index = table->invperm[i];
2061  level = perm[index];
2062  if (level < minLevel) {
2063  minLevel = level;
2064  minIndex = index;
2065  }
2066  if (level > maxLevel)
2067  maxLevel = level;
2068  }
2069  size = maxLevel - minLevel + 1;
2070  if (minIndex == -1) return(0);
2071  if (size == treenode->size) {
2072  treenode->low = minLevel;
2073  treenode->index = minIndex;
2074  } else {
2075  return(0);
2076  }
2077 
2078  if (treenode->child != NULL) {
2079  if (!ddUpdateMtrTree(table, treenode->child, perm, invperm))
2080  return(0);
2081  }
2082  if (treenode->younger != NULL) {
2083  if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm))
2084  return(0);
2085  }
2086  return(1);
2087 }
2088 
2089 
2090 /**Function********************************************************************
2091 
2092  Synopsis [Checks the BDD variable group tree before a shuffle.]
2093 
2094  Description [Checks the BDD variable group tree before a shuffle.
2095  Returns 1 if successful; 0 otherwise.]
2096 
2097  SideEffects [Changes the BDD variable group tree.]
2098 
2099  SeeAlso []
2100 
2101 ******************************************************************************/
2102 static int
2104  DdManager * table,
2105  MtrNode * treenode,
2106  int * perm,
2107  int * invperm)
2108 {
2109  int i, size;
2110  int index, level, minLevel, maxLevel;
2111 
2112  if (treenode == NULL) return(1);
2113 
2114  minLevel = table->size;
2115  maxLevel = 0;
2116  /* i : level */
2117  for (i = treenode->low; i < treenode->low + treenode->size; i++) {
2118  index = table->invperm[i];
2119  level = perm[index];
2120  if (level < minLevel)
2121  minLevel = level;
2122  if (level > maxLevel)
2123  maxLevel = level;
2124  }
2125  size = maxLevel - minLevel + 1;
2126  if (size != treenode->size)
2127  return(0);
2128 
2129  if (treenode->child != NULL) {
2130  if (!ddCheckPermuation(table, treenode->child, perm, invperm))
2131  return(0);
2132  }
2133  if (treenode->younger != NULL) {
2134  if (!ddCheckPermuation(table, treenode->younger, perm, invperm))
2135  return(0);
2136  }
2137  return(1);
2138 }
2139 
2140 
2142 
static int * entry
Definition: cuddReorder.c:105
DdHalfWord ref
Definition: cudd.h:280
static int ddCheckPermuation(DdManager *table, MtrNode *treenode, int *perm, int *invperm)
Definition: cuddReorder.c:2103
unsigned int keys
Definition: cuddInt.h:330
void cuddCacheFlush(DdManager *table)
Definition: cuddCache.c:1047
#define CUDD_OUT_OF_MEM
Definition: cudd.h:95
void(* DD_OOMFP)(long)
Definition: cudd.h:324
unsigned short DdHalfWord
Definition: cudd.h:262
#define ddHash(f, g, s)
Definition: cuddInt.h:737
long reordTime
Definition: cuddInt.h:454
static Move * ddSiftingDown(DdManager *table, int x, int xHigh)
Definition: cuddReorder.c:1695
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2837
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
Cudd_ReorderingType autoMethod
Definition: cuddInt.h:418
unsigned int peakLiveNodes
Definition: cuddInt.h:465
Definition: cudd.h:278
int cuddSwapping(DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
Definition: cuddReorder.c:605
#define Cudd_Not(node)
Definition: cudd.h:367
MtrHalfWord size
Definition: mtr.h:134
int siftMaxSwap
Definition: cuddInt.h:412
static Move * ddSwapAny(DdManager *table, int x, int y)
Definition: cuddReorder.c:1347
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
DdHook * preReorderingHook
Definition: cuddInt.h:439
int * invpermZ
Definition: cuddInt.h:389
int reordCycle
Definition: cuddInt.h:415
static char rcsid[] DD_UNUSED
Definition: cuddReorder.c:102
int(* DD_QSFP)(const void *, const void *)
Definition: cudd.h:326
int size
Definition: cuddInt.h:361
double gcFrac
Definition: cuddInt.h:375
int var(Lit p)
Definition: SolverTypes.h:62
Definition: cuddInt.h:492
unsigned int maxCacheHard
Definition: cuddInt.h:359
unsigned int slots
Definition: cuddInt.h:368
int cuddInitInteract(DdManager *table)
Definition: cuddInteract.c:237
#define Cudd_Regular(node)
Definition: cudd.h:397
double maxGrowthAlt
Definition: cuddInt.h:414
int realign
Definition: cuddInt.h:420
double maxGrowth
Definition: cuddInt.h:413
FILE * err
Definition: cuddInt.h:442
static int ddSiftingAux(DdManager *table, int x, int xLow, int xHigh)
Definition: cuddReorder.c:1488
static int ddSiftUp(DdManager *table, int x, int xLow)
Definition: cuddReorder.c:1974
int cuddSifting(DdManager *table, int lower, int upper)
Definition: cuddReorder.c:508
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
int bindVar
Definition: cuddInt.h:334
DdSubtable * subtables
Definition: cuddInt.h:365
struct MtrNode * parent
Definition: mtr.h:136
#define DD_DYN_RATIO
Definition: cuddInt.h:152
MtrNode * tree
Definition: cuddInt.h:424
#define util_cpu_time
Definition: util_hack.h:36
static void bddFixTree(DdManager *table, MtrNode *treenode)
Definition: cuddReorder.c:2010
word M(word f1, word f2, int n)
Definition: kitPerm.c:240
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:126
int Cudd_ShuffleHeap(DdManager *table, int *permutation)
Definition: cuddReorder.c:338
DD_HFP f
Definition: cuddInt.h:246
Cudd_VariableType
Definition: cudd.h:252
int ddTotalNumberSwapping
Definition: cuddReorder.c:107
struct DdNode DdNode
Definition: cudd.h:270
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:729
struct MtrNode * younger
Definition: mtr.h:139
unsigned int initSlots
Definition: cuddInt.h:379
Cudd_VariableType varType
Definition: cuddInt.h:336
int reordered
Definition: cuddInt.h:409
unsigned int nextDyn
Definition: cuddInt.h:422
unsigned int dead
Definition: cuddInt.h:371
long Cudd_Random(void)
Definition: cuddUtil.c:2702
unsigned int cacheSlots
Definition: cuddInt.h:353
#define Cudd_IsComplement(node)
Definition: cudd.h:425
void cuddLocalCacheClearAll(DdManager *manager)
Definition: cuddLCache.c:404
DdNode sentinel
Definition: cuddInt.h:344
char * stash
Definition: cuddInt.h:399
MtrHalfWord index
Definition: mtr.h:135
DdHook * postReorderingHook
Definition: cuddInt.h:440
int cuddNextLow(DdManager *table, int x)
Definition: cuddReorder.c:738
unsigned int keys
Definition: cuddInt.h:369
int cuddNextHigh(DdManager *table, int x)
Definition: cuddReorder.c:716
static int ddReorderPostprocess(DdManager *table)
Definition: cuddReorder.c:1864
unsigned int dead
Definition: cuddInt.h:332
FILE * out
Definition: cuddInt.h:441
static int numvars
Definition: cuddGenetic.c:111
DdHalfWord x
Definition: cuddInt.h:493
DdNode * next
Definition: cudd.h:281
static int ddUniqueCompare(int *ptrX, int *ptrY)
Definition: cuddReorder.c:1323
Cudd_LazyGroupType varToBeGrouped
Definition: cuddInt.h:339
static int ddUpdateMtrTree(DdManager *table, MtrNode *treenode, int *perm, int *invperm)
Definition: cuddReorder.c:2044
long * interact
Definition: cuddInt.h:394
unsigned int maxKeys
Definition: cuddInt.h:331
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
if(last==0)
Definition: sparse_int.h:34
static double max
Definition: cuddSubsetHB.c:134
DdNode ** nodelist
Definition: cuddInt.h:327
static int size
Definition: cuddSign.c:86
#define cuddF2L(f)
Definition: cuddInt.h:718
#define ddMin(x, y)
Definition: cuddInt.h:818
MtrHalfWord low
Definition: mtr.h:133
int reorderings
Definition: cuddInt.h:410
#define DD_MAX_CACHE_TO_SLOTS_RATIO
Definition: cuddInt.h:144
int cacheSlack
Definition: cuddInt.h:358
int cuddTreeSifting(DdManager *table, Cudd_ReorderingType method)
Definition: cuddGroup.c:274
#define cuddT(node)
Definition: cuddInt.h:636
Definition: mtr.h:131
int varHandled
Definition: cuddInt.h:338
#define cuddDeallocNode(unique, node)
Definition: cuddInt.h:547
int cuddBddAlignToZdd(DdManager *table)
Definition: cuddReorder.c:1251
int Cudd_ReduceHeap(DdManager *table, Cudd_ReorderingType heuristic, int minsize)
Definition: cuddReorder.c:176
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
static int ddReorderPreprocess(DdManager *table)
Definition: cuddReorder.c:1826
DdNode ** memoryList
Definition: cuddInt.h:397
unsigned long memused
Definition: cuddInt.h:449
int siftMaxVar
Definition: cuddInt.h:411
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
static int ddSiftingBackward(DdManager *table, int size, Move *moves)
Definition: cuddReorder.c:1787
DdNode * nextFree
Definition: cuddInt.h:398
struct DdHook * next
Definition: cuddInt.h:247
int sizeZ
Definition: cuddInt.h:362
DdHalfWord index
Definition: cudd.h:279
#define ABC_FREE(obj)
Definition: abc_global.h:232
unsigned int slots
Definition: cuddInt.h:329
DdHalfWord y
Definition: cuddInt.h:494
DdNode ** vars
Definition: cuddInt.h:390
static int ddShuffle(DdManager *table, int *permutation)
Definition: cuddReorder.c:1897
int pairIndex
Definition: cuddInt.h:337
#define CUDD_MAXINDEX
Definition: cudd.h:112
#define cuddE(node)
Definition: cuddInt.h:652
struct Move * next
Definition: cuddInt.h:497
#define cuddSatDec(x)
Definition: cuddInt.h:896
int cuddZddAlignToBdd(DdManager *table)
Definition: cuddZddReord.c:352
#define assert(ex)
Definition: util_old.h:213
int * invperm
Definition: cuddInt.h:388
DdSubtable constants
Definition: cuddInt.h:367
static int result
Definition: cuddGenetic.c:125
int isolated
Definition: cuddInt.h:385
#define DD_MEM_CHUNK
Definition: cuddInt.h:104
int cuddTestInteract(DdManager *table, int x, int y)
Definition: cuddInteract.c:191
static Move * ddSiftingUp(DdManager *table, int y, int xLow)
Definition: cuddReorder.c:1595
int shift
Definition: cuddInt.h:328
Cudd_ReorderingType
Definition: cudd.h:151
Cudd_LazyGroupType
Definition: cudd.h:237
struct MtrNode * child
Definition: mtr.h:137
int * perm
Definition: cuddInt.h:386
int size
Definition: cuddInt.h:496
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
unsigned int minDead
Definition: cuddInt.h:374
#define cuddSatInc(x)
Definition: cuddInt.h:878
#define MMoutOfMemory
Definition: util_hack.h:38