abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cuddZddReord.c
Go to the documentation of this file.
1 /**CFile***********************************************************************
2 
3  FileName [cuddZddReord.c]
4 
5  PackageName [cudd]
6 
7  Synopsis [Procedures for dynamic variable ordering of ZDDs.]
8 
9  Description [External procedures included in this module:
10  <ul>
11  <li> Cudd_zddReduceHeap()
12  <li> Cudd_zddShuffleHeap()
13  </ul>
14  Internal procedures included in this module:
15  <ul>
16  <li> cuddZddAlignToBdd()
17  <li> cuddZddNextHigh()
18  <li> cuddZddNextLow()
19  <li> cuddZddUniqueCompare()
20  <li> cuddZddSwapInPlace()
21  <li> cuddZddSwapping()
22  <li> cuddZddSifting()
23  </ul>
24  Static procedures included in this module:
25  <ul>
26  <li> zddSwapAny()
27  <li> cuddZddSiftingAux()
28  <li> cuddZddSiftingUp()
29  <li> cuddZddSiftingDown()
30  <li> cuddZddSiftingBackward()
31  <li> zddReorderPreprocess()
32  <li> zddReorderPostprocess()
33  <li> zddShuffle()
34  <li> zddSiftUp()
35  </ul>
36  ]
37 
38  SeeAlso []
39 
40  Author [Hyong-Kyoon Shin, In-Ho Moon]
41 
42  Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
43 
44  All rights reserved.
45 
46  Redistribution and use in source and binary forms, with or without
47  modification, are permitted provided that the following conditions
48  are met:
49 
50  Redistributions of source code must retain the above copyright
51  notice, this list of conditions and the following disclaimer.
52 
53  Redistributions in binary form must reproduce the above copyright
54  notice, this list of conditions and the following disclaimer in the
55  documentation and/or other materials provided with the distribution.
56 
57  Neither the name of the University of Colorado nor the names of its
58  contributors may be used to endorse or promote products derived from
59  this software without specific prior written permission.
60 
61  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
62  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
63  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
64  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
65  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
66  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
67  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
68  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
69  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
71  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
72  POSSIBILITY OF SUCH DAMAGE.]
73 
74 ******************************************************************************/
75 
76 #include "misc/util/util_hack.h"
77 #include "cuddInt.h"
78 
80 
81 
82 
83 /*---------------------------------------------------------------------------*/
84 /* Constant declarations */
85 /*---------------------------------------------------------------------------*/
86 
87 #define DD_MAX_SUBTABLE_SPARSITY 8
88 #define DD_SHRINK_FACTOR 2
89 
90 /*---------------------------------------------------------------------------*/
91 /* Stucture declarations */
92 /*---------------------------------------------------------------------------*/
93 
94 
95 /*---------------------------------------------------------------------------*/
96 /* Type declarations */
97 /*---------------------------------------------------------------------------*/
98 
99 
100 /*---------------------------------------------------------------------------*/
101 /* Variable declarations */
102 /*---------------------------------------------------------------------------*/
103 
104 #ifndef lint
105 static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.47 2004/08/13 18:04:53 fabio Exp $";
106 #endif
107 
109 
111 
112 static DdNode *empty;
113 
114 
115 /*---------------------------------------------------------------------------*/
116 /* Macro declarations */
117 /*---------------------------------------------------------------------------*/
118 
119 
120 /**AutomaticStart*************************************************************/
121 
122 /*---------------------------------------------------------------------------*/
123 /* Static function prototypes */
124 /*---------------------------------------------------------------------------*/
125 
126 static Move * zddSwapAny (DdManager *table, int x, int y);
127 static int cuddZddSiftingAux (DdManager *table, int x, int x_low, int x_high);
128 static Move * cuddZddSiftingUp (DdManager *table, int x, int x_low, int initial_size);
129 static Move * cuddZddSiftingDown (DdManager *table, int x, int x_high, int initial_size);
130 static int cuddZddSiftingBackward (DdManager *table, Move *moves, int size);
131 static void zddReorderPreprocess (DdManager *table);
132 static int zddReorderPostprocess (DdManager *table);
133 static int zddShuffle (DdManager *table, int *permutation);
134 static int zddSiftUp (DdManager *table, int x, int xLow);
135 static void zddFixTree (DdManager *table, MtrNode *treenode);
136 
137 /**AutomaticEnd***************************************************************/
138 
139 
140 /*---------------------------------------------------------------------------*/
141 /* Definition of exported functions */
142 /*---------------------------------------------------------------------------*/
143 
144 
145 /**Function********************************************************************
146 
147  Synopsis [Main dynamic reordering routine for ZDDs.]
148 
149  Description [Main dynamic reordering routine for ZDDs.
150  Calls one of the possible reordering procedures:
151  <ul>
152  <li>Swapping
153  <li>Sifting
154  <li>Symmetric Sifting
155  </ul>
156 
157  For sifting and symmetric sifting it is possible to request reordering
158  to convergence.<p>
159 
160  The core of all methods is the reordering procedure
161  cuddZddSwapInPlace() which swaps two adjacent variables.
162  Returns 1 in case of success; 0 otherwise. In the case of symmetric
163  sifting (with and without convergence) returns 1 plus the number of
164  symmetric variables, in case of success.]
165 
166  SideEffects [Changes the variable order for all ZDDs and clears
167  the cache.]
168 
169 ******************************************************************************/
170 int
172  DdManager * table /* DD manager */,
173  Cudd_ReorderingType heuristic /* method used for reordering */,
174  int minsize /* bound below which no reordering occurs */)
175 {
176  DdHook *hook;
177  int result;
178  unsigned int nextDyn;
179 #ifdef DD_STATS
180  unsigned int initialSize;
181  unsigned int finalSize;
182 #endif
183  long localTime;
184 
185  /* Don't reorder if there are too many dead nodes. */
186  if (table->keysZ - table->deadZ < (unsigned) minsize)
187  return(1);
188 
189  if (heuristic == CUDD_REORDER_SAME) {
190  heuristic = table->autoMethodZ;
191  }
192  if (heuristic == CUDD_REORDER_NONE) {
193  return(1);
194  }
195 
196  /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore
197  ** we count it.
198  */
199  table->reorderings++;
200  empty = table->zero;
201 
202  localTime = util_cpu_time();
203 
204  /* Run the hook functions. */
205  hook = table->preReorderingHook;
206  while (hook != NULL) {
207  int res = (hook->f)(table, "ZDD", (void *)heuristic);
208  if (res == 0) return(0);
209  hook = hook->next;
210  }
211 
212  /* Clear the cache and collect garbage. */
213  zddReorderPreprocess(table);
215 
216 #ifdef DD_STATS
217  initialSize = table->keysZ;
218 
219  switch(heuristic) {
220  case CUDD_REORDER_RANDOM:
222  (void) fprintf(table->out,"#:I_RANDOM ");
223  break;
224  case CUDD_REORDER_SIFT:
228  (void) fprintf(table->out,"#:I_SIFTING ");
229  break;
230  case CUDD_REORDER_LINEAR:
232  (void) fprintf(table->out,"#:I_LINSIFT ");
233  break;
234  default:
235  (void) fprintf(table->err,"Unsupported ZDD reordering method\n");
236  return(0);
237  }
238  (void) fprintf(table->out,"%8d: initial size",initialSize);
239 #endif
240 
241  result = cuddZddTreeSifting(table,heuristic);
242 
243 #ifdef DD_STATS
244  (void) fprintf(table->out,"\n");
245  finalSize = table->keysZ;
246  (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
247  (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
248  ((double)(util_cpu_time() - localTime)/1000.0));
249  (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
251 #endif
252 
253  if (result == 0)
254  return(0);
255 
256  if (!zddReorderPostprocess(table))
257  return(0);
258 
259  if (table->realignZ) {
260  if (!cuddBddAlignToZdd(table))
261  return(0);
262  }
263 
264  nextDyn = table->keysZ * DD_DYN_RATIO;
265  if (table->reorderings < 20 || nextDyn > table->nextDyn)
266  table->nextDyn = nextDyn;
267  else
268  table->nextDyn += 20;
269 
270  table->reordered = 1;
271 
272  /* Run hook functions. */
273  hook = table->postReorderingHook;
274  while (hook != NULL) {
275  int res = (hook->f)(table, "ZDD", (void *)localTime);
276  if (res == 0) return(0);
277  hook = hook->next;
278  }
279  /* Update cumulative reordering time. */
280  table->reordTime += util_cpu_time() - localTime;
281 
282  return(result);
283 
284 } /* end of Cudd_zddReduceHeap */
285 
286 
287 /**Function********************************************************************
288 
289  Synopsis [Reorders ZDD variables according to given permutation.]
290 
291  Description [Reorders ZDD variables according to given permutation.
292  The i-th entry of the permutation array contains the index of the variable
293  that should be brought to the i-th level. The size of the array should be
294  equal or greater to the number of variables currently in use.
295  Returns 1 in case of success; 0 otherwise.]
296 
297  SideEffects [Changes the ZDD variable order for all diagrams and clears
298  the cache.]
299 
300  SeeAlso [Cudd_zddReduceHeap]
301 
302 ******************************************************************************/
303 int
305  DdManager * table /* DD manager */,
306  int * permutation /* required variable permutation */)
307 {
308 
309  int result;
310 
311  empty = table->zero;
312  zddReorderPreprocess(table);
313 
314  result = zddShuffle(table,permutation);
315 
316  if (!zddReorderPostprocess(table)) return(0);
317 
318  return(result);
319 
320 } /* end of Cudd_zddShuffleHeap */
321 
322 
323 /*---------------------------------------------------------------------------*/
324 /* Definition of internal functions */
325 /*---------------------------------------------------------------------------*/
326 
327 
328 /**Function********************************************************************
329 
330  Synopsis [Reorders ZDD variables according to the order of the BDD
331  variables.]
332 
333  Description [Reorders ZDD variables according to the order of the
334  BDD variables. This function can be called at the end of BDD
335  reordering to insure that the order of the ZDD variables is
336  consistent with the order of the BDD variables. The number of ZDD
337  variables must be a multiple of the number of BDD variables. Let
338  <code>M</code> be the ratio of the two numbers. cuddZddAlignToBdd
339  then considers the ZDD variables from <code>M*i</code> to
340  <code>(M+1)*i-1</code> as corresponding to BDD variable
341  <code>i</code>. This function should be normally called from
342  Cudd_ReduceHeap, which clears the cache. Returns 1 in case of
343  success; 0 otherwise.]
344 
345  SideEffects [Changes the ZDD variable order for all diagrams and performs
346  garbage collection of the ZDD unique table.]
347 
348  SeeAlso [Cudd_zddShuffleHeap Cudd_ReduceHeap]
349 
350 ******************************************************************************/
351 int
353  DdManager * table /* DD manager */)
354 {
355  int *invpermZ; /* permutation array */
356  int M; /* ratio of ZDD variables to BDD variables */
357  int i,j; /* loop indices */
358  int result; /* return value */
359 
360  /* We assume that a ratio of 0 is OK. */
361  if (table->sizeZ == 0)
362  return(1);
363 
364  empty = table->zero;
365  M = table->sizeZ / table->size;
366  /* Check whether the number of ZDD variables is a multiple of the
367  ** number of BDD variables.
368  */
369  if (M * table->size != table->sizeZ)
370  return(0);
371  /* Create and initialize the inverse permutation array. */
372  invpermZ = ABC_ALLOC(int,table->sizeZ);
373  if (invpermZ == NULL) {
374  table->errorCode = CUDD_MEMORY_OUT;
375  return(0);
376  }
377  for (i = 0; i < table->size; i++) {
378  int index = table->invperm[i];
379  int indexZ = index * M;
380  int levelZ = table->permZ[indexZ];
381  levelZ = (levelZ / M) * M;
382  for (j = 0; j < M; j++) {
383  invpermZ[M * i + j] = table->invpermZ[levelZ + j];
384  }
385  }
386  /* Eliminate dead nodes. Do not scan the cache again, because we
387  ** assume that Cudd_ReduceHeap has already cleared it.
388  */
389  cuddGarbageCollect(table,0);
390 
391  result = zddShuffle(table, invpermZ);
392  ABC_FREE(invpermZ);
393  /* Fix the ZDD variable group tree. */
394  zddFixTree(table,table->treeZ);
395  return(result);
396 
397 } /* end of cuddZddAlignToBdd */
398 
399 
400 /**Function********************************************************************
401 
402  Synopsis [Finds the next subtable with a larger index.]
403 
404  Description [Finds the next subtable with a larger index. Returns the
405  index.]
406 
407  SideEffects [None]
408 
409  SeeAlso []
410 
411 ******************************************************************************/
412 int
414  DdManager * table,
415  int x)
416 {
417  return(x + 1);
418 
419 } /* end of cuddZddNextHigh */
420 
421 
422 /**Function********************************************************************
423 
424  Synopsis [Finds the next subtable with a smaller index.]
425 
426  Description [Finds the next subtable with a smaller index. Returns the
427  index.]
428 
429  SideEffects [None]
430 
431  SeeAlso []
432 
433 ******************************************************************************/
434 int
436  DdManager * table,
437  int x)
438 {
439  return(x - 1);
440 
441 } /* end of cuddZddNextLow */
442 
443 
444 /**Function********************************************************************
445 
446  Synopsis [Comparison function used by qsort.]
447 
448  Description [Comparison function used by qsort to order the
449  variables according to the number of keys in the subtables.
450  Returns the difference in number of keys between the two
451  variables being compared.]
452 
453  SideEffects [None]
454 
455  SeeAlso []
456 
457 ******************************************************************************/
458 int
460  int * ptr_x,
461  int * ptr_y)
462 {
463  return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]);
464 
465 } /* end of cuddZddUniqueCompare */
466 
467 
468 /**Function********************************************************************
469 
470  Synopsis [Swaps two adjacent variables.]
471 
472  Description [Swaps two adjacent variables. It assumes that no dead
473  nodes are present on entry to this procedure. The procedure then
474  guarantees that no dead nodes will be present when it terminates.
475  cuddZddSwapInPlace assumes that x &lt; y. Returns the number of keys in
476  the table if successful; 0 otherwise.]
477 
478  SideEffects [None]
479 
480  SeeAlso []
481 
482 ******************************************************************************/
483 int
485  DdManager * table,
486  int x,
487  int y)
488 {
489  DdNodePtr *xlist, *ylist;
490  int xindex, yindex;
491  int xslots, yslots;
492  int xshift, yshift;
493  int oldxkeys, oldykeys;
494  int newxkeys, newykeys;
495  int i;
496  int posn;
497  DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00;
498  DdNode *newf1=NULL, *newf0, *next;
499  DdNodePtr g, *lastP, *previousP;
500 
501 #ifdef DD_DEBUG
502  assert(x < y);
503  assert(cuddZddNextHigh(table,x) == y);
504  assert(table->subtableZ[x].keys != 0);
505  assert(table->subtableZ[y].keys != 0);
506  assert(table->subtableZ[x].dead == 0);
507  assert(table->subtableZ[y].dead == 0);
508 #endif
509 
511 
512  /* Get parameters of x subtable. */
513  xindex = table->invpermZ[x];
514  xlist = table->subtableZ[x].nodelist;
515  oldxkeys = table->subtableZ[x].keys;
516  xslots = table->subtableZ[x].slots;
517  xshift = table->subtableZ[x].shift;
518  newxkeys = 0;
519 
520  yindex = table->invpermZ[y];
521  ylist = table->subtableZ[y].nodelist;
522  oldykeys = table->subtableZ[y].keys;
523  yslots = table->subtableZ[y].slots;
524  yshift = table->subtableZ[y].shift;
525  newykeys = oldykeys;
526 
527  /* The nodes in the x layer that don't depend on y directly
528  ** will stay there; the others are put in a chain.
529  ** The chain is handled as a FIFO; g points to the beginning and
530  ** last points to the end.
531  */
532 
533  g = NULL;
534  lastP = &g;
535  for (i = 0; i < xslots; i++) {
536  previousP = &(xlist[i]);
537  f = *previousP;
538  while (f != NULL) {
539  next = f->next;
540  f1 = cuddT(f); f0 = cuddE(f);
541  if ((f1->index != (DdHalfWord) yindex) &&
542  (f0->index != (DdHalfWord) yindex)) { /* stays */
543  newxkeys++;
544  *previousP = f;
545  previousP = &(f->next);
546  } else {
547  f->index = yindex;
548  *lastP = f;
549  lastP = &(f->next);
550  }
551  f = next;
552  } /* while there are elements in the collision chain */
553  *previousP = NULL;
554  } /* for each slot of the x subtable */
555  *lastP = NULL;
556 
557 
558 #ifdef DD_COUNT
559  table->swapSteps += oldxkeys - newxkeys;
560 #endif
561  /* Take care of the x nodes that must be re-expressed.
562  ** They form a linked list pointed by g. Their index has been
563  ** changed to yindex already.
564  */
565  f = g;
566  while (f != NULL) {
567  next = f->next;
568  /* Find f1, f0, f11, f10, f01, f00. */
569  f1 = cuddT(f);
570  if ((int) f1->index == yindex) {
571  f11 = cuddT(f1); f10 = cuddE(f1);
572  } else {
573  f11 = empty; f10 = f1;
574  }
575  f0 = cuddE(f);
576  if ((int) f0->index == yindex) {
577  f01 = cuddT(f0); f00 = cuddE(f0);
578  } else {
579  f01 = empty; f00 = f0;
580  }
581 
582  /* Decrease ref count of f1. */
583  cuddSatDec(f1->ref);
584  /* Create the new T child. */
585  if (f11 == empty) {
586  if (f01 != empty) {
587  newf1 = f01;
588  cuddSatInc(newf1->ref);
589  }
590  /* else case was already handled when finding nodes
591  ** with both children below level y
592  */
593  } else {
594  /* Check xlist for triple (xindex, f11, f01). */
595  posn = ddHash(cuddF2L(f11), cuddF2L(f01), xshift);
596  /* For each element newf1 in collision list xlist[posn]. */
597  newf1 = xlist[posn];
598  while (newf1 != NULL) {
599  if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
600  cuddSatInc(newf1->ref);
601  break; /* match */
602  }
603  newf1 = newf1->next;
604  } /* while newf1 */
605  if (newf1 == NULL) { /* no match */
606  newf1 = cuddDynamicAllocNode(table);
607  if (newf1 == NULL)
608  goto zddSwapOutOfMem;
609  newf1->index = xindex; newf1->ref = 1;
610  cuddT(newf1) = f11;
611  cuddE(newf1) = f01;
612  /* Insert newf1 in the collision list xlist[pos];
613  ** increase the ref counts of f11 and f01
614  */
615  newxkeys++;
616  newf1->next = xlist[posn];
617  xlist[posn] = newf1;
618  cuddSatInc(f11->ref);
619  cuddSatInc(f01->ref);
620  }
621  }
622  cuddT(f) = newf1;
623 
624  /* Do the same for f0. */
625  /* Decrease ref count of f0. */
626  cuddSatDec(f0->ref);
627  /* Create the new E child. */
628  if (f10 == empty) {
629  newf0 = f00;
630  cuddSatInc(newf0->ref);
631  } else {
632  /* Check xlist for triple (xindex, f10, f00). */
633  posn = ddHash(cuddF2L(f10), cuddF2L(f00), xshift);
634  /* For each element newf0 in collision list xlist[posn]. */
635  newf0 = xlist[posn];
636  while (newf0 != NULL) {
637  if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
638  cuddSatInc(newf0->ref);
639  break; /* match */
640  }
641  newf0 = newf0->next;
642  } /* while newf0 */
643  if (newf0 == NULL) { /* no match */
644  newf0 = cuddDynamicAllocNode(table);
645  if (newf0 == NULL)
646  goto zddSwapOutOfMem;
647  newf0->index = xindex; newf0->ref = 1;
648  cuddT(newf0) = f10; cuddE(newf0) = f00;
649  /* Insert newf0 in the collision list xlist[posn];
650  ** increase the ref counts of f10 and f00.
651  */
652  newxkeys++;
653  newf0->next = xlist[posn];
654  xlist[posn] = newf0;
655  cuddSatInc(f10->ref);
656  cuddSatInc(f00->ref);
657  }
658  }
659  cuddE(f) = newf0;
660 
661  /* Insert the modified f in ylist.
662  ** The modified f does not already exists in ylist.
663  ** (Because of the uniqueness of the cofactors.)
664  */
665  posn = ddHash(cuddF2L(newf1), cuddF2L(newf0), yshift);
666  newykeys++;
667  f->next = ylist[posn];
668  ylist[posn] = f;
669  f = next;
670  } /* while f != NULL */
671 
672  /* GC the y layer. */
673 
674  /* For each node f in ylist. */
675  for (i = 0; i < yslots; i++) {
676  previousP = &(ylist[i]);
677  f = *previousP;
678  while (f != NULL) {
679  next = f->next;
680  if (f->ref == 0) {
681  cuddSatDec(cuddT(f)->ref);
682  cuddSatDec(cuddE(f)->ref);
683  cuddDeallocNode(table, f);
684  newykeys--;
685  } else {
686  *previousP = f;
687  previousP = &(f->next);
688  }
689  f = next;
690  } /* while f */
691  *previousP = NULL;
692  } /* for i */
693 
694  /* Set the appropriate fields in table. */
695  table->subtableZ[x].nodelist = ylist;
696  table->subtableZ[x].slots = yslots;
697  table->subtableZ[x].shift = yshift;
698  table->subtableZ[x].keys = newykeys;
699  table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
700 
701  table->subtableZ[y].nodelist = xlist;
702  table->subtableZ[y].slots = xslots;
703  table->subtableZ[y].shift = xshift;
704  table->subtableZ[y].keys = newxkeys;
705  table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
706 
707  table->permZ[xindex] = y; table->permZ[yindex] = x;
708  table->invpermZ[x] = yindex; table->invpermZ[y] = xindex;
709 
710  table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
711 
712  /* Update univ section; univ[x] remains the same. */
713  table->univ[y] = cuddT(table->univ[x]);
714 
715  return (table->keysZ);
716 
717 zddSwapOutOfMem:
718  (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
719 
720  return (0);
721 
722 } /* end of cuddZddSwapInPlace */
723 
724 
725 /**Function********************************************************************
726 
727  Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.]
728 
729  Description [Implementation of Plessier's algorithm that reorders
730  variables by a sequence of (non-adjacent) swaps.
731  <ol>
732  <li> Select two variables (RANDOM or HEURISTIC).
733  <li> Permute these variables.
734  <li> If the nodes have decreased accept the permutation.
735  <li> Otherwise reconstruct the original heap.
736  <li> Loop.
737  </ol>
738  Returns 1 in case of success; 0 otherwise.]
739 
740  SideEffects [None]
741 
742  SeeAlso []
743 
744 ******************************************************************************/
745 int
747  DdManager * table,
748  int lower,
749  int upper,
750  Cudd_ReorderingType heuristic)
751 {
752  int i, j;
753  int max, keys;
754  int nvars;
755  int x, y;
756  int iterate;
757  int previousSize;
758  Move *moves, *move;
759  int pivot = -1;
760  int modulo;
761  int result;
762 
763 #ifdef DD_DEBUG
764  /* Sanity check */
765  assert(lower >= 0 && upper < table->sizeZ && lower <= upper);
766 #endif
767 
768  nvars = upper - lower + 1;
769  iterate = nvars;
770 
771  for (i = 0; i < iterate; i++) {
772  if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
773  /* Find pivot <= id with maximum keys. */
774  for (max = -1, j = lower; j <= upper; j++) {
775  if ((keys = table->subtableZ[j].keys) > max) {
776  max = keys;
777  pivot = j;
778  }
779  }
780 
781  modulo = upper - pivot;
782  if (modulo == 0) {
783  y = pivot; /* y = nvars-1 */
784  } else {
785  /* y = random # from {pivot+1 .. nvars-1} */
786  y = pivot + 1 + (int) (Cudd_Random() % modulo);
787  }
788 
789  modulo = pivot - lower - 1;
790  if (modulo < 1) { /* if pivot = 1 or 0 */
791  x = lower;
792  } else {
793  do { /* x = random # from {0 .. pivot-2} */
794  x = (int) Cudd_Random() % modulo;
795  } while (x == y);
796  /* Is this condition really needed, since x and y
797  are in regions separated by pivot? */
798  }
799  } else {
800  x = (int) (Cudd_Random() % nvars) + lower;
801  do {
802  y = (int) (Cudd_Random() % nvars) + lower;
803  } while (x == y);
804  }
805 
806  previousSize = table->keysZ;
807  moves = zddSwapAny(table, x, y);
808  if (moves == NULL)
809  goto cuddZddSwappingOutOfMem;
810 
811  result = cuddZddSiftingBackward(table, moves, previousSize);
812  if (!result)
813  goto cuddZddSwappingOutOfMem;
814 
815  while (moves != NULL) {
816  move = moves->next;
817  cuddDeallocMove(table, moves);
818  moves = move;
819  }
820 #ifdef DD_STATS
821  if (table->keysZ < (unsigned) previousSize) {
822  (void) fprintf(table->out,"-");
823  } else if (table->keysZ > (unsigned) previousSize) {
824  (void) fprintf(table->out,"+"); /* should never happen */
825  } else {
826  (void) fprintf(table->out,"=");
827  }
828  fflush(table->out);
829 #endif
830  }
831 
832  return(1);
833 
834 cuddZddSwappingOutOfMem:
835  while (moves != NULL) {
836  move = moves->next;
837  cuddDeallocMove(table, moves);
838  moves = move;
839  }
840  return(0);
841 
842 } /* end of cuddZddSwapping */
843 
844 
845 /**Function********************************************************************
846 
847  Synopsis [Implementation of Rudell's sifting algorithm.]
848 
849  Description [Implementation of Rudell's sifting algorithm.
850  Assumes that no dead nodes are present.
851  <ol>
852  <li> Order all the variables according to the number of entries
853  in each unique table.
854  <li> Sift the variable up and down, remembering each time the
855  total size of the DD heap.
856  <li> Select the best permutation.
857  <li> Repeat 3 and 4 for all variables.
858  </ol>
859  Returns 1 if successful; 0 otherwise.]
860 
861  SideEffects [None]
862 
863  SeeAlso []
864 
865 ******************************************************************************/
866 int
868  DdManager * table,
869  int lower,
870  int upper)
871 {
872  int i;
873  int *var;
874  int size;
875  int x;
876  int result;
877 #ifdef DD_STATS
878  int previousSize;
879 #endif
880 
881  size = table->sizeZ;
882 
883  /* Find order in which to sift variables. */
884  var = NULL;
885  zdd_entry = ABC_ALLOC(int, size);
886  if (zdd_entry == NULL) {
887  table->errorCode = CUDD_MEMORY_OUT;
888  goto cuddZddSiftingOutOfMem;
889  }
890  var = ABC_ALLOC(int, size);
891  if (var == NULL) {
892  table->errorCode = CUDD_MEMORY_OUT;
893  goto cuddZddSiftingOutOfMem;
894  }
895 
896  for (i = 0; i < size; i++) {
897  x = table->permZ[i];
898  zdd_entry[i] = table->subtableZ[x].keys;
899  var[i] = i;
900  }
901 
902  qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
903 
904  /* Now sift. */
905  for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
906  if (zddTotalNumberSwapping >= table->siftMaxSwap)
907  break;
908  x = table->permZ[var[i]];
909  if (x < lower || x > upper) continue;
910 #ifdef DD_STATS
911  previousSize = table->keysZ;
912 #endif
913  result = cuddZddSiftingAux(table, x, lower, upper);
914  if (!result)
915  goto cuddZddSiftingOutOfMem;
916 #ifdef DD_STATS
917  if (table->keysZ < (unsigned) previousSize) {
918  (void) fprintf(table->out,"-");
919  } else if (table->keysZ > (unsigned) previousSize) {
920  (void) fprintf(table->out,"+"); /* should never happen */
921  (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
922  } else {
923  (void) fprintf(table->out,"=");
924  }
925  fflush(table->out);
926 #endif
927  }
928 
929  ABC_FREE(var);
931 
932  return(1);
933 
934 cuddZddSiftingOutOfMem:
935 
936  if (zdd_entry != NULL) ABC_FREE(zdd_entry);
937  if (var != NULL) ABC_FREE(var);
938 
939  return(0);
940 
941 } /* end of cuddZddSifting */
942 
943 
944 /*---------------------------------------------------------------------------*/
945 /* Definition of static functions */
946 /*---------------------------------------------------------------------------*/
947 
948 
949 /**Function********************************************************************
950 
951  Synopsis [Swaps any two variables.]
952 
953  Description [Swaps any two variables. Returns the set of moves.]
954 
955  SideEffects [None]
956 
957  SeeAlso []
958 
959 ******************************************************************************/
960 static Move *
962  DdManager * table,
963  int x,
964  int y)
965 {
966  Move *move, *moves;
967  int tmp, size;
968  int x_ref, y_ref;
969  int x_next, y_next;
970  int limit_size;
971 
972  if (x > y) { /* make x precede y */
973  tmp = x; x = y; y = tmp;
974  }
975 
976  x_ref = x; y_ref = y;
977 
978  x_next = cuddZddNextHigh(table, x);
979  y_next = cuddZddNextLow(table, y);
980  moves = NULL;
981  limit_size = table->keysZ;
982 
983  for (;;) {
984  if (x_next == y_next) { /* x < x_next = y_next < y */
985  size = cuddZddSwapInPlace(table, x, x_next);
986  if (size == 0)
987  goto zddSwapAnyOutOfMem;
988  move = (Move *) cuddDynamicAllocNode(table);
989  if (move == NULL)
990  goto zddSwapAnyOutOfMem;
991  move->x = x;
992  move->y = x_next;
993  move->size = size;
994  move->next = moves;
995  moves = move;
996 
997  size = cuddZddSwapInPlace(table, y_next, y);
998  if (size == 0)
999  goto zddSwapAnyOutOfMem;
1000  move = (Move *)cuddDynamicAllocNode(table);
1001  if (move == NULL)
1002  goto zddSwapAnyOutOfMem;
1003  move->x = y_next;
1004  move->y = y;
1005  move->size = size;
1006  move->next = moves;
1007  moves = move;
1008 
1009  size = cuddZddSwapInPlace(table, x, x_next);
1010  if (size == 0)
1011  goto zddSwapAnyOutOfMem;
1012  move = (Move *)cuddDynamicAllocNode(table);
1013  if (move == NULL)
1014  goto zddSwapAnyOutOfMem;
1015  move->x = x;
1016  move->y = x_next;
1017  move->size = size;
1018  move->next = moves;
1019  moves = move;
1020 
1021  tmp = x; x = y; y = tmp;
1022 
1023  } else if (x == y_next) { /* x = y_next < y = x_next */
1024  size = cuddZddSwapInPlace(table, x, x_next);
1025  if (size == 0)
1026  goto zddSwapAnyOutOfMem;
1027  move = (Move *)cuddDynamicAllocNode(table);
1028  if (move == NULL)
1029  goto zddSwapAnyOutOfMem;
1030  move->x = x;
1031  move->y = x_next;
1032  move->size = size;
1033  move->next = moves;
1034  moves = move;
1035 
1036  tmp = x; x = y; y = tmp;
1037  } else {
1038  size = cuddZddSwapInPlace(table, x, x_next);
1039  if (size == 0)
1040  goto zddSwapAnyOutOfMem;
1041  move = (Move *)cuddDynamicAllocNode(table);
1042  if (move == NULL)
1043  goto zddSwapAnyOutOfMem;
1044  move->x = x;
1045  move->y = x_next;
1046  move->size = size;
1047  move->next = moves;
1048  moves = move;
1049 
1050  size = cuddZddSwapInPlace(table, y_next, y);
1051  if (size == 0)
1052  goto zddSwapAnyOutOfMem;
1053  move = (Move *)cuddDynamicAllocNode(table);
1054  if (move == NULL)
1055  goto zddSwapAnyOutOfMem;
1056  move->x = y_next;
1057  move->y = y;
1058  move->size = size;
1059  move->next = moves;
1060  moves = move;
1061 
1062  x = x_next; y = y_next;
1063  }
1064 
1065  x_next = cuddZddNextHigh(table, x);
1066  y_next = cuddZddNextLow(table, y);
1067  if (x_next > y_ref)
1068  break; /* if x == y_ref */
1069 
1070  if ((double) size > table->maxGrowth * (double) limit_size)
1071  break;
1072  if (size < limit_size)
1073  limit_size = size;
1074  }
1075  if (y_next >= x_ref) {
1076  size = cuddZddSwapInPlace(table, y_next, y);
1077  if (size == 0)
1078  goto zddSwapAnyOutOfMem;
1079  move = (Move *)cuddDynamicAllocNode(table);
1080  if (move == NULL)
1081  goto zddSwapAnyOutOfMem;
1082  move->x = y_next;
1083  move->y = y;
1084  move->size = size;
1085  move->next = moves;
1086  moves = move;
1087  }
1088 
1089  return(moves);
1090 
1091 zddSwapAnyOutOfMem:
1092  while (moves != NULL) {
1093  move = moves->next;
1094  cuddDeallocMove(table, moves);
1095  moves = move;
1096  }
1097  return(NULL);
1098 
1099 } /* end of zddSwapAny */
1100 
1101 
1102 /**Function********************************************************************
1103 
1104  Synopsis [Given xLow <= x <= xHigh moves x up and down between the
1105  boundaries.]
1106 
1107  Description [Given xLow <= x <= xHigh moves x up and down between the
1108  boundaries. Finds the best position and does the required changes.
1109  Returns 1 if successful; 0 otherwise.]
1110 
1111  SideEffects [None]
1112 
1113  SeeAlso []
1114 
1115 ******************************************************************************/
1116 static int
1118  DdManager * table,
1119  int x,
1120  int x_low,
1121  int x_high)
1122 {
1123  Move *move;
1124  Move *moveUp; /* list of up move */
1125  Move *moveDown; /* list of down move */
1126 
1127  int initial_size;
1128  int result;
1129 
1130  initial_size = table->keysZ;
1131 
1132 #ifdef DD_DEBUG
1133  assert(table->subtableZ[x].keys > 0);
1134 #endif
1135 
1136  moveDown = NULL;
1137  moveUp = NULL;
1138 
1139  if (x == x_low) {
1140  moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
1141  /* after that point x --> x_high */
1142  if (moveDown == NULL)
1143  goto cuddZddSiftingAuxOutOfMem;
1144  result = cuddZddSiftingBackward(table, moveDown,
1145  initial_size);
1146  /* move backward and stop at best position */
1147  if (!result)
1148  goto cuddZddSiftingAuxOutOfMem;
1149 
1150  }
1151  else if (x == x_high) {
1152  moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
1153  /* after that point x --> x_low */
1154  if (moveUp == NULL)
1155  goto cuddZddSiftingAuxOutOfMem;
1156  result = cuddZddSiftingBackward(table, moveUp, initial_size);
1157  /* move backward and stop at best position */
1158  if (!result)
1159  goto cuddZddSiftingAuxOutOfMem;
1160  }
1161  else if ((x - x_low) > (x_high - x)) {
1162  /* must go down first:shorter */
1163  moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
1164  /* after that point x --> x_high */
1165  if (moveDown == NULL)
1166  goto cuddZddSiftingAuxOutOfMem;
1167  moveUp = cuddZddSiftingUp(table, moveDown->y, x_low,
1168  initial_size);
1169  if (moveUp == NULL)
1170  goto cuddZddSiftingAuxOutOfMem;
1171  result = cuddZddSiftingBackward(table, moveUp, initial_size);
1172  /* move backward and stop at best position */
1173  if (!result)
1174  goto cuddZddSiftingAuxOutOfMem;
1175  }
1176  else {
1177  moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
1178  /* after that point x --> x_high */
1179  if (moveUp == NULL)
1180  goto cuddZddSiftingAuxOutOfMem;
1181  moveDown = cuddZddSiftingDown(table, moveUp->x, x_high,
1182  initial_size);
1183  /* then move up */
1184  if (moveDown == NULL)
1185  goto cuddZddSiftingAuxOutOfMem;
1186  result = cuddZddSiftingBackward(table, moveDown,
1187  initial_size);
1188  /* move backward and stop at best position */
1189  if (!result)
1190  goto cuddZddSiftingAuxOutOfMem;
1191  }
1192 
1193  while (moveDown != NULL) {
1194  move = moveDown->next;
1195  cuddDeallocMove(table, moveDown);
1196  moveDown = move;
1197  }
1198  while (moveUp != NULL) {
1199  move = moveUp->next;
1200  cuddDeallocMove(table, moveUp);
1201  moveUp = move;
1202  }
1203 
1204  return(1);
1205 
1206 cuddZddSiftingAuxOutOfMem:
1207  while (moveDown != NULL) {
1208  move = moveDown->next;
1209  cuddDeallocMove(table, moveDown);
1210  moveDown = move;
1211  }
1212  while (moveUp != NULL) {
1213  move = moveUp->next;
1214  cuddDeallocMove(table, moveUp);
1215  moveUp = move;
1216  }
1217 
1218  return(0);
1219 
1220 } /* end of cuddZddSiftingAux */
1221 
1222 
1223 /**Function********************************************************************
1224 
1225  Synopsis [Sifts a variable up.]
1226 
1227  Description [Sifts a variable up. Moves y up until either it reaches
1228  the bound (x_low) or the size of the ZDD heap increases too much.
1229  Returns the set of moves in case of success; NULL if memory is full.]
1230 
1231  SideEffects [None]
1232 
1233  SeeAlso []
1234 
1235 ******************************************************************************/
1236 static Move *
1238  DdManager * table,
1239  int x,
1240  int x_low,
1241  int initial_size)
1242 {
1243  Move *moves;
1244  Move *move;
1245  int y;
1246  int size;
1247  int limit_size = initial_size;
1248 
1249  moves = NULL;
1250  y = cuddZddNextLow(table, x);
1251  while (y >= x_low) {
1252  size = cuddZddSwapInPlace(table, y, x);
1253  if (size == 0)
1254  goto cuddZddSiftingUpOutOfMem;
1255  move = (Move *)cuddDynamicAllocNode(table);
1256  if (move == NULL)
1257  goto cuddZddSiftingUpOutOfMem;
1258  move->x = y;
1259  move->y = x;
1260  move->size = size;
1261  move->next = moves;
1262  moves = move;
1263 
1264  if ((double)size > (double)limit_size * table->maxGrowth)
1265  break;
1266  if (size < limit_size)
1267  limit_size = size;
1268 
1269  x = y;
1270  y = cuddZddNextLow(table, x);
1271  }
1272  return(moves);
1273 
1274 cuddZddSiftingUpOutOfMem:
1275  while (moves != NULL) {
1276  move = moves->next;
1277  cuddDeallocMove(table, moves);
1278  moves = move;
1279  }
1280  return(NULL);
1281 
1282 } /* end of cuddZddSiftingUp */
1283 
1284 
1285 /**Function********************************************************************
1286 
1287  Synopsis [Sifts a variable down.]
1288 
1289  Description [Sifts a variable down. Moves x down until either it
1290  reaches the bound (x_high) or the size of the ZDD heap increases too
1291  much. Returns the set of moves in case of success; NULL if memory is
1292  full.]
1293 
1294  SideEffects [None]
1295 
1296  SeeAlso []
1297 
1298 ******************************************************************************/
1299 static Move *
1301  DdManager * table,
1302  int x,
1303  int x_high,
1304  int initial_size)
1305 {
1306  Move *moves;
1307  Move *move;
1308  int y;
1309  int size;
1310  int limit_size = initial_size;
1311 
1312  moves = NULL;
1313  y = cuddZddNextHigh(table, x);
1314  while (y <= x_high) {
1315  size = cuddZddSwapInPlace(table, x, y);
1316  if (size == 0)
1317  goto cuddZddSiftingDownOutOfMem;
1318  move = (Move *)cuddDynamicAllocNode(table);
1319  if (move == NULL)
1320  goto cuddZddSiftingDownOutOfMem;
1321  move->x = x;
1322  move->y = y;
1323  move->size = size;
1324  move->next = moves;
1325  moves = move;
1326 
1327  if ((double)size > (double)limit_size * table->maxGrowth)
1328  break;
1329  if (size < limit_size)
1330  limit_size = size;
1331 
1332  x = y;
1333  y = cuddZddNextHigh(table, x);
1334  }
1335  return(moves);
1336 
1337 cuddZddSiftingDownOutOfMem:
1338  while (moves != NULL) {
1339  move = moves->next;
1340  cuddDeallocMove(table, moves);
1341  moves = move;
1342  }
1343  return(NULL);
1344 
1345 } /* end of cuddZddSiftingDown */
1346 
1347 
1348 /**Function********************************************************************
1349 
1350  Synopsis [Given a set of moves, returns the ZDD heap to the position
1351  giving the minimum size.]
1352 
1353  Description [Given a set of moves, returns the ZDD heap to the
1354  position giving the minimum size. In case of ties, returns to the
1355  closest position giving the minimum size. Returns 1 in case of
1356  success; 0 otherwise.]
1357 
1358  SideEffects [None]
1359 
1360  SeeAlso []
1361 
1362 ******************************************************************************/
1363 static int
1365  DdManager * table,
1366  Move * moves,
1367  int size)
1368 {
1369  int i;
1370  int i_best;
1371  Move *move;
1372  int res;
1373 
1374  /* Find the minimum size among moves. */
1375  i_best = -1;
1376  for (move = moves, i = 0; move != NULL; move = move->next, i++) {
1377  if (move->size < size) {
1378  i_best = i;
1379  size = move->size;
1380  }
1381  }
1382 
1383  for (move = moves, i = 0; move != NULL; move = move->next, i++) {
1384  if (i == i_best)
1385  break;
1386  res = cuddZddSwapInPlace(table, move->x, move->y);
1387  if (!res)
1388  return(0);
1389  if (i_best == -1 && res == size)
1390  break;
1391  }
1392 
1393  return(1);
1394 
1395 } /* end of cuddZddSiftingBackward */
1396 
1397 
1398 /**Function********************************************************************
1399 
1400  Synopsis [Prepares the ZDD heap for dynamic reordering.]
1401 
1402  Description [Prepares the ZDD heap for dynamic reordering. Does
1403  garbage collection, to guarantee that there are no dead nodes;
1404  and clears the cache, which is invalidated by dynamic reordering.]
1405 
1406  SideEffects [None]
1407 
1408 ******************************************************************************/
1409 static void
1411  DdManager * table)
1412 {
1413 
1414  /* Clear the cache. */
1415  cuddCacheFlush(table);
1416 
1417  /* Eliminate dead nodes. Do not scan the cache again. */
1418  cuddGarbageCollect(table,0);
1419 
1420  return;
1421 
1422 } /* end of ddReorderPreprocess */
1423 
1424 
1425 /**Function********************************************************************
1426 
1427  Synopsis [Shrinks almost empty ZDD subtables at the end of reordering
1428  to guarantee that they have a reasonable load factor.]
1429 
1430  Description [Shrinks almost empty subtables at the end of reordering to
1431  guarantee that they have a reasonable load factor. However, if there many
1432  nodes are being reclaimed, then no resizing occurs. Returns 1 in case of
1433  success; 0 otherwise.]
1434 
1435  SideEffects [None]
1436 
1437 ******************************************************************************/
1438 static int
1440  DdManager * table)
1441 {
1442  int i, j, posn;
1443  DdNodePtr *nodelist, *oldnodelist;
1444  DdNode *node, *next;
1445  unsigned int slots, oldslots;
1446  extern DD_OOMFP MMoutOfMemory;
1447  DD_OOMFP saveHandler;
1448 
1449 #ifdef DD_VERBOSE
1450  (void) fflush(table->out);
1451 #endif
1452 
1453  /* If we have very many reclaimed nodes, we do not want to shrink
1454  ** the subtables, because this will lead to more garbage
1455  ** collections. More garbage collections mean shorter mean life for
1456  ** nodes with zero reference count; hence lower probability of finding
1457  ** a result in the cache.
1458  */
1459  if (table->reclaimed > table->allocated / 2) return(1);
1460 
1461  /* Resize subtables. */
1462  for (i = 0; i < table->sizeZ; i++) {
1463  int shift;
1464  oldslots = table->subtableZ[i].slots;
1465  if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY ||
1466  oldslots <= table->initSlots) continue;
1467  oldnodelist = table->subtableZ[i].nodelist;
1468  slots = oldslots >> 1;
1469  saveHandler = MMoutOfMemory;
1470  MMoutOfMemory = Cudd_OutOfMem;
1471  nodelist = ABC_ALLOC(DdNodePtr, slots);
1472  MMoutOfMemory = saveHandler;
1473  if (nodelist == NULL) {
1474  return(1);
1475  }
1476  table->subtableZ[i].nodelist = nodelist;
1477  table->subtableZ[i].slots = slots;
1478  table->subtableZ[i].shift++;
1479  table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
1480 #ifdef DD_VERBOSE
1481  (void) fprintf(table->err,
1482  "shrunk layer %d (%d keys) from %d to %d slots\n",
1483  i, table->subtableZ[i].keys, oldslots, slots);
1484 #endif
1485 
1486  for (j = 0; (unsigned) j < slots; j++) {
1487  nodelist[j] = NULL;
1488  }
1489  shift = table->subtableZ[i].shift;
1490  for (j = 0; (unsigned) j < oldslots; j++) {
1491  node = oldnodelist[j];
1492  while (node != NULL) {
1493  next = node->next;
1494  posn = ddHash(cuddF2L(cuddT(node)), cuddF2L(cuddE(node)), shift);
1495  node->next = nodelist[posn];
1496  nodelist[posn] = node;
1497  node = next;
1498  }
1499  }
1500  ABC_FREE(oldnodelist);
1501 
1502  table->memused += (slots - oldslots) * sizeof(DdNode *);
1503  table->slots += slots - oldslots;
1504  table->minDead = (unsigned) (table->gcFrac * (double) table->slots);
1505  table->cacheSlack = (int) ddMin(table->maxCacheHard,
1507  2 * (int) table->cacheSlots;
1508  }
1509  /* We don't look at the constant subtable, because it is not
1510  ** affected by reordering.
1511  */
1512 
1513  return(1);
1514 
1515 } /* end of zddReorderPostprocess */
1516 
1517 
1518 /**Function********************************************************************
1519 
1520  Synopsis [Reorders ZDD variables according to a given permutation.]
1521 
1522  Description [Reorders ZDD variables according to a given permutation.
1523  The i-th permutation array contains the index of the variable that
1524  should be brought to the i-th level. zddShuffle assumes that no
1525  dead nodes are present. The reordering is achieved by a series of
1526  upward sifts. Returns 1 if successful; 0 otherwise.]
1527 
1528  SideEffects [None]
1529 
1530  SeeAlso []
1531 
1532 ******************************************************************************/
1533 static int
1535  DdManager * table,
1536  int * permutation)
1537 {
1538  int index;
1539  int level;
1540  int position;
1541  int numvars;
1542  int result;
1543 #ifdef DD_STATS
1544  long localTime;
1545  int initialSize;
1546  int finalSize;
1547  int previousSize;
1548 #endif
1549 
1551 #ifdef DD_STATS
1552  localTime = util_cpu_time();
1553  initialSize = table->keysZ;
1554  (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
1555  initialSize);
1556 #endif
1557 
1558  numvars = table->sizeZ;
1559 
1560  for (level = 0; level < numvars; level++) {
1561  index = permutation[level];
1562  position = table->permZ[index];
1563 #ifdef DD_STATS
1564  previousSize = table->keysZ;
1565 #endif
1566  result = zddSiftUp(table,position,level);
1567  if (!result) return(0);
1568 #ifdef DD_STATS
1569  if (table->keysZ < (unsigned) previousSize) {
1570  (void) fprintf(table->out,"-");
1571  } else if (table->keysZ > (unsigned) previousSize) {
1572  (void) fprintf(table->out,"+"); /* should never happen */
1573  } else {
1574  (void) fprintf(table->out,"=");
1575  }
1576  fflush(table->out);
1577 #endif
1578  }
1579 
1580 #ifdef DD_STATS
1581  (void) fprintf(table->out,"\n");
1582  finalSize = table->keysZ;
1583  (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize);
1584  (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
1585  ((double)(util_cpu_time() - localTime)/1000.0));
1586  (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
1588 #endif
1589 
1590  return(1);
1591 
1592 } /* end of zddShuffle */
1593 
1594 
1595 /**Function********************************************************************
1596 
1597  Synopsis [Moves one ZDD variable up.]
1598 
1599  Description [Takes a ZDD variable from position x and sifts it up to
1600  position xLow; xLow should be less than or equal to x.
1601  Returns 1 if successful; 0 otherwise]
1602 
1603  SideEffects [None]
1604 
1605  SeeAlso []
1606 
1607 ******************************************************************************/
1608 static int
1610  DdManager * table,
1611  int x,
1612  int xLow)
1613 {
1614  int y;
1615  int size;
1616 
1617  y = cuddZddNextLow(table,x);
1618  while (y >= xLow) {
1619  size = cuddZddSwapInPlace(table,y,x);
1620  if (size == 0) {
1621  return(0);
1622  }
1623  x = y;
1624  y = cuddZddNextLow(table,x);
1625  }
1626  return(1);
1627 
1628 } /* end of zddSiftUp */
1629 
1630 
1631 /**Function********************************************************************
1632 
1633  Synopsis [Fixes the ZDD variable group tree after a shuffle.]
1634 
1635  Description [Fixes the ZDD variable group tree after a
1636  shuffle. Assumes that the order of the variables in a terminal node
1637  has not been changed.]
1638 
1639  SideEffects [Changes the ZDD variable group tree.]
1640 
1641  SeeAlso []
1642 
1643 ******************************************************************************/
1644 static void
1646  DdManager * table,
1647  MtrNode * treenode)
1648 {
1649  if (treenode == NULL) return;
1650  treenode->low = ((int) treenode->index < table->sizeZ) ?
1651  table->permZ[treenode->index] : treenode->index;
1652  if (treenode->child != NULL) {
1653  zddFixTree(table, treenode->child);
1654  }
1655  if (treenode->younger != NULL)
1656  zddFixTree(table, treenode->younger);
1657  if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
1658  treenode->parent->low = treenode->low;
1659  treenode->parent->index = treenode->index;
1660  }
1661  return;
1662 
1663 } /* end of zddFixTree */
1664 
1665 
1667 
1668 
DdHalfWord ref
Definition: cudd.h:280
ABC_INT64_T allocated
Definition: cuddInt.h:382
static Move * cuddZddSiftingUp(DdManager *table, int x, int x_low, int initial_size)
unsigned int keys
Definition: cuddInt.h:330
void cuddCacheFlush(DdManager *table)
Definition: cuddCache.c:1047
void(* DD_OOMFP)(long)
Definition: cudd.h:324
unsigned short DdHalfWord
Definition: cudd.h:262
int cuddZddSwapping(DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
Definition: cuddZddReord.c:746
#define ddHash(f, g, s)
Definition: cuddInt.h:737
long reordTime
Definition: cuddInt.h:454
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2837
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
static char rcsid[] DD_UNUSED
Definition: cuddZddReord.c:105
Definition: cudd.h:278
unsigned int deadZ
Definition: cuddInt.h:372
int siftMaxSwap
Definition: cuddInt.h:412
DdHook * preReorderingHook
Definition: cuddInt.h:439
int * invpermZ
Definition: cuddInt.h:389
static Move * cuddZddSiftingDown(DdManager *table, int x, int x_high, int initial_size)
static void zddReorderPreprocess(DdManager *table)
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
int cuddZddNextHigh(DdManager *table, int x)
Definition: cuddZddReord.c:413
unsigned int slots
Definition: cuddInt.h:368
DdNode * zero
Definition: cuddInt.h:346
double maxGrowth
Definition: cuddInt.h:413
FILE * err
Definition: cuddInt.h:442
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:484
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
Cudd_ReorderingType autoMethodZ
Definition: cuddInt.h:419
int * permZ
Definition: cuddInt.h:387
struct MtrNode * parent
Definition: mtr.h:136
#define DD_DYN_RATIO
Definition: cuddInt.h:152
#define util_cpu_time
Definition: util_hack.h:36
word M(word f1, word f2, int n)
Definition: kitPerm.c:240
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:126
DD_HFP f
Definition: cuddInt.h:246
int cuddZddNextLow(DdManager *table, int x)
Definition: cuddZddReord.c:435
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:729
static DdNode * empty
Definition: cuddZddReord.c:112
struct MtrNode * younger
Definition: mtr.h:139
#define DD_MAX_SUBTABLE_SPARSITY
Definition: cuddZddReord.c:87
int reordered
Definition: cuddInt.h:409
unsigned int nextDyn
Definition: cuddInt.h:422
long Cudd_Random(void)
Definition: cuddUtil.c:2702
unsigned int cacheSlots
Definition: cuddInt.h:353
static int cuddZddSiftingAux(DdManager *table, int x, int x_low, int x_high)
MtrHalfWord index
Definition: mtr.h:135
DdHook * postReorderingHook
Definition: cuddInt.h:440
int zddTotalNumberSwapping
Definition: cuddZddReord.c:110
unsigned int dead
Definition: cuddInt.h:332
FILE * out
Definition: cuddInt.h:441
static int numvars
Definition: cuddGenetic.c:111
int realignZ
Definition: cuddInt.h:421
DdHalfWord x
Definition: cuddInt.h:493
DdNode * next
Definition: cudd.h:281
int cuddZddSifting(DdManager *table, int lower, int upper)
Definition: cuddZddReord.c:867
unsigned int maxKeys
Definition: cuddInt.h:331
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
static Move * zddSwapAny(DdManager *table, int x, int y)
Definition: cuddZddReord.c:961
static double max
Definition: cuddSubsetHB.c:134
static int zddReorderPostprocess(DdManager *table)
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 cuddZddUniqueCompare(int *ptr_x, int *ptr_y)
Definition: cuddZddReord.c:459
int cacheSlack
Definition: cuddInt.h:358
#define cuddT(node)
Definition: cuddInt.h:636
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
static int zddSiftUp(DdManager *table, int x, int xLow)
Definition: mtr.h:131
#define cuddDeallocNode(unique, node)
Definition: cuddInt.h:547
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
int cuddZddAlignToBdd(DdManager *table)
Definition: cuddZddReord.c:352
unsigned long memused
Definition: cuddInt.h:449
int siftMaxVar
Definition: cuddInt.h:411
static int cuddZddSiftingBackward(DdManager *table, Move *moves, int size)
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
int cuddZddTreeSifting(DdManager *table, Cudd_ReorderingType method)
Definition: cuddZddGroup.c:232
MtrNode * treeZ
Definition: cuddInt.h:425
#define cuddE(node)
Definition: cuddInt.h:652
struct Move * next
Definition: cuddInt.h:497
#define cuddSatDec(x)
Definition: cuddInt.h:896
#define assert(ex)
Definition: util_old.h:213
int * invperm
Definition: cuddInt.h:388
static int result
Definition: cuddGenetic.c:125
static void zddFixTree(DdManager *table, MtrNode *treenode)
int cuddBddAlignToZdd(DdManager *table)
Definition: cuddReorder.c:1251
int shift
Definition: cuddInt.h:328
static int zddShuffle(DdManager *table, int *permutation)
unsigned int keysZ
Definition: cuddInt.h:370
int * zdd_entry
Definition: cuddZddReord.c:108
Cudd_ReorderingType
Definition: cudd.h:151
int Cudd_zddShuffleHeap(DdManager *table, int *permutation)
Definition: cuddZddReord.c:304
struct MtrNode * child
Definition: mtr.h:137
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
double reclaimed
Definition: cuddInt.h:384
DdSubtable * subtableZ
Definition: cuddInt.h:366
#define MMoutOfMemory
Definition: util_hack.h:38
DdNode ** univ
Definition: cuddInt.h:392
int Cudd_zddReduceHeap(DdManager *table, Cudd_ReorderingType heuristic, int minsize)
Definition: cuddZddReord.c:171