abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cuddReorder.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 int ddUniqueCompare (int *ptrX, int *ptrY)
 
static MoveddSwapAny (DdManager *table, int x, int y)
 
static int ddSiftingAux (DdManager *table, int x, int xLow, int xHigh)
 
static MoveddSiftingUp (DdManager *table, int y, int xLow)
 
static MoveddSiftingDown (DdManager *table, int x, int xHigh)
 
static int ddSiftingBackward (DdManager *table, int size, Move *moves)
 
static int ddReorderPreprocess (DdManager *table)
 
static int ddReorderPostprocess (DdManager *table)
 
static int ddShuffle (DdManager *table, int *permutation)
 
static int ddSiftUp (DdManager *table, int x, int xLow)
 
static void bddFixTree (DdManager *table, MtrNode *treenode)
 
static int ddUpdateMtrTree (DdManager *table, MtrNode *treenode, int *perm, int *invperm)
 
static int ddCheckPermuation (DdManager *table, MtrNode *treenode, int *perm, int *invperm)
 
int Cudd_ReduceHeap (DdManager *table, Cudd_ReorderingType heuristic, int minsize)
 
int Cudd_ShuffleHeap (DdManager *table, int *permutation)
 
DdNodecuddDynamicAllocNode (DdManager *table)
 
int cuddSifting (DdManager *table, int lower, int upper)
 
int cuddSwapping (DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
 
int cuddNextHigh (DdManager *table, int x)
 
int cuddNextLow (DdManager *table, int x)
 
int cuddSwapInPlace (DdManager *table, int x, int y)
 
int cuddBddAlignToZdd (DdManager *table)
 

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddReorder.c,v 1.69 2009/02/21 18:24:10 fabio Exp $"
 
static int * entry
 
int ddTotalNumberSwapping
 

Macro Definition Documentation

#define DD_MAX_SUBTABLE_SPARSITY   8

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

FileName [cuddReorder.c]

PackageName [cudd]

Synopsis [Functions for dynamic variable reordering.]

Description [External procedures included in this file:

Internal procedures included in this module:

Static procedures included in this module:

]

Author [Shipra Panda, Bernard Plessier, Fabio Somenzi]

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

All rights reserved.

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

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

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

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

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

Definition at line 86 of file cuddReorder.c.

#define DD_SHRINK_FACTOR   2

Definition at line 87 of file cuddReorder.c.

Function Documentation

static void bddFixTree ( DdManager table,
MtrNode treenode 
)
static

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

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

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

SideEffects [Changes the BDD variable group tree.]

SeeAlso []

Definition at line 2010 of file cuddReorder.c.

2013 {
2014  if (treenode == NULL) return;
2015  treenode->low = ((int) treenode->index < table->size) ?
2016  table->perm[treenode->index] : treenode->index;
2017  if (treenode->child != NULL) {
2018  bddFixTree(table, treenode->child);
2019  }
2020  if (treenode->younger != NULL)
2021  bddFixTree(table, treenode->younger);
2022  if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
2023  treenode->parent->low = treenode->low;
2024  treenode->parent->index = treenode->index;
2025  }
2026  return;
2027 
2028 } /* end of bddFixTree */
int size
Definition: cuddInt.h:361
struct MtrNode * parent
Definition: mtr.h:136
static void bddFixTree(DdManager *table, MtrNode *treenode)
Definition: cuddReorder.c:2010
struct MtrNode * younger
Definition: mtr.h:139
MtrHalfWord index
Definition: mtr.h:135
MtrHalfWord low
Definition: mtr.h:133
struct MtrNode * child
Definition: mtr.h:137
int * perm
Definition: cuddInt.h:386
int Cudd_ReduceHeap ( DdManager table,
Cudd_ReorderingType  heuristic,
int  minsize 
)

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

Synopsis [Main dynamic reordering routine.]

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

  • Swapping
  • Sifting
  • Symmetric Sifting
  • Group Sifting
  • Window Permutation
  • Simulated Annealing
  • Genetic Algorithm
  • Dynamic Programming (exact)

For sifting, symmetric sifting, group sifting, and window permutation it is possible to request reordering to convergence.

The core of all methods is the reordering procedure cuddSwapInPlace() which swaps two adjacent variables and is based on Rudell's paper. 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 diagrams and clears the cache.]

Definition at line 176 of file cuddReorder.c.

