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

Go to the source code of this file.

Macros

#define DD_MAX_SUBTABLE_SPARSITY   8
 
#define DD_SHRINK_FACTOR   2
 

Functions

static MovezddSwapAny (DdManager *table, int x, int y)
 
static int cuddZddSiftingAux (DdManager *table, int x, int x_low, int x_high)
 
static MovecuddZddSiftingUp (DdManager *table, int x, int x_low, int initial_size)
 
static MovecuddZddSiftingDown (DdManager *table, int x, int x_high, int initial_size)
 
static int cuddZddSiftingBackward (DdManager *table, Move *moves, int size)
 
static void zddReorderPreprocess (DdManager *table)
 
static int zddReorderPostprocess (DdManager *table)
 
static int zddShuffle (DdManager *table, int *permutation)
 
static int zddSiftUp (DdManager *table, int x, int xLow)
 
static void zddFixTree (DdManager *table, MtrNode *treenode)
 
int Cudd_zddReduceHeap (DdManager *table, Cudd_ReorderingType heuristic, int minsize)
 
int Cudd_zddShuffleHeap (DdManager *table, int *permutation)
 
int cuddZddAlignToBdd (DdManager *table)
 
int cuddZddNextHigh (DdManager *table, int x)
 
int cuddZddNextLow (DdManager *table, int x)
 
int cuddZddUniqueCompare (int *ptr_x, int *ptr_y)
 
int cuddZddSwapInPlace (DdManager *table, int x, int y)
 
