SVF
Macros | Functions | Variables
cuddZddReord.c File Reference
#include "CUDD/util.h"
#include "CUDD/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.49 2012/02/05 01:07:19 fabio Exp $"
 
int * zdd_entry
 
int zddTotalNumberSwapping
 
static DdNodeempty
 

Macro Definition Documentation

◆ DD_MAX_SUBTABLE_SPARSITY

#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-2012, 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 83 of file cuddZddReord.c.

◆ DD_SHRINK_FACTOR

#define DD_SHRINK_FACTOR   2

Definition at line 84 of file cuddZddReord.c.

Function Documentation

◆ Cudd_zddReduceHeap()

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

171 {
172  DdHook *hook;
173  int result;
174  unsigned int nextDyn;
175 #ifdef DD_STATS
176  unsigned int initialSize;
177  unsigned int finalSize;
178 #endif
179  unsigned long localTime;
180 
181  /* Don't reorder if there are too many dead nodes. */
182  if (table->keysZ - table->deadZ < (unsigned) minsize)
183  return(1);
184 
185  if (heuristic == CUDD_REORDER_SAME) {
186  heuristic = table->autoMethodZ;
187  }
188  if (heuristic == CUDD_REORDER_NONE) {
189  return(1);
190  }
191 
192  /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore
193  ** we count it.
194  */
195  table->reorderings++;
196  empty = table->zero;
197 
198  localTime = util_cpu_time();
199 
200  /* Run the hook functions. */
201  hook = table->preReorderingHook;
202  while (hook != NULL) {
203  int res = (hook->f)(table, "ZDD", (void *)heuristic);
204  if (res == 0) return(0);
205  hook = hook->next;
206  }
207 
208  /* Clear the cache and collect garbage. */
209  zddReorderPreprocess(table);
211 
212 #ifdef DD_STATS
213  initialSize = table->keysZ;
214 
215  switch(heuristic) {
216  case CUDD_REORDER_RANDOM:
218  (void) fprintf(table->out,"#:I_RANDOM ");
219  break;
220  case CUDD_REORDER_SIFT:
224  (void) fprintf(table->out,"#:I_SIFTING ");
225  break;
226  case CUDD_REORDER_LINEAR:
228  (void) fprintf(table->out,"#:I_LINSIFT ");
229  break;
230  default:
231  (void) fprintf(table->err,"Unsupported ZDD reordering method\n");
232  return(0);
233  }
234  (void) fprintf(table->out,"%8d: initial size",initialSize);
235 #endif
236 
237  result = cuddZddTreeSifting(table,heuristic);
238 
239 #ifdef DD_STATS
240  (void) fprintf(table->out,"\n");
241  finalSize = table->keysZ;
242  (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
243  (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
244  ((double)(util_cpu_time() - localTime)/1000.0));
245  (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
247 #endif
248 
249  if (result == 0)
250  return(0);
251 
252  if (!zddReorderPostprocess(table))
253  return(0);
254 
255  if (table->realignZ) {
256  if (!cuddBddAlignToZdd(table))
257  return(0);
258  }
259 
260  nextDyn = table->keysZ * DD_DYN_RATIO;
261  if (table->reorderings < 20 || nextDyn > table->nextDyn)
262  table->nextDyn = nextDyn;
263  else
264  table->nextDyn += 20;
265 
266  table->reordered = 1;
267 
268  /* Run hook functions. */
269  hook = table->postReorderingHook;
270  while (hook != NULL) {
271  int res = (hook->f)(table, "ZDD", (void *)localTime);
272  if (res == 0) return(0);
273  hook = hook->next;
274  }
275  /* Update cumulative reordering time. */
276  table->reordTime += util_cpu_time() - localTime;
277 
278  return(result);
279 
280 } /* end of Cudd_zddReduceHeap */
unsigned long reordTime
Definition: cuddInt.h:434
unsigned int deadZ
Definition: cuddInt.h:356
DdHook * preReorderingHook
Definition: cuddInt.h:421
static void zddReorderPreprocess(DdManager *table)
DdNode * zero
Definition: cuddInt.h:330
FILE * err
Definition: cuddInt.h:424
Cudd_ReorderingType autoMethodZ
Definition: cuddInt.h:403
#define DD_DYN_RATIO
Definition: cuddInt.h:153
DD_HFP f
Definition: cuddInt.h:241
static DdNode * empty
Definition: cuddZddReord.c:108
int reordered
Definition: cuddInt.h:392
unsigned int nextDyn
Definition: cuddInt.h:406
DdHook * postReorderingHook
Definition: cuddInt.h:422
int zddTotalNumberSwapping
Definition: cuddZddReord.c:106
FILE * out
Definition: cuddInt.h:423
int realignZ
Definition: cuddInt.h:405
static int zddReorderPostprocess(DdManager *table)
long util_cpu_time(void)
Definition: cpu_time.c:34
struct DdHook * next
Definition: cuddInt.h:242
unsigned int reorderings
Definition: cuddInt.h:393
int cuddZddTreeSifting(DdManager *table, Cudd_ReorderingType method)
Definition: cuddZddGroup.c:228
static int result
Definition: cuddGenetic.c:121
int cuddBddAlignToZdd(DdManager *table)
Definition: cuddReorder.c:1250
unsigned int keysZ
Definition: cuddInt.h:354

◆ Cudd_zddShuffleHeap()

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

303 {
304 
305  int result;
306 
307  empty = table->zero;
308  zddReorderPreprocess(table);
309 
310  result = zddShuffle(table,permutation);
311 
312  if (!zddReorderPostprocess(table)) return(0);
313 
314  return(result);
315 
316 } /* end of Cudd_zddShuffleHeap */
static void zddReorderPreprocess(DdManager *table)
DdNode * zero
Definition: cuddInt.h:330
static DdNode * empty
Definition: cuddZddReord.c:108
static int zddReorderPostprocess(DdManager *table)
static int result
Definition: cuddGenetic.c:121
static int zddShuffle(DdManager *table, int *permutation)

◆ cuddZddAlignToBdd()

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

350 {
351  int *invpermZ; /* permutation array */
352  int M; /* ratio of ZDD variables to BDD variables */
353  int i,j; /* loop indices */
354  int result; /* return value */
355 
356  /* We assume that a ratio of 0 is OK. */
357  if (table->sizeZ == 0)
358  return(1);
359 
360  empty = table->zero;
361  M = table->sizeZ / table->size;
362  /* Check whether the number of ZDD variables is a multiple of the
363  ** number of BDD variables.
364  */
365  if (M * table->size != table->sizeZ)
366  return(0);
367  /* Create and initialize the inverse permutation array. */
368  invpermZ = ALLOC(int,table->sizeZ);
369  if (invpermZ == NULL) {
370  table->errorCode = CUDD_MEMORY_OUT;
371  return(0);
372  }
373  for (i = 0; i < table->size; i++) {
374  int index = table->invperm[i];
375  int indexZ = index * M;
376  int levelZ = table->permZ[indexZ];
377  levelZ = (levelZ / M) * M;
378  for (j = 0; j < M; j++) {
379  invpermZ[M * i + j] = table->invpermZ[levelZ + j];
380  }
381  }
382  /* Eliminate dead nodes. Do not scan the cache again, because we
383  ** assume that Cudd_ReduceHeap has already cleared it.
384  */
385  cuddGarbageCollect(table,0);
386 
387  result = zddShuffle(table, invpermZ);
388  FREE(invpermZ);
389  /* Fix the ZDD variable group tree. */
390  zddFixTree(table,table->treeZ);
391  return(result);
392 
393 } /* end of cuddZddAlignToBdd */
#define FREE(obj)
Definition: util.h:80
int * invpermZ
Definition: cuddInt.h:372
int size
Definition: cuddInt.h:345
DdNode * zero
Definition: cuddInt.h:330
int * permZ
Definition: cuddInt.h:370
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:762
static DdNode * empty
Definition: cuddZddReord.c:108
#define ALLOC(type, num)
Definition: util.h:76
int sizeZ
Definition: cuddInt.h:346
MtrNode * treeZ
Definition: cuddInt.h:409
int * invperm
Definition: cuddInt.h:371
static int result
Definition: cuddGenetic.c:121
static void zddFixTree(DdManager *table, MtrNode *treenode)
static int zddShuffle(DdManager *table, int *permutation)
Cudd_ErrorType errorCode
Definition: cuddInt.h:425

◆ cuddZddNextHigh()

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

412 {
413  return(x + 1);
414 
415 } /* end of cuddZddNextHigh */

◆ cuddZddNextLow()

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

434 {
435  return(x - 1);
436 
437 } /* end of cuddZddNextLow */

◆ cuddZddSifting()

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

867 {
868  int i;
869  int *var;
870  int size;
871  int x;
872  int result;
873 #ifdef DD_STATS
874  int previousSize;
875 #endif
876 
877  size = table->sizeZ;
878 
879  /* Find order in which to sift variables. */
880  var = NULL;
881  zdd_entry = ALLOC(int, size);
882  if (zdd_entry == NULL) {
883  table->errorCode = CUDD_MEMORY_OUT;
884  goto cuddZddSiftingOutOfMem;
885  }
886  var = ALLOC(int, size);
887  if (var == NULL) {
888  table->errorCode = CUDD_MEMORY_OUT;
889  goto cuddZddSiftingOutOfMem;
890  }
891 
892  for (i = 0; i < size; i++) {
893  x = table->permZ[i];
894  zdd_entry[i] = table->subtableZ[x].keys;
895  var[i] = i;
896  }
897 
898  qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
899 
900  /* Now sift. */
901  for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
902  if (zddTotalNumberSwapping >= table->siftMaxSwap)
903  break;
904  if (util_cpu_time() - table->startTime > table->timeLimit) {
905  table->autoDynZ = 0; /* prevent further reordering */
906  break;
907  }
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  FREE(var);
930  FREE(zdd_entry);
931 
932  return(1);
933 
934 cuddZddSiftingOutOfMem:
935 
936  if (zdd_entry != NULL) FREE(zdd_entry);
937  if (var != NULL) FREE(var);
938 
939  return(0);
940 
941 } /* end of cuddZddSifting */
unsigned int keys
Definition: cuddInt.h:314
#define FREE(obj)
Definition: util.h:80
int siftMaxSwap
Definition: cuddInt.h:396
int(* DD_QSFP)(const void *, const void *)
Definition: cudd.h:313
unsigned long startTime
Definition: cuddInt.h:426
int * permZ
Definition: cuddInt.h:370
static int cuddZddSiftingAux(DdManager *table, int x, int x_low, int x_high)
int zddTotalNumberSwapping
Definition: cuddZddReord.c:106
#define ALLOC(type, num)
Definition: util.h:76
FILE * out
Definition: cuddInt.h:423
#define ddMin(x, y)
Definition: cuddInt.h:771
int cuddZddUniqueCompare(int *ptr_x, int *ptr_y)
Definition: cuddZddReord.c:455
long util_cpu_time(void)
Definition: cpu_time.c:34
int siftMaxVar
Definition: cuddInt.h:395
int sizeZ
Definition: cuddInt.h:346
int autoDynZ
Definition: cuddInt.h:401
static int result
Definition: cuddGenetic.c:121
unsigned int keysZ
Definition: cuddInt.h:354
int * zdd_entry
Definition: cuddZddReord.c:104
unsigned long timeLimit
Definition: cuddInt.h:427
Cudd_ErrorType errorCode
Definition: cuddInt.h:425
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddSiftingAux()

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:314
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
static Move * cuddZddSiftingDown(DdManager *table, int x, int x_high, int initial_size)
#define assert(ex)
Definition: util.h:141
Definition: cuddInt.h:469
DdHalfWord x
Definition: cuddInt.h:470
static int cuddZddSiftingBackward(DdManager *table, Move *moves, int size)
DdHalfWord y
Definition: cuddInt.h:471
struct Move * next
Definition: cuddInt.h:474
static int result
Definition: cuddGenetic.c:121
unsigned int keysZ
Definition: cuddInt.h:354
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddSiftingBackward()

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:469
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:480
DdHalfWord x
Definition: cuddInt.h:470
DdHalfWord y
Definition: cuddInt.h:471
struct Move * next
Definition: cuddInt.h:474
int size
Definition: cuddInt.h:473

◆ cuddZddSiftingDown()

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:537
Definition: cuddInt.h:469
int cuddZddNextHigh(DdManager *table, int x)
Definition: cuddZddReord.c:409
double maxGrowth
Definition: cuddInt.h:397
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:480
DdHalfWord x
Definition: cuddInt.h:470
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:405
DdHalfWord y
Definition: cuddInt.h:471
struct Move * next
Definition: cuddInt.h:474
int size
Definition: cuddInt.h:473

◆ cuddZddSiftingUp()

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:537
Definition: cuddInt.h:469
double maxGrowth
Definition: cuddInt.h:397
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:480
int cuddZddNextLow(DdManager *table, int x)
Definition: cuddZddReord.c:431
DdHalfWord x
Definition: cuddInt.h:470
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:405
DdHalfWord y
Definition: cuddInt.h:471
struct Move * next
Definition: cuddInt.h:474
int size
Definition: cuddInt.h:473

◆ cuddZddSwapInPlace()

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

484 {
485  DdNodePtr *xlist, *ylist;
486  int xindex, yindex;
487  int xslots, yslots;
488  int xshift, yshift;
489  int oldxkeys, oldykeys;
490  int newxkeys, newykeys;
491  int i;
492  int posn;
493  DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00;
494  DdNode *newf1, *newf0, *next;
495  DdNodePtr g, *lastP, *previousP;
496 
497 #ifdef DD_DEBUG
498  assert(x < y);
499  assert(cuddZddNextHigh(table,x) == y);
500  assert(table->subtableZ[x].keys != 0);
501  assert(table->subtableZ[y].keys != 0);
502  assert(table->subtableZ[x].dead == 0);
503  assert(table->subtableZ[y].dead == 0);
504 #endif
505 
507 
508  /* Get parameters of x subtable. */
509  xindex = table->invpermZ[x];
510  xlist = table->subtableZ[x].nodelist;
511  oldxkeys = table->subtableZ[x].keys;
512  xslots = table->subtableZ[x].slots;
513  xshift = table->subtableZ[x].shift;
514  newxkeys = 0;
515 
516  yindex = table->invpermZ[y];
517  ylist = table->subtableZ[y].nodelist;
518  oldykeys = table->subtableZ[y].keys;
519  yslots = table->subtableZ[y].slots;
520  yshift = table->subtableZ[y].shift;
521  newykeys = oldykeys;
522 
523  /* The nodes in the x layer that don't depend on y directly
524  ** will stay there; the others are put in a chain.
525  ** The chain is handled as a FIFO; g points to the beginning and
526  ** last points to the end.
527  */
528 
529  g = NULL;
530  lastP = &g;
531  for (i = 0; i < xslots; i++) {
532  previousP = &(xlist[i]);
533  f = *previousP;
534  while (f != NULL) {
535  next = f->next;
536  f1 = cuddT(f); f0 = cuddE(f);
537  if ((f1->index != (DdHalfWord) yindex) &&
538  (f0->index != (DdHalfWord) yindex)) { /* stays */
539  newxkeys++;
540  *previousP = f;
541  previousP = &(f->next);
542  } else {
543  f->index = yindex;
544  *lastP = f;
545  lastP = &(f->next);
546  }
547  f = next;
548  } /* while there are elements in the collision chain */
549  *previousP = NULL;
550  } /* for each slot of the x subtable */
551  *lastP = NULL;
552 
553 
554 #ifdef DD_COUNT
555  table->swapSteps += oldxkeys - newxkeys;
556 #endif
557  /* Take care of the x nodes that must be re-expressed.
558  ** They form a linked list pointed by g. Their index has been
559  ** changed to yindex already.
560  */
561  f = g;
562  while (f != NULL) {
563  next = f->next;
564  /* Find f1, f0, f11, f10, f01, f00. */
565  f1 = cuddT(f);
566  if ((int) f1->index == yindex) {
567  f11 = cuddT(f1); f10 = cuddE(f1);
568  } else {
569  f11 = empty; f10 = f1;
570  }
571  f0 = cuddE(f);
572  if ((int) f0->index == yindex) {
573  f01 = cuddT(f0); f00 = cuddE(f0);
574  } else {
575  f01 = empty; f00 = f0;
576  }
577 
578  /* Decrease ref count of f1. */
579  cuddSatDec(f1->ref);
580  /* Create the new T child. */
581  if (f11 == empty) {
582  if (f01 != empty) {
583  newf1 = f01;
584  cuddSatInc(newf1->ref);
585  }
586  /* else case was already handled when finding nodes
587  ** with both children below level y
588  */
589  } else {
590  /* Check xlist for triple (xindex, f11, f01). */
591  posn = ddHash(f11, f01, xshift);
592  /* For each element newf1 in collision list xlist[posn]. */
593  newf1 = xlist[posn];
594  while (newf1 != NULL) {
595  if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
596  cuddSatInc(newf1->ref);
597  break; /* match */
598  }
599  newf1 = newf1->next;
600  } /* while newf1 */
601  if (newf1 == NULL) { /* no match */
602  newf1 = cuddDynamicAllocNode(table);
603  if (newf1 == NULL)
604  goto zddSwapOutOfMem;
605  newf1->index = xindex; newf1->ref = 1;
606  cuddT(newf1) = f11;
607  cuddE(newf1) = f01;
608  /* Insert newf1 in the collision list xlist[pos];
609  ** increase the ref counts of f11 and f01
610  */
611  newxkeys++;
612  newf1->next = xlist[posn];
613  xlist[posn] = newf1;
614  cuddSatInc(f11->ref);
615  cuddSatInc(f01->ref);
616  }
617  }
618  cuddT(f) = newf1;
619 
620  /* Do the same for f0. */
621  /* Decrease ref count of f0. */
622  cuddSatDec(f0->ref);
623  /* Create the new E child. */
624  if (f10 == empty) {
625  newf0 = f00;
626  cuddSatInc(newf0->ref);
627  } else {
628  /* Check xlist for triple (xindex, f10, f00). */
629  posn = ddHash(f10, f00, xshift);
630  /* For each element newf0 in collision list xlist[posn]. */
631  newf0 = xlist[posn];
632  while (newf0 != NULL) {
633  if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
634  cuddSatInc(newf0->ref);
635  break; /* match */
636  }
637  newf0 = newf0->next;
638  } /* while newf0 */
639  if (newf0 == NULL) { /* no match */
640  newf0 = cuddDynamicAllocNode(table);
641  if (newf0 == NULL)
642  goto zddSwapOutOfMem;
643  newf0->index = xindex; newf0->ref = 1;
644  cuddT(newf0) = f10; cuddE(newf0) = f00;
645  /* Insert newf0 in the collision list xlist[posn];
646  ** increase the ref counts of f10 and f00.
647  */
648  newxkeys++;
649  newf0->next = xlist[posn];
650  xlist[posn] = newf0;
651  cuddSatInc(f10->ref);
652  cuddSatInc(f00->ref);
653  }
654  }
655  cuddE(f) = newf0;
656 
657  /* Insert the modified f in ylist.
658  ** The modified f does not already exists in ylist.
659  ** (Because of the uniqueness of the cofactors.)
660  */
661  posn = ddHash(newf1, newf0, yshift);
662  newykeys++;
663  f->next = ylist[posn];
664  ylist[posn] = f;
665  f = next;
666  } /* while f != NULL */
667 
668  /* GC the y layer. */
669 
670  /* For each node f in ylist. */
671  for (i = 0; i < yslots; i++) {
672  previousP = &(ylist[i]);
673  f = *previousP;
674  while (f != NULL) {
675  next = f->next;
676  if (f->ref == 0) {
677  cuddSatDec(cuddT(f)->ref);
678  cuddSatDec(cuddE(f)->ref);
679  cuddDeallocNode(table, f);
680  newykeys--;
681  } else {
682  *previousP = f;
683  previousP = &(f->next);
684  }
685  f = next;
686  } /* while f */
687  *previousP = NULL;
688  } /* for i */
689 
690  /* Set the appropriate fields in table. */
691  table->subtableZ[x].nodelist = ylist;
692  table->subtableZ[x].slots = yslots;
693  table->subtableZ[x].shift = yshift;
694  table->subtableZ[x].keys = newykeys;
695  table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
696 
697  table->subtableZ[y].nodelist = xlist;
698  table->subtableZ[y].slots = xslots;
699  table->subtableZ[y].shift = xshift;
700  table->subtableZ[y].keys = newxkeys;
701  table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
702 
703  table->permZ[xindex] = y; table->permZ[yindex] = x;
704  table->invpermZ[x] = yindex; table->invpermZ[y] = xindex;
705 
706  table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
707 
708  /* Update univ section; univ[x] remains the same. */
709  table->univ[y] = cuddT(table->univ[x]);
710 
711  return (table->keysZ);
712 
713 zddSwapOutOfMem:
714  (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
715 
716  return (0);
717 
718 } /* end of cuddZddSwapInPlace */
DdHalfWord ref
Definition: cudd.h:272
unsigned int keys
Definition: cuddInt.h:314
unsigned short DdHalfWord
Definition: cudd.h:259
#define ddHash(f, g, s)
Definition: cuddInt.h:696
Definition: cudd.h:270
int * invpermZ
Definition: cuddInt.h:372
#define assert(ex)
Definition: util.h:141
int cuddZddNextHigh(DdManager *table, int x)
Definition: cuddZddReord.c:409
FILE * err
Definition: cuddInt.h:424
int * permZ
Definition: cuddInt.h:370
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:127
static DdNode * empty
Definition: cuddZddReord.c:108
int zddTotalNumberSwapping
Definition: cuddZddReord.c:106
unsigned int dead
Definition: cuddInt.h:316
DdNode * next
Definition: cudd.h:273
unsigned int maxKeys
Definition: cuddInt.h:315
DdNode ** nodelist
Definition: cuddInt.h:311
#define cuddT(node)
Definition: cuddInt.h:609
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:405
#define cuddDeallocNode(unique, node)
Definition: cuddInt.h:520
DdHalfWord index
Definition: cudd.h:271
unsigned int slots
Definition: cuddInt.h:313
#define cuddE(node)
Definition: cuddInt.h:625
#define cuddSatDec(x)
Definition: cuddInt.h:849
int shift
Definition: cuddInt.h:312
unsigned int keysZ
Definition: cuddInt.h:354
#define cuddSatInc(x)
Definition: cuddInt.h:831
DdSubtable * subtableZ
Definition: cuddInt.h:350
DdNode ** univ
Definition: cuddInt.h:375

◆ cuddZddSwapping()

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

747 {
748  int i, j;
749  int max, keys;
750  int nvars;
751  int x, y;
752  int iterate;
753  int previousSize;
754  Move *moves, *move;
755  int pivot;
756  int modulo;
757  int result;
758 
759 #ifdef DD_DEBUG
760  /* Sanity check */
761  assert(lower >= 0 && upper < table->sizeZ && lower <= upper);
762 #endif
763 
764  nvars = upper - lower + 1;
765  iterate = nvars;
766 
767  for (i = 0; i < iterate; i++) {
768  if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
769  /* Find pivot <= id with maximum keys. */
770  for (max = -1, j = lower; j <= upper; j++) {
771  if ((keys = table->subtableZ[j].keys) > max) {
772  max = keys;
773  pivot = j;
774  }
775  }
776 
777  modulo = upper - pivot;
778  if (modulo == 0) {
779  y = pivot; /* y = nvars-1 */
780  } else {
781  /* y = random # from {pivot+1 .. nvars-1} */
782  y = pivot + 1 + (int) (Cudd_Random() % modulo);
783  }
784 
785  modulo = pivot - lower - 1;
786  if (modulo < 1) { /* if pivot = 1 or 0 */
787  x = lower;
788  } else {
789  do { /* x = random # from {0 .. pivot-2} */
790  x = (int) Cudd_Random() % modulo;
791  } while (x == y);
792  /* Is this condition really needed, since x and y
793  are in regions separated by pivot? */
794  }
795  } else {
796  x = (int) (Cudd_Random() % nvars) + lower;
797  do {
798  y = (int) (Cudd_Random() % nvars) + lower;
799  } while (x == y);
800  }
801 
802  previousSize = table->keysZ;
803  moves = zddSwapAny(table, x, y);
804  if (moves == NULL)
805  goto cuddZddSwappingOutOfMem;
806 
807  result = cuddZddSiftingBackward(table, moves, previousSize);
808  if (!result)
809  goto cuddZddSwappingOutOfMem;
810 
811  while (moves != NULL) {
812  move = moves->next;
813  cuddDeallocMove(table, moves);
814  moves = move;
815  }
816 #ifdef DD_STATS
817  if (table->keysZ < (unsigned) previousSize) {
818  (void) fprintf(table->out,"-");
819  } else if (table->keysZ > (unsigned) previousSize) {
820  (void) fprintf(table->out,"+"); /* should never happen */
821  } else {
822  (void) fprintf(table->out,"=");
823  }
824  fflush(table->out);
825 #endif
826  }
827 
828  return(1);
829 
830 cuddZddSwappingOutOfMem:
831  while (moves != NULL) {
832  move = moves->next;
833  cuddDeallocMove(table, moves);
834  moves = move;
835  }
836  return(0);
837 
838 } /* end of cuddZddSwapping */
unsigned int keys
Definition: cuddInt.h:314
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
#define assert(ex)
Definition: util.h:141
Definition: cuddInt.h:469
long Cudd_Random(void)
Definition: cuddUtil.c:2710
FILE * out
Definition: cuddInt.h:423
static Move * zddSwapAny(DdManager *table, int x, int y)
Definition: cuddZddReord.c:961
static int cuddZddSiftingBackward(DdManager *table, Move *moves, int size)
struct Move * next
Definition: cuddInt.h:474
static int result
Definition: cuddGenetic.c:121
unsigned int keysZ
Definition: cuddInt.h:354
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddUniqueCompare()

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