180 {
181  DdHook *hook;
182  int result;
183  unsigned int nextDyn;
184 #ifdef DD_STATS
185  unsigned int initialSize;
186  unsigned int finalSize;
187 #endif
188  long localTime;
189 
190  /* Don't reorder if there are too many dead nodes. */
191  if (table->keys - table->dead < (unsigned) minsize)
192  return(1);
193 
194  if (heuristic == CUDD_REORDER_SAME) {
195  heuristic = table->autoMethod;
196  }
197  if (heuristic == CUDD_REORDER_NONE) {
198  return(1);
199  }
200 
201  /* This call to Cudd_ReduceHeap does initiate reordering. Therefore
202  ** we count it.
203  */
204  table->reorderings++;
205 
206  localTime = util_cpu_time();
207 
208  /* Run the hook functions. */
209  hook = table->preReorderingHook;
210  while (hook != NULL) {
211  int res = (hook->f)(table, "BDD", (void *)heuristic);
212  if (res == 0) return(0);
213  hook = hook->next;
214  }
215 
216  if (!ddReorderPreprocess(table)) return(0);
218 
219  if (table->keys > table->peakLiveNodes) {
220  table->peakLiveNodes = table->keys;
221  }
222 #ifdef DD_STATS
223  initialSize = table->keys - table->isolated;
224  ddTotalNISwaps = 0;
225 
226  switch(heuristic) {
227  case CUDD_REORDER_RANDOM:
229  (void) fprintf(table->out,"#:I_RANDOM ");
230  break;
231  case CUDD_REORDER_SIFT:
237  (void) fprintf(table->out,"#:I_SIFTING ");
238  break;
245  (void) fprintf(table->out,"#:I_WINDOW ");
246  break;
248  (void) fprintf(table->out,"#:I_ANNEAL ");
249  break;
251  (void) fprintf(table->out,"#:I_GENETIC ");
252  break;
253  case CUDD_REORDER_LINEAR:
255  (void) fprintf(table->out,"#:I_LINSIFT ");
256  break;
257  case CUDD_REORDER_EXACT:
258  (void) fprintf(table->out,"#:I_EXACT ");
259  break;
260  default:
261  return(0);
262  }
263  (void) fprintf(table->out,"%8d: initial size",initialSize);
264 #endif
265 
266  /* See if we should use alternate threshold for maximum growth. */
267  if (table->reordCycle && table->reorderings % table->reordCycle == 0) {
268  double saveGrowth = table->maxGrowth;
269  table->maxGrowth = table->maxGrowthAlt;
270  result = cuddTreeSifting(table,heuristic);
271  table->maxGrowth = saveGrowth;
272  } else {
273  result = cuddTreeSifting(table,heuristic);
274  }
275 
276 #ifdef DD_STATS
277  (void) fprintf(table->out,"\n");
278  finalSize = table->keys - table->isolated;
279  (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
280  (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
281  ((double)(util_cpu_time() - localTime)/1000.0));
282  (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
284  (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps);
285 #endif
286 
287  if (result == 0)
288  return(0);
289 
290  if (!ddReorderPostprocess(table))
291  return(0);
292 
293  if (table->realign) {
294  if (!cuddZddAlignToBdd(table))
295  return(0);
296  }
297 
298  nextDyn = (table->keys - table->constants.keys + 1) *
299  DD_DYN_RATIO + table->constants.keys;
300  if (table->reorderings < 20 || nextDyn > table->nextDyn)
301  table->nextDyn = nextDyn;
302  else
303  table->nextDyn += 20;
304  table->reordered = 1;
305 
306  /* Run hook functions. */
307  hook = table->postReorderingHook;
308  while (hook != NULL) {
309  int res = (hook->f)(table, "BDD", (void *)localTime);
310  if (res == 0) return(0);
311  hook = hook->next;
312  }
313  /* Update cumulative reordering time. */
314  table->reordTime += util_cpu_time() - localTime;
315 
316  return(result);
317 
318 } /* end of Cudd_ReduceHeap */
unsigned int keys
Definition: cuddInt.h:330
long reordTime
Definition: cuddInt.h:454
Cudd_ReorderingType autoMethod
Definition: cuddInt.h:418
unsigned int peakLiveNodes
Definition: cuddInt.h:465
DdHook * preReorderingHook
Definition: cuddInt.h:439
int reordCycle
Definition: cuddInt.h:415
double maxGrowthAlt
Definition: cuddInt.h:414
int realign
Definition: cuddInt.h:420
double maxGrowth
Definition: cuddInt.h:413
#define DD_DYN_RATIO
Definition: cuddInt.h:152
#define util_cpu_time
Definition: util_hack.h:36
DD_HFP f
Definition: cuddInt.h:246
int ddTotalNumberSwapping
Definition: cuddReorder.c:107
int reordered
Definition: cuddInt.h:409
unsigned int nextDyn
Definition: cuddInt.h:422
unsigned int dead
Definition: cuddInt.h:371
DdHook * postReorderingHook
Definition: cuddInt.h:440
unsigned int keys
Definition: cuddInt.h:369
static int ddReorderPostprocess(DdManager *table)
Definition: cuddReorder.c:1864
FILE * out
Definition: cuddInt.h:441
if(last==0)
Definition: sparse_int.h:34
int reorderings
Definition: cuddInt.h:410
int cuddTreeSifting(DdManager *table, Cudd_ReorderingType method)
Definition: cuddGroup.c:274
static int ddReorderPreprocess(DdManager *table)
Definition: cuddReorder.c:1826
struct DdHook * next
Definition: cuddInt.h:247
int cuddZddAlignToBdd(DdManager *table)
Definition: cuddZddReord.c:352
DdSubtable constants
Definition: cuddInt.h:367
static int result
Definition: cuddGenetic.c:125
int isolated
Definition: cuddInt.h:385
int Cudd_ShuffleHeap ( DdManager table,
int *  permutation 
)

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

Synopsis [Reorders variables according to given permutation.]

Description [Reorders 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 variable order for all diagrams and clears the cache.]

SeeAlso [Cudd_ReduceHeap]

Definition at line 338 of file cuddReorder.c.

341 {
342 
343  int result;
344  int i;
345  int identity = 1;
346  int *perm;
347 
348  /* Don't waste time in case of identity permutation. */
349  for (i = 0; i < table->size; i++) {
350  if (permutation[i] != table->invperm[i]) {
351  identity = 0;
352  break;
353  }
354  }
355  if (identity == 1) {
356  return(1);
357  }
358  if (!ddReorderPreprocess(table)) return(0);
359  if (table->keys > table->peakLiveNodes) {
360  table->peakLiveNodes = table->keys;
361  }
362 
363  perm = ABC_ALLOC(int, table->size);
364  for (i = 0; i < table->size; i++)
365  perm[permutation[i]] = i;
366  if (!ddCheckPermuation(table,table->tree,perm,permutation)) {
367  ABC_FREE(perm);
368  return(0);
369  }
370  if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) {
371  ABC_FREE(perm);
372  return(0);
373  }
374  ABC_FREE(perm);
375 
376  result = ddShuffle(table,permutation);
377 
378  if (!ddReorderPostprocess(table)) return(0);
379 
380  return(result);
381 
382 } /* end of Cudd_ShuffleHeap */
static int ddCheckPermuation(DdManager *table, MtrNode *treenode, int *perm, int *invperm)
Definition: cuddReorder.c:2103
unsigned int peakLiveNodes
Definition: cuddInt.h:465
int size
Definition: cuddInt.h:361
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
MtrNode * tree
Definition: cuddInt.h:424
unsigned int keys
Definition: cuddInt.h:369
static int ddReorderPostprocess(DdManager *table)
Definition: cuddReorder.c:1864
static int ddUpdateMtrTree(DdManager *table, MtrNode *treenode, int *perm, int *invperm)
Definition: cuddReorder.c:2044
static int ddReorderPreprocess(DdManager *table)
Definition: cuddReorder.c:1826
#define ABC_FREE(obj)
Definition: abc_global.h:232
static int ddShuffle(DdManager *table, int *permutation)
Definition: cuddReorder.c:1897
int * invperm
Definition: cuddInt.h:388
static int result
Definition: cuddGenetic.c:125
int cuddBddAlignToZdd ( DdManager table)

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

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

Description [Reorders BDD variables according to the order of the ZDD variables. This function can be called at the end of ZDD reordering to insure that the order of the BDD variables is consistent with the order of the ZDD 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. cuddBddAlignToZdd 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_zddReduceHeap, which clears the cache. Returns 1 in case of success; 0 otherwise.]

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

SeeAlso [Cudd_ShuffleHeap Cudd_zddReduceHeap]

Definition at line 1251 of file cuddReorder.c.

1253 {
1254  int *invperm; /* permutation array */
1255  int M; /* ratio of ZDD variables to BDD variables */
1256  int i; /* loop index */
1257  int result; /* return value */
1258 
1259  /* We assume that a ratio of 0 is OK. */
1260  if (table->size == 0)
1261  return(1);
1262 
1263  M = table->sizeZ / table->size;
1264  /* Check whether the number of ZDD variables is a multiple of the
1265  ** number of BDD variables.
1266  */
1267  if (M * table->size != table->sizeZ)
1268  return(0);
1269  /* Create and initialize the inverse permutation array. */
1270  invperm = ABC_ALLOC(int,table->size);
1271  if (invperm == NULL) {
1272  table->errorCode = CUDD_MEMORY_OUT;
1273  return(0);
1274  }
1275  for (i = 0; i < table->sizeZ; i += M) {
1276  int indexZ = table->invpermZ[i];
1277  int index = indexZ / M;
1278  invperm[i / M] = index;
1279  }
1280  /* Eliminate dead nodes. Do not scan the cache again, because we
1281  ** assume that Cudd_zddReduceHeap has already cleared it.
1282  */
1283  cuddGarbageCollect(table,0);
1284 
1285  /* Initialize number of isolated projection functions. */
1286  table->isolated = 0;
1287  for (i = 0; i < table->size; i++) {
1288  if (table->vars[i]->ref == 1) table->isolated++;
1289  }
1290 
1291  /* Initialize the interaction matrix. */
1292  result = cuddInitInteract(table);
1293  if (result == 0) return(0);
1294 
1295  result = ddShuffle(table, invperm);
1296  ABC_FREE(invperm);
1297  /* Free interaction matrix. */
1298  ABC_FREE(table->interact);
1299  /* Fix the BDD variable group tree. */
1300  bddFixTree(table,table->tree);
1301  return(result);
1302 
1303 } /* end of cuddBddAlignToZdd */
DdHalfWord ref
Definition: cudd.h:280
int * invpermZ
Definition: cuddInt.h:389
int size
Definition: cuddInt.h:361
int cuddInitInteract(DdManager *table)
Definition: cuddInteract.c:237
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
MtrNode * tree
Definition: cuddInt.h:424
static void bddFixTree(DdManager *table, MtrNode *treenode)
Definition: cuddReorder.c:2010
word M(word f1, word f2, int n)
Definition: kitPerm.c:240
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:729
long * interact
Definition: cuddInt.h:394
int sizeZ
Definition: cuddInt.h:362
#define ABC_FREE(obj)
Definition: abc_global.h:232
DdNode ** vars
Definition: cuddInt.h:390
static int ddShuffle(DdManager *table, int *permutation)
Definition: cuddReorder.c:1897
static int result
Definition: cuddGenetic.c:125
int isolated
Definition: cuddInt.h:385
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
DdNode* cuddDynamicAllocNode ( DdManager table)

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

Synopsis [Dynamically allocates a Node.]

Description [Dynamically allocates a Node. This procedure is similar to cuddAllocNode in Cudd_Table.c, but it does not attempt garbage collection, because during reordering there are no dead nodes. Returns a pointer to a new node if successful; NULL is memory is full.]

SideEffects [None]

SeeAlso [cuddAllocNode]

Definition at line 406 of file cuddReorder.c.

408 {
409  int i;
410  DdNodePtr *mem;
411  DdNode *list, *node;
412  extern DD_OOMFP MMoutOfMemory;
413  DD_OOMFP saveHandler;
414 
415  if (table->nextFree == NULL) { /* free list is empty */
416  /* Try to allocate a new block. */
417  saveHandler = MMoutOfMemory;
418  MMoutOfMemory = Cudd_OutOfMem;
419 // mem = (DdNodePtr *) ABC_ALLOC(DdNode, DD_MEM_CHUNK + 1);
420  mem = (DdNodePtr *) ABC_ALLOC(DdNode, DD_MEM_CHUNK + 2);
421  MMoutOfMemory = saveHandler;
422  if (mem == NULL && table->stash != NULL) {
423  ABC_FREE(table->stash);
424  table->stash = NULL;
425  /* Inhibit resizing of tables. */
426  table->maxCacheHard = table->cacheSlots - 1;
427  table->cacheSlack = - (int) (table->cacheSlots + 1);
428  for (i = 0; i < table->size; i++) {
429  table->subtables[i].maxKeys <<= 2;
430  }
431 // mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 1);
432  mem = (DdNodePtr *) ABC_ALLOC(DdNode,DD_MEM_CHUNK + 2);
433  }
434  if (mem == NULL) {
435  /* Out of luck. Call the default handler to do
436  ** whatever it specifies for a failed malloc. If this
437  ** handler returns, then set error code, print
438  ** warning, and return. */
439  (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
440  table->errorCode = CUDD_MEMORY_OUT;
441 #ifdef DD_VERBOSE
442  (void) fprintf(table->err,
443  "cuddDynamicAllocNode: out of memory");
444  (void) fprintf(table->err,"Memory in use = %lu\n",
445  table->memused);
446 #endif
447  return(NULL);
448  } else { /* successful allocation; slice memory */
449  unsigned long offset;
450  table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
451  mem[0] = (DdNode *) table->memoryList;
452  table->memoryList = mem;
453 
454  /* Here we rely on the fact that the size of a DdNode is a
455  ** power of 2 and a multiple of the size of a pointer.
456  ** If we align one node, all the others will be aligned
457  ** as well. */
458 // offset = (unsigned long) mem & (sizeof(DdNode) - 1);
459 // mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
460  offset = (unsigned long) mem & (32 - 1);
461  mem += (32 - offset) / sizeof(DdNodePtr);
462 #ifdef DD_DEBUG
463 // assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0);
464  assert(((unsigned long) mem & (32 - 1)) == 0);
465 #endif
466  list = (DdNode *) mem;
467 
468  i = 1;
469  do {
470  list[i - 1].ref = 0;
471  list[i - 1].next = &list[i];
472  } while (++i < DD_MEM_CHUNK);
473 
474  list[DD_MEM_CHUNK-1].ref = 0;
475  list[DD_MEM_CHUNK - 1].next = NULL;
476 
477  table->nextFree = &list[0];
478  }
479  } /* if free list empty */
480 
481  node = table->nextFree;
482  table->nextFree = node->next;
483  return (node);
484 
485 } /* end of cuddDynamicAllocNode */
DdHalfWord ref
Definition: cudd.h:280
void(* DD_OOMFP)(long)
Definition: cudd.h:324
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2837
Definition: cudd.h:278
int size
Definition: cuddInt.h:361
unsigned int maxCacheHard
Definition: cuddInt.h:359
FILE * err
Definition: cuddInt.h:442
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
DdSubtable * subtables
Definition: cuddInt.h:365
struct DdNode DdNode
Definition: cudd.h:270
unsigned int cacheSlots
Definition: cuddInt.h:353
char * stash
Definition: cuddInt.h:399
DdNode * next
Definition: cudd.h:281
unsigned int maxKeys
Definition: cuddInt.h:331
int cacheSlack
Definition: cuddInt.h:358
DdNode ** memoryList
Definition: cuddInt.h:397
unsigned long memused
Definition: cuddInt.h:449
DdNode * nextFree
Definition: cuddInt.h:398
#define ABC_FREE(obj)
Definition: abc_global.h:232
#define assert(ex)
Definition: util_old.h:213
#define DD_MEM_CHUNK
Definition: cuddInt.h:104
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
#define MMoutOfMemory
Definition: util_hack.h:38
int cuddNextHigh ( 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 [cuddNextLow]

Definition at line 716 of file cuddReorder.c.

719 {
720  return(x+1);
721 
722 } /* end of cuddNextHigh */
int cuddNextLow ( 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 [cuddNextHigh]

Definition at line 738 of file cuddReorder.c.

741 {
742  return(x-1);
743 
744 } /* end of cuddNextLow */
int cuddSifting ( 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]

Definition at line 508 of file cuddReorder.c.

512 {
513  int i;
514  int *var;
515  int size;
516  int x;
517  int result;
518 #ifdef DD_STATS
519  int previousSize;
520 #endif
521 
522  size = table->size;
523 
524  /* Find order in which to sift variables. */
525  var = NULL;
526  entry = ABC_ALLOC(int,size);
527  if (entry == NULL) {
528  table->errorCode = CUDD_MEMORY_OUT;
529  goto cuddSiftingOutOfMem;
530  }
531  var = ABC_ALLOC(int,size);
532  if (var == NULL) {
533  table->errorCode = CUDD_MEMORY_OUT;
534  goto cuddSiftingOutOfMem;
535  }
536 
537  for (i = 0; i < size; i++) {
538  x = table->perm[i];
539  entry[i] = table->subtables[x].keys;
540  var[i] = i;
541  }
542 
543  qsort((void *)var,size,sizeof(int),(DD_QSFP)ddUniqueCompare);
544 
545  /* Now sift. */
546  for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
547  if (ddTotalNumberSwapping >= table->siftMaxSwap)
548  break;
549  x = table->perm[var[i]];
550 
551  if (x < lower || x > upper || table->subtables[x].bindVar == 1)
552  continue;
553 #ifdef DD_STATS
554  previousSize = table->keys - table->isolated;
555 #endif
556  result = ddSiftingAux(table, x, lower, upper);
557  if (!result) goto cuddSiftingOutOfMem;
558 #ifdef DD_STATS
559  if (table->keys < (unsigned) previousSize + table->isolated) {
560  (void) fprintf(table->out,"-");
561  } else if (table->keys > (unsigned) previousSize + table->isolated) {
562  (void) fprintf(table->out,"+"); /* should never happen */
563  (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
564  } else {
565  (void) fprintf(table->out,"=");
566  }
567  fflush(table->out);
568 #endif
569  }
570 
571  ABC_FREE(var);
572  ABC_FREE(entry);
573 
574  return(1);
575 
576 cuddSiftingOutOfMem:
577 
578  if (entry != NULL) ABC_FREE(entry);
579  if (var != NULL) ABC_FREE(var);
580 
581  return(0);
582 
583 } /* end of cuddSifting */
static int * entry
Definition: cuddReorder.c:105
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 size
Definition: cuddInt.h:361
int var(Lit p)
Definition: SolverTypes.h:62
FILE * err
Definition: cuddInt.h:442
static int ddSiftingAux(DdManager *table, int x, int xLow, int xHigh)
Definition: cuddReorder.c:1488
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
int bindVar
Definition: cuddInt.h:334
DdSubtable * subtables
Definition: cuddInt.h:365
int ddTotalNumberSwapping
Definition: cuddReorder.c:107
unsigned int keys
Definition: cuddInt.h:369
FILE * out
Definition: cuddInt.h:441
static int ddUniqueCompare(int *ptrX, int *ptrY)
Definition: cuddReorder.c:1323
static int size
Definition: cuddSign.c:86
#define ddMin(x, y)
Definition: cuddInt.h:818
int siftMaxVar
Definition: cuddInt.h:411
#define ABC_FREE(obj)
Definition: abc_global.h:232
static int result
Definition: cuddGenetic.c:125
int isolated
Definition: cuddInt.h:385
int * perm
Definition: cuddInt.h:386
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
int cuddSwapInPlace ( 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. cuddSwapInPlace assumes that x < y. Returns the number of keys in the table if successful; 0 otherwise.]

SideEffects [None]

Definition at line 761 of file cuddReorder.c.

765 {
766  DdNodePtr *xlist, *ylist;
767  int xindex, yindex;
768  int xslots, yslots;
769  int xshift, yshift;
770  int oldxkeys, oldykeys;
771  int newxkeys, newykeys;
772  int comple, newcomplement;
773  int i;
774  Cudd_VariableType varType;
775  Cudd_LazyGroupType groupType;
776  int posn;
777  int isolated;
778  DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
779  DdNode *g,*next;
780  DdNodePtr *previousP;
781  DdNode *tmp;
782  DdNode *sentinel = &(table->sentinel);
783  extern DD_OOMFP MMoutOfMemory;
784  DD_OOMFP saveHandler;
785 
786 #ifdef DD_DEBUG
787  int count,idcheck;
788 #endif
789 
790 #ifdef DD_DEBUG
791  assert(x < y);
792  assert(cuddNextHigh(table,x) == y);
793  assert(table->subtables[x].keys != 0);
794  assert(table->subtables[y].keys != 0);
795  assert(table->subtables[x].dead == 0);
796  assert(table->subtables[y].dead == 0);
797 #endif
798 
800 
801  /* Get parameters of x subtable. */
802  xindex = table->invperm[x];
803  xlist = table->subtables[x].nodelist;
804  oldxkeys = table->subtables[x].keys;
805  xslots = table->subtables[x].slots;
806  xshift = table->subtables[x].shift;
807 
808  /* Get parameters of y subtable. */
809  yindex = table->invperm[y];
810  ylist = table->subtables[y].nodelist;
811  oldykeys = table->subtables[y].keys;
812  yslots = table->subtables[y].slots;
813  yshift = table->subtables[y].shift;
814 
815  if (!cuddTestInteract(table,xindex,yindex)) {
816 #ifdef DD_STATS
817  ddTotalNISwaps++;
818 #endif
819  newxkeys = oldxkeys;
820  newykeys = oldykeys;
821  } else {
822  newxkeys = 0;
823  newykeys = oldykeys;
824 
825  /* Check whether the two projection functions involved in this
826  ** swap are isolated. At the end, we'll be able to tell how many
827  ** isolated projection functions are there by checking only these
828  ** two functions again. This is done to eliminate the isolated
829  ** projection functions from the node count.
830  */
831  isolated = - ((table->vars[xindex]->ref == 1) +
832  (table->vars[yindex]->ref == 1));
833 
834  /* The nodes in the x layer that do not depend on
835  ** y will stay there; the others are put in a chain.
836  ** The chain is handled as a LIFO; g points to the beginning.
837  */
838  g = NULL;
839  if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) &&
840  oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) {
841  for (i = 0; i < xslots; i++) {
842  previousP = &(xlist[i]);
843  f = *previousP;
844  while (f != sentinel) {
845  next = f->next;
846  f1 = cuddT(f); f0 = cuddE(f);
847  if (f1->index != (DdHalfWord) yindex &&
848  Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
849  /* stays */
850  newxkeys++;
851  *previousP = f;
852  previousP = &(f->next);
853  } else {
854  f->index = yindex;
855  f->next = g;
856  g = f;
857  }
858  f = next;
859  } /* while there are elements in the collision chain */
860  *previousP = sentinel;
861  } /* for each slot of the x subtable */
862  } else { /* resize xlist */
863  DdNode *h = NULL;
864  DdNodePtr *newxlist;
865  unsigned int newxslots;
866  int newxshift;
867  /* Empty current xlist. Nodes that stay go to list h;
868  ** nodes that move go to list g. */
869  for (i = 0; i < xslots; i++) {
870  f = xlist[i];
871  while (f != sentinel) {
872  next = f->next;
873  f1 = cuddT(f); f0 = cuddE(f);
874  if (f1->index != (DdHalfWord) yindex &&
875  Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
876  /* stays */
877  f->next = h;
878  h = f;
879  newxkeys++;
880  } else {
881  f->index = yindex;
882  f->next = g;
883  g = f;
884  }
885  f = next;
886  } /* while there are elements in the collision chain */
887  } /* for each slot of the x subtable */
888  /* Decide size of new subtable. */
889  newxshift = xshift;
890  newxslots = xslots;
891  while ((unsigned) oldxkeys > DD_MAX_SUBTABLE_DENSITY * newxslots) {
892  newxshift--;
893  newxslots <<= 1;
894  }
895  while ((unsigned) oldxkeys < newxslots &&
896  newxslots > table->initSlots) {
897  newxshift++;
898  newxslots >>= 1;
899  }
900  /* Try to allocate new table. Be ready to back off. */
901  saveHandler = MMoutOfMemory;
902  MMoutOfMemory = Cudd_OutOfMem;
903  newxlist = ABC_ALLOC(DdNodePtr, newxslots);
904  MMoutOfMemory = saveHandler;
905  if (newxlist == NULL) {
906  (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i);
907  newxlist = xlist;
908  newxslots = xslots;
909  newxshift = xshift;
910  } else {
911  table->slots += ((int) newxslots - xslots);
912  table->minDead = (unsigned)
913  (table->gcFrac * (double) table->slots);
914  table->cacheSlack = (int)
916  * table->slots) - 2 * (int) table->cacheSlots;
917  table->memused +=
918  ((int) newxslots - xslots) * sizeof(DdNodePtr);
919  ABC_FREE(xlist);
920  xslots = newxslots;
921  xshift = newxshift;
922  xlist = newxlist;
923  }
924  /* Initialize new subtable. */
925  for (i = 0; i < xslots; i++) {
926  xlist[i] = sentinel;
927  }
928  /* Move nodes that were parked in list h to their new home. */
929  f = h;
930  while (f != NULL) {
931  next = f->next;
932  f1 = cuddT(f);
933  f0 = cuddE(f);
934  /* Check xlist for pair (f11,f01). */
935  posn = ddHash(cuddF2L(f1), cuddF2L(f0), xshift);
936  /* For each element tmp in collision list xlist[posn]. */
937  previousP = &(xlist[posn]);
938  tmp = *previousP;
939  while (f1 < cuddT(tmp)) {
940  previousP = &(tmp->next);
941  tmp = *previousP;
942  }
943  while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) {
944  previousP = &(tmp->next);
945  tmp = *previousP;
946  }
947  f->next = *previousP;
948  *previousP = f;
949  f = next;
950  }
951  }
952 
953 #ifdef DD_COUNT
954  table->swapSteps += oldxkeys - newxkeys;
955 #endif
956  /* Take care of the x nodes that must be re-expressed.
957  ** They form a linked list pointed by g. Their index has been
958  ** already changed to yindex.
959  */
960  f = g;
961  while (f != NULL) {
962  next = f->next;
963  /* Find f1, f0, f11, f10, f01, f00. */
964  f1 = cuddT(f);
965 #ifdef DD_DEBUG
966  assert(!(Cudd_IsComplement(f1)));
967 #endif
968  if ((int) f1->index == yindex) {
969  f11 = cuddT(f1); f10 = cuddE(f1);
970  } else {
971  f11 = f10 = f1;
972  }
973 #ifdef DD_DEBUG
974  assert(!(Cudd_IsComplement(f11)));
975 #endif
976  f0 = cuddE(f);
977  comple = Cudd_IsComplement(f0);
978  f0 = Cudd_Regular(f0);
979  if ((int) f0->index == yindex) {
980  f01 = cuddT(f0); f00 = cuddE(f0);
981  } else {
982  f01 = f00 = f0;
983  }
984  if (comple) {
985  f01 = Cudd_Not(f01);
986  f00 = Cudd_Not(f00);
987  }
988  /* Decrease ref count of f1. */
989  cuddSatDec(f1->ref);
990  /* Create the new T child. */
991  if (f11 == f01) {
992  newf1 = f11;
993  cuddSatInc(newf1->ref);
994  } else {
995  /* Check xlist for triple (xindex,f11,f01). */
996  posn = ddHash(cuddF2L(f11), cuddF2L(f01), xshift);
997  /* For each element newf1 in collision list xlist[posn]. */
998  previousP = &(xlist[posn]);
999  newf1 = *previousP;
1000  while (f11 < cuddT(newf1)) {
1001  previousP = &(newf1->next);
1002  newf1 = *previousP;
1003  }
1004  while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) {
1005  previousP = &(newf1->next);
1006  newf1 = *previousP;
1007  }
1008  if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
1009  cuddSatInc(newf1->ref);
1010  } else { /* no match */
1011  newf1 = cuddDynamicAllocNode(table);
1012  if (newf1 == NULL)
1013  goto cuddSwapOutOfMem;
1014  newf1->index = xindex; newf1->ref = 1;
1015  cuddT(newf1) = f11;
1016  cuddE(newf1) = f01;
1017  /* Insert newf1 in the collision list xlist[posn];
1018  ** increase the ref counts of f11 and f01.
1019  */
1020  newxkeys++;
1021  newf1->next = *previousP;
1022  *previousP = newf1;
1023  cuddSatInc(f11->ref);
1024  tmp = Cudd_Regular(f01);
1025  cuddSatInc(tmp->ref);
1026  }
1027  }
1028  cuddT(f) = newf1;
1029 #ifdef DD_DEBUG
1030  assert(!(Cudd_IsComplement(newf1)));
1031 #endif
1032 
1033  /* Do the same for f0, keeping complement dots into account. */
1034  /* Decrease ref count of f0. */
1035  tmp = Cudd_Regular(f0);
1036  cuddSatDec(tmp->ref);
1037  /* Create the new E child. */
1038  if (f10 == f00) {
1039  newf0 = f00;
1040  tmp = Cudd_Regular(newf0);
1041  cuddSatInc(tmp->ref);
1042  } else {
1043  /* make sure f10 is regular */
1044  newcomplement = Cudd_IsComplement(f10);
1045  if (newcomplement) {
1046  f10 = Cudd_Not(f10);
1047  f00 = Cudd_Not(f00);
1048  }
1049  /* Check xlist for triple (xindex,f10,f00). */
1050  posn = ddHash(cuddF2L(f10), cuddF2L(f00), xshift);
1051  /* For each element newf0 in collision list xlist[posn]. */
1052  previousP = &(xlist[posn]);
1053  newf0 = *previousP;
1054  while (f10 < cuddT(newf0)) {
1055  previousP = &(newf0->next);
1056  newf0 = *previousP;
1057  }
1058  while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) {
1059  previousP = &(newf0->next);
1060  newf0 = *previousP;
1061  }
1062  if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
1063  cuddSatInc(newf0->ref);
1064  } else { /* no match */
1065  newf0 = cuddDynamicAllocNode(table);
1066  if (newf0 == NULL)
1067  goto cuddSwapOutOfMem;
1068  newf0->index = xindex; newf0->ref = 1;
1069  cuddT(newf0) = f10;
1070  cuddE(newf0) = f00;
1071  /* Insert newf0 in the collision list xlist[posn];
1072  ** increase the ref counts of f10 and f00.
1073  */
1074  newxkeys++;
1075  newf0->next = *previousP;
1076  *previousP = newf0;
1077  cuddSatInc(f10->ref);
1078  tmp = Cudd_Regular(f00);
1079  cuddSatInc(tmp->ref);
1080  }
1081  if (newcomplement) {
1082  newf0 = Cudd_Not(newf0);
1083  }
1084  }
1085  cuddE(f) = newf0;
1086 
1087  /* Insert the modified f in ylist.
1088  ** The modified f does not already exists in ylist.
1089  ** (Because of the uniqueness of the cofactors.)
1090  */
1091  posn = ddHash(cuddF2L(newf1), cuddF2L(newf0), yshift);
1092  newykeys++;
1093  previousP = &(ylist[posn]);
1094  tmp = *previousP;
1095  while (newf1 < cuddT(tmp)) {
1096  previousP = &(tmp->next);
1097  tmp = *previousP;
1098  }
1099  while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
1100  previousP = &(tmp->next);
1101  tmp = *previousP;
1102  }
1103  f->next = *previousP;
1104  *previousP = f;
1105  f = next;
1106  } /* while f != NULL */
1107 
1108  /* GC the y layer. */
1109 
1110  /* For each node f in ylist. */
1111  for (i = 0; i < yslots; i++) {
1112  previousP = &(ylist[i]);
1113  f = *previousP;
1114  while (f != sentinel) {
1115  next = f->next;
1116  if (f->ref == 0) {
1117  tmp = cuddT(f);
1118  cuddSatDec(tmp->ref);
1119  tmp = Cudd_Regular(cuddE(f));
1120  cuddSatDec(tmp->ref);
1121  cuddDeallocNode(table,f);
1122  newykeys--;
1123  } else {
1124  *previousP = f;
1125  previousP = &(f->next);
1126  }
1127  f = next;
1128  } /* while f */
1129  *previousP = sentinel;
1130  } /* for i */
1131 
1132 #ifdef DD_DEBUG
1133 #if 0
1134  (void) fprintf(table->out,"Swapping %d and %d\n",x,y);
1135 #endif
1136  count = 0;
1137  idcheck = 0;
1138  for (i = 0; i < yslots; i++) {
1139  f = ylist[i];
1140  while (f != sentinel) {
1141  count++;
1142  if (f->index != (DdHalfWord) yindex)
1143  idcheck++;
1144  f = f->next;
1145  }
1146  }
1147  if (count != newykeys) {
1148  (void) fprintf(table->out,
1149  "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",
1150  oldykeys,newykeys,count);
1151  }
1152  if (idcheck != 0)
1153  (void) fprintf(table->out,
1154  "Error in id's of ylist\twrong id's = %d\n",
1155  idcheck);
1156  count = 0;
1157  idcheck = 0;
1158  for (i = 0; i < xslots; i++) {
1159  f = xlist[i];
1160  while (f != sentinel) {
1161  count++;
1162  if (f->index != (DdHalfWord) xindex)
1163  idcheck++;
1164  f = f->next;
1165  }
1166  }
1167  if (count != newxkeys) {
1168  (void) fprintf(table->out,
1169  "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",
1170  oldxkeys,newxkeys,count);
1171  }
1172  if (idcheck != 0)
1173  (void) fprintf(table->out,
1174  "Error in id's of xlist\twrong id's = %d\n",
1175  idcheck);
1176 #endif
1177 
1178  isolated += (table->vars[xindex]->ref == 1) +
1179  (table->vars[yindex]->ref == 1);
1180  table->isolated += isolated;
1181  }
1182 
1183  /* Set the appropriate fields in table. */
1184  table->subtables[x].nodelist = ylist;
1185  table->subtables[x].slots = yslots;
1186  table->subtables[x].shift = yshift;
1187  table->subtables[x].keys = newykeys;
1188  table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
1189  i = table->subtables[x].bindVar;
1190  table->subtables[x].bindVar = table->subtables[y].bindVar;
1191  table->subtables[y].bindVar = i;
1192  /* Adjust filds for lazy sifting. */
1193  varType = table->subtables[x].varType;
1194  table->subtables[x].varType = table->subtables[y].varType;
1195  table->subtables[y].varType = varType;
1196  i = table->subtables[x].pairIndex;
1197  table->subtables[x].pairIndex = table->subtables[y].pairIndex;
1198  table->subtables[y].pairIndex = i;
1199  i = table->subtables[x].varHandled;
1200  table->subtables[x].varHandled = table->subtables[y].varHandled;
1201  table->subtables[y].varHandled = i;
1202  groupType = table->subtables[x].varToBeGrouped;
1203  table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped;
1204  table->subtables[y].varToBeGrouped = groupType;
1205 
1206  table->subtables[y].nodelist = xlist;
1207  table->subtables[y].slots = xslots;
1208  table->subtables[y].shift = xshift;
1209  table->subtables[y].keys = newxkeys;
1210  table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
1211 
1212  table->perm[xindex] = y; table->perm[yindex] = x;
1213  table->invperm[x] = yindex; table->invperm[y] = xindex;
1214 
1215  table->keys += newxkeys + newykeys - oldxkeys - oldykeys;
1216 
1217  return(table->keys - table->isolated);
1218 
1219 cuddSwapOutOfMem:
1220  (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n");
1221 
1222  return (0);
1223 
1224 } /* end of cuddSwapInPlace */
DdHalfWord ref
Definition: cudd.h:280
unsigned int keys
Definition: cuddInt.h:330
void(* DD_OOMFP)(long)
Definition: cudd.h:324
unsigned short DdHalfWord
Definition: cudd.h:262
#define ddHash(f, g, s)
Definition: cuddInt.h:737
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2837
Definition: cudd.h:278
#define Cudd_Not(node)
Definition: cudd.h:367
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
double gcFrac
Definition: cuddInt.h:375
unsigned int maxCacheHard
Definition: cuddInt.h:359
unsigned int slots
Definition: cuddInt.h:368
#define Cudd_Regular(node)
Definition: cudd.h:397
FILE * err
Definition: cuddInt.h:442
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
int bindVar
Definition: cuddInt.h:334
DdSubtable * subtables
Definition: cuddInt.h:365
#define DD_MAX_SUBTABLE_DENSITY
Definition: cuddInt.h:126
Cudd_VariableType
Definition: cudd.h:252
int ddTotalNumberSwapping
Definition: cuddReorder.c:107
unsigned int initSlots
Definition: cuddInt.h:379
Cudd_VariableType varType
Definition: cuddInt.h:336
unsigned int cacheSlots
Definition: cuddInt.h:353
#define Cudd_IsComplement(node)
Definition: cudd.h:425
DdNode sentinel
Definition: cuddInt.h:344
unsigned int keys
Definition: cuddInt.h:369
int cuddNextHigh(DdManager *table, int x)
Definition: cuddReorder.c:716
unsigned int dead
Definition: cuddInt.h:332
FILE * out
Definition: cuddInt.h:441
DdNode * next
Definition: cudd.h:281
Cudd_LazyGroupType varToBeGrouped
Definition: cuddInt.h:339
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
int varHandled
Definition: cuddInt.h:338
#define cuddDeallocNode(unique, node)
Definition: cuddInt.h:547
unsigned long memused
Definition: cuddInt.h:449
DdHalfWord index
Definition: cudd.h:279
#define ABC_FREE(obj)
Definition: abc_global.h:232
unsigned int slots
Definition: cuddInt.h:329
DdNode ** vars
Definition: cuddInt.h:390
int pairIndex
Definition: cuddInt.h:337
#define cuddE(node)
Definition: cuddInt.h:652
#define cuddSatDec(x)
Definition: cuddInt.h:896
#define assert(ex)
Definition: util_old.h:213
int * invperm
Definition: cuddInt.h:388
int isolated
Definition: cuddInt.h:385
int cuddTestInteract(DdManager *table, int x, int y)
Definition: cuddInteract.c:191
int shift
Definition: cuddInt.h:328
Cudd_LazyGroupType
Definition: cudd.h:237
int * perm
Definition: cuddInt.h:386
unsigned int minDead
Definition: cuddInt.h:374
#define cuddSatInc(x)
Definition: cuddInt.h:878
#define MMoutOfMemory
Definition: util_hack.h:38
int cuddSwapping ( 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]

