abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cuddExact.c
Go to the documentation of this file.
1 /**CFile***********************************************************************
2 
3  FileName [cuddExact.c]
4 
5  PackageName [cudd]
6 
7  Synopsis [Functions for exact variable reordering.]
8 
9  Description [External procedures included in this file:
10  <ul>
11  </ul>
12  Internal procedures included in this module:
13  <ul>
14  <li> cuddExact()
15  </ul>
16  Static procedures included in this module:
17  <ul>
18  <li> getMaxBinomial()
19  <li> gcd()
20  <li> getMatrix()
21  <li> freeMatrix()
22  <li> getLevelKeys()
23  <li> ddShuffle()
24  <li> ddSiftUp()
25  <li> updateUB()
26  <li> ddCountRoots()
27  <li> ddClearGlobal()
28  <li> computeLB()
29  <li> updateEntry()
30  <li> pushDown()
31  <li> initSymmInfo()
32  </ul>]
33 
34  Author [Cheng Hua, Fabio Somenzi]
35 
36  Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
37 
38  All rights reserved.
39 
40  Redistribution and use in source and binary forms, with or without
41  modification, are permitted provided that the following conditions
42  are met:
43 
44  Redistributions of source code must retain the above copyright
45  notice, this list of conditions and the following disclaimer.
46 
47  Redistributions in binary form must reproduce the above copyright
48  notice, this list of conditions and the following disclaimer in the
49  documentation and/or other materials provided with the distribution.
50 
51  Neither the name of the University of Colorado nor the names of its
52  contributors may be used to endorse or promote products derived from
53  this software without specific prior written permission.
54 
55  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
56  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
57  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
58  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
59  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
60  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
61  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
62  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
63  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
65  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
66  POSSIBILITY OF SUCH DAMAGE.]
67 
68 ******************************************************************************/
69 
70 #include "misc/util/util_hack.h"
71 #include "cuddInt.h"
72 
74 
75 
76 
77 /*---------------------------------------------------------------------------*/
78 /* Constant declarations */
79 /*---------------------------------------------------------------------------*/
80 
81 
82 /*---------------------------------------------------------------------------*/
83 /* Stucture declarations */
84 /*---------------------------------------------------------------------------*/
85 
86 /*---------------------------------------------------------------------------*/
87 /* Type declarations */
88 /*---------------------------------------------------------------------------*/
89 
90 /*---------------------------------------------------------------------------*/
91 /* Variable declarations */
92 /*---------------------------------------------------------------------------*/
93 
94 #ifndef lint
95 static char rcsid[] DD_UNUSED = "$Id: cuddExact.c,v 1.28 2009/02/19 16:19:19 fabio Exp $";
96 #endif
97 
98 #ifdef DD_STATS
99 static int ddTotalShuffles;
100 #endif
101 
102 /*---------------------------------------------------------------------------*/
103 /* Macro declarations */
104 /*---------------------------------------------------------------------------*/
105 
106 /**AutomaticStart*************************************************************/
107 
108 /*---------------------------------------------------------------------------*/
109 /* Static function prototypes */
110 /*---------------------------------------------------------------------------*/
111 
112 static int getMaxBinomial (int n);
113 static DdHalfWord ** getMatrix (int rows, int cols);
114 static void freeMatrix (DdHalfWord **matrix);
115 static int getLevelKeys (DdManager *table, int l);
116 static int ddShuffle (DdManager *table, DdHalfWord *permutation, int lower, int upper);
117 static int ddSiftUp (DdManager *table, int x, int xLow);
118 static int updateUB (DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper);
119 static int ddCountRoots (DdManager *table, int lower, int upper);
120 static void ddClearGlobal (DdManager *table, int lower, int maxlevel);
121 static int computeLB (DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level);
122 static int updateEntry (DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper);
123 static void pushDown (DdHalfWord *order, int j, int level);
124 static DdHalfWord * initSymmInfo (DdManager *table, int lower, int upper);
125 static int checkSymmInfo (DdManager *table, DdHalfWord *symmInfo, int index, int level);
126 
127 /**AutomaticEnd***************************************************************/
128 
129 
130 /*---------------------------------------------------------------------------*/
131 /* Definition of exported functions */
132 /*---------------------------------------------------------------------------*/
133 
134 /*---------------------------------------------------------------------------*/
135 /* Definition of internal functions */
136 /*---------------------------------------------------------------------------*/
137 
138 
139 /**Function********************************************************************
140 
141  Synopsis [Exact variable ordering algorithm.]
142 
143  Description [Exact variable ordering algorithm. Finds an optimum
144  order for the variables between lower and upper. Returns 1 if
145  successful; 0 otherwise.]
146 
147  SideEffects [None]
148 
149  SeeAlso []
150 
151 ******************************************************************************/
152 int
154  DdManager * table,
155  int lower,
156  int upper)
157 {
158  int k, i, j;
159  int maxBinomial, oldSubsets, newSubsets;
160  int subsetCost;
161  int size; /* number of variables to be reordered */
162  int unused, nvars, level, result;
163  int upperBound, lowerBound, cost;
164  int roots;
165  char *mask = NULL;
166  DdHalfWord *symmInfo = NULL;
167  DdHalfWord **newOrder = NULL;
168  DdHalfWord **oldOrder = NULL;
169  int *newCost = NULL;
170  int *oldCost = NULL;
171  DdHalfWord **tmpOrder;
172  int *tmpCost;
173  DdHalfWord *bestOrder = NULL;
174  DdHalfWord *order;
175 #ifdef DD_STATS
176  int ddTotalSubsets;
177 #endif
178 
179  /* Restrict the range to be reordered by excluding unused variables
180  ** at the two ends. */
181  while (table->subtables[lower].keys == 1 &&
182  table->vars[table->invperm[lower]]->ref == 1 &&
183  lower < upper)
184  lower++;
185  while (table->subtables[upper].keys == 1 &&
186  table->vars[table->invperm[upper]]->ref == 1 &&
187  lower < upper)
188  upper--;
189  if (lower == upper) return(1); /* trivial problem */
190 
191  /* Apply symmetric sifting to get a good upper bound and to extract
192  ** symmetry information. */
193  result = cuddSymmSiftingConv(table,lower,upper);
194  if (result == 0) goto cuddExactOutOfMem;
195 
196 #ifdef DD_STATS
197  (void) fprintf(table->out,"\n");
198  ddTotalShuffles = 0;
199  ddTotalSubsets = 0;
200 #endif
201 
202  /* Initialization. */
203  nvars = table->size;
204  size = upper - lower + 1;
205  /* Count unused variable among those to be reordered. This is only
206  ** used to compute maxBinomial. */
207  unused = 0;
208  for (i = lower + 1; i < upper; i++) {
209  if (table->subtables[i].keys == 1 &&
210  table->vars[table->invperm[i]]->ref == 1)
211  unused++;
212  }
213 
214  /* Find the maximum number of subsets we may have to store. */
215  maxBinomial = getMaxBinomial(size - unused);
216  if (maxBinomial == -1) goto cuddExactOutOfMem;
217 
218  newOrder = getMatrix(maxBinomial, size);
219  if (newOrder == NULL) goto cuddExactOutOfMem;
220 
221  newCost = ABC_ALLOC(int, maxBinomial);
222  if (newCost == NULL) goto cuddExactOutOfMem;
223 
224  oldOrder = getMatrix(maxBinomial, size);
225  if (oldOrder == NULL) goto cuddExactOutOfMem;
226 
227  oldCost = ABC_ALLOC(int, maxBinomial);
228  if (oldCost == NULL) goto cuddExactOutOfMem;
229 
230  bestOrder = ABC_ALLOC(DdHalfWord, size);
231  if (bestOrder == NULL) goto cuddExactOutOfMem;
232 
233  mask = ABC_ALLOC(char, nvars);
234  if (mask == NULL) goto cuddExactOutOfMem;
235 
236  symmInfo = initSymmInfo(table, lower, upper);
237  if (symmInfo == NULL) goto cuddExactOutOfMem;
238 
239  roots = ddCountRoots(table, lower, upper);
240 
241  /* Initialize the old order matrix for the empty subset and the best
242  ** order to the current order. The cost for the empty subset includes
243  ** the cost of the levels between upper and the constants. These levels
244  ** are not going to change. Hence, we count them only once.
245  */
246  oldSubsets = 1;
247  for (i = 0; i < size; i++) {
248  oldOrder[0][i] = bestOrder[i] = (DdHalfWord) table->invperm[i+lower];
249  }
250  subsetCost = table->constants.keys;
251  for (i = upper + 1; i < nvars; i++)
252  subsetCost += getLevelKeys(table,i);
253  oldCost[0] = subsetCost;
254  /* The upper bound is initialized to the current size of the BDDs. */
255  upperBound = table->keys - table->isolated;
256 
257  /* Now consider subsets of increasing size. */
258  for (k = 1; k <= size; k++) {
259 #ifdef DD_STATS
260  (void) fprintf(table->out,"Processing subsets of size %d\n", k);
261  fflush(table->out);
262 #endif
263  newSubsets = 0;
264  level = size - k; /* offset of first bottom variable */
265 
266  for (i = 0; i < oldSubsets; i++) { /* for each subset of size k-1 */
267  order = oldOrder[i];
268  cost = oldCost[i];
269  lowerBound = computeLB(table, order, roots, cost, lower, upper,
270  level);
271  if (lowerBound >= upperBound)
272  continue;
273  /* Impose new order. */
274  result = ddShuffle(table, order, lower, upper);
275  if (result == 0) goto cuddExactOutOfMem;
276  upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
277  /* For each top bottom variable. */
278  for (j = level; j >= 0; j--) {
279  /* Skip unused variables. */
280  if (table->subtables[j+lower-1].keys == 1 &&
281  table->vars[table->invperm[j+lower-1]]->ref == 1) continue;
282  /* Find cost under this order. */
283  subsetCost = cost + getLevelKeys(table, lower + level);
284  newSubsets = updateEntry(table, order, level, subsetCost,
285  newOrder, newCost, newSubsets, mask,
286  lower, upper);
287  if (j == 0)
288  break;
289  if (checkSymmInfo(table, symmInfo, order[j-1], level) == 0)
290  continue;
291  pushDown(order,j-1,level);
292  /* Impose new order. */
293  result = ddShuffle(table, order, lower, upper);
294  if (result == 0) goto cuddExactOutOfMem;
295  upperBound = updateUB(table,upperBound,bestOrder,lower,upper);
296  } /* for each bottom variable */
297  } /* for each subset of size k */
298 
299  /* New orders become old orders in preparation for next iteration. */
300  tmpOrder = oldOrder; tmpCost = oldCost;
301  oldOrder = newOrder; oldCost = newCost;
302  newOrder = tmpOrder; newCost = tmpCost;
303 #ifdef DD_STATS
304  ddTotalSubsets += newSubsets;
305 #endif
306  oldSubsets = newSubsets;
307  }
308  result = ddShuffle(table, bestOrder, lower, upper);
309  if (result == 0) goto cuddExactOutOfMem;
310 #ifdef DD_STATS
311 #ifdef DD_VERBOSE
312  (void) fprintf(table->out,"\n");
313 #endif
314  (void) fprintf(table->out,"#:S_EXACT %8d: total subsets\n",
315  ddTotalSubsets);
316  (void) fprintf(table->out,"#:H_EXACT %8d: total shuffles",
317  ddTotalShuffles);
318 #endif
319 
320  freeMatrix(newOrder);
321  freeMatrix(oldOrder);
322  ABC_FREE(bestOrder);
323  ABC_FREE(oldCost);
324  ABC_FREE(newCost);
325  ABC_FREE(symmInfo);
326  ABC_FREE(mask);
327  return(1);
328 
329 cuddExactOutOfMem:
330 
331  if (newOrder != NULL) freeMatrix(newOrder);
332  if (oldOrder != NULL) freeMatrix(oldOrder);
333  if (bestOrder != NULL) ABC_FREE(bestOrder);
334  if (oldCost != NULL) ABC_FREE(oldCost);
335  if (newCost != NULL) ABC_FREE(newCost);
336  if (symmInfo != NULL) ABC_FREE(symmInfo);
337  if (mask != NULL) ABC_FREE(mask);
338  table->errorCode = CUDD_MEMORY_OUT;
339  return(0);
340 
341 } /* end of cuddExact */
342 
343 
344 /**Function********************************************************************
345 
346  Synopsis [Returns the maximum value of (n choose k) for a given n.]
347 
348  Description [Computes the maximum value of (n choose k) for a given
349  n. The maximum value occurs for k = n/2 when n is even, or k =
350  (n-1)/2 when n is odd. The algorithm used in this procedure avoids
351  intermediate overflow problems. It is based on the identity
352  <pre>
353  binomial(n,k) = n/k * binomial(n-1,k-1).
354  </pre>
355  Returns the computed value if successful; -1 if out of range.]
356 
357  SideEffects [None]
358 
359  SeeAlso []
360 
361 ******************************************************************************/
362 static int
364  int n)
365 {
366  double i, j, result;
367 
368  if (n < 0 || n > 33) return(-1); /* error */
369  if (n < 2) return(1);
370 
371  for (result = (double)((n+3)/2), i = result+1, j=2; i <= n; i++, j++) {
372  result *= i;
373  result /= j;
374  }
375 
376  return((int)result);
377 
378 } /* end of getMaxBinomial */
379 
380 
381 #if 0
382 /**Function********************************************************************
383 
384  Synopsis [Returns the gcd of two integers.]
385 
386  Description [Returns the gcd of two integers. Uses the binary GCD
387  algorithm described in Cormen, Leiserson, and Rivest.]
388 
389  SideEffects [None]
390 
391  SeeAlso []
392 
393 ******************************************************************************/
394 static int
395 gcd(
396  int x,
397  int y)
398 {
399  int a;
400  int b;
401  int lsbMask;
402 
403  /* GCD(n,0) = n. */
404  if (x == 0) return(y);
405  if (y == 0) return(x);
406 
407  a = x; b = y; lsbMask = 1;
408 
409  /* Here both a and b are != 0. The iteration maintains this invariant.
410  ** Hence, we only need to check for when they become equal.
411  */
412  while (a != b) {
413  if (a & lsbMask) {
414  if (b & lsbMask) { /* both odd */
415  if (a < b) {
416  b = (b - a) >> 1;
417  } else {
418  a = (a - b) >> 1;
419  }
420  } else { /* a odd, b even */
421  b >>= 1;
422  }
423  } else {
424  if (b & lsbMask) { /* a even, b odd */
425  a >>= 1;
426  } else { /* both even */
427  lsbMask <<= 1;
428  }
429  }
430  }
431 
432  return(a);
433 
434 } /* end of gcd */
435 #endif
436 
437 
438 /**Function********************************************************************
439 
440  Synopsis [Allocates a two-dimensional matrix of ints.]
441 
442  Description [Allocates a two-dimensional matrix of ints.
443  Returns the pointer to the matrix if successful; NULL otherwise.]
444 
445  SideEffects [None]
446 
447  SeeAlso [freeMatrix]
448 
449 ******************************************************************************/
450 static DdHalfWord **
452  int rows /* number of rows */,
453  int cols /* number of columns */)
454 {
455  DdHalfWord **matrix;
456  int i;
457 
458  if (cols*rows == 0) return(NULL);
459  matrix = ABC_ALLOC(DdHalfWord *, rows);
460  if (matrix == NULL) return(NULL);
461  matrix[0] = ABC_ALLOC(DdHalfWord, cols*rows);
462  if (matrix[0] == NULL) {
463  ABC_FREE(matrix);
464  return(NULL);
465  }
466  for (i = 1; i < rows; i++) {
467  matrix[i] = matrix[i-1] + cols;
468  }
469  return(matrix);
470 
471 } /* end of getMatrix */
472 
473 
474 /**Function********************************************************************
475 
476  Synopsis [Frees a two-dimensional matrix allocated by getMatrix.]
477 
478  Description []
479 
480  SideEffects [None]
481 
482  SeeAlso [getMatrix]
483 
484 ******************************************************************************/
485 static void
487  DdHalfWord ** matrix)
488 {
489  ABC_FREE(matrix[0]);
490  ABC_FREE(matrix);
491  return;
492 
493 } /* end of freeMatrix */
494 
495 
496 /**Function********************************************************************
497 
498  Synopsis [Returns the number of nodes at one level of a unique table.]
499 
500  Description [Returns the number of nodes at one level of a unique table.
501  The projection function, if isolated, is not counted.]
502 
503  SideEffects [None]
504 
505  SeeAlso []
506 
507 ******************************************************************************/
508 static int
510  DdManager * table,
511  int l)
512 {
513  int isolated;
514  int x; /* x is an index */
515 
516  x = table->invperm[l];
517  isolated = table->vars[x]->ref == 1;
518 
519  return(table->subtables[l].keys - isolated);
520 
521 } /* end of getLevelKeys */
522 
523 
524 /**Function********************************************************************
525 
526  Synopsis [Reorders variables according to a given permutation.]
527 
528  Description [Reorders variables according to a given permutation.
529  The i-th permutation array contains the index of the variable that
530  should be brought to the i-th level. ddShuffle assumes that no
531  dead nodes are present and that the interaction matrix is properly
532  initialized. The reordering is achieved by a series of upward sifts.
533  Returns 1 if successful; 0 otherwise.]
534 
535  SideEffects [None]
536 
537  SeeAlso []
538 
539 ******************************************************************************/
540 static int
542  DdManager * table,
543  DdHalfWord * permutation,
544  int lower,
545  int upper)
546 {
547  DdHalfWord index;
548  int level;
549  int position;
550 #if 0
551  int numvars;
552 #endif
553  int result;
554 #ifdef DD_STATS
555  long localTime;
556  int initialSize;
557 #ifdef DD_VERBOSE
558  int finalSize;
559 #endif
560  int previousSize;
561 #endif
562 
563 #ifdef DD_STATS
564  localTime = util_cpu_time();
565  initialSize = table->keys - table->isolated;
566 #endif
567 
568 #if 0
569  numvars = table->size;
570 
571  (void) fprintf(table->out,"%d:", ddTotalShuffles);
572  for (level = 0; level < numvars; level++) {
573  (void) fprintf(table->out," %d", table->invperm[level]);
574  }
575  (void) fprintf(table->out,"\n");
576 #endif
577 
578  for (level = 0; level <= upper - lower; level++) {
579  index = permutation[level];
580  position = table->perm[index];
581 #ifdef DD_STATS
582  previousSize = table->keys - table->isolated;
583 #endif
584  result = ddSiftUp(table,position,level+lower);
585  if (!result) return(0);
586  }
587 
588 #ifdef DD_STATS
589  ddTotalShuffles++;
590 #ifdef DD_VERBOSE
591  finalSize = table->keys - table->isolated;
592  if (finalSize < initialSize) {
593  (void) fprintf(table->out,"-");
594  } else if (finalSize > initialSize) {
595  (void) fprintf(table->out,"+");
596  } else {
597  (void) fprintf(table->out,"=");
598  }
599  if ((ddTotalShuffles & 63) == 0) (void) fprintf(table->out,"\n");
600  fflush(table->out);
601 #endif
602 #endif
603 
604  return(1);
605 
606 } /* end of ddShuffle */
607 
608 
609 /**Function********************************************************************
610 
611  Synopsis [Moves one variable up.]
612 
613  Description [Takes a variable from position x and sifts it up to
614  position xLow; xLow should be less than or equal to x.
615  Returns 1 if successful; 0 otherwise]
616 
617  SideEffects [None]
618 
619  SeeAlso []
620 
621 ******************************************************************************/
622 static int
624  DdManager * table,
625  int x,
626  int xLow)
627 {
628  int y;
629  int size;
630 
631  y = cuddNextLow(table,x);
632  while (y >= xLow) {
633  size = cuddSwapInPlace(table,y,x);
634  if (size == 0) {
635  return(0);
636  }
637  x = y;
638  y = cuddNextLow(table,x);
639  }
640  return(1);
641 
642 } /* end of ddSiftUp */
643 
644 
645 /**Function********************************************************************
646 
647  Synopsis [Updates the upper bound and saves the best order seen so far.]
648 
649  Description [Updates the upper bound and saves the best order seen so far.
650  Returns the current value of the upper bound.]
651 
652  SideEffects [None]
653 
654  SeeAlso []
655 
656 ******************************************************************************/
657 static int
659  DdManager * table,
660  int oldBound,
661  DdHalfWord * bestOrder,
662  int lower,
663  int upper)
664 {
665  int i;
666  int newBound = table->keys - table->isolated;
667 
668  if (newBound < oldBound) {
669 #ifdef DD_STATS
670  (void) fprintf(table->out,"New upper bound = %d\n", newBound);
671  fflush(table->out);
672 #endif
673  for (i = lower; i <= upper; i++)
674  bestOrder[i-lower] = (DdHalfWord) table->invperm[i];
675  return(newBound);
676  } else {
677  return(oldBound);
678  }
679 
680 } /* end of updateUB */
681 
682 
683 /**Function********************************************************************
684 
685  Synopsis [Counts the number of roots.]
686 
687  Description [Counts the number of roots at the levels between lower and
688  upper. The computation is based on breadth-first search.
689  A node is a root if it is not reachable from any previously visited node.
690  (All the nodes at level lower are therefore considered roots.)
691  The visited flag uses the LSB of the next pointer. Returns the root
692  count. The roots that are constant nodes are always ignored.]
693 
694  SideEffects [None]
695 
696  SeeAlso [ddClearGlobal]
697 
698 ******************************************************************************/
699 static int
701  DdManager * table,
702  int lower,
703  int upper)
704 {
705  int i,j;
706  DdNode *f;
707  DdNodePtr *nodelist;
708  DdNode *sentinel = &(table->sentinel);
709  int slots;
710  int roots = 0;
711  int maxlevel = lower;
712 
713  for (i = lower; i <= upper; i++) {
714  nodelist = table->subtables[i].nodelist;
715  slots = table->subtables[i].slots;
716  for (j = 0; j < slots; j++) {
717  f = nodelist[j];
718  while (f != sentinel) {
719  /* A node is a root of the DAG if it cannot be
720  ** reached by nodes above it. If a node was never
721  ** reached during the previous depth-first searches,
722  ** then it is a root, and we start a new depth-first
723  ** search from it.
724  */
725  if (!Cudd_IsComplement(f->next)) {
726  if (f != table->vars[f->index]) {
727  roots++;
728  }
729  }
730  if (!Cudd_IsConstant(cuddT(f))) {
731  cuddT(f)->next = Cudd_Complement(cuddT(f)->next);
732  if (table->perm[cuddT(f)->index] > maxlevel)
733  maxlevel = table->perm[cuddT(f)->index];
734  }
735  if (!Cudd_IsConstant(cuddE(f))) {
736  Cudd_Regular(cuddE(f))->next =
738  if (table->perm[Cudd_Regular(cuddE(f))->index] > maxlevel)
739  maxlevel = table->perm[Cudd_Regular(cuddE(f))->index];
740  }
741  f = Cudd_Regular(f->next);
742  }
743  }
744  }
745  ddClearGlobal(table, lower, maxlevel);
746 
747  return(roots);
748 
749 } /* end of ddCountRoots */
750 
751 
752 /**Function********************************************************************
753 
754  Synopsis [Scans the DD and clears the LSB of the next pointers.]
755 
756  Description [Scans the DD and clears the LSB of the next pointers.
757  The LSB of the next pointers are used as markers to tell whether a
758  node was reached. Once the roots are counted, these flags are
759  reset.]
760 
761  SideEffects [None]
762 
763  SeeAlso [ddCountRoots]
764 
765 ******************************************************************************/
766 static void
768  DdManager * table,
769  int lower,
770  int maxlevel)
771 {
772  int i,j;
773  DdNode *f;
774  DdNodePtr *nodelist;
775  DdNode *sentinel = &(table->sentinel);
776  int slots;
777 
778  for (i = lower; i <= maxlevel; i++) {
779  nodelist = table->subtables[i].nodelist;
780  slots = table->subtables[i].slots;
781  for (j = 0; j < slots; j++) {
782  f = nodelist[j];
783  while (f != sentinel) {
784  f->next = Cudd_Regular(f->next);
785  f = f->next;
786  }
787  }
788  }
789 
790 } /* end of ddClearGlobal */
791 
792 
793 /**Function********************************************************************
794 
795  Synopsis [Computes a lower bound on the size of a BDD.]
796 
797  Description [Computes a lower bound on the size of a BDD from the
798  following factors:
799  <ul>
800  <li> size of the lower part of it;
801  <li> size of the part of the upper part not subjected to reordering;
802  <li> number of roots in the part of the BDD subjected to reordering;
803  <li> variable in the support of the roots in the upper part of the
804  BDD subjected to reordering.
805  <ul/>]
806 
807  SideEffects [None]
808 
809  SeeAlso []
810 
811 ******************************************************************************/
812 static int
814  DdManager * table /* manager */,
815  DdHalfWord * order /* optimal order for the subset */,
816  int roots /* roots between lower and upper */,
817  int cost /* minimum cost for the subset */,
818  int lower /* lower level to be reordered */,
819  int upper /* upper level to be reordered */,
820  int level /* offset for the current top bottom var */
821  )
822 {
823  int i;
824  int lb = cost;
825  int lb1 = 0;
826  int lb2;
827  int support;
828  DdHalfWord ref;
829 
830  /* The levels not involved in reordering are not going to change.
831  ** Add their sizes to the lower bound.
832  */
833  for (i = 0; i < lower; i++) {
834  lb += getLevelKeys(table,i);
835  }
836  /* If a variable is in the support, then there is going
837  ** to be at least one node labeled by that variable.
838  */
839  for (i = lower; i <= lower+level; i++) {
840  support = table->subtables[i].keys > 1 ||
841  table->vars[order[i-lower]]->ref > 1;
842  lb1 += support;
843  }
844 
845  /* Estimate the number of nodes required to connect the roots to
846  ** the nodes in the bottom part. */
847  if (lower+level+1 < table->size) {
848  if (lower+level < upper)
849  ref = table->vars[order[level+1]]->ref;
850  else
851  ref = table->vars[table->invperm[upper+1]]->ref;
852  lb2 = table->subtables[lower+level+1].keys -
853  (ref > (DdHalfWord) 1) - roots;
854  } else {
855  lb2 = 0;
856  }
857 
858  lb += lb1 > lb2 ? lb1 : lb2;
859 
860  return(lb);
861 
862 } /* end of computeLB */
863 
864 
865 /**Function********************************************************************
866 
867  Synopsis [Updates entry for a subset.]
868 
869  Description [Updates entry for a subset. Finds the subset, if it exists.
870  If the new order for the subset has lower cost, or if the subset did not
871  exist, it stores the new order and cost. Returns the number of subsets
872  currently in the table.]
873 
874  SideEffects [None]
875 
876  SeeAlso []
877 
878 ******************************************************************************/
879 static int
881  DdManager * table,
882  DdHalfWord * order,
883  int level,
884  int cost,
885  DdHalfWord ** orders,
886  int * costs,
887  int subsets,
888  char * mask,
889  int lower,
890  int upper)
891 {
892  int i, j;
893  int size = upper - lower + 1;
894 
895  /* Build a mask that says what variables are in this subset. */
896  for (i = lower; i <= upper; i++)
897  mask[table->invperm[i]] = 0;
898  for (i = level; i < size; i++)
899  mask[order[i]] = 1;
900 
901  /* Check each subset until a match is found or all subsets are examined. */
902  for (i = 0; i < subsets; i++) {
903  DdHalfWord *subset = orders[i];
904  for (j = level; j < size; j++) {
905  if (mask[subset[j]] == 0)
906  break;
907  }
908  if (j == size) /* no mismatches: success */
909  break;
910  }
911  if (i == subsets || cost < costs[i]) { /* add or replace */
912  for (j = 0; j < size; j++)
913  orders[i][j] = order[j];
914  costs[i] = cost;
915  subsets += (i == subsets);
916  }
917  return(subsets);
918 
919 } /* end of updateEntry */
920 
921 
922 /**Function********************************************************************
923 
924  Synopsis [Pushes a variable in the order down to position "level."]
925 
926  Description []
927 
928  SideEffects [None]
929 
930  SeeAlso []
931 
932 ******************************************************************************/
933 static void
935  DdHalfWord * order,
936  int j,
937  int level)
938 {
939  int i;
940  DdHalfWord tmp;
941 
942  tmp = order[j];
943  for (i = j; i < level; i++) {
944  order[i] = order[i+1];
945  }
946  order[level] = tmp;
947  return;
948 
949 } /* end of pushDown */
950 
951 
952 /**Function********************************************************************
953 
954  Synopsis [Gathers symmetry information.]
955 
956  Description [Translates the symmetry information stored in the next
957  field of each subtable from level to indices. This procedure is called
958  immediately after symmetric sifting, so that the next fields are correct.
959  By translating this informaton in terms of indices, we make it independent
960  of subsequent reorderings. The format used is that of the next fields:
961  a circular list where each variable points to the next variable in the
962  same symmetry group. Only the entries between lower and upper are
963  considered. The procedure returns a pointer to an array
964  holding the symmetry information if successful; NULL otherwise.]
965 
966  SideEffects [None]
967 
968  SeeAlso [checkSymmInfo]
969 
970 ******************************************************************************/
971 static DdHalfWord *
973  DdManager * table,
974  int lower,
975  int upper)
976 {
977  int level, index, next, nextindex;
978  DdHalfWord *symmInfo;
979 
980  symmInfo = ABC_ALLOC(DdHalfWord, table->size);
981  if (symmInfo == NULL) return(NULL);
982 
983  for (level = lower; level <= upper; level++) {
984  index = table->invperm[level];
985  next = table->subtables[level].next;
986  nextindex = table->invperm[next];
987  symmInfo[index] = nextindex;
988  }
989  return(symmInfo);
990 
991 } /* end of initSymmInfo */
992 
993 
994 /**Function********************************************************************
995 
996  Synopsis [Check symmetry condition.]
997 
998  Description [Returns 1 if a variable is the one with the highest index
999  among those belonging to a symmetry group that are in the top part of
1000  the BDD. The top part is given by level.]
1001 
1002  SideEffects [None]
1003 
1004  SeeAlso [initSymmInfo]
1005 
1006 ******************************************************************************/
1007 static int
1009  DdManager * table,
1010  DdHalfWord * symmInfo,
1011  int index,
1012  int level)
1013 {
1014  int i;
1015 
1016  i = symmInfo[index];
1017  while (i != index) {
1018  if (index < i && table->perm[i] <= level)
1019  return(0);
1020  i = symmInfo[i];
1021  }
1022  return(1);
1023 
1024 } /* end of checkSymmInfo */
1025 
1026 
1028 
DdHalfWord ref
Definition: cudd.h:280
unsigned int keys
Definition: cuddInt.h:330
int cuddExact(DdManager *table, int lower, int upper)
Definition: cuddExact.c:153
unsigned short DdHalfWord
Definition: cudd.h:262
static int ddShuffle(DdManager *table, DdHalfWord *permutation, int lower, int upper)
Definition: cuddExact.c:541
static int computeLB(DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level)
Definition: cuddExact.c:813
static void ddClearGlobal(DdManager *table, int lower, int maxlevel)
Definition: cuddExact.c:767
Definition: cudd.h:278
static void freeMatrix(DdHalfWord **matrix)
Definition: cuddExact.c:486
static int getMaxBinomial(int n)
Definition: cuddExact.c:363
static ABC_NAMESPACE_IMPL_START char rcsid[] DD_UNUSED
Definition: cuddExact.c:95
int size
Definition: cuddInt.h:361
static int getLevelKeys(DdManager *table, int l)
Definition: cuddExact.c:509
#define Cudd_IsConstant(node)
Definition: cudd.h:352
#define Cudd_Regular(node)
Definition: cudd.h:397
int cuddNextLow(DdManager *table, int x)
Definition: cuddReorder.c:738
static void pushDown(DdHalfWord *order, int j, int level)
Definition: cuddExact.c:934
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
DdSubtable * subtables
Definition: cuddInt.h:365
#define util_cpu_time
Definition: util_hack.h:36
for(p=first;p->value< newval;p=p->next)
static int updateUB(DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper)
Definition: cuddExact.c:658
int cuddSymmSiftingConv(DdManager *table, int lower, int upper)
Definition: cuddSymmetry.c:442
#define Cudd_IsComplement(node)
Definition: cudd.h:425
DdNode sentinel
Definition: cuddInt.h:344
unsigned int keys
Definition: cuddInt.h:369
FILE * out
Definition: cuddInt.h:441
static DdHalfWord ** getMatrix(int rows, int cols)
Definition: cuddExact.c:451
static int numvars
Definition: cuddGenetic.c:111
DdNode * next
Definition: cudd.h:281
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
DdNode ** nodelist
Definition: cuddInt.h:327
static int checkSymmInfo(DdManager *table, DdHalfWord *symmInfo, int index, int level)
Definition: cuddExact.c:1008
static int size
Definition: cuddSign.c:86
#define Cudd_Complement(node)
Definition: cudd.h:411
#define cuddT(node)
Definition: cuddInt.h:636
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
static int ddCountRoots(DdManager *table, int lower, int upper)
Definition: cuddExact.c:700
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
static DdHalfWord * initSymmInfo(DdManager *table, int lower, int upper)
Definition: cuddExact.c:972
static int updateEntry(DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper)
Definition: cuddExact.c:880
DdHalfWord index
Definition: cudd.h:279
#define ABC_FREE(obj)
Definition: abc_global.h:232
unsigned int slots
Definition: cuddInt.h:329
DdNode ** vars
Definition: cuddInt.h:390
struct TlClause * next
Definition: cuddEssent.c:135
unsigned int next
Definition: cuddInt.h:333
#define cuddE(node)
Definition: cuddInt.h:652
int * invperm
Definition: cuddInt.h:388
static int ddSiftUp(DdManager *table, int x, int xLow)
Definition: cuddExact.c:623
DdSubtable constants
Definition: cuddInt.h:367
static int result
Definition: cuddGenetic.c:125
int isolated
Definition: cuddInt.h:385
int * perm
Definition: cuddInt.h:386
Cudd_ErrorType errorCode
Definition: cuddInt.h:447