int cuddZddSwapping (DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
 
int cuddZddSifting (DdManager *table, int lower, int upper)
 

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.47 2004/08/13 18:04:53 fabio Exp $"
 
int * zdd_entry
 
int zddTotalNumberSwapping
 
static DdNodeempty
 

Macro Definition Documentation

#define DD_MAX_SUBTABLE_SPARSITY   8

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

FileName [cuddZddReord.c]

PackageName [cudd]

Synopsis [Procedures for dynamic variable ordering of ZDDs.]

Description [External procedures included in this module:

Internal procedures included in this module:

Static procedures included in this module:

]

SeeAlso []

Author [Hyong-Kyoon Shin, In-Ho Moon]

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 87 of file cuddZddReord.c.

#define DD_SHRINK_FACTOR   2

Definition at line 88 of file cuddZddReord.c.

Function Documentation

int Cudd_zddReduceHeap ( DdManager table,
Cudd_ReorderingType  heuristic,
int  minsize 
)

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

Synopsis [Main dynamic reordering routine for ZDDs.]

Description [Main dynamic reordering routine for ZDDs. Calls one of the possible reordering procedures:

  • Swapping
  • Sifting
  • Symmetric Sifting

For sifting and symmetric sifting it is possible to request reordering to convergence.

The core of all methods is the reordering procedure cuddZddSwapInPlace() which swaps two adjacent variables. Returns 1 in case of success; 0 otherwise. In the case of symmetric sifting (with and without convergence) returns 1 plus the number of symmetric variables, in case of success.]

SideEffects [Changes the variable order for all ZDDs and clears the cache.]

Definition at line 171 of file cuddZddReord.c.

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 */
long reordTime
Definition: cuddInt.h:454
unsigned int deadZ
Definition: cuddInt.h:372
DdHook * preReorderingHook
Definition: cuddInt.h:439
static void zddReorderPreprocess(DdManager *table)
DdNode * zero
Definition: cuddInt.h:346
FILE * err
Definition: cuddInt.h:442
Cudd_ReorderingType autoMethodZ
Definition: cuddInt.h:419
#define DD_DYN_RATIO
Definition: cuddInt.h:152
#define util_cpu_time
Definition: util_hack.h:36
DD_HFP f
Definition: cuddInt.h:246
static DdNode * empty
Definition: cuddZddReord.c:112
int reordered
Definition: cuddInt.h:409
unsigned int nextDyn
Definition: cuddInt.h:422
DdHook * postReorderingHook
Definition: cuddInt.h:440
int zddTotalNumberSwapping
Definition: cuddZddReord.c:110
FILE * out
Definition: cuddInt.h:441
int realignZ
Definition: cuddInt.h:421
static int zddReorderPostprocess(DdManager *table)
int reorderings
Definition: cuddInt.h:410
struct DdHook * next
Definition: cuddInt.h:247
int cuddZddTreeSifting(DdManager *table, Cudd_ReorderingType method)
Definition: cuddZddGroup.c:232
static int result
Definition: cuddGenetic.c:125
int cuddBddAlignToZdd(DdManager *table)
Definition: cuddReorder.c:1251
unsigned int keysZ
Definition: cuddInt.h:370
int Cudd_zddShuffleHeap ( DdManager table,
int *  permutation 
)

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

Synopsis [Reorders ZDD variables according to given permutation.]

Description [Reorders ZDD variables according to given permutation. The i-th entry of the permutation array contains the index of the variable that should be brought to the i-th level. The size of the array should be equal or greater to the number of variables currently in use. Returns 1 in case of success; 0 otherwise.]

SideEffects [Changes the ZDD variable order for all diagrams and clears the cache.]

SeeAlso [Cudd_zddReduceHeap]

Definition at line 304 of file cuddZddReord.c.

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 */
static void zddReorderPreprocess(DdManager *table)
DdNode * zero
Definition: cuddInt.h:346
static DdNode * empty
Definition: cuddZddReord.c:112
static int zddReorderPostprocess(DdManager *table)
static int result
Definition: cuddGenetic.c:125
static int zddShuffle(DdManager *table, int *permutation)
int cuddZddAlignToBdd ( DdManager table)

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

Synopsis [Reorders ZDD variables according to the order of the BDD variables.]

Description [Reorders ZDD variables according to the order of the BDD variables. This function can be called at the end of BDD reordering to insure that the order of the ZDD variables is consistent with the order of the BDD variables. The number of ZDD variables must be a multiple of the number of BDD variables. Let M be the ratio of the two numbers. cuddZddAlignToBdd then considers the ZDD variables from M*i to (M+1)*i-1 as corresponding to BDD variable i. This function should be normally called from Cudd_ReduceHeap, which clears the cache. Returns 1 in case of success; 0 otherwise.]

SideEffects [Changes the ZDD variable order for all diagrams and performs garbage collection of the ZDD unique table.]

SeeAlso [Cudd_zddShuffleHeap Cudd_ReduceHeap]

Definition at line 352 of file cuddZddReord.c.

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 */
int * invpermZ
Definition: cuddInt.h:389
int size
Definition: cuddInt.h:361
DdNode * zero
Definition: cuddInt.h:346
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
int * permZ
Definition: cuddInt.h:387
word M(word f1, word f2, int n)
Definition: kitPerm.c:240
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:729
static DdNode * empty
Definition: cuddZddReord.c:112
int sizeZ
Definition: cuddInt.h:362
#define ABC_FREE(obj)
Definition: abc_global.h:232
MtrNode * treeZ
Definition: cuddInt.h:425
int * invperm
Definition: cuddInt.h:388
static int result
Definition: cuddGenetic.c:125
static void zddFixTree(DdManager *table, MtrNode *treenode)
static int zddShuffle(DdManager *table, int *permutation)
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
int cuddZddNextHigh ( DdManager table,
int  x 
)

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

Synopsis [Finds the next subtable with a larger index.]

Description [Finds the next subtable with a larger index. Returns the index.]

SideEffects [None]

SeeAlso []

Definition at line 413 of file cuddZddReord.c.

416 {
417  return(x + 1);
418 
419 } /* end of cuddZddNextHigh */
int cuddZddNextLow ( DdManager table,
int  x 
)

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

Synopsis [Finds the next subtable with a smaller index.]

Description [Finds the next subtable with a smaller index. Returns the index.]

SideEffects [None]

SeeAlso []

Definition at line 435 of file cuddZddReord.c.

438 {
439  return(x - 1);
440 
441 } /* end of cuddZddNextLow */
int cuddZddSifting ( DdManager table,
int  lower,
int  upper 
)

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

Synopsis [Implementation of Rudell's sifting algorithm.]

Description [Implementation of Rudell's sifting algorithm. Assumes that no dead nodes are present.

  1. Order all the variables according to the number of entries in each unique table.
  2. Sift the variable up and down, remembering each time the total size of the DD heap.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.

Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 867 of file cuddZddReord.c.

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 */
unsigned int keys
Definition: cuddInt.h:330
int siftMaxSwap
Definition: cuddInt.h:412
int(* DD_QSFP)(const void *, const void *)
Definition: cudd.h:326
int var(Lit p)
Definition: SolverTypes.h:62
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
int * permZ
Definition: cuddInt.h:387
static int cuddZddSiftingAux(DdManager *table, int x, int x_low, int x_high)
int zddTotalNumberSwapping
Definition: cuddZddReord.c:110
FILE * out
Definition: cuddInt.h:441
static int size
Definition: cuddSign.c:86
#define ddMin(x, y)
Definition: cuddInt.h:818
int cuddZddUniqueCompare(int *ptr_x, int *ptr_y)
Definition: cuddZddReord.c:459
int siftMaxVar
Definition: cuddInt.h:411
int sizeZ
Definition: cuddInt.h:362
#define ABC_FREE(obj)
Definition: abc_global.h:232
static int result
Definition: cuddGenetic.c:125
unsigned int keysZ
Definition: cuddInt.h:370
int * zdd_entry
Definition: cuddZddReord.c:108
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
DdSubtable * subtableZ
Definition: cuddInt.h:366
static int cuddZddSiftingAux ( DdManager table,
int  x,
int  x_low,
int  x_high 
)
static

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

Synopsis [Given xLow <= x <= xHigh moves x up and down between the boundaries.]

Description [Given xLow <= x <= xHigh moves x up and down between the boundaries. Finds the best position and does the required changes. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 1117 of file cuddZddReord.c.

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 */
static Move * cuddZddSiftingUp(DdManager *table, int x, int x_low, int initial_size)
unsigned int keys
Definition: cuddInt.h:330
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
static Move * cuddZddSiftingDown(DdManager *table, int x, int x_high, int initial_size)
Definition: cuddInt.h:492
DdHalfWord x
Definition: cuddInt.h:493
static int cuddZddSiftingBackward(DdManager *table, Move *moves, int size)
DdHalfWord y
Definition: cuddInt.h:494
struct Move * next
Definition: cuddInt.h:497
#define assert(ex)
Definition: util_old.h:213
static int result
Definition: cuddGenetic.c:125
unsigned int keysZ
Definition: cuddInt.h:370
DdSubtable * subtableZ
Definition: cuddInt.h:366
static int cuddZddSiftingBackward ( DdManager table,
Move moves,
int  size 
)
static

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

Synopsis [Given a set of moves, returns the ZDD heap to the position giving the minimum size.]

Description [Given a set of moves, returns the ZDD heap to the position giving the minimum size. In case of ties, returns to the closest position giving the minimum size. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 1364 of file cuddZddReord.c.

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 */
Definition: cuddInt.h:492
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:484
DdHalfWord x
Definition: cuddInt.h:493
static int size
Definition: cuddSign.c:86
DdHalfWord y
Definition: cuddInt.h:494
struct Move * next
Definition: cuddInt.h:497
int size
Definition: cuddInt.h:496
static Move * cuddZddSiftingDown ( DdManager table,
int  x,
int  x_high,
int  initial_size 
)
static

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

Synopsis [Sifts a variable down.]

Description [Sifts a variable down. Moves x down until either it reaches the bound (x_high) or the size of the ZDD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.]

SideEffects [None]

SeeAlso []

Definition at line 1300 of file cuddZddReord.c.

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 */
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
Definition: cuddInt.h:492
int cuddZddNextHigh(DdManager *table, int x)
Definition: cuddZddReord.c:413
double maxGrowth
Definition: cuddInt.h:413
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:484
DdHalfWord x
Definition: cuddInt.h:493
static int size
Definition: cuddSign.c:86
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
DdHalfWord y
Definition: cuddInt.h:494
struct Move * next
Definition: cuddInt.h:497
int size
Definition: cuddInt.h:496
static Move * cuddZddSiftingUp ( DdManager table,
int  x,
int  x_low,
int  initial_size 
)
static

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

Synopsis [Sifts a variable up.]

Description [Sifts a variable up. Moves y up until either it reaches the bound (x_low) or the size of the ZDD heap increases too much. Returns the set of moves in case of success; NULL if memory is full.]

SideEffects [None]

SeeAlso []

Definition at line 1237 of file cuddZddReord.c.

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 */
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
Definition: cuddInt.h:492
double maxGrowth
Definition: cuddInt.h:413
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:484
int cuddZddNextLow(DdManager *table, int x)
Definition: cuddZddReord.c:435
DdHalfWord x
Definition: cuddInt.h:493
static int size
Definition: cuddSign.c:86
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
DdHalfWord y
Definition: cuddInt.h:494
struct Move * next
Definition: cuddInt.h:497
int size
Definition: cuddInt.h:496
int cuddZddSwapInPlace ( DdManager table,
int  x,
int  y 
)

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

Synopsis [Swaps two adjacent variables.]

Description [Swaps two adjacent variables. It assumes that no dead nodes are present on entry to this procedure. The procedure then guarantees that no dead nodes will be present when it terminates. cuddZddSwapInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 484 of file cuddZddReord.c.

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 */
DdHalfWord ref
Definition: cudd.h:280
unsigned int keys
Definition: cuddInt.h:330
unsigned short DdHalfWord
Definition: cudd.h:262
#define ddHash(f, g, s)
Definition: cuddInt.h:737
Definition: cudd.h:278
int * invpermZ
Definition: cuddInt.h:389
int cuddZddNextHigh(DdManager *table, int x)
Definition: cuddZddReord.c:413
FILE * err
Definition: cuddInt.h:442
int * permZ
Definition: cuddInt.h:387
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:126
static DdNode * empty
Definition: cuddZddReord.c:112
int zddTotalNumberSwapping
Definition: cuddZddReord.c:110
unsigned int dead
Definition: cuddInt.h:332
DdNode * next
Definition: cudd.h:281
unsigned int maxKeys
Definition: cuddInt.h:331
DdNode ** nodelist
Definition: cuddInt.h:327
#define cuddF2L(f)
Definition: cuddInt.h:718
#define cuddT(node)
Definition: cuddInt.h:636
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
#define cuddDeallocNode(unique, node)
Definition: cuddInt.h:547
DdHalfWord index
Definition: cudd.h:279
unsigned int slots
Definition: cuddInt.h:329
#define cuddE(node)
Definition: cuddInt.h:652
#define cuddSatDec(x)
Definition: cuddInt.h:896
#define assert(ex)
Definition: util_old.h:213
int shift
Definition: cuddInt.h:328
unsigned int keysZ
Definition: cuddInt.h:370
#define cuddSatInc(x)
Definition: cuddInt.h:878
DdSubtable * subtableZ
Definition: cuddInt.h:366
DdNode ** univ
Definition: cuddInt.h:392
int cuddZddSwapping ( DdManager table,
int  lower,
int  upper,
Cudd_ReorderingType  heuristic 
)

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

Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.]

Description [Implementation of Plessier's algorithm that reorders variables by a sequence of (non-adjacent) swaps.

  1. Select two variables (RANDOM or HEURISTIC).
  2. Permute these variables.
  3. If the nodes have decreased accept the permutation.
  4. Otherwise reconstruct the original heap.
  5. Loop.

Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 746 of file cuddZddReord.c.

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 */
unsigned int keys
Definition: cuddInt.h:330
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
Definition: cuddInt.h:492
long Cudd_Random(void)
Definition: cuddUtil.c:2702
FILE * out
Definition: cuddInt.h:441
static Move * zddSwapAny(DdManager *table, int x, int y)
Definition: cuddZddReord.c:961
static double max
Definition: cuddSubsetHB.c:134
static int cuddZddSiftingBackward(DdManager *table, Move *moves, int size)
struct Move * next
Definition: cuddInt.h:497
#define assert(ex)
Definition: util_old.h:213
static int result
Definition: cuddGenetic.c:125
unsigned int keysZ
Definition: cuddInt.h:370
DdSubtable * subtableZ
Definition: cuddInt.h:366
int cuddZddUniqueCompare ( int *  ptr_x,
int *  ptr_y 
)

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

Synopsis [Comparison function used by qsort.]

Description [Comparison function used by qsort to order the variables according to the number of keys in the subtables. Returns the difference in number of keys between the two variables being compared.]

SideEffects [None]

SeeAlso []

Definition at line 459 of file cuddZddReord.c.

462 {
463  return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]);
464 
465 } /* end of cuddZddUniqueCompare */
int * zdd_entry
Definition: cuddZddReord.c:108
static void zddFixTree ( DdManager table,
MtrNode treenode 
)
static

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

Synopsis [Fixes the ZDD variable group tree after a shuffle.]

Description [Fixes the ZDD variable group tree after a shuffle. Assumes that the order of the variables in a terminal node has not been changed.]

SideEffects [Changes the ZDD variable group tree.]

SeeAlso []

Definition at line 1645 of file cuddZddReord.c.

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 */
int * permZ
Definition: cuddInt.h:387
struct MtrNode * parent
Definition: mtr.h:136
struct MtrNode * younger
Definition: mtr.h:139
MtrHalfWord index
Definition: mtr.h:135
MtrHalfWord low
Definition: mtr.h:133
int sizeZ
Definition: cuddInt.h:362
static void zddFixTree(DdManager *table, MtrNode *treenode)
struct MtrNode * child
Definition: mtr.h:137
static int zddReorderPostprocess ( DdManager table)
static

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

Synopsis [Shrinks almost empty ZDD subtables at the end of reordering to guarantee that they have a reasonable load factor.]

Description [Shrinks almost empty subtables at the end of reordering to guarantee that they have a reasonable load factor. However, if there many nodes are being reclaimed, then no resizing occurs. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 1439 of file cuddZddReord.c.

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 */
ABC_INT64_T allocated
Definition: cuddInt.h:382
unsigned int keys
Definition: cuddInt.h:330
void(* DD_OOMFP)(long)
Definition: cudd.h:324
#define ddHash(f, g, s)
Definition: cuddInt.h:737
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2837
Definition: cudd.h:278
double gcFrac
Definition: cuddInt.h:375
unsigned int maxCacheHard
Definition: cuddInt.h:359
unsigned int slots
Definition: cuddInt.h:368
FILE * err
Definition: cuddInt.h:442
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:126
#define DD_MAX_SUBTABLE_SPARSITY
Definition: cuddZddReord.c:87
unsigned int cacheSlots
Definition: cuddInt.h:353
FILE * out
Definition: cuddInt.h:441
DdNode * next
Definition: cudd.h:281
unsigned int maxKeys
Definition: cuddInt.h:331
DdNode ** nodelist
Definition: cuddInt.h:327
#define cuddF2L(f)
Definition: cuddInt.h:718
#define ddMin(x, y)
Definition: cuddInt.h:818
#define DD_MAX_CACHE_TO_SLOTS_RATIO
Definition: cuddInt.h:144
int cacheSlack
Definition: cuddInt.h:358
#define cuddT(node)
Definition: cuddInt.h:636
unsigned long memused
Definition: cuddInt.h:449
int sizeZ
Definition: cuddInt.h:362
#define ABC_FREE(obj)
Definition: abc_global.h:232
unsigned int slots
Definition: cuddInt.h:329
#define cuddE(node)
Definition: cuddInt.h:652
int shift
Definition: cuddInt.h:328
unsigned int minDead
Definition: cuddInt.h:374
double reclaimed
Definition: cuddInt.h:384
DdSubtable * subtableZ
Definition: cuddInt.h:366
#define MMoutOfMemory
Definition: util_hack.h:38
static void zddReorderPreprocess ( DdManager table)
static

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

Synopsis [Prepares the ZDD heap for dynamic reordering.]

Description [Prepares the ZDD heap for dynamic reordering. Does garbage collection, to guarantee that there are no dead nodes; and clears the cache, which is invalidated by dynamic reordering.]

SideEffects [None]

Definition at line 1410 of file cuddZddReord.c.

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 */
void cuddCacheFlush(DdManager *table)
Definition: cuddCache.c:1047
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:729
static int zddShuffle ( DdManager table,
int *  permutation 
)
static

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

Synopsis [Reorders ZDD variables according to a given permutation.]

Description [Reorders ZDD 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. zddShuffle assumes that no dead nodes are present. The reordering is achieved by a series of upward sifts. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 1534 of file cuddZddReord.c.

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 */
int * permZ
Definition: cuddInt.h:387
#define util_cpu_time
Definition: util_hack.h:36
int zddTotalNumberSwapping
Definition: cuddZddReord.c:110
FILE * out
Definition: cuddInt.h:441
static int numvars
Definition: cuddGenetic.c:111
static int zddSiftUp(DdManager *table, int x, int xLow)
int sizeZ
Definition: cuddInt.h:362
static int result
Definition: cuddGenetic.c:125
unsigned int keysZ
Definition: cuddInt.h:370
static int zddSiftUp ( DdManager table,
int  x,
int  xLow 
)
static

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

Synopsis [Moves one ZDD variable up.]

Description [Takes a ZDD 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 1609 of file cuddZddReord.c.

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 */
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:484
int cuddZddNextLow(DdManager *table, int x)
Definition: cuddZddReord.c:435
static int size
Definition: cuddSign.c:86
static Move * zddSwapAny ( DdManager table,
int  x,
int  y 
)
static

AutomaticStart

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

Synopsis [Swaps any two variables.]

Description [Swaps any two variables. Returns the set of moves.]

SideEffects [None]

SeeAlso []

Definition at line 961 of file cuddZddReord.c.

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 */
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
Definition: cuddInt.h:492
int cuddZddNextHigh(DdManager *table, int x)
Definition: cuddZddReord.c:413
double maxGrowth
Definition: cuddInt.h:413
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:484
int cuddZddNextLow(DdManager *table, int x)
Definition: cuddZddReord.c:435
DdHalfWord x
Definition: cuddInt.h:493
static int size
Definition: cuddSign.c:86
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
DdHalfWord y
Definition: cuddInt.h:494
struct Move * next
Definition: cuddInt.h:497
unsigned int keysZ
Definition: cuddInt.h:370
int size
Definition: cuddInt.h:496

Variable Documentation

char rcsid [] DD_UNUSED = "$Id: cuddZddReord.c,v 1.47 2004/08/13 18:04:53 fabio Exp $"
static

Definition at line 105 of file cuddZddReord.c.

DdNode* empty
static

Definition at line 112 of file cuddZddReord.c.

int* zdd_entry

Definition at line 108 of file cuddZddReord.c.

int zddTotalNumberSwapping

Definition at line 110 of file cuddZddReord.c.