Definition at line 605 of file cuddReorder.c.

610 {
611  int i, j;
612  int max, keys;
613  int nvars;
614  int x, y;
615  int iterate;
616  int previousSize;
617  Move *moves, *move;
618  int pivot = -1;
619  int modulo;
620  int result;
621 
622 #ifdef DD_DEBUG
623  /* Sanity check */
624  assert(lower >= 0 && upper < table->size && lower <= upper);
625 #endif
626 
627  nvars = upper - lower + 1;
628  iterate = nvars;
629 
630  for (i = 0; i < iterate; i++) {
631  if (ddTotalNumberSwapping >= table->siftMaxSwap)
632  break;
633  if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
634  max = -1;
635  for (j = lower; j <= upper; j++) {
636  if ((keys = table->subtables[j].keys) > max) {
637  max = keys;
638  pivot = j;
639  }
640  }
641 
642  modulo = upper - pivot;
643  if (modulo == 0) {
644  y = pivot;
645  } else{
646  y = pivot + 1 + ((int) Cudd_Random() % modulo);
647  }
648 
649  modulo = pivot - lower - 1;
650  if (modulo < 1) {
651  x = lower;
652  } else{
653  do {
654  x = (int) Cudd_Random() % modulo;
655  } while (x == y);
656  }
657  } else {
658  x = ((int) Cudd_Random() % nvars) + lower;
659  do {
660  y = ((int) Cudd_Random() % nvars) + lower;
661  } while (x == y);
662  }
663  previousSize = table->keys - table->isolated;
664  moves = ddSwapAny(table,x,y);
665  if (moves == NULL) goto cuddSwappingOutOfMem;
666  result = ddSiftingBackward(table,previousSize,moves);
667  if (!result) goto cuddSwappingOutOfMem;
668  while (moves != NULL) {
669  move = moves->next;
670  cuddDeallocMove(table, moves);
671  moves = move;
672  }
673 #ifdef DD_STATS
674  if (table->keys < (unsigned) previousSize + table->isolated) {
675  (void) fprintf(table->out,"-");
676  } else if (table->keys > (unsigned) previousSize + table->isolated) {
677  (void) fprintf(table->out,"+"); /* should never happen */
678  } else {
679  (void) fprintf(table->out,"=");
680  }
681  fflush(table->out);
682 #endif
683 #if 0
684  (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n",
685  table->keys - table->isolated);
686 #endif
687  }
688 
689  return(1);
690 
691 cuddSwappingOutOfMem:
692  while (moves != NULL) {
693  move = moves->next;
694  cuddDeallocMove(table, moves);
695  moves = move;
696  }
697 
698  return(0);
699 
700 } /* end of cuddSwapping */
unsigned int keys
Definition: cuddInt.h:330
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
int siftMaxSwap
Definition: cuddInt.h:412
static Move * ddSwapAny(DdManager *table, int x, int y)
Definition: cuddReorder.c:1347
Definition: cuddInt.h:492
DdSubtable * subtables
Definition: cuddInt.h:365
int ddTotalNumberSwapping
Definition: cuddReorder.c:107
long Cudd_Random(void)
Definition: cuddUtil.c:2702
unsigned int keys
Definition: cuddInt.h:369
FILE * out
Definition: cuddInt.h:441
static double max
Definition: cuddSubsetHB.c:134
static int size
Definition: cuddSign.c:86
static int ddSiftingBackward(DdManager *table, int size, Move *moves)
Definition: cuddReorder.c:1787
struct Move * next
Definition: cuddInt.h:497
#define assert(ex)
Definition: util_old.h:213
static int result
Definition: cuddGenetic.c:125
int isolated
Definition: cuddInt.h:385
static int ddCheckPermuation ( DdManager table,
MtrNode treenode,
int *  perm,
int *  invperm 
)
static

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

