abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cuddExact.c File Reference
#include "misc/util/util_hack.h"
#include "cuddInt.h"

Go to the source code of this file.

Functions

static int getMaxBinomial (int n)
 
static DdHalfWord ** getMatrix (int rows, int cols)
 
static void freeMatrix (DdHalfWord **matrix)
 
static int getLevelKeys (DdManager *table, int l)
 
static int ddShuffle (DdManager *table, DdHalfWord *permutation, int lower, int upper)
 
static int ddSiftUp (DdManager *table, int x, int xLow)
 
static int updateUB (DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper)
 
static int ddCountRoots (DdManager *table, int lower, int upper)
 
static void ddClearGlobal (DdManager *table, int lower, int maxlevel)
 
static int computeLB (DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level)
 
static int updateEntry (DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper)
 
static void pushDown (DdHalfWord *order, int j, int level)
 
static DdHalfWordinitSymmInfo (DdManager *table, int lower, int upper)
 
static int checkSymmInfo (DdManager *table, DdHalfWord *symmInfo, int index, int level)
 
int cuddExact (DdManager *table, int lower, int upper)
 

Variables

static
ABC_NAMESPACE_IMPL_START char
rcsid[] 
DD_UNUSED = "$Id: cuddExact.c,v 1.28 2009/02/19 16:19:19 fabio Exp $"
 

Function Documentation

static int checkSymmInfo ( DdManager table,
DdHalfWord symmInfo,
int  index,
int  level 
)
static

Function********************************************************************

Synopsis [Check symmetry condition.]

Description [Returns 1 if a variable is the one with the highest index among those belonging to a symmetry group that are in the top part of the BDD. The top part is given by level.]

SideEffects [None]

SeeAlso [initSymmInfo]

Definition at line 1008 of file cuddExact.c.

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 */
static int computeLB ( DdManager table,
DdHalfWord order,
int  roots,
int  cost,
int  lower,
int  upper,
int  level 
)
static

Function********************************************************************

Synopsis [Computes a lower bound on the size of a BDD.]