458 {
459  return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]);
460 
461 } /* end of cuddZddUniqueCompare */
int * zdd_entry
Definition: cuddZddReord.c:104

◆ zddFixTree()

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:370
struct MtrNode * parent
Definition: mtr.h:131
struct MtrNode * younger
Definition: mtr.h:134
MtrHalfWord index
Definition: mtr.h:130
MtrHalfWord low
Definition: mtr.h:128
int sizeZ
Definition: cuddInt.h:346
static void zddFixTree(DdManager *table, MtrNode *treenode)
struct MtrNode * child
Definition: mtr.h:132

◆ zddReorderPostprocess()

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 * 0.5) 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 = 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(cuddT(node), cuddE(node), shift);
1495  node->next = nodelist[posn];
1496  nodelist[posn] = node;
1497  node = next;
1498  }
1499  }
1500  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 */
unsigned int keys
Definition: cuddInt.h:314
#define ddHash(f, g, s)
Definition: cuddInt.h:696
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2845
double allocated
Definition: cuddInt.h:365
Definition: cudd.h:270
#define FREE(obj)
Definition: util.h:80
double gcFrac
Definition: cuddInt.h:359
unsigned int maxCacheHard
Definition: cuddInt.h:343
unsigned int slots
Definition: cuddInt.h:352
FILE * err
Definition: cuddInt.h:424
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:127
void(* DD_OOMFP)(long)
Definition: cudd.h:311
#define DD_MAX_SUBTABLE_SPARSITY
Definition: cuddZddReord.c:83
unsigned int cacheSlots
Definition: cuddInt.h:337
#define ALLOC(type, num)
Definition: util.h:76
FILE * out
Definition: cuddInt.h:423
DdNode * next
Definition: cudd.h:273
unsigned int maxKeys
Definition: cuddInt.h:315
DdNode ** nodelist
Definition: cuddInt.h:311
#define ddMin(x, y)
Definition: cuddInt.h:771
#define DD_MAX_CACHE_TO_SLOTS_RATIO
Definition: cuddInt.h:145
int cacheSlack
Definition: cuddInt.h:342
#define cuddT(node)
Definition: cuddInt.h:609
void(* MMoutOfMemory)(long)
Definition: safe_mem.c:32
unsigned long memused
Definition: cuddInt.h:429
int sizeZ
Definition: cuddInt.h:346
unsigned int slots
Definition: cuddInt.h:313
#define cuddE(node)
Definition: cuddInt.h:625
int shift
Definition: cuddInt.h:312
unsigned int minDead
Definition: cuddInt.h:358
double reclaimed
Definition: cuddInt.h:367
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ zddReorderPreprocess()

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 */
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:762
void cuddCacheFlush(DdManager *table)
Definition: cuddCache.c:1004