Synopsis [Checks the BDD variable group tree before a shuffle.]

Description [Checks the BDD variable group tree before a shuffle. Returns 1 if successful; 0 otherwise.]

SideEffects [Changes the BDD variable group tree.]

SeeAlso []

Definition at line 2103 of file cuddReorder.c.

2108 {
2109  int i, size;
2110  int index, level, minLevel, maxLevel;
2111 
2112  if (treenode == NULL) return(1);
2113 
2114  minLevel = table->size;
2115  maxLevel = 0;
2116  /* i : level */
2117  for (i = treenode->low; i < treenode->low + treenode->size; i++) {
2118  index = table->invperm[i];
2119  level = perm[index];
2120  if (level < minLevel)
2121  minLevel = level;
2122  if (level > maxLevel)
2123  maxLevel = level;
2124  }
2125  size = maxLevel - minLevel + 1;
2126  if (size != treenode->size)
2127  return(0);
2128 
2129  if (treenode->child != NULL) {
2130  if (!ddCheckPermuation(table, treenode->child, perm, invperm))
2131  return(0);
2132  }
2133  if (treenode->younger != NULL) {
2134  if (!ddCheckPermuation(table, treenode->younger, perm, invperm))
2135  return(0);
2136  }
2137  return(1);
2138 }
static int ddCheckPermuation(DdManager *table, MtrNode *treenode, int *perm, int *invperm)
Definition: cuddReorder.c:2103
MtrHalfWord size
Definition: mtr.h:134
int size
Definition: cuddInt.h:361
struct MtrNode * younger
Definition: mtr.h:139
static int size
Definition: cuddSign.c:86
MtrHalfWord low
Definition: mtr.h:133
int * invperm
Definition: cuddInt.h:388
struct MtrNode * child
Definition: mtr.h:137
static int ddReorderPostprocess ( DdManager table)
static

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

