SVF
Macros | Functions | Variables
cuddReorder.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 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.71 2012/02/05 01:07:19 fabio Exp $"
 
static int * entry
 
int ddTotalNumberSwapping
 

Macro Definition Documentation

◆ DD_MAX_SUBTABLE_SPARSITY

#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-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 82 of file cuddReorder.c.

◆ DD_SHRINK_FACTOR

#define DD_SHRINK_FACTOR   2

Definition at line 83 of file cuddReorder.c.

Function Documentation

◆ bddFixTree()

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 2009 of file cuddReorder.c.

2012 {
2013  if (treenode == NULL) return;
2014  treenode->low = ((int) treenode->index < table->size) ?
2015  table->perm[treenode->index] : treenode->index;
2016  if (treenode->child != NULL) {
2017  bddFixTree(table, treenode->child);
2018  }
2019  if (treenode->younger != NULL)
2020  bddFixTree(table, treenode->younger);
2021  if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
2022  treenode->parent->low = treenode->low;
2023  treenode->parent->index = treenode->index;
2024  }
2025  return;
2026 
2027 } /* end of bddFixTree */
int size
Definition: cuddInt.h:345
struct MtrNode * parent
Definition: mtr.h:131
static void bddFixTree(DdManager *table, MtrNode *treenode)
Definition: cuddReorder.c:2009
struct MtrNode * younger
Definition: mtr.h:134
MtrHalfWord index
Definition: mtr.h:130
MtrHalfWord low
Definition: mtr.h:128
struct MtrNode * child
Definition: mtr.h:132
int * perm
Definition: cuddInt.h:369

◆ Cudd_ReduceHeap()

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 172 of file cuddReorder.c.