Description [Computes a lower bound on the size of a BDD from the following factors:

  • size of the lower part of it;
  • size of the part of the upper part not subjected to reordering;
  • number of roots in the part of the BDD subjected to reordering;
  • variable in the support of the roots in the upper part of the BDD subjected to reordering.

    SideEffects [None]

    SeeAlso []

Definition at line 813 of file cuddExact.c.

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 */
DdHalfWord ref
Definition: cudd.h:280
unsigned int keys
Definition: cuddInt.h:330
unsigned short DdHalfWord
Definition: cudd.h:262
int size
Definition: cuddInt.h:361
static int getLevelKeys(DdManager *table, int l)
Definition: cuddExact.c:509
DdSubtable * subtables
Definition: cuddInt.h:365
int support
Definition: abcSaucy.c:64
DdNode ** vars
Definition: cuddInt.h:390
int * invperm
Definition: cuddInt.h:388
int cuddExact ( DdManager table,
int  lower,
int  upper 
)

AutomaticEnd Function********************************************************************

Synopsis [Exact variable ordering algorithm.]

Description [Exact variable ordering algorithm. Finds an optimum order for the variables between lower and upper. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 153 of file cuddExact.c.

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 */
DdHalfWord ref
Definition: cudd.h:280
unsigned int keys
Definition: cuddInt.h:330
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 freeMatrix(DdHalfWord **matrix)
Definition: cuddExact.c:486
static int getMaxBinomial(int n)
Definition: cuddExact.c:363
int size
Definition: cuddInt.h:361
static int getLevelKeys(DdManager *table, int l)
Definition: cuddExact.c:509
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
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
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 checkSymmInfo(DdManager *table, DdHalfWord *symmInfo, int index, int level)
Definition: cuddExact.c:1008
static int size
Definition: cuddSign.c:86
static int ddCountRoots(DdManager *table, int lower, int upper)
Definition: cuddExact.c:700
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
#define ABC_FREE(obj)
Definition: abc_global.h:232
DdNode ** vars
Definition: cuddInt.h:390
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
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
static void ddClearGlobal ( DdManager table,
int  lower,
int  maxlevel 
)
static

Function********************************************************************

Synopsis [Scans the DD and clears the LSB of the next pointers.]

Description [Scans the DD and clears the LSB of the next pointers. The LSB of the next pointers are used as markers to tell whether a node was reached. Once the roots are counted, these flags are reset.]

SideEffects [None]

SeeAlso [ddCountRoots]

Definition at line 767 of file cuddExact.c.

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 */
Definition: cudd.h:278
#define Cudd_Regular(node)
Definition: cudd.h:397
DdSubtable * subtables
Definition: cuddInt.h:365
DdNode sentinel
Definition: cuddInt.h:344
DdNode * next
Definition: cudd.h:281
DdNode ** nodelist
Definition: cuddInt.h:327
unsigned int slots
Definition: cuddInt.h:329
static int ddCountRoots ( DdManager table,
int  lower,
int  upper 
)
static

Function********************************************************************

Synopsis [Counts the number of roots.]

Description [Counts the number of roots at the levels between lower and upper. The computation is based on breadth-first search. A node is a root if it is not reachable from any previously visited node. (All the nodes at level lower are therefore considered roots.) The visited flag uses the LSB of the next pointer. Returns the root count. The roots that are constant nodes are always ignored.]

SideEffects [None]

SeeAlso [ddClearGlobal]

Definition at line 700 of file cuddExact.c.

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 */
static void ddClearGlobal(DdManager *table, int lower, int maxlevel)
Definition: cuddExact.c:767
Definition: cudd.h:278
#define Cudd_IsConstant(node)
Definition: cudd.h:352
#define Cudd_Regular(node)
Definition: cudd.h:397
DdSubtable * subtables
Definition: cuddInt.h:365
#define Cudd_IsComplement(node)
Definition: cudd.h:425
DdNode sentinel
Definition: cuddInt.h:344
DdNode * next
Definition: cudd.h:281
DdNode ** nodelist
Definition: cuddInt.h:327
#define Cudd_Complement(node)
Definition: cudd.h:411
#define cuddT(node)
Definition: cuddInt.h:636
DdHalfWord index
Definition: cudd.h:279
unsigned int slots
Definition: cuddInt.h:329
DdNode ** vars
Definition: cuddInt.h:390
#define cuddE(node)
Definition: cuddInt.h:652
int * perm
Definition: cuddInt.h:386
static int ddShuffle ( DdManager table,
DdHalfWord permutation,
int  lower,
int  upper 
)
static

Function********************************************************************

Synopsis [Reorders variables according to a given permutation.]

Description [Reorders variables according to a given permutation. The i-th permutation array contains the index of the variable that should be brought to the i-th level. ddShuffle assumes that no dead nodes are present and that the interaction matrix is properly initialized. The reordering is achieved by a series of upward sifts. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 541 of file cuddExact.c.

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 */
unsigned short DdHalfWord
Definition: cudd.h:262
int size
Definition: cuddInt.h:361
#define util_cpu_time
Definition: util_hack.h:36
unsigned int keys
Definition: cuddInt.h:369
FILE * out
Definition: cuddInt.h:441
static int numvars
Definition: cuddGenetic.c:111
int * invperm
Definition: cuddInt.h:388
static int ddSiftUp(DdManager *table, int x, int xLow)
Definition: cuddExact.c:623
static int result
Definition: cuddGenetic.c:125
int isolated
Definition: cuddInt.h:385
int * perm
Definition: cuddInt.h:386
static int ddSiftUp ( DdManager table,
int  x,
int  xLow 
)
static

Function********************************************************************

Synopsis [Moves one variable up.]

Description [Takes a variable from position x and sifts it up to position xLow; xLow should be less than or equal to x. Returns 1 if successful; 0 otherwise]

SideEffects [None]

SeeAlso []

Definition at line 623 of file cuddExact.c.

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 */
int cuddNextLow(DdManager *table, int x)
Definition: cuddReorder.c:738
static int size
Definition: cuddSign.c:86
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
static void freeMatrix ( DdHalfWord **  matrix)
static

Function********************************************************************

Synopsis [Frees a two-dimensional matrix allocated by getMatrix.]

Description []

SideEffects [None]

SeeAlso [getMatrix]

Definition at line 486 of file cuddExact.c.

488 {
489  ABC_FREE(matrix[0]);
490  ABC_FREE(matrix);
491  return;
492 
493 } /* end of freeMatrix */
#define ABC_FREE(obj)
Definition: abc_global.h:232
static int getLevelKeys ( DdManager table,
int  l 
)
static

Function********************************************************************

Synopsis [Returns the number of nodes at one level of a unique table.]

Description [Returns the number of nodes at one level of a unique table. The projection function, if isolated, is not counted.]

SideEffects [None]

SeeAlso []

Definition at line 509 of file cuddExact.c.

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 */
DdHalfWord ref
Definition: cudd.h:280
unsigned int keys
Definition: cuddInt.h:330
DdSubtable * subtables
Definition: cuddInt.h:365
DdNode ** vars
Definition: cuddInt.h:390
int * invperm
Definition: cuddInt.h:388
static DdHalfWord ** getMatrix ( int  rows,
int  cols 
)
static

Function********************************************************************

Synopsis [Allocates a two-dimensional matrix of ints.]

Description [Allocates a two-dimensional matrix of ints. Returns the pointer to the matrix if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [freeMatrix]

Definition at line 451 of file cuddExact.c.

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 */
unsigned short DdHalfWord
Definition: cudd.h:262
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
#define ABC_FREE(obj)
Definition: abc_global.h:232
static int getMaxBinomial ( int  n)
static

AutomaticStart

Function********************************************************************

Synopsis [Returns the maximum value of (n choose k) for a given n.]

Description [Computes the maximum value of (n choose k) for a given n. The maximum value occurs for k = n/2 when n is even, or k = (n-1)/2 when n is odd. The algorithm used in this procedure avoids intermediate overflow problems. It is based on the identity

  binomial(n,k) = n/k * binomial(n-1,k-1).

Returns the computed value if successful; -1 if out of range.]

SideEffects [None]

SeeAlso []

Definition at line 363 of file cuddExact.c.

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 */
static int result
Definition: cuddGenetic.c:125
static DdHalfWord * initSymmInfo ( DdManager table,
int  lower,
int  upper 
)
static

Function********************************************************************

Synopsis [Gathers symmetry information.]

Description [Translates the symmetry information stored in the next field of each subtable from level to indices. This procedure is called immediately after symmetric sifting, so that the next fields are correct. By translating this informaton in terms of indices, we make it independent of subsequent reorderings. The format used is that of the next fields: a circular list where each variable points to the next variable in the same symmetry group. Only the entries between lower and upper are considered. The procedure returns a pointer to an array holding the symmetry information if successful; NULL otherwise.]

SideEffects [None]

SeeAlso [checkSymmInfo]

Definition at line 972 of file cuddExact.c.

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 */
unsigned short DdHalfWord
Definition: cudd.h:262
int size
Definition: cuddInt.h:361
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
DdSubtable * subtables
Definition: cuddInt.h:365
unsigned int next
Definition: cuddInt.h:333
int * invperm
Definition: cuddInt.h:388
static void pushDown ( DdHalfWord order,
int  j,
int  level 
)
static

Function********************************************************************

Synopsis [Pushes a variable in the order down to position "level."]

Description []

SideEffects [None]

SeeAlso []

Definition at line 934 of file cuddExact.c.

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 */
unsigned short DdHalfWord
Definition: cudd.h:262
static int updateEntry ( DdManager table,
DdHalfWord order,
int  level,
int  cost,
DdHalfWord **  orders,
int *  costs,
int  subsets,
char *  mask,
int  lower,
int  upper 
)
static

Function********************************************************************

Synopsis [Updates entry for a subset.]

Description [Updates entry for a subset. Finds the subset, if it exists. If the new order for the subset has lower cost, or if the subset did not exist, it stores the new order and cost. Returns the number of subsets currently in the table.]

SideEffects [None]

SeeAlso []

Definition at line 880 of file cuddExact.c.

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 */
unsigned short DdHalfWord
Definition: cudd.h:262
for(p=first;p->value< newval;p=p->next)
static int size
Definition: cuddSign.c:86
int * invperm
Definition: cuddInt.h:388
static int updateUB ( DdManager table,
int  oldBound,
DdHalfWord bestOrder,
int  lower,
int  upper 
)
static

Function********************************************************************

Synopsis [Updates the upper bound and saves the best order seen so far.]

Description [Updates the upper bound and saves the best order seen so far. Returns the current value of the upper bound.]

SideEffects [None]

SeeAlso []

Definition at line 658 of file cuddExact.c.

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 */
unsigned short DdHalfWord
Definition: cudd.h:262
unsigned int keys
Definition: cuddInt.h:369
FILE * out
Definition: cuddInt.h:441
int * invperm
Definition: cuddInt.h:388
int isolated
Definition: cuddInt.h:385

Variable Documentation

ABC_NAMESPACE_IMPL_START char rcsid [] DD_UNUSED = "$Id: cuddExact.c,v 1.28 2009/02/19 16:19:19 fabio Exp $"
static

CFile***********************************************************************

FileName [cuddExact.c]

PackageName [cudd]

Synopsis [Functions for exact variable reordering.]

Description [External procedures included in this file:

Internal procedures included in this module:

Static procedures included in this module:

]

Author [Cheng Hua, Fabio Somenzi]

Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]

Definition at line 95 of file cuddExact.c.