Synopsis [Cleans up at the end of reordering.]

Description []

SideEffects [None]

Definition at line 1864 of file cuddReorder.c.

1866 {
1867 
1868 #ifdef DD_VERBOSE
1869  (void) fflush(table->out);
1870 #endif
1871 
1872  /* Free interaction matrix. */
1873  ABC_FREE(table->interact);
1874 
1875  return(1);
1876 
1877 } /* end of ddReorderPostprocess */
FILE * out
Definition: cuddInt.h:441
long * interact
Definition: cuddInt.h:394
#define ABC_FREE(obj)
Definition: abc_global.h:232
static int ddReorderPreprocess ( DdManager table)
static

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

Synopsis [Prepares the DD heap for dynamic reordering.]

Description [Prepares the DD heap for dynamic reordering. Does garbage collection, to guarantee that there are no dead nodes; clears the cache, which is invalidated by dynamic reordering; initializes the number of isolated projection functions; and initializes the interaction matrix. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 1826 of file cuddReorder.c.

1828 {
1829  int i;
1830  int res;
1831 
1832  /* Clear the cache. */
1833  cuddCacheFlush(table);
1834  cuddLocalCacheClearAll(table);
1835 
1836  /* Eliminate dead nodes. Do not scan the cache again. */
1837  cuddGarbageCollect(table,0);
1838 
1839  /* Initialize number of isolated projection functions. */
1840  table->isolated = 0;
1841  for (i = 0; i < table->size; i++) {
1842  if (table->vars[i]->ref == 1) table->isolated++;
1843  }
1844 
1845  /* Initialize the interaction matrix. */
1846  res = cuddInitInteract(table);
1847  if (res == 0) return(0);
1848 
1849  return(1);
1850 
1851 } /* end of ddReorderPreprocess */
DdHalfWord ref
Definition: cudd.h:280
void cuddCacheFlush(DdManager *table)
Definition: cuddCache.c:1047
int size
Definition: cuddInt.h:361
int cuddInitInteract(DdManager *table)
Definition: cuddInteract.c:237
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:729
void cuddLocalCacheClearAll(DdManager *manager)
Definition: cuddLCache.c:404
DdNode ** vars
Definition: cuddInt.h:390
int isolated
Definition: cuddInt.h:385
static int ddShuffle ( DdManager table,
int *  permutation 
)
static

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

Synopsis [Reorders variables according to a given permutation.]

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

SideEffects [None]

SeeAlso []

Definition at line 1897 of file cuddReorder.c.

1900 {
1901  int index;
1902  int level;
1903  int position;
1904  int numvars;
1905  int result;
1906 #ifdef DD_STATS
1907  long localTime;
1908  int initialSize;
1909  int finalSize;
1910  int previousSize;
1911 #endif
1912 
1914 #ifdef DD_STATS
1915  localTime = util_cpu_time();
1916  initialSize = table->keys - table->isolated;
1917  (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
1918  initialSize);
1919  ddTotalNISwaps = 0;
1920 #endif
1921 
1922  numvars = table->size;
1923 
1924  for (level = 0; level < numvars; level++) {
1925  index = permutation[level];
1926  position = table->perm[index];
1927 #ifdef DD_STATS
1928  previousSize = table->keys - table->isolated;
1929 #endif
1930  result = ddSiftUp(table,position,level);
1931  if (!result) return(0);
1932 #ifdef DD_STATS
1933  if (table->keys < (unsigned) previousSize + table->isolated) {
1934  (void) fprintf(table->out,"-");
1935  } else if (table->keys > (unsigned) previousSize + table->isolated) {
1936  (void) fprintf(table->out,"+"); /* should never happen */
1937  } else {
1938  (void) fprintf(table->out,"=");
1939  }
1940  fflush(table->out);
1941 #endif
1942  }
1943 
1944 #ifdef DD_STATS
1945  (void) fprintf(table->out,"\n");
1946  finalSize = table->keys - table->isolated;
1947  (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize);
1948  (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
1949  ((double)(util_cpu_time() - localTime)/1000.0));
1950  (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
1952  (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps);
1953 #endif
1954 
1955  return(1);
1956 
1957 } /* end of ddShuffle */
int size
Definition: cuddInt.h:361
static int ddSiftUp(DdManager *table, int x, int xLow)
Definition: cuddReorder.c:1974
#define util_cpu_time
Definition: util_hack.h:36
int ddTotalNumberSwapping
Definition: cuddReorder.c:107
unsigned int keys
Definition: cuddInt.h:369
FILE * out
Definition: cuddInt.h:441
static int numvars
Definition: cuddGenetic.c:111
static int result
Definition: cuddGenetic.c:125
int isolated
Definition: cuddInt.h:385
int * perm
Definition: cuddInt.h:386
static int ddSiftingAux ( DdManager table,
int  x,
int  xLow,
int  xHigh 
)
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]

Definition at line 1488 of file cuddReorder.c.

1493 {
1494 
1495  Move *move;
1496  Move *moveUp; /* list of up moves */
1497  Move *moveDown; /* list of down moves */
1498  int initialSize;
1499  int result;
1500 
1501  initialSize = table->keys - table->isolated;
1502 
1503  moveDown = NULL;
1504  moveUp = NULL;
1505 
1506  if (x == xLow) {
1507  moveDown = ddSiftingDown(table,x,xHigh);
1508  /* At this point x --> xHigh unless bounding occurred. */
1509  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1510  /* Move backward and stop at best position. */
1511  result = ddSiftingBackward(table,initialSize,moveDown);
1512  if (!result) goto ddSiftingAuxOutOfMem;
1513 
1514  } else if (x == xHigh) {
1515  moveUp = ddSiftingUp(table,x,xLow);
1516  /* At this point x --> xLow unless bounding occurred. */
1517  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1518  /* Move backward and stop at best position. */
1519  result = ddSiftingBackward(table,initialSize,moveUp);
1520  if (!result) goto ddSiftingAuxOutOfMem;
1521 
1522  } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
1523  moveDown = ddSiftingDown(table,x,xHigh);
1524  /* At this point x --> xHigh unless bounding occurred. */
1525  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1526  if (moveDown != NULL) {
1527  x = moveDown->y;
1528  }
1529  moveUp = ddSiftingUp(table,x,xLow);
1530  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1531  /* Move backward and stop at best position */
1532  result = ddSiftingBackward(table,initialSize,moveUp);
1533  if (!result) goto ddSiftingAuxOutOfMem;
1534 
1535  } else { /* must go up first: shorter */
1536  moveUp = ddSiftingUp(table,x,xLow);
1537  /* At this point x --> xLow unless bounding occurred. */
1538  if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1539  if (moveUp != NULL) {
1540  x = moveUp->x;
1541  }
1542  moveDown = ddSiftingDown(table,x,xHigh);
1543  if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
1544  /* Move backward and stop at best position. */
1545  result = ddSiftingBackward(table,initialSize,moveDown);
1546  if (!result) goto ddSiftingAuxOutOfMem;
1547  }
1548 
1549  while (moveDown != NULL) {
1550  move = moveDown->next;
1551  cuddDeallocMove(table, moveDown);
1552  moveDown = move;
1553  }
1554  while (moveUp != NULL) {
1555  move = moveUp->next;
1556  cuddDeallocMove(table, moveUp);
1557  moveUp = move;
1558  }
1559 
1560  return(1);
1561 
1562 ddSiftingAuxOutOfMem:
1563  if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
1564  while (moveDown != NULL) {
1565  move = moveDown->next;
1566  cuddDeallocMove(table, moveDown);
1567  moveDown = move;
1568  }
1569  }
1570  if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
1571  while (moveUp != NULL) {
1572  move = moveUp->next;
1573  cuddDeallocMove(table, moveUp);
1574  moveUp = move;
1575  }
1576  }
1577 
1578  return(0);
1579 
1580 } /* end of ddSiftingAux */
#define CUDD_OUT_OF_MEM
Definition: cudd.h:95
static Move * ddSiftingDown(DdManager *table, int x, int xHigh)
Definition: cuddReorder.c:1695
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
Definition: cuddInt.h:492
unsigned int keys
Definition: cuddInt.h:369
DdHalfWord x
Definition: cuddInt.h:493
static int ddSiftingBackward(DdManager *table, int size, Move *moves)
Definition: cuddReorder.c:1787
DdHalfWord y
Definition: cuddInt.h:494
struct Move * next
Definition: cuddInt.h:497
static int result
Definition: cuddGenetic.c:125
int isolated
Definition: cuddInt.h:385
static Move * ddSiftingUp(DdManager *table, int y, int xLow)
Definition: cuddReorder.c:1595
static int ddSiftingBackward ( DdManager table,
int  size,
Move moves 
)
static

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

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