176 {
177  DdHook *hook;
178  int result;
179  unsigned int nextDyn;
180 #ifdef DD_STATS
181  unsigned int initialSize;
182  unsigned int finalSize;
183 #endif
184  unsigned long localTime;
185 
186  /* Don't reorder if there are too many dead nodes. */
187  if (table->keys - table->dead < (unsigned) minsize)
188  return(1);
189 
190  if (heuristic == CUDD_REORDER_SAME) {
191  heuristic = table->autoMethod;
192  }
193  if (heuristic == CUDD_REORDER_NONE) {
194  return(1);
195  }
196 
197  /* This call to Cudd_ReduceHeap does initiate reordering. Therefore
198  ** we count it.
199  */
200  table->reorderings++;
201 
202  localTime = util_cpu_time();
203 
204  /* Run the hook functions. */
205  hook = table->preReorderingHook;
206  while (hook != NULL) {
207  int res = (hook->f)(table, "BDD", (void *)heuristic);
208  if (res == 0) return(0);
209  hook = hook->next;
210  }
211 
212  if (!ddReorderPreprocess(table)) return(0);
214 
215  if (table->keys > table->peakLiveNodes) {
216  table->peakLiveNodes = table->keys;
217  }
218 #ifdef DD_STATS
219  initialSize = table->keys - table->isolated;
220  ddTotalNISwaps = 0;
221 
222  switch(heuristic) {
223  case CUDD_REORDER_RANDOM:
225  (void) fprintf(table->out,"#:I_RANDOM ");
226  break;
227  case CUDD_REORDER_SIFT:
233  (void) fprintf(table->out,"#:I_SIFTING ");
234  break;
241  (void) fprintf(table->out,"#:I_WINDOW ");
242  break;
244  (void) fprintf(table->out,"#:I_ANNEAL ");
245  break;
247  (void) fprintf(table->out,"#:I_GENETIC ");
248  break;
249  case CUDD_REORDER_LINEAR:
251  (void) fprintf(table->out,"#:I_LINSIFT ");
252  break;
253  case CUDD_REORDER_EXACT:
254  (void) fprintf(table->out,"#:I_EXACT ");
255  break;
256  default:
257  return(0);
258  }
259  (void) fprintf(table->out,"%8d: initial size",initialSize);
260 #endif
261 
262  /* See if we should use alternate threshold for maximum growth. */
263  if (table->reordCycle && table->reorderings % table->reordCycle == 0) {
264  double saveGrowth = table->maxGrowth;
265  table->maxGrowth = table->maxGrowthAlt;
266  result = cuddTreeSifting(table,heuristic);
267  table->maxGrowth = saveGrowth;
268  } else {
269  result = cuddTreeSifting(table,heuristic);
270  }
271 
272 #ifdef DD_STATS
273  (void) fprintf(table->out,"\n");
274  finalSize = table->keys - table->isolated;
275  (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
276  (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
277  ((double)(util_cpu_time() - localTime)/1000.0));
278  (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
280  (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps);
281 #endif
282 
283  if (result == 0)
284  return(0);
285 
286  if (!ddReorderPostprocess(table))
287  return(0);
288 
289  if (table->realign) {
290  if (!cuddZddAlignToBdd(table))
291  return(0);
292  }
293 
294  nextDyn = (table->keys - table->constants.keys + 1) *
295  DD_DYN_RATIO + table->constants.keys;
296  if (table->reorderings < 20 || nextDyn > table->nextDyn)
297  table->nextDyn = nextDyn;
298  else
299  table->nextDyn += 20;
300  if (table->randomizeOrder != 0) {
301  table->nextDyn += Cudd_Random() & table->randomizeOrder;
302  }
303  table->reordered = 1;
304 
305  /* Run hook functions. */
306  hook = table->postReorderingHook;
307  while (hook != NULL) {
308  int res = (hook->f)(table, "BDD", (void *)localTime);
309  if (res == 0) return(0);
310  hook = hook->next;
311  }
312  /* Update cumulative reordering time. */
313  table->reordTime += util_cpu_time() - localTime;
314 
315  return(result);
316 
317 } /* end of Cudd_ReduceHeap */
unsigned int keys
Definition: cuddInt.h:314
unsigned long reordTime
Definition: cuddInt.h:434
Cudd_ReorderingType autoMethod
Definition: cuddInt.h:402
unsigned int peakLiveNodes
Definition: cuddInt.h:445
DdHook * preReorderingHook
Definition: cuddInt.h:421
int reordCycle
Definition: cuddInt.h:399
double maxGrowthAlt
Definition: cuddInt.h:398
int realign
Definition: cuddInt.h:404
double maxGrowth
Definition: cuddInt.h:397
#define DD_DYN_RATIO
Definition: cuddInt.h:153
int cuddTreeSifting(DdManager *table, Cudd_ReorderingType method)
Definition: cuddGroup.c:271
DD_HFP f
Definition: cuddInt.h:241
int ddTotalNumberSwapping
Definition: cuddReorder.c:103
unsigned int randomizeOrder
Definition: cuddInt.h:416
int reordered
Definition: cuddInt.h:392
unsigned int nextDyn
Definition: cuddInt.h:406
unsigned int dead
Definition: cuddInt.h:355
long Cudd_Random(void)
Definition: cuddUtil.c:2710
DdHook * postReorderingHook
Definition: cuddInt.h:422
unsigned int keys
Definition: cuddInt.h:353
static int ddReorderPostprocess(DdManager *table)
Definition: cuddReorder.c:1863
FILE * out
Definition: cuddInt.h:423
long util_cpu_time(void)
Definition: cpu_time.c:34
static int ddReorderPreprocess(DdManager *table)
Definition: cuddReorder.c:1825
struct DdHook * next
Definition: cuddInt.h:242
unsigned int reorderings
Definition: cuddInt.h:393
int cuddZddAlignToBdd(DdManager *table)
Definition: cuddZddReord.c:348
DdSubtable constants
Definition: cuddInt.h:351
static int result
Definition: cuddGenetic.c:121
int isolated
Definition: cuddInt.h:368
if(DEFINED IN_SOURCE_BUILD) set(LLVM_LINK_COMPONENTS BitWriter Core IPO IrReader InstCombine Instrumentation Target Linker Analysis ScalarOpts Support Svf Cudd) add_llvm_tool(dvf dda.cpp) else() add_executable(dvf dda.cpp) target_link_libraries(dvf Svf Cudd $
Definition: CMakeLists.txt:2

◆ Cudd_ShuffleHeap()

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 337 of file cuddReorder.c.

340 {
341 
342  int result;
343  int i;
344  int identity = 1;
345  int *perm;
346 
347  /* Don't waste time in case of identity permutation. */
348  for (i = 0; i < table->size; i++) {
349  if (permutation[i] != table->invperm[i]) {
350  identity = 0;
351  break;
352  }
353  }
354  if (identity == 1) {
355  return(1);
356  }
357  if (!ddReorderPreprocess(table)) return(0);
358  if (table->keys > table->peakLiveNodes) {
359  table->peakLiveNodes = table->keys;
360  }
361 
362  perm = ALLOC(int, table->size);
363  for (i = 0; i < table->size; i++)
364  perm[permutation[i]] = i;
365  if (!ddCheckPermuation(table,table->tree,perm,permutation)) {
366  FREE(perm);
367  return(0);
368  }
369  if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) {
370  FREE(perm);
371  return(0);
372  }
373  FREE(perm);
374 
375  result = ddShuffle(table,permutation);
376 
377  if (!ddReorderPostprocess(table)) return(0);
378 
379  return(result);
380 
381 } /* end of Cudd_ShuffleHeap */
static int ddCheckPermuation(DdManager *table, MtrNode *treenode, int *perm, int *invperm)
Definition: cuddReorder.c:2102
unsigned int peakLiveNodes
Definition: cuddInt.h:445
#define FREE(obj)
Definition: util.h:80
int size
Definition: cuddInt.h:345
MtrNode * tree
Definition: cuddInt.h:408
unsigned int keys
Definition: cuddInt.h:353
#define ALLOC(type, num)
Definition: util.h:76
static int ddReorderPostprocess(DdManager *table)
Definition: cuddReorder.c:1863
static int ddUpdateMtrTree(DdManager *table, MtrNode *treenode, int *perm, int *invperm)
Definition: cuddReorder.c:2043
static int ddReorderPreprocess(DdManager *table)
Definition: cuddReorder.c:1825
static int ddShuffle(DdManager *table, int *permutation)
Definition: cuddReorder.c:1896
int * invperm
Definition: cuddInt.h:371
static int result
Definition: cuddGenetic.c:121

◆ cuddBddAlignToZdd()

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 1250 of file cuddReorder.c.

1252 {
1253  int *invperm; /* permutation array */
1254  int M; /* ratio of ZDD variables to BDD variables */
1255  int i; /* loop index */
1256  int result; /* return value */
1257 
1258  /* We assume that a ratio of 0 is OK. */
1259  if (table->size == 0)
1260  return(1);
1261 
1262  M = table->sizeZ / table->size;
1263  /* Check whether the number of ZDD variables is a multiple of the
1264  ** number of BDD variables.
1265  */
1266  if (M * table->size != table->sizeZ)
1267  return(0);
1268  /* Create and initialize the inverse permutation array. */
1269  invperm = ALLOC(int,table->size);
1270  if (invperm == NULL) {
1271  table->errorCode = CUDD_MEMORY_OUT;
1272  return(0);
1273  }
1274  for (i = 0; i < table->sizeZ; i += M) {
1275  int indexZ = table->invpermZ[i];
1276  int index = indexZ / M;
1277  invperm[i / M] = index;
1278  }
1279  /* Eliminate dead nodes. Do not scan the cache again, because we
1280  ** assume that Cudd_zddReduceHeap has already cleared it.
1281  */
1282  cuddGarbageCollect(table,0);
1283 
1284  /* Initialize number of isolated projection functions. */
1285  table->isolated = 0;
1286  for (i = 0; i < table->size; i++) {
1287  if (table->vars[i]->ref == 1) table->isolated++;
1288  }
1289 
1290  /* Initialize the interaction matrix. */
1291  result = cuddInitInteract(table);
1292  if (result == 0) return(0);
1293 
1294  result = ddShuffle(table, invperm);
1295  FREE(invperm);
1296  /* Free interaction matrix. */
1297  FREE(table->interact);
1298  /* Fix the BDD variable group tree. */
1299  bddFixTree(table,table->tree);
1300  return(result);
1301 
1302 } /* end of cuddBddAlignToZdd */
DdHalfWord ref
Definition: cudd.h:272
#define FREE(obj)
Definition: util.h:80
int * invpermZ
Definition: cuddInt.h:372
int size
Definition: cuddInt.h:345
int cuddInitInteract(DdManager *table)
Definition: cuddInteract.c:234
MtrNode * tree
Definition: cuddInt.h:408
static void bddFixTree(DdManager *table, MtrNode *treenode)
Definition: cuddReorder.c:2009
int cuddGarbageCollect(DdManager *unique, int clearCache)
Definition: cuddTable.c:762
#define ALLOC(type, num)
Definition: util.h:76
long * interact
Definition: cuddInt.h:377
int sizeZ
Definition: cuddInt.h:346
DdNode ** vars
Definition: cuddInt.h:373
static int ddShuffle(DdManager *table, int *permutation)
Definition: cuddReorder.c:1896
static int result
Definition: cuddGenetic.c:121
int isolated
Definition: cuddInt.h:368
Cudd_ErrorType errorCode
Definition: cuddInt.h:425

◆ cuddDynamicAllocNode()

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 405 of file cuddReorder.c.

407 {
408  int i;
409  DdNodePtr *mem;
410  DdNode *list, *node;
411  extern DD_OOMFP MMoutOfMemory;
412  DD_OOMFP saveHandler;
413 
414  if (table->nextFree == NULL) { /* free list is empty */
415  /* Try to allocate a new block. */
416  saveHandler = MMoutOfMemory;
417  MMoutOfMemory = Cudd_OutOfMem;
418  mem = (DdNodePtr *) ALLOC(DdNode, DD_MEM_CHUNK + 1);
419  MMoutOfMemory = saveHandler;
420  if (mem == NULL && table->stash != NULL) {
421  FREE(table->stash);
422  table->stash = NULL;
423  /* Inhibit resizing of tables. */
424  table->maxCacheHard = table->cacheSlots - 1;
425  table->cacheSlack = - (int) (table->cacheSlots + 1);
426  for (i = 0; i < table->size; i++) {
427  table->subtables[i].maxKeys <<= 2;
428  }
429  mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
430  }
431  if (mem == NULL) {
432  /* Out of luck. Call the default handler to do
433  ** whatever it specifies for a failed malloc. If this
434  ** handler returns, then set error code, print
435  ** warning, and return. */
436  (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
437  table->errorCode = CUDD_MEMORY_OUT;
438 #ifdef DD_VERBOSE
439  (void) fprintf(table->err,
440  "cuddDynamicAllocNode: out of memory");
441  (void) fprintf(table->err,"Memory in use = %lu\n",
442  table->memused);
443 #endif
444  return(NULL);
445  } else { /* successful allocation; slice memory */
446  unsigned long offset;
447  table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
448  mem[0] = (DdNode *) table->memoryList;
449  table->memoryList = mem;
450 
451  /* Here we rely on the fact that the size of a DdNode is a
452  ** power of 2 and a multiple of the size of a pointer.
453  ** If we align one node, all the others will be aligned
454  ** as well. */
455  offset = (unsigned long) mem & (sizeof(DdNode) - 1);
456  mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
457 #ifdef DD_DEBUG
458  assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0);
459 #endif
460  list = (DdNode *) mem;
461 
462  i = 1;
463  do {
464  list[i - 1].ref = 0;
465  list[i - 1].next = &list[i];
466  } while (++i < DD_MEM_CHUNK);
467 
468  list[DD_MEM_CHUNK-1].ref = 0;
469  list[DD_MEM_CHUNK - 1].next = NULL;
470 
471  table->nextFree = &list[0];
472  }
473  } /* if free list empty */
474 
475  node = table->nextFree;
476  table->nextFree = node->next;
477  return (node);
478 
479 } /* end of cuddDynamicAllocNode */
DdHalfWord ref
Definition: cudd.h:272
void Cudd_OutOfMem(long size)
Definition: cuddUtil.c:2845
Definition: cudd.h:270
#define FREE(obj)
Definition: util.h:80
#define assert(ex)
Definition: util.h:141
int size
Definition: cuddInt.h:345
unsigned int maxCacheHard
Definition: cuddInt.h:343
FILE * err
Definition: cuddInt.h:424
DdSubtable * subtables
Definition: cuddInt.h:349
DdNode * DdNodePtr
Definition: cuddInt.h:253
void(* DD_OOMFP)(long)
Definition: cudd.h:311
struct DdNode DdNode
Definition: cudd.h:262
unsigned int cacheSlots
Definition: cuddInt.h:337
char * stash
Definition: cuddInt.h:382
#define ALLOC(type, num)
Definition: util.h:76
DdNode * next
Definition: cudd.h:273
unsigned int maxKeys
Definition: cuddInt.h:315
int cacheSlack
Definition: cuddInt.h:342
void(* MMoutOfMemory)(long)
Definition: safe_mem.c:32
DdNode ** memoryList
Definition: cuddInt.h:380
unsigned long memused
Definition: cuddInt.h:429
DdNode * nextFree
Definition: cuddInt.h:381
#define DD_MEM_CHUNK
Definition: cuddInt.h:105
Cudd_ErrorType errorCode
Definition: cuddInt.h:425

◆ cuddNextHigh()

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 715 of file cuddReorder.c.

718 {
719  return(x+1);
720 
721 } /* end of cuddNextHigh */

◆ cuddNextLow()

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 737 of file cuddReorder.c.

740 {
741  return(x-1);
742 
743 } /* end of cuddNextLow */

◆ cuddSifting()

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 502 of file cuddReorder.c.

506 {
507  int i;
508  int *var;
509  int size;
510  int x;
511  int result;
512 #ifdef DD_STATS
513  int previousSize;
514 #endif
515 
516  size = table->size;
517 
518  /* Find order in which to sift variables. */
519  var = NULL;
520  entry = ALLOC(int,size);
521  if (entry == NULL) {
522  table->errorCode = CUDD_MEMORY_OUT;
523  goto cuddSiftingOutOfMem;
524  }
525  var = ALLOC(int,size);
526  if (var == NULL) {
527  table->errorCode = CUDD_MEMORY_OUT;
528  goto cuddSiftingOutOfMem;
529  }
530 
531  for (i = 0; i < size; i++) {
532  x = table->perm[i];
533  entry[i] = table->subtables[x].keys;
534  var[i] = i;
535  }
536 
537  qsort((void *)var,size,sizeof(int),(DD_QSFP)ddUniqueCompare);
538 
539  /* Now sift. */
540  for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
541  if (ddTotalNumberSwapping >= table->siftMaxSwap)
542  break;
543  if (util_cpu_time() - table->startTime + table->reordTime
544  > table->timeLimit) {
545  table->autoDyn = 0; /* prevent further reordering */
546  break;
547  }
548  x = table->perm[var[i]];
549 
550  if (x < lower || x > upper || table->subtables[x].bindVar == 1)
551  continue;
552 #ifdef DD_STATS
553  previousSize = table->keys - table->isolated;
554 #endif
555  result = ddSiftingAux(table, x, lower, upper);
556  if (!result) goto cuddSiftingOutOfMem;
557 #ifdef DD_STATS
558  if (table->keys < (unsigned) previousSize + table->isolated) {
559  (void) fprintf(table->out,"-");
560  } else if (table->keys > (unsigned) previousSize + table->isolated) {
561  (void) fprintf(table->out,"+"); /* should never happen */
562  (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
563  } else {
564  (void) fprintf(table->out,"=");
565  }
566  fflush(table->out);
567 #endif
568  }
569 
570  FREE(var);
571  FREE(entry);
572 
573  return(1);
574 
575 cuddSiftingOutOfMem:
576 
577  if (entry != NULL) FREE(entry);
578  if (var != NULL) FREE(var);
579 
580  return(0);
581 
582 } /* end of cuddSifting */
static int * entry
Definition: cuddReorder.c:101
unsigned int keys
Definition: cuddInt.h:314
unsigned long reordTime
Definition: cuddInt.h:434
#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 size
Definition: cuddInt.h:345
FILE * err
Definition: cuddInt.h:424
static int ddSiftingAux(DdManager *table, int x, int xLow, int xHigh)
Definition: cuddReorder.c:1487
int bindVar
Definition: cuddInt.h:318
DdSubtable * subtables
Definition: cuddInt.h:349
int ddTotalNumberSwapping
Definition: cuddReorder.c:103
unsigned int keys
Definition: cuddInt.h:353
#define ALLOC(type, num)
Definition: util.h:76
FILE * out
Definition: cuddInt.h:423
static int ddUniqueCompare(int *ptrX, int *ptrY)
Definition: cuddReorder.c:1322
#define ddMin(x, y)
Definition: cuddInt.h:771
long util_cpu_time(void)
Definition: cpu_time.c:34
int siftMaxVar
Definition: cuddInt.h:395
static int result
Definition: cuddGenetic.c:121
int isolated
Definition: cuddInt.h:368
int autoDyn
Definition: cuddInt.h:400
int * perm
Definition: cuddInt.h:369
unsigned long timeLimit
Definition: cuddInt.h:427
Cudd_ErrorType errorCode
Definition: cuddInt.h:425

◆ cuddSwapInPlace()

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 760 of file cuddReorder.c.

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

◆ cuddSwapping()

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 604 of file cuddReorder.c.

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

◆ ddCheckPermuation()

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 2102 of file cuddReorder.c.

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

◆ ddReorderPostprocess()

static int ddReorderPostprocess ( DdManager table)
static

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

Synopsis [Cleans up at the end of reordering.]

Description []

SideEffects [None]

Definition at line 1863 of file cuddReorder.c.

1865 {
1866 
1867 #ifdef DD_VERBOSE
1868  (void) fflush(table->out);
1869 #endif
1870 
1871  /* Free interaction matrix. */
1872  FREE(table->interact);
1873 
1874  return(1);
1875 
1876 } /* end of ddReorderPostprocess */
#define FREE(obj)
Definition: util.h:80
FILE * out
Definition: cuddInt.h:423
long * interact
Definition: cuddInt.h:377

◆ ddReorderPreprocess()

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 1825 of file cuddReorder.c.

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

◆ ddShuffle()

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 1896 of file cuddReorder.c.

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

◆ ddSiftingAux()

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 1487 of file cuddReorder.c.

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

◆ ddSiftingBackward()

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 1786 of file cuddReorder.c.

1790 {
1791  Move *move;
1792  int res;
1793 
1794  for (move = moves; move != NULL; move = move->next) {
1795  if (move->size < size) {
1796  size = move->size;
1797  }
1798  }
1799 
1800  for (move = moves; move != NULL; move = move->next) {
1801  if (move->size == size) return(1);
1802  res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
1803  if (!res) return(0);
1804  }
1805 
1806  return(1);
1807 
1808 } /* end of ddSiftingBackward */
Definition: cuddInt.h:469
DdHalfWord x
Definition: cuddInt.h:470
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:760
DdHalfWord y
Definition: cuddInt.h:471
struct Move * next
Definition: cuddInt.h:474
int size
Definition: cuddInt.h:473

◆ ddSiftingDown()

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 1694 of file cuddReorder.c.

1698 {
1699  Move *moves;
1700  Move *move;
1701  int y;
1702  int size;
1703  int R; /* upper bound on node decrease */
1704  int limitSize;
1705  int xindex, yindex;
1706  int isolated;
1707 #ifdef DD_DEBUG
1708  int checkR;
1709  int z;
1710  int zindex;
1711 #endif
1712 
1713  moves = NULL;
1714  /* Initialize R */
1715  xindex = table->invperm[x];
1716  limitSize = size = table->keys - table->isolated;
1717  R = 0;
1718  for (y = xHigh; y > x; y--) {
1719  yindex = table->invperm[y];
1720  if (cuddTestInteract(table,xindex,yindex)) {
1721  isolated = table->vars[yindex]->ref == 1;
1722  R += table->subtables[y].keys - isolated;
1723  }
1724  }
1725 
1726  y = cuddNextHigh(table,x);
1727  while (y <= xHigh && size - R < limitSize) {
1728 #ifdef DD_DEBUG
1729  checkR = 0;
1730  for (z = xHigh; z > x; z--) {
1731  zindex = table->invperm[z];
1732  if (cuddTestInteract(table,xindex,zindex)) {
1733  isolated = table->vars[zindex]->ref == 1;
1734  checkR += table->subtables[z].keys - isolated;
1735  }
1736  }
1737  assert(R == checkR);
1738 #endif
1739  /* Update upper bound on node decrease. */
1740  yindex = table->invperm[y];
1741  if (cuddTestInteract(table,xindex,yindex)) {
1742  isolated = table->vars[yindex]->ref == 1;
1743  R -= table->subtables[y].keys - isolated;
1744  }
1745  size = cuddSwapInPlace(table,x,y);
1746  if (size == 0) goto ddSiftingDownOutOfMem;
1747  move = (Move *) cuddDynamicAllocNode(table);
1748  if (move == NULL) goto ddSiftingDownOutOfMem;
1749  move->x = x;
1750  move->y = y;
1751  move->size = size;
1752  move->next = moves;
1753  moves = move;
1754  if ((double) size > (double) limitSize * table->maxGrowth) break;
1755  if (size < limitSize) limitSize = size;
1756  x = y;
1757  y = cuddNextHigh(table,x);
1758  }
1759  return(moves);
1760 
1761 ddSiftingDownOutOfMem:
1762  while (moves != NULL) {
1763  move = moves->next;
1764  cuddDeallocMove(table, moves);
1765  moves = move;
1766  }
1767  return((Move *) CUDD_OUT_OF_MEM);
1768 
1769 } /* end of ddSiftingDown */
DdHalfWord ref
Definition: cudd.h:272
unsigned int keys
Definition: cuddInt.h:314
#define CUDD_OUT_OF_MEM
Definition: cudd.h:91
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:405
#define assert(ex)
Definition: util.h:141
Definition: cuddInt.h:469
double maxGrowth
Definition: cuddInt.h:397
DdSubtable * subtables
Definition: cuddInt.h:349
unsigned int keys
Definition: cuddInt.h:353
int cuddNextHigh(DdManager *table, int x)
Definition: cuddReorder.c:715
DdHalfWord x
Definition: cuddInt.h:470
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:760
DdHalfWord y
Definition: cuddInt.h:471
DdNode ** vars
Definition: cuddInt.h:373
struct Move * next
Definition: cuddInt.h:474
int * invperm
Definition: cuddInt.h:371
int isolated
Definition: cuddInt.h:368
int cuddTestInteract(DdManager *table, int x, int y)
Definition: cuddInteract.c:188
int size
Definition: cuddInt.h:473

◆ ddSiftingUp()

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 1594 of file cuddReorder.c.

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

◆ ddSiftUp()

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 1973 of file cuddReorder.c.

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

◆ ddSwapAny()

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 1346 of file cuddReorder.c.

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

◆ ddUniqueCompare()

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 1322 of file cuddReorder.c.

1325 {
1326 #if 0
1327  if (entry[*ptrY] == entry[*ptrX]) {
1328  return((*ptrX) - (*ptrY));
1329  }
1330 #endif
1331  return(entry[*ptrY] - entry[*ptrX]);
1332 
1333 } /* end of ddUniqueCompare */
static int * entry
Definition: cuddReorder.c:101

◆ ddUpdateMtrTree()

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 2043 of file cuddReorder.c.

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

Variable Documentation

◆ DD_UNUSED

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

Definition at line 98 of file cuddReorder.c.

◆ ddTotalNumberSwapping

int ddTotalNumberSwapping

Definition at line 103 of file cuddReorder.c.

◆ entry

int* entry
static

Definition at line 101 of file cuddReorder.c.