◆ zddShuffle()

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  unsigned 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:370
int zddTotalNumberSwapping
Definition: cuddZddReord.c:106
FILE * out
Definition: cuddInt.h:423
static int numvars
Definition: cuddGenetic.c:107
long util_cpu_time(void)
Definition: cpu_time.c:34
static int zddSiftUp(DdManager *table, int x, int xLow)
int sizeZ
Definition: cuddInt.h:346
static int result
Definition: cuddGenetic.c:121
unsigned int keysZ
Definition: cuddInt.h:354

◆ zddSiftUp()

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:480
int cuddZddNextLow(DdManager *table, int x)
Definition: cuddZddReord.c:431

◆ zddSwapAny()

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:537
Definition: cuddInt.h:469
int cuddZddNextHigh(DdManager *table, int x)
Definition: cuddZddReord.c:409
double maxGrowth
Definition: cuddInt.h:397
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:480
int cuddZddNextLow(DdManager *table, int x)
Definition: cuddZddReord.c:431
DdHalfWord x
Definition: cuddInt.h:470
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:405
DdHalfWord y
Definition: cuddInt.h:471
struct Move * next
Definition: cuddInt.h:474
unsigned int keysZ
Definition: cuddInt.h:354
int size
Definition: cuddInt.h:473

Variable Documentation

◆ DD_UNUSED

char rcsid [] DD_UNUSED = "$Id: cuddZddReord.c,v 1.49 2012/02/05 01:07:19 fabio Exp $"
static

Definition at line 101 of file cuddZddReord.c.

◆ empty

DdNode* empty
static

Definition at line 108 of file cuddZddReord.c.

◆ zdd_entry

int* zdd_entry

Definition at line 104 of file cuddZddReord.c.

◆ zddTotalNumberSwapping

int zddTotalNumberSwapping

Definition at line 106 of file cuddZddReord.c.