Description [Given a set of moves, returns the DD 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]

Definition at line 1787 of file cuddReorder.c.

1791 {
1792  Move *move;
1793  int res;
1794 
1795  for (move = moves; move != NULL; move = move->next) {
1796  if (move->size < size) {
1797  size = move->size;
1798  }
1799  }
1800 
1801  for (move = moves; move != NULL; move = move->next) {
1802  if (move->size == size) return(1);
1803  res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
1804  if (!res) return(0);
1805  }
1806 
1807  return(1);
1808 
1809 } /* end of ddSiftingBackward */
Definition: cuddInt.h:492
DdHalfWord x
Definition: cuddInt.h:493
static int size
Definition: cuddSign.c:86
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
DdHalfWord y
Definition: cuddInt.h:494
struct Move * next
Definition: cuddInt.h:497
int size
Definition: cuddInt.h:496
static Move * ddSiftingDown ( DdManager table,
int  x,
int  xHigh 
)
static

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

Synopsis [Sifts a variable down.]

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

SideEffects [None]

Definition at line 1695 of file cuddReorder.c.

1699 {
1700  Move *moves;
1701  Move *move;
1702  int y;
1703  int size;
1704  int R; /* upper bound on node decrease */
1705  int limitSize;
1706  int xindex, yindex;
1707  int isolated;
1708 #ifdef DD_DEBUG
1709  int checkR;
1710  int z;
1711  int zindex;
1712 #endif
1713 
1714  moves = NULL;
1715  /* Initialize R */
1716  xindex = table->invperm[x];
1717  limitSize = size = table->keys - table->isolated;
1718  R = 0;
1719  for (y = xHigh; y > x; y--) {
1720  yindex = table->invperm[y];
1721  if (cuddTestInteract(table,xindex,yindex)) {
1722  isolated = table->vars[yindex]->ref == 1;
1723  R += table->subtables[y].keys - isolated;
1724  }
1725  }
1726 
1727  y = cuddNextHigh(table,x);
1728  while (y <= xHigh && size - R < limitSize) {
1729 #ifdef DD_DEBUG
1730  checkR = 0;
1731  for (z = xHigh; z > x; z--) {
1732  zindex = table->invperm[z];
1733  if (cuddTestInteract(table,xindex,zindex)) {
1734  isolated = table->vars[zindex]->ref == 1;
1735  checkR += table->subtables[z].keys - isolated;
1736  }
1737  }
1738  assert(R == checkR);
1739 #endif
1740  /* Update upper bound on node decrease. */
1741  yindex = table->invperm[y];
1742  if (cuddTestInteract(table,xindex,yindex)) {
1743  isolated = table->vars[yindex]->ref == 1;
1744  R -= table->subtables[y].keys - isolated;
1745  }
1746  size = cuddSwapInPlace(table,x,y);
1747  if (size == 0) goto ddSiftingDownOutOfMem;
1748  move = (Move *) cuddDynamicAllocNode(table);
1749  if (move == NULL) goto ddSiftingDownOutOfMem;
1750  move->x = x;
1751  move->y = y;
1752  move->size = size;
1753  move->next = moves;
1754  moves = move;
1755  if ((double) size > (double) limitSize * table->maxGrowth) break;
1756  if (size < limitSize) limitSize = size;
1757  x = y;
1758  y = cuddNextHigh(table,x);
1759  }
1760  return(moves);
1761 
1762 ddSiftingDownOutOfMem:
1763  while (moves != NULL) {
1764  move = moves->next;
1765  cuddDeallocMove(table, moves);
1766  moves = move;
1767  }
1768  return((Move *) CUDD_OUT_OF_MEM);
1769 
1770 } /* end of ddSiftingDown */
DdHalfWord ref
Definition: cudd.h:280
unsigned int keys
Definition: cuddInt.h:330
#define CUDD_OUT_OF_MEM
Definition: cudd.h:95
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
Definition: cuddInt.h:492
double maxGrowth
Definition: cuddInt.h:413
DdSubtable * subtables
Definition: cuddInt.h:365
unsigned int keys
Definition: cuddInt.h:369
int cuddNextHigh(DdManager *table, int x)
Definition: cuddReorder.c:716
DdHalfWord x
Definition: cuddInt.h:493
static int size
Definition: cuddSign.c:86
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
DdHalfWord y
Definition: cuddInt.h:494
DdNode ** vars
Definition: cuddInt.h:390
struct Move * next
Definition: cuddInt.h:497
#define assert(ex)
Definition: util_old.h:213
int * invperm
Definition: cuddInt.h:388
int isolated
Definition: cuddInt.h:385
int cuddTestInteract(DdManager *table, int x, int y)
Definition: cuddInteract.c:191
int size
Definition: cuddInt.h:496
static Move * ddSiftingUp ( DdManager table,
int  y,
int  xLow 
)
static

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

Synopsis [Sifts a variable up.]

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

SideEffects [None]

Definition at line 1595 of file cuddReorder.c.

1599 {
1600  Move *moves;
1601  Move *move;
1602  int x;
1603  int size;
1604  int limitSize;
1605  int xindex, yindex;
1606  int isolated;
1607  int L; /* lower bound on DD size */
1608 #ifdef DD_DEBUG
1609  int checkL;
1610  int z;
1611  int zindex;
1612 #endif
1613 
1614  moves = NULL;
1615  yindex = table->invperm[y];
1616 
1617  /* Initialize the lower bound.
1618  ** The part of the DD below y will not change.
1619  ** The part of the DD above y that does not interact with y will not
1620  ** change. The rest may vanish in the best case, except for
1621  ** the nodes at level xLow, which will not vanish, regardless.
1622  */
1623  limitSize = L = table->keys - table->isolated;
1624  for (x = xLow + 1; x < y; x++) {
1625  xindex = table->invperm[x];
1626  if (cuddTestInteract(table,xindex,yindex)) {
1627  isolated = table->vars[xindex]->ref == 1;
1628  L -= table->subtables[x].keys - isolated;
1629  }
1630  }
1631  isolated = table->vars[yindex]->ref == 1;
1632  L -= table->subtables[y].keys - isolated;
1633 
1634  x = cuddNextLow(table,y);
1635  while (x >= xLow && L <= limitSize) {
1636  xindex = table->invperm[x];
1637 #ifdef DD_DEBUG
1638  checkL = table->keys - table->isolated;
1639  for (z = xLow + 1; z < y; z++) {
1640  zindex = table->invperm[z];
1641  if (cuddTestInteract(table,zindex,yindex)) {
1642  isolated = table->vars[zindex]->ref == 1;
1643  checkL -= table->subtables[z].keys - isolated;
1644  }
1645  }
1646  isolated = table->vars[yindex]->ref == 1;
1647  checkL -= table->subtables[y].keys - isolated;
1648  assert(L == checkL);
1649 #endif
1650  size = cuddSwapInPlace(table,x,y);
1651  if (size == 0) goto ddSiftingUpOutOfMem;
1652  /* Update the lower bound. */
1653  if (cuddTestInteract(table,xindex,yindex)) {
1654  isolated = table->vars[xindex]->ref == 1;
1655  L += table->subtables[y].keys - isolated;
1656  }
1657  move = (Move *) cuddDynamicAllocNode(table);
1658  if (move == NULL) goto ddSiftingUpOutOfMem;
1659  move->x = x;
1660  move->y = y;
1661  move->size = size;
1662  move->next = moves;
1663  moves = move;
1664  if ((double) size > (double) limitSize * table->maxGrowth) break;
1665  if (size < limitSize) limitSize = size;
1666  y = x;
1667  x = cuddNextLow(table,y);
1668  }
1669  return(moves);
1670 
1671 ddSiftingUpOutOfMem:
1672  while (moves != NULL) {
1673  move = moves->next;
1674  cuddDeallocMove(table, moves);
1675  moves = move;
1676  }
1677  return((Move *) CUDD_OUT_OF_MEM);
1678 
1679 } /* end of ddSiftingUp */
DdHalfWord ref
Definition: cudd.h:280
unsigned int keys
Definition: cuddInt.h:330
#define CUDD_OUT_OF_MEM
Definition: cudd.h:95
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
Definition: cuddInt.h:492
double maxGrowth
Definition: cuddInt.h:413
DdSubtable * subtables
Definition: cuddInt.h:365
int cuddNextLow(DdManager *table, int x)
Definition: cuddReorder.c:738
unsigned int keys
Definition: cuddInt.h:369
DdHalfWord x
Definition: cuddInt.h:493
static int size
Definition: cuddSign.c:86
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
DdHalfWord y
Definition: cuddInt.h:494
DdNode ** vars
Definition: cuddInt.h:390
struct Move * next
Definition: cuddInt.h:497
#define assert(ex)
Definition: util_old.h:213
int * invperm
Definition: cuddInt.h:388
int isolated
Definition: cuddInt.h:385
int cuddTestInteract(DdManager *table, int x, int y)
Definition: cuddInteract.c:191
int size
Definition: cuddInt.h:496
static int ddSiftUp ( DdManager table,
int  x,
int  xLow 
)
static

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

Synopsis [Moves one variable up.]

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

SideEffects [None]

SeeAlso []

Definition at line 1974 of file cuddReorder.c.

1978 {
1979  int y;
1980  int size;
1981 
1982  y = cuddNextLow(table,x);
1983  while (y >= xLow) {
1984  size = cuddSwapInPlace(table,y,x);
1985  if (size == 0) {
1986  return(0);
1987  }
1988  x = y;
1989  y = cuddNextLow(table,x);
1990  }
1991  return(1);
1992 
1993 } /* end of ddSiftUp */
int cuddNextLow(DdManager *table, int x)
Definition: cuddReorder.c:738
static int size
Definition: cuddSign.c:86
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
static Move * ddSwapAny ( DdManager table,
int  x,
int  y 
)
static

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

Synopsis [Swaps any two variables.]

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

SideEffects [None]

Definition at line 1347 of file cuddReorder.c.

1351 {
1352  Move *move, *moves;
1353  int xRef,yRef;
1354  int xNext,yNext;
1355  int size;
1356  int limitSize;
1357  int tmp;
1358 
1359  if (x >y) {
1360  tmp = x; x = y; y = tmp;
1361  }
1362 
1363  xRef = x; yRef = y;
1364 
1365  xNext = cuddNextHigh(table,x);
1366  yNext = cuddNextLow(table,y);
1367  moves = NULL;
1368  limitSize = table->keys - table->isolated;
1369 
1370  for (;;) {
1371  if ( xNext == yNext) {
1372  size = cuddSwapInPlace(table,x,xNext);
1373  if (size == 0) goto ddSwapAnyOutOfMem;
1374  move = (Move *) cuddDynamicAllocNode(table);
1375  if (move == NULL) goto ddSwapAnyOutOfMem;
1376  move->x = x;
1377  move->y = xNext;
1378  move->size = size;
1379  move->next = moves;
1380  moves = move;
1381 
1382  size = cuddSwapInPlace(table,yNext,y);
1383  if (size == 0) goto ddSwapAnyOutOfMem;
1384  move = (Move *) cuddDynamicAllocNode(table);
1385  if (move == NULL) goto ddSwapAnyOutOfMem;
1386  move->x = yNext;
1387  move->y = y;
1388  move->size = size;
1389  move->next = moves;
1390  moves = move;
1391 
1392  size = cuddSwapInPlace(table,x,xNext);
1393  if (size == 0) goto ddSwapAnyOutOfMem;
1394  move = (Move *) cuddDynamicAllocNode(table);
1395  if (move == NULL) goto ddSwapAnyOutOfMem;
1396  move->x = x;
1397  move->y = xNext;
1398  move->size = size;
1399  move->next = moves;
1400  moves = move;
1401 
1402  tmp = x; x = y; y = tmp;
1403 
1404  } else if (x == yNext) {
1405 
1406  size = cuddSwapInPlace(table,x,xNext);
1407  if (size == 0) goto ddSwapAnyOutOfMem;
1408  move = (Move *) cuddDynamicAllocNode(table);
1409  if (move == NULL) goto ddSwapAnyOutOfMem;
1410  move->x = x;
1411  move->y = xNext;
1412  move->size = size;
1413  move->next = moves;
1414  moves = move;
1415 
1416  tmp = x; x = y; y = tmp;
1417 
1418  } else {
1419  size = cuddSwapInPlace(table,x,xNext);
1420  if (size == 0) goto ddSwapAnyOutOfMem;
1421  move = (Move *) cuddDynamicAllocNode(table);
1422  if (move == NULL) goto ddSwapAnyOutOfMem;
1423  move->x = x;
1424  move->y = xNext;
1425  move->size = size;
1426  move->next = moves;
1427  moves = move;
1428 
1429  size = cuddSwapInPlace(table,yNext,y);
1430  if (size == 0) goto ddSwapAnyOutOfMem;
1431  move = (Move *) cuddDynamicAllocNode(table);
1432  if (move == NULL) goto ddSwapAnyOutOfMem;
1433  move->x = yNext;
1434  move->y = y;
1435  move->size = size;
1436  move->next = moves;
1437  moves = move;
1438 
1439  x = xNext;
1440  y = yNext;
1441  }
1442 
1443  xNext = cuddNextHigh(table,x);
1444  yNext = cuddNextLow(table,y);
1445  if (xNext > yRef) break;
1446 
1447  if ((double) size > table->maxGrowth * (double) limitSize) break;
1448  if (size < limitSize) limitSize = size;
1449  }
1450  if (yNext>=xRef) {
1451  size = cuddSwapInPlace(table,yNext,y);
1452  if (size == 0) goto ddSwapAnyOutOfMem;
1453  move = (Move *) cuddDynamicAllocNode(table);
1454  if (move == NULL) goto ddSwapAnyOutOfMem;
1455  move->x = yNext;
1456  move->y = y;
1457  move->size = size;
1458  move->next = moves;
1459  moves = move;
1460  }
1461 
1462  return(moves);
1463 
1464 ddSwapAnyOutOfMem:
1465  while (moves != NULL) {
1466  move = moves->next;
1467  cuddDeallocMove(table, moves);
1468  moves = move;
1469  }
1470  return(NULL);
1471 
1472 } /* end of ddSwapAny */
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
Definition: cuddInt.h:492
double maxGrowth
Definition: cuddInt.h:413
int cuddNextLow(DdManager *table, int x)
Definition: cuddReorder.c:738
unsigned int keys
Definition: cuddInt.h:369
int cuddNextHigh(DdManager *table, int x)
Definition: cuddReorder.c:716
DdHalfWord x
Definition: cuddInt.h:493
static int size
Definition: cuddSign.c:86
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
DdHalfWord y
Definition: cuddInt.h:494
struct Move * next
Definition: cuddInt.h:497
int isolated
Definition: cuddInt.h:385
int size
Definition: cuddInt.h:496
static int ddUniqueCompare ( int *  ptrX,
int *  ptrY 
)
static

AutomaticStart

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]

Definition at line 1323 of file cuddReorder.c.

1326 {
1327 #if 0
1328  if (entry[*ptrY] == entry[*ptrX]) {
1329  return((*ptrX) - (*ptrY));
1330  }
1331 #endif
1332  return(entry[*ptrY] - entry[*ptrX]);
1333 
1334 } /* end of ddUniqueCompare */
static int * entry
Definition: cuddReorder.c:105
static int ddUpdateMtrTree ( DdManager table,
MtrNode treenode,
int *  perm,
int *  invperm 
)
static

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

Synopsis [Updates the BDD variable group tree before a shuffle.]

Description [Updates the BDD variable group tree before a shuffle. Returns 1 if successful; 0 otherwise.]

SideEffects [Changes the BDD variable group tree.]

SeeAlso []

Definition at line 2044 of file cuddReorder.c.

2049 {
2050  int i, size;
2051  int index, level, minLevel, maxLevel, minIndex;
2052 
2053  if (treenode == NULL) return(1);
2054 
2055  minLevel = CUDD_MAXINDEX;
2056  maxLevel = 0;
2057  minIndex = -1;
2058  /* i : level */
2059  for (i = treenode->low; i < treenode->low + treenode->size; i++) {
2060  index = table->invperm[i];
2061  level = perm[index];
2062  if (level < minLevel) {
2063  minLevel = level;
2064  minIndex = index;
2065  }
2066  if (level > maxLevel)
2067  maxLevel = level;
2068  }
2069  size = maxLevel - minLevel + 1;
2070  if (minIndex == -1) return(0);
2071  if (size == treenode->size) {
2072  treenode->low = minLevel;
2073  treenode->index = minIndex;
2074  } else {
2075  return(0);
2076  }
2077 
2078  if (treenode->child != NULL) {
2079  if (!ddUpdateMtrTree(table, treenode->child, perm, invperm))
2080  return(0);
2081  }
2082  if (treenode->younger != NULL) {
2083  if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm))
2084  return(0);
2085  }
2086  return(1);
2087 }
MtrHalfWord size
Definition: mtr.h:134
struct MtrNode * younger
Definition: mtr.h:139
MtrHalfWord index
Definition: mtr.h:135
static int ddUpdateMtrTree(DdManager *table, MtrNode *treenode, int *perm, int *invperm)
Definition: cuddReorder.c:2044
static int size
Definition: cuddSign.c:86
MtrHalfWord low
Definition: mtr.h:133
#define CUDD_MAXINDEX
Definition: cudd.h:112
int * invperm
Definition: cuddInt.h:388
struct MtrNode * child
Definition: mtr.h:137

Variable Documentation

char rcsid [] DD_UNUSED = "$Id: cuddReorder.c,v 1.69 2009/02/21 18:24:10 fabio Exp $"
static

Definition at line 102 of file cuddReorder.c.

int ddTotalNumberSwapping

Definition at line 107 of file cuddReorder.c.

int* entry
static

Definition at line 105 of file cuddReorder.c.