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

Go to the source code of this file.

Macros

#define DD_NORMAL_SIFT   0
 
#define DD_LAZY_SIFT   1
 
#define DD_SIFT_DOWN   0
 
#define DD_SIFT_UP   1
 

Typedefs

typedef int(* DD_CHKFP )(DdManager *, int, int)
 

Functions

static int ddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
 
static int ddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
 
static void ddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper)
 
static int ddUniqueCompareGroup (int *ptrX, int *ptrY)
 
static int ddGroupSifting (DdManager *table, int lower, int upper, DD_CHKFP checkFunction, int lazyFlag)
 
static void ddCreateGroup (DdManager *table, int x, int y)
 
static int ddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh, DD_CHKFP checkFunction, int lazyFlag)
 
static int ddGroupSiftingUp (DdManager *table, int y, int xLow, DD_CHKFP checkFunction, Move **moves)
 
static int ddGroupSiftingDown (DdManager *table, int x, int xHigh, DD_CHKFP checkFunction, Move **moves)
 
static int ddGroupMove (DdManager *table, int x, int y, Move **moves)
 
static int ddGroupMoveBackward (DdManager *table, int x, int y)
 
static int ddGroupSiftingBackward (DdManager *table, Move *moves, int size, int upFlag, int lazyFlag)
 
static void ddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high)
 
static void ddDissolveGroup (DdManager *table, int x, int y)
 
static int ddNoCheck (DdManager *table, int x, int y)
 
static int ddSecDiffCheck (DdManager *table, int x, int y)
 
static int ddExtSymmCheck (DdManager *table, int x, int y)
 
static int ddVarGroupCheck (DdManager *table, int x, int y)
 
static int ddSetVarHandled (DdManager *dd, int index)
 
static int ddResetVarHandled (DdManager *dd, int index)
 
static int ddIsVarHandled (DdManager *dd, int index)
 
MtrNodeCudd_MakeTreeNode (DdManager *dd, unsigned int low, unsigned int size, unsigned int type)
 
int cuddTreeSifting (DdManager *table, Cudd_ReorderingType method)
 

Variables

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

Macro Definition Documentation

#define DD_LAZY_SIFT   1

Definition at line 92 of file cuddGroup.c.

#define DD_NORMAL_SIFT   0

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

FileName [cuddGroup.c]

PackageName [cudd]

Synopsis [Functions for group sifting.]

Description [External procedures included in this file:

Internal procedures included in this file:

Static procedures included in this module:

]

Author [Shipra Panda, 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 91 of file cuddGroup.c.

#define DD_SIFT_DOWN   0

Definition at line 95 of file cuddGroup.c.

#define DD_SIFT_UP   1

Definition at line 96 of file cuddGroup.c.

Typedef Documentation

typedef int(* DD_CHKFP)(DdManager *, int, int)

Definition at line 109 of file cuddGroup.c.

Function Documentation

MtrNode* Cudd_MakeTreeNode ( DdManager dd,
unsigned int  low,
unsigned int  size,
unsigned int  type 
)

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

Synopsis [Creates a new variable group.]

Description [Creates a new variable group. The group starts at variable and contains size variables. The parameter low is the index of the first variable. If the variable already exists, its current position in the order is known to the manager. If the variable does not exist yet, the position is assumed to be the same as the index. The group tree is created if it does not exist yet. Returns a pointer to the group if successful; NULL otherwise.]

SideEffects [The variable tree is changed.]

SeeAlso [Cudd_MakeZddTreeNode]

Definition at line 206 of file cuddGroup.c.

211 {
212  MtrNode *group;
213  MtrNode *tree;
214  unsigned int level;
215 
216  /* If the variable does not exist yet, the position is assumed to be
217  ** the same as the index. Therefore, applications that rely on
218  ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new
219  ** variables have to create the variables before they group them.
220  */
221  level = (low < (unsigned int) dd->size) ? dd->perm[low] : low;
222 
223  if (level + size - 1> (int) MTR_MAXHIGH)
224  return(NULL);
225 
226  /* If the tree does not exist yet, create it. */
227  tree = dd->tree;
228  if (tree == NULL) {
229  dd->tree = tree = Mtr_InitGroupTree(0, dd->size);
230  if (tree == NULL)
231  return(NULL);
232  tree->index = dd->invperm[0];
233  }
234 
235  /* Extend the upper bound of the tree if necessary. This allows the
236  ** application to create groups even before the variables are created.
237  */
238  tree->size = ddMax(tree->size, ddMax(level + size, (unsigned) dd->size));
239 
240  /* Create the group. */
241  group = Mtr_MakeGroup(tree, level, size, type);
242  if (group == NULL)
243  return(NULL);
244 
245  /* Initialize the index field to the index of the variable currently
246  ** in position low. This field will be updated by the reordering
247  ** procedure to provide a handle to the group once it has been moved.
248  */
249  group->index = (MtrHalfWord) low;
250 
251  return(group);
252 
253 } /* end of Cudd_MakeTreeNode */
#define MTR_MAXHIGH
Definition: mtr.h:112
unsigned short MtrHalfWord
Definition: mtr.h:128
MtrHalfWord size
Definition: mtr.h:134
int size
Definition: cuddInt.h:361
MtrNode * tree
Definition: cuddInt.h:424
MtrHalfWord index
Definition: mtr.h:135
#define ddMax(x, y)
Definition: cuddInt.h:832
static int size
Definition: cuddSign.c:86
Definition: mtr.h:131
MtrNode * Mtr_InitGroupTree(int lower, int size)
Definition: mtrGroup.c:121
int * invperm
Definition: cuddInt.h:388
MtrNode * Mtr_MakeGroup(MtrNode *root, unsigned int low, unsigned int high, unsigned int flags)
Definition: mtrGroup.c:158
int * perm
Definition: cuddInt.h:386
int cuddTreeSifting ( DdManager table,
Cudd_ReorderingType  method 
)

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

Synopsis [Tree sifting algorithm.]

Description [Tree sifting algorithm. Assumes that a tree representing a group hierarchy is passed as a parameter. It then reorders each group in postorder fashion by calling ddTreeSiftingAux. Assumes that no dead nodes are present. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

Definition at line 274 of file cuddGroup.c.

277 {
278  int i;
279  int nvars;
280  int result;
281  int tempTree;
282 
283  /* If no tree is provided we create a temporary one in which all
284  ** variables are in a single group. After reordering this tree is
285  ** destroyed.
286  */
287  tempTree = table->tree == NULL;
288  if (tempTree) {
289  table->tree = Mtr_InitGroupTree(0,table->size);
290  table->tree->index = table->invperm[0];
291  }
292  nvars = table->size;
293 
294 #ifdef DD_DEBUG
295  if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:");
296  Mtr_PrintGroups(table->tree,pr <= 0);
297 #endif
298 
299 #ifdef DD_STATS
300  extsymmcalls = 0;
301  extsymm = 0;
302  secdiffcalls = 0;
303  secdiff = 0;
304  secdiffmisfire = 0;
305 
306  (void) fprintf(table->out,"\n");
307  if (!tempTree)
308  (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n",
309  ddCountInternalMtrNodes(table,table->tree));
310 #endif
311 
312  /* Initialize the group of each subtable to itself. Initially
313  ** there are no groups. Groups are created according to the tree
314  ** structure in postorder fashion.
315  */
316  for (i = 0; i < nvars; i++)
317  table->subtables[i].next = i;
318 
319 
320  /* Reorder. */
321  result = ddTreeSiftingAux(table, table->tree, method);
322 
323 #ifdef DD_STATS /* print stats */
324  if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
325  (table->groupcheck == CUDD_GROUP_CHECK7 ||
326  table->groupcheck == CUDD_GROUP_CHECK5)) {
327  (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
328  (void) fprintf(table->out,"extsymm = %d",extsymm);
329  }
330  if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
331  table->groupcheck == CUDD_GROUP_CHECK7) {
332  (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
333  (void) fprintf(table->out,"secdiff = %d\n",secdiff);
334  (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
335  }
336 #endif
337 
338  if (tempTree)
339  Cudd_FreeTree(table);
340  return(result);
341 
342 } /* end of cuddTreeSifting */
Cudd_AggregationType groupcheck
Definition: cuddInt.h:426
int size
Definition: cuddInt.h:361
DdSubtable * subtables
Definition: cuddInt.h:365
MtrNode * tree
Definition: cuddInt.h:424
void Cudd_FreeTree(DdManager *dd)
Definition: cuddAPI.c:2180
MtrHalfWord index
Definition: mtr.h:135
FILE * out
Definition: cuddInt.h:441
static int ddTreeSiftingAux(DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
Definition: cuddGroup.c:361
void Mtr_PrintGroups(MtrNode *root, int silent)
Definition: mtrGroup.c:537
MtrNode * Mtr_InitGroupTree(int lower, int size)
Definition: mtrGroup.c:121
unsigned int next
Definition: cuddInt.h:333
int * invperm
Definition: cuddInt.h:388
static int result
Definition: cuddGenetic.c:125
static void ddCreateGroup ( DdManager table,
int  x,
int  y 
)
static

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

Synopsis [Creates a group encompassing variables from x to y in the DD table.]

Description [Creates a group encompassing variables from x to y in the DD table. In the current implementation it must be y == x+1. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 915 of file cuddGroup.c.

919 {
920  int gybot;
921 
922 #ifdef DD_DEBUG
923  assert(y == x+1);
924 #endif
925 
926  /* Find bottom of second group. */
927  gybot = y;
928  while ((unsigned) gybot < table->subtables[gybot].next)
929  gybot = table->subtables[gybot].next;
930 
931  /* Link groups. */
932  table->subtables[x].next = y;
933  table->subtables[gybot].next = x;
934 
935  return;
936 
937 } /* ddCreateGroup */
DdSubtable * subtables
Definition: cuddInt.h:365
unsigned int next
Definition: cuddInt.h:333
#define assert(ex)
Definition: util_old.h:213
static void ddDissolveGroup ( DdManager table,
int  x,
int  y 
)
static

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

Synopsis [Dissolves a group in the DD table.]

Description [x and y are variables in a group to be cut in two. The cut is to pass between x and y.]

SideEffects [None]

Definition at line 1823 of file cuddGroup.c.

1827 {
1828  int topx;
1829  int boty;
1830 
1831  /* find top and bottom of the two groups */
1832  boty = y;
1833  while ((unsigned) boty < table->subtables[boty].next)
1834  boty = table->subtables[boty].next;
1835 
1836  topx = table->subtables[boty].next;
1837 
1838  table->subtables[boty].next = y;
1839  table->subtables[x].next = topx;
1840 
1841  return;
1842 
1843 } /* end of ddDissolveGroup */
DdSubtable * subtables
Definition: cuddInt.h:365
unsigned int next
Definition: cuddInt.h:333
static int ddExtSymmCheck ( DdManager table,
int  x,
int  y 
)
static

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

Synopsis [Checks for extended symmetry of x and y.]

Description [Checks for extended symmetry of x and y. Returns 1 in case of extended symmetry; 0 otherwise.]

SideEffects [None]

Definition at line 1938 of file cuddGroup.c.

1942 {
1943  DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
1944  DdNode *one;
1945  unsigned comple; /* f0 is complemented */
1946  int notproj; /* f is not a projection function */
1947  int arccount; /* number of arcs from layer x to layer y */
1948  int TotalRefCount; /* total reference count of layer y minus 1 */
1949  int counter; /* number of nodes of layer x that are allowed */
1950  /* to violate extended symmetry conditions */
1951  int arccounter; /* number of arcs into layer y that are allowed */
1952  /* to come from layers other than x */
1953  int i;
1954  int xindex;
1955  int yindex;
1956  int res;
1957  int slots;
1958  DdNodePtr *list;
1959  DdNode *sentinel = &(table->sentinel);
1960 
1961  xindex = table->invperm[x];
1962  yindex = table->invperm[y];
1963 
1964  /* If the two variables do not interact, we do not want to merge them. */
1965  if (!cuddTestInteract(table,xindex,yindex))
1966  return(0);
1967 
1968 #ifdef DD_DEBUG
1969  /* Checks that x and y do not contain just the projection functions.
1970  ** With the test on interaction, these test become redundant,
1971  ** because an isolated projection function does not interact with
1972  ** any other variable.
1973  */
1974  if (table->subtables[x].keys == 1) {
1975  assert(table->vars[xindex]->ref != 1);
1976  }
1977  if (table->subtables[y].keys == 1) {
1978  assert(table->vars[yindex]->ref != 1);
1979  }
1980 #endif
1981 
1982 #ifdef DD_STATS
1983  extsymmcalls++;
1984 #endif
1985 
1986  arccount = 0;
1987  counter = (int) (table->subtables[x].keys *
1988  (table->symmviolation/100.0) + 0.5);
1989  one = DD_ONE(table);
1990 
1991  slots = table->subtables[x].slots;
1992  list = table->subtables[x].nodelist;
1993  for (i = 0; i < slots; i++) {
1994  f = list[i];
1995  while (f != sentinel) {
1996  /* Find f1, f0, f11, f10, f01, f00. */
1997  f1 = cuddT(f);
1998  f0 = Cudd_Regular(cuddE(f));
1999  comple = Cudd_IsComplement(cuddE(f));
2000  notproj = f1 != one || f0 != one || f->ref != (DdHalfWord) 1;
2001  if (f1->index == (unsigned) yindex) {
2002  arccount++;
2003  f11 = cuddT(f1); f10 = cuddE(f1);
2004  } else {
2005  if ((int) f0->index != yindex) {
2006  /* If f is an isolated projection function it is
2007  ** allowed to bypass layer y.
2008  */
2009  if (notproj) {
2010  if (counter == 0)
2011  return(0);
2012  counter--; /* f bypasses layer y */
2013  }
2014  }
2015  f11 = f10 = f1;
2016  }
2017  if ((int) f0->index == yindex) {
2018  arccount++;
2019  f01 = cuddT(f0); f00 = cuddE(f0);
2020  } else {
2021  f01 = f00 = f0;
2022  }
2023  if (comple) {
2024  f01 = Cudd_Not(f01);
2025  f00 = Cudd_Not(f00);
2026  }
2027 
2028  /* Unless we are looking at a projection function
2029  ** without external references except the one from the
2030  ** table, we insist that f01 == f10 or f11 == f00
2031  */
2032  if (notproj) {
2033  if (f01 != f10 && f11 != f00) {
2034  if (counter == 0)
2035  return(0);
2036  counter--;
2037  }
2038  }
2039 
2040  f = f->next;
2041  } /* while */
2042  } /* for */
2043 
2044  /* Calculate the total reference counts of y */
2045  TotalRefCount = -1; /* -1 for projection function */
2046  slots = table->subtables[y].slots;
2047  list = table->subtables[y].nodelist;
2048  for (i = 0; i < slots; i++) {
2049  f = list[i];
2050  while (f != sentinel) {
2051  TotalRefCount += f->ref;
2052  f = f->next;
2053  }
2054  }
2055 
2056  arccounter = (int) (table->subtables[y].keys *
2057  (table->arcviolation/100.0) + 0.5);
2058  res = arccount >= TotalRefCount - arccounter;
2059 
2060 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
2061  if (res) {
2062  (void) fprintf(table->out,
2063  "Found extended symmetry! x = %d\ty = %d\tPos(%d,%d)\n",
2064  xindex,yindex,x,y);
2065  }
2066 #endif
2067 
2068 #ifdef DD_STATS
2069  if (res)
2070  extsymm++;
2071 #endif
2072  return(res);
2073 
2074 } /* end ddExtSymmCheck */
DdHalfWord ref
Definition: cudd.h:280
unsigned int keys
Definition: cuddInt.h:330
unsigned short DdHalfWord
Definition: cudd.h:262
Definition: cudd.h:278
#define Cudd_Not(node)
Definition: cudd.h:367
#define Cudd_Regular(node)
Definition: cudd.h:397
DdSubtable * subtables
Definition: cuddInt.h:365
#define Cudd_IsComplement(node)
Definition: cudd.h:425
DdNode sentinel
Definition: cuddInt.h:344
static DdNode * one
Definition: cuddDecomp.c:112
FILE * out
Definition: cuddInt.h:441
DdNode * next
Definition: cudd.h:281
int symmviolation
Definition: cuddInt.h:428
DdNode ** nodelist
Definition: cuddInt.h:327
#define cuddT(node)
Definition: cuddInt.h:636
DdHalfWord index
Definition: cudd.h:279
unsigned int slots
Definition: cuddInt.h:329
DdNode ** vars
Definition: cuddInt.h:390
#define cuddE(node)
Definition: cuddInt.h:652
int arcviolation
Definition: cuddInt.h:429
#define assert(ex)
Definition: util_old.h:213
int * invperm
Definition: cuddInt.h:388
int cuddTestInteract(DdManager *table, int x, int y)
Definition: cuddInteract.c:191
#define DD_ONE(dd)
Definition: cuddInt.h:911
static void ddFindNodeHiLo ( DdManager table,
MtrNode treenode,
int *  lower,
int *  upper 
)
static

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

Synopsis [Finds the lower and upper bounds of the group represented by treenode.]

Description [Finds the lower and upper bounds of the group represented by treenode. From the index and size fields we need to derive the current positions, and find maximum and minimum.]

SideEffects [The bounds are returned as side effects.]

SeeAlso []

Definition at line 617 of file cuddGroup.c.

622 {
623  int low;
624  int high;
625 
626  /* Check whether no variables in this group already exist.
627  ** If so, return immediately. The calling procedure will know from
628  ** the values of upper that no reordering is needed.
629  */
630  if ((int) treenode->low >= table->size) {
631  *lower = table->size;
632  *upper = -1;
633  return;
634  }
635 
636  *lower = low = (unsigned int) table->perm[treenode->index];
637  high = (int) (low + treenode->size - 1);
638 
639  if (high >= table->size) {
640  /* This is the case of a partially existing group. The aim is to
641  ** reorder as many variables as safely possible. If the tree
642  ** node is terminal, we just reorder the subset of the group
643  ** that is currently in existence. If the group has
644  ** subgroups, then we only reorder those subgroups that are
645  ** fully instantiated. This way we avoid breaking up a group.
646  */
647  MtrNode *auxnode = treenode->child;
648  if (auxnode == NULL) {
649  *upper = (unsigned int) table->size - 1;
650  } else {
651  /* Search the subgroup that strands the table->size line.
652  ** If the first group starts at 0 and goes past table->size
653  ** upper will get -1, thus correctly signaling that no reordering
654  ** should take place.
655  */
656  while (auxnode != NULL) {
657  int thisLower = table->perm[auxnode->low];
658  int thisUpper = thisLower + auxnode->size - 1;
659  if (thisUpper >= table->size && thisLower < table->size)
660  *upper = (unsigned int) thisLower - 1;
661  auxnode = auxnode->younger;
662  }
663  }
664  } else {
665  /* Normal case: All the variables of the group exist. */
666  *upper = (unsigned int) high;
667  }
668 
669 #ifdef DD_DEBUG
670  /* Make sure that all variables in group are contiguous. */
671  assert(treenode->size >= *upper - *lower + 1);
672 #endif
673 
674  return;
675 
676 } /* end of ddFindNodeHiLo */
MtrHalfWord size
Definition: mtr.h:134
int size
Definition: cuddInt.h:361
struct MtrNode * younger
Definition: mtr.h:139
MtrHalfWord index
Definition: mtr.h:135
static int size
Definition: cuddSign.c:86
MtrHalfWord low
Definition: mtr.h:133
Definition: mtr.h:131
#define assert(ex)
Definition: util_old.h:213
struct MtrNode * child
Definition: mtr.h:137
int * perm
Definition: cuddInt.h:386
static int ddGroupMove ( DdManager table,
int  x,
int  y,
Move **  moves 
)
static

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

Synopsis [Swaps two groups and records the move.]

Description [Swaps two groups and records the move. Returns the number of keys in the DD table in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 1488 of file cuddGroup.c.

1493 {
1494  Move *move;
1495  int size;
1496  int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
1497  int swapx = -1,swapy = -1;
1498 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
1499  int initialSize,bestSize;
1500 #endif
1501 
1502 #ifdef DD_DEBUG
1503  /* We assume that x < y */
1504  assert(x < y);
1505 #endif
1506  /* Find top, bottom, and size for the two groups. */
1507  xbot = x;
1508  xtop = table->subtables[x].next;
1509  xsize = xbot - xtop + 1;
1510  ybot = y;
1511  while ((unsigned) ybot < table->subtables[ybot].next)
1512  ybot = table->subtables[ybot].next;
1513  ytop = y;
1514  ysize = ybot - ytop + 1;
1515 
1516 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
1517  initialSize = bestSize = table->keys - table->isolated;
1518 #endif
1519  /* Sift the variables of the second group up through the first group */
1520  for (i = 1; i <= ysize; i++) {
1521  for (j = 1; j <= xsize; j++) {
1522  size = cuddSwapInPlace(table,x,y);
1523  if (size == 0) goto ddGroupMoveOutOfMem;
1524 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
1525  if (size < bestSize)
1526  bestSize = size;
1527 #endif
1528  swapx = x; swapy = y;
1529  y = x;
1530  x = cuddNextLow(table,y);
1531  }
1532  y = ytop + i;
1533  x = cuddNextLow(table,y);
1534  }
1535 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
1536  if ((bestSize < initialSize) && (bestSize < size))
1537  (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size);
1538 #endif
1539 
1540  /* fix groups */
1541  y = xtop; /* ytop is now where xtop used to be */
1542  for (i = 0; i < ysize - 1; i++) {
1543  table->subtables[y].next = cuddNextHigh(table,y);
1544  y = cuddNextHigh(table,y);
1545  }
1546  table->subtables[y].next = xtop; /* y is bottom of its group, join */
1547  /* it to top of its group */
1548  x = cuddNextHigh(table,y);
1549  newxtop = x;
1550  for (i = 0; i < xsize - 1; i++) {
1551  table->subtables[x].next = cuddNextHigh(table,x);
1552  x = cuddNextHigh(table,x);
1553  }
1554  table->subtables[x].next = newxtop; /* x is bottom of its group, join */
1555  /* it to top of its group */
1556 #ifdef DD_DEBUG
1557  if (pr > 0) (void) fprintf(table->out,"ddGroupMove:\n");
1558 #endif
1559 
1560  /* Store group move */
1561  move = (Move *) cuddDynamicAllocNode(table);
1562  if (move == NULL) goto ddGroupMoveOutOfMem;
1563  move->x = swapx;
1564  move->y = swapy;
1565  move->flags = MTR_DEFAULT;
1566  move->size = table->keys - table->isolated;
1567  move->next = *moves;
1568  *moves = move;
1569 
1570  return(table->keys - table->isolated);
1571 
1572 ddGroupMoveOutOfMem:
1573  while (*moves != NULL) {
1574  move = (*moves)->next;
1575  cuddDeallocMove(table, *moves);
1576  *moves = move;
1577  }
1578  return(0);
1579 
1580 } /* end of ddGroupMove */
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
Definition: cuddInt.h:492
int cuddNextLow(DdManager *table, int x)
Definition: cuddReorder.c:738
DdSubtable * subtables
Definition: cuddInt.h:365
#define MTR_DEFAULT
Definition: mtr.h:99
unsigned int keys
Definition: cuddInt.h:369
FILE * out
Definition: cuddInt.h:441
unsigned int flags
Definition: cuddInt.h:495
DdHalfWord x
Definition: cuddInt.h:493
static int size
Definition: cuddSign.c:86
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
int cuddNextHigh(DdManager *table, int x)
Definition: cuddReorder.c:716
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
DdHalfWord y
Definition: cuddInt.h:494
unsigned int next
Definition: cuddInt.h:333
struct Move * next
Definition: cuddInt.h:497
#define assert(ex)
Definition: util_old.h:213
int isolated
Definition: cuddInt.h:385
int size
Definition: cuddInt.h:496
static int ddGroupMoveBackward ( DdManager table,
int  x,
int  y 
)
static

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

Synopsis [Undoes the swap two groups.]

Description [Undoes the swap two groups. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 1594 of file cuddGroup.c.

1598 {
1599  int size;
1600  int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
1601 
1602 
1603 #ifdef DD_DEBUG
1604  /* We assume that x < y */
1605  assert(x < y);
1606 #endif
1607 
1608  /* Find top, bottom, and size for the two groups. */
1609  xbot = x;
1610  xtop = table->subtables[x].next;
1611  xsize = xbot - xtop + 1;
1612  ybot = y;
1613  while ((unsigned) ybot < table->subtables[ybot].next)
1614  ybot = table->subtables[ybot].next;
1615  ytop = y;
1616  ysize = ybot - ytop + 1;
1617 
1618  /* Sift the variables of the second group up through the first group */
1619  for (i = 1; i <= ysize; i++) {
1620  for (j = 1; j <= xsize; j++) {
1621  size = cuddSwapInPlace(table,x,y);
1622  if (size == 0)
1623  return(0);
1624  y = x;
1625  x = cuddNextLow(table,y);
1626  }
1627  y = ytop + i;
1628  x = cuddNextLow(table,y);
1629  }
1630 
1631  /* fix groups */
1632  y = xtop;
1633  for (i = 0; i < ysize - 1; i++) {
1634  table->subtables[y].next = cuddNextHigh(table,y);
1635  y = cuddNextHigh(table,y);
1636  }
1637  table->subtables[y].next = xtop; /* y is bottom of its group, join */
1638  /* to its top */
1639  x = cuddNextHigh(table,y);
1640  newxtop = x;
1641  for (i = 0; i < xsize - 1; i++) {
1642  table->subtables[x].next = cuddNextHigh(table,x);
1643  x = cuddNextHigh(table,x);
1644  }
1645  table->subtables[x].next = newxtop; /* x is bottom of its group, join */
1646  /* to its top */
1647 #ifdef DD_DEBUG
1648  if (pr > 0) (void) fprintf(table->out,"ddGroupMoveBackward:\n");
1649 #endif
1650 
1651  return(1);
1652 
1653 } /* end of ddGroupMoveBackward */
int cuddNextLow(DdManager *table, int x)
Definition: cuddReorder.c:738
DdSubtable * subtables
Definition: cuddInt.h:365
FILE * out
Definition: cuddInt.h:441
static int size
Definition: cuddSign.c:86
int cuddNextHigh(DdManager *table, int x)
Definition: cuddReorder.c:716
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
unsigned int next
Definition: cuddInt.h:333
#define assert(ex)
Definition: util_old.h:213
static int ddGroupSifting ( DdManager table,
int  lower,
int  upper,
DD_CHKFP  checkFunction,
int  lazyFlag 
)
static

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

Synopsis [Sifts from treenode->low to treenode->high.]

Description [Sifts from treenode->low to treenode->high. If croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the end of the initial sifting. If a group is created, it is then sifted again. After sifting one variable, the group that contains it is dissolved. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 720 of file cuddGroup.c.

726 {
727  int *var;
728  int i,j,x,xInit;
729  int nvars;
730  int classes;
731  int result;
732  int *sifted;
733  int merged;
734  int dissolve;
735 #ifdef DD_STATS
736  unsigned previousSize;
737 #endif
738  int xindex;
739 
740  nvars = table->size;
741 
742  /* Order variables to sift. */
743  entry = NULL;
744  sifted = NULL;
745  var = ABC_ALLOC(int,nvars);
746  if (var == NULL) {
747  table->errorCode = CUDD_MEMORY_OUT;
748  goto ddGroupSiftingOutOfMem;
749  }
750  entry = ABC_ALLOC(int,nvars);
751  if (entry == NULL) {
752  table->errorCode = CUDD_MEMORY_OUT;
753  goto ddGroupSiftingOutOfMem;
754  }
755  sifted = ABC_ALLOC(int,nvars);
756  if (sifted == NULL) {
757  table->errorCode = CUDD_MEMORY_OUT;
758  goto ddGroupSiftingOutOfMem;
759  }
760 
761  /* Here we consider only one representative for each group. */
762  for (i = 0, classes = 0; i < nvars; i++) {
763  sifted[i] = 0;
764  x = table->perm[i];
765  if ((unsigned) x >= table->subtables[x].next) {
766  entry[i] = table->subtables[x].keys;
767  var[classes] = i;
768  classes++;
769  }
770  }
771 
772  qsort((void *)var,classes,sizeof(int),
774 
775  if (lazyFlag) {
776  for (i = 0; i < nvars; i ++) {
777  ddResetVarHandled(table, i);
778  }
779  }
780 
781  /* Now sift. */
782  for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
783  if (ddTotalNumberSwapping >= table->siftMaxSwap)
784  break;
785  xindex = var[i];
786  if (sifted[xindex] == 1) /* variable already sifted as part of group */
787  continue;
788  x = table->perm[xindex]; /* find current level of this variable */
789 
790  if (x < lower || x > upper || table->subtables[x].bindVar == 1)
791  continue;
792 #ifdef DD_STATS
793  previousSize = table->keys - table->isolated;
794 #endif
795 #ifdef DD_DEBUG
796  /* x is bottom of group */
797  assert((unsigned) x >= table->subtables[x].next);
798 #endif
799  if ((unsigned) x == table->subtables[x].next) {
800  dissolve = 1;
801  result = ddGroupSiftingAux(table,x,lower,upper,checkFunction,
802  lazyFlag);
803  } else {
804  dissolve = 0;
805  result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
806  }
807  if (!result) goto ddGroupSiftingOutOfMem;
808 
809  /* check for aggregation */
810  merged = 0;
811  if (lazyFlag == 0 && table->groupcheck == CUDD_GROUP_CHECK7) {
812  x = table->perm[xindex]; /* find current level */
813  if ((unsigned) x == table->subtables[x].next) { /* not part of a group */
814  if (x != upper && sifted[table->invperm[x+1]] == 0 &&
815  (unsigned) x+1 == table->subtables[x+1].next) {
816  if (ddSecDiffCheck(table,x,x+1)) {
817  merged =1;
818  ddCreateGroup(table,x,x+1);
819  }
820  }
821  if (x != lower && sifted[table->invperm[x-1]] == 0 &&
822  (unsigned) x-1 == table->subtables[x-1].next) {
823  if (ddSecDiffCheck(table,x-1,x)) {
824  merged =1;
825  ddCreateGroup(table,x-1,x);
826  }
827  }
828  }
829  }
830 
831  if (merged) { /* a group was created */
832  /* move x to bottom of group */
833  while ((unsigned) x < table->subtables[x].next)
834  x = table->subtables[x].next;
835  /* sift */
836  result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
837  if (!result) goto ddGroupSiftingOutOfMem;
838 #ifdef DD_STATS
839  if (table->keys < previousSize + table->isolated) {
840  (void) fprintf(table->out,"_");
841  } else if (table->keys > previousSize + table->isolated) {
842  (void) fprintf(table->out,"^");
843  } else {
844  (void) fprintf(table->out,"*");
845  }
846  fflush(table->out);
847  } else {
848  if (table->keys < previousSize + table->isolated) {
849  (void) fprintf(table->out,"-");
850  } else if (table->keys > previousSize + table->isolated) {
851  (void) fprintf(table->out,"+");
852  } else {
853  (void) fprintf(table->out,"=");
854  }
855  fflush(table->out);
856 #endif
857  }
858 
859  /* Mark variables in the group just sifted. */
860  x = table->perm[xindex];
861  if ((unsigned) x != table->subtables[x].next) {
862  xInit = x;
863  do {
864  j = table->invperm[x];
865  sifted[j] = 1;
866  x = table->subtables[x].next;
867  } while (x != xInit);
868 
869  /* Dissolve the group if it was created. */
870  if (lazyFlag == 0 && dissolve) {
871  do {
872  j = table->subtables[x].next;
873  table->subtables[x].next = x;
874  x = j;
875  } while (x != xInit);
876  }
877  }
878 
879 #ifdef DD_DEBUG
880  if (pr > 0) (void) fprintf(table->out,"ddGroupSifting:");
881 #endif
882 
883  if (lazyFlag) ddSetVarHandled(table, xindex);
884  } /* for */
885 
886  ABC_FREE(sifted);
887  ABC_FREE(var);
888  ABC_FREE(entry);
889 
890  return(1);
891 
892 ddGroupSiftingOutOfMem:
893  if (entry != NULL) ABC_FREE(entry);
894  if (var != NULL) ABC_FREE(var);
895  if (sifted != NULL) ABC_FREE(sifted);
896 
897  return(0);
898 
899 } /* end of ddGroupSifting */
Cudd_AggregationType groupcheck
Definition: cuddInt.h:426
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
static int ddNoCheck(DdManager *table, int x, int y)
Definition: cuddGroup.c:1857
static int ddSetVarHandled(DdManager *dd, int index)
Definition: cuddGroup.c:2128
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
int bindVar
Definition: cuddInt.h:334
DdSubtable * subtables
Definition: cuddInt.h:365
static int * entry
Definition: cuddGroup.c:122
static int ddResetVarHandled(DdManager *dd, int index)
Definition: cuddGroup.c:2152
int ddTotalNumberSwapping
Definition: cuddReorder.c:107
unsigned int keys
Definition: cuddInt.h:369
FILE * out
Definition: cuddInt.h:441
#define ddMin(x, y)
Definition: cuddInt.h:818
static int ddSecDiffCheck(DdManager *table, int x, int y)
Definition: cuddGroup.c:1881
static void ddCreateGroup(DdManager *table, int x, int y)
Definition: cuddGroup.c:915
int siftMaxVar
Definition: cuddInt.h:411
#define ABC_FREE(obj)
Definition: abc_global.h:232
unsigned int next
Definition: cuddInt.h:333
#define assert(ex)
Definition: util_old.h:213
static int ddGroupSiftingAux(DdManager *table, int x, int xLow, int xHigh, DD_CHKFP checkFunction, int lazyFlag)
Definition: cuddGroup.c:956
static int ddUniqueCompareGroup(int *ptrX, int *ptrY)
Definition: cuddGroup.c:692
int * invperm
Definition: cuddInt.h:388
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
static int ddGroupSiftingAux ( DdManager table,
int  x,
int  xLow,
int  xHigh,
DD_CHKFP  checkFunction,
int  lazyFlag 
)
static

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

Synopsis [Sifts one variable up and down until it has taken all positions. Checks for aggregation.]

Description [Sifts one variable up and down until it has taken all positions. Checks for aggregation. There may be at most two sweeps, even if the group grows. Assumes that x is either an isolated variable, or it is the bottom of a group. All groups may not have been found. The variable being moved is returned to the best position seen during sifting. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 956 of file cuddGroup.c.

963 {
964  Move *move;
965  Move *moves; /* list of moves */
966  int initialSize;
967  int result;
968  int y;
969  int topbot;
970 
971 #ifdef DD_DEBUG
972  if (pr > 0) (void) fprintf(table->out,
973  "ddGroupSiftingAux from %d to %d\n",xLow,xHigh);
974  assert((unsigned) x >= table->subtables[x].next); /* x is bottom of group */
975 #endif
976 
977  initialSize = table->keys - table->isolated;
978  moves = NULL;
979 
980  originalSize = initialSize; /* for lazy sifting */
981 
982  /* If we have a singleton, we check for aggregation in both
983  ** directions before we sift.
984  */
985  if ((unsigned) x == table->subtables[x].next) {
986  /* Will go down first, unless x == xHigh:
987  ** Look for aggregation above x.
988  */
989  for (y = x; y > xLow; y--) {
990  if (!checkFunction(table,y-1,y))
991  break;
992  topbot = table->subtables[y-1].next; /* find top of y-1's group */
993  table->subtables[y-1].next = y;
994  table->subtables[x].next = topbot; /* x is bottom of group so its */
995  /* next is top of y-1's group */
996  y = topbot + 1; /* add 1 for y--; new y is top of group */
997  }
998  /* Will go up first unless x == xlow:
999  ** Look for aggregation below x.
1000  */
1001  for (y = x; y < xHigh; y++) {
1002  if (!checkFunction(table,y,y+1))
1003  break;
1004  /* find bottom of y+1's group */
1005  topbot = y + 1;
1006  while ((unsigned) topbot < table->subtables[topbot].next) {
1007  topbot = table->subtables[topbot].next;
1008  }
1009  table->subtables[topbot].next = table->subtables[y].next;
1010  table->subtables[y].next = y + 1;
1011  y = topbot - 1; /* subtract 1 for y++; new y is bottom of group */
1012  }
1013  }
1014 
1015  /* Now x may be in the middle of a group.
1016  ** Find bottom of x's group.
1017  */
1018  while ((unsigned) x < table->subtables[x].next)
1019  x = table->subtables[x].next;
1020 
1021  if (x == xLow) { /* Sift down */
1022 #ifdef DD_DEBUG
1023  /* x must be a singleton */
1024  assert((unsigned) x == table->subtables[x].next);
1025 #endif
1026  if (x == xHigh) return(1); /* just one variable */
1027 
1028  if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
1029  goto ddGroupSiftingAuxOutOfMem;
1030  /* at this point x == xHigh, unless early term */
1031 
1032  /* move backward and stop at best position */
1033  result = ddGroupSiftingBackward(table,moves,initialSize,
1034  DD_SIFT_DOWN,lazyFlag);
1035 #ifdef DD_DEBUG
1036  assert(table->keys - table->isolated <= (unsigned) initialSize);
1037 #endif
1038  if (!result) goto ddGroupSiftingAuxOutOfMem;
1039 
1040  } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
1041 #ifdef DD_DEBUG
1042  /* x is bottom of group */
1043  assert((unsigned) x >= table->subtables[x].next);
1044 #endif
1045  /* Find top of x's group */
1046  x = table->subtables[x].next;
1047 
1048  if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
1049  goto ddGroupSiftingAuxOutOfMem;
1050  /* at this point x == xLow, unless early term */
1051 
1052  /* move backward and stop at best position */
1053  result = ddGroupSiftingBackward(table,moves,initialSize,
1054  DD_SIFT_UP,lazyFlag);
1055 #ifdef DD_DEBUG
1056  assert(table->keys - table->isolated <= (unsigned) initialSize);
1057 #endif
1058  if (!result) goto ddGroupSiftingAuxOutOfMem;
1059 
1060  } else if (x - xLow > xHigh - x) { /* must go down first: shorter */
1061  if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
1062  goto ddGroupSiftingAuxOutOfMem;
1063  /* at this point x == xHigh, unless early term */
1064 
1065  /* Find top of group */
1066  if (moves) {
1067  x = moves->y;
1068  }
1069  while ((unsigned) x < table->subtables[x].next)
1070  x = table->subtables[x].next;
1071  x = table->subtables[x].next;
1072 #ifdef DD_DEBUG
1073  /* x should be the top of a group */
1074  assert((unsigned) x <= table->subtables[x].next);
1075 #endif
1076 
1077  if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
1078  goto ddGroupSiftingAuxOutOfMem;
1079 
1080  /* move backward and stop at best position */
1081  result = ddGroupSiftingBackward(table,moves,initialSize,
1082  DD_SIFT_UP,lazyFlag);
1083 #ifdef DD_DEBUG
1084  assert(table->keys - table->isolated <= (unsigned) initialSize);
1085 #endif
1086  if (!result) goto ddGroupSiftingAuxOutOfMem;
1087 
1088  } else { /* moving up first: shorter */
1089  /* Find top of x's group */
1090  x = table->subtables[x].next;
1091 
1092  if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
1093  goto ddGroupSiftingAuxOutOfMem;
1094  /* at this point x == xHigh, unless early term */
1095 
1096  if (moves) {
1097  x = moves->x;
1098  }
1099  while ((unsigned) x < table->subtables[x].next)
1100  x = table->subtables[x].next;
1101 #ifdef DD_DEBUG
1102  /* x is bottom of a group */
1103  assert((unsigned) x >= table->subtables[x].next);
1104 #endif
1105 
1106  if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
1107  goto ddGroupSiftingAuxOutOfMem;
1108 
1109  /* move backward and stop at best position */
1110  result = ddGroupSiftingBackward(table,moves,initialSize,
1111  DD_SIFT_DOWN,lazyFlag);
1112 #ifdef DD_DEBUG
1113  assert(table->keys - table->isolated <= (unsigned) initialSize);
1114 #endif
1115  if (!result) goto ddGroupSiftingAuxOutOfMem;
1116  }
1117 
1118  while (moves != NULL) {
1119  move = moves->next;
1120  cuddDeallocMove(table, moves);
1121  moves = move;
1122  }
1123 
1124  return(1);
1125 
1126 ddGroupSiftingAuxOutOfMem:
1127  while (moves != NULL) {
1128  move = moves->next;
1129  cuddDeallocMove(table, moves);
1130  moves = move;
1131  }
1132 
1133  return(0);
1134 
1135 } /* end of ddGroupSiftingAux */
#define DD_SIFT_DOWN
Definition: cuddGroup.c:95
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
static unsigned int originalSize
Definition: cuddGroup.c:136
static int ddGroupSiftingUp(DdManager *table, int y, int xLow, DD_CHKFP checkFunction, Move **moves)
Definition: cuddGroup.c:1154
Definition: cuddInt.h:492
DdSubtable * subtables
Definition: cuddInt.h:365
static int ddGroupSiftingDown(DdManager *table, int x, int xHigh, DD_CHKFP checkFunction, Move **moves)
Definition: cuddGroup.c:1312
unsigned int keys
Definition: cuddInt.h:369
#define DD_SIFT_UP
Definition: cuddGroup.c:96
FILE * out
Definition: cuddInt.h:441
DdHalfWord x
Definition: cuddInt.h:493
static int ddGroupSiftingBackward(DdManager *table, Move *moves, int size, int upFlag, int lazyFlag)
Definition: cuddGroup.c:1668
int cuddNextHigh(DdManager *table, int x)
Definition: cuddReorder.c:716
DdHalfWord y
Definition: cuddInt.h:494
unsigned int next
Definition: cuddInt.h:333
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 ddGroupSiftingBackward ( DdManager table,
Move moves,
int  size,
int  upFlag,
int  lazyFlag 
)
static

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

Synopsis [Determines the best position for a variables and returns it there.]

Description [Determines the best position for a variables and returns it there. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 1668 of file cuddGroup.c.

1674 {
1675  Move *move;
1676  int res;
1677  Move *end_move = NULL;
1678  int diff, tmp_diff;
1679  int index;
1680  unsigned int pairlev;
1681 
1682  if (lazyFlag) {
1683  end_move = NULL;
1684 
1685  /* Find the minimum size, and the earliest position at which it
1686  ** was achieved. */
1687  for (move = moves; move != NULL; move = move->next) {
1688  if (move->size < size) {
1689  size = move->size;
1690  end_move = move;
1691  } else if (move->size == size) {
1692  if (end_move == NULL) end_move = move;
1693  }
1694  }
1695 
1696  /* Find among the moves that give minimum size the one that
1697  ** minimizes the distance from the corresponding variable. */
1698  if (moves != NULL) {
1699  diff = Cudd_ReadSize(table) + 1;
1700  index = (upFlag == 1) ?
1701  table->invperm[moves->x] : table->invperm[moves->y];
1702  pairlev =
1703  (unsigned) table->perm[Cudd_bddReadPairIndex(table, index)];
1704 
1705  for (move = moves; move != NULL; move = move->next) {
1706  if (move->size == size) {
1707  if (upFlag == 1) {
1708  tmp_diff = (move->x > pairlev) ?
1709  move->x - pairlev : pairlev - move->x;
1710  } else {
1711  tmp_diff = (move->y > pairlev) ?
1712  move->y - pairlev : pairlev - move->y;
1713  }
1714  if (tmp_diff < diff) {
1715  diff = tmp_diff;
1716  end_move = move;
1717  }
1718  }
1719  }
1720  }
1721  } else {
1722  /* Find the minimum size. */
1723  for (move = moves; move != NULL; move = move->next) {
1724  if (move->size < size) {
1725  size = move->size;
1726  }
1727  }
1728  }
1729 
1730  /* In case of lazy sifting, end_move identifies the position at
1731  ** which we want to stop. Otherwise, we stop as soon as we meet
1732  ** the minimum size. */
1733  for (move = moves; move != NULL; move = move->next) {
1734  if (lazyFlag) {
1735  if (move == end_move) return(1);
1736  } else {
1737  if (move->size == size) return(1);
1738  }
1739  if ((table->subtables[move->x].next == move->x) &&
1740  (table->subtables[move->y].next == move->y)) {
1741  res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
1742  if (!res) return(0);
1743 #ifdef DD_DEBUG
1744  if (pr > 0) (void) fprintf(table->out,"ddGroupSiftingBackward:\n");
1745  assert(table->subtables[move->x].next == move->x);
1746  assert(table->subtables[move->y].next == move->y);
1747 #endif
1748  } else { /* Group move necessary */
1749  if (move->flags == MTR_NEWNODE) {
1750  ddDissolveGroup(table,(int)move->x,(int)move->y);
1751  } else {
1752  res = ddGroupMoveBackward(table,(int)move->x,(int)move->y);
1753  if (!res) return(0);
1754  }
1755  }
1756 
1757  }
1758 
1759  return(1);
1760 
1761 } /* end of ddGroupSiftingBackward */
Definition: cuddInt.h:492
static int ddGroupMoveBackward(DdManager *table, int x, int y)
Definition: cuddGroup.c:1594
DdSubtable * subtables
Definition: cuddInt.h:365
int Cudd_ReadSize(DdManager *dd)
Definition: cuddAPI.c:1441
FILE * out
Definition: cuddInt.h:441
unsigned int flags
Definition: cuddInt.h:495
DdHalfWord x
Definition: cuddInt.h:493
#define MTR_NEWNODE
Definition: mtr.h:103
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
static void ddDissolveGroup(DdManager *table, int x, int y)
Definition: cuddGroup.c:1823
unsigned int next
Definition: cuddInt.h:333
int Cudd_bddReadPairIndex(DdManager *dd, int index)
Definition: cuddAPI.c:4148
struct Move * next
Definition: cuddInt.h:497
#define assert(ex)
Definition: util_old.h:213
int * invperm
Definition: cuddInt.h:388
int * perm
Definition: cuddInt.h:386
int size
Definition: cuddInt.h:496
static int ddGroupSiftingDown ( DdManager table,
int  x,
int  xHigh,
DD_CHKFP  checkFunction,
Move **  moves 
)
static

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

Synopsis [Sifts down a variable until it reaches position xHigh.]

Description [Sifts down a variable until it reaches position xHigh. Assumes that x is the bottom of a group (or a singleton). Records all the moves. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 1312 of file cuddGroup.c.

1318 {
1319  Move *move;
1320  int y;
1321  int size;
1322  int limitSize;
1323  int gxtop,gybot;
1324  int R; /* upper bound on node decrease */
1325  int xindex, yindex;
1326  int isolated, allVars;
1327  int z;
1328  int zindex;
1329 #ifdef DD_DEBUG
1330  int checkR;
1331 #endif
1332 
1333  /* If the group consists of simple variables, there is no point in
1334  ** sifting it down. This check is redundant if the projection functions
1335  ** do not have external references, because the computation of the
1336  ** lower bound takes care of the problem. It is necessary otherwise to
1337  ** prevent the sifting down of simple variables. */
1338  y = x;
1339  allVars = 1;
1340  do {
1341  if (table->subtables[y].keys != 1) {
1342  allVars = 0;
1343  break;
1344  }
1345  y = table->subtables[y].next;
1346  } while (table->subtables[y].next != (unsigned) x);
1347  if (allVars)
1348  return(1);
1349 
1350  /* Initialize R. */
1351  xindex = table->invperm[x];
1352  gxtop = table->subtables[x].next;
1353  limitSize = size = table->keys - table->isolated;
1354  R = 0;
1355  for (z = xHigh; z > gxtop; z--) {
1356  zindex = table->invperm[z];
1357  if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
1358  isolated = table->vars[zindex]->ref == 1;
1359  R += table->subtables[z].keys - isolated;
1360  }
1361  }
1362 
1363  y = cuddNextHigh(table,x);
1364  while (y <= xHigh && size - R < limitSize) {
1365 #ifdef DD_DEBUG
1366  gxtop = table->subtables[x].next;
1367  checkR = 0;
1368  for (z = xHigh; z > gxtop; z--) {
1369  zindex = table->invperm[z];
1370  if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
1371  isolated = table->vars[zindex]->ref == 1;
1372  checkR += table->subtables[z].keys - isolated;
1373  }
1374  }
1375  assert(R >= checkR);
1376 #endif
1377  /* Find bottom of y group. */
1378  gybot = table->subtables[y].next;
1379  while (table->subtables[gybot].next != (unsigned) y)
1380  gybot = table->subtables[gybot].next;
1381 
1382  if (checkFunction(table,x,y)) {
1383  /* Group found: attach groups and record move. */
1384  gxtop = table->subtables[x].next;
1385  table->subtables[x].next = y;
1386  table->subtables[gybot].next = gxtop;
1387  move = (Move *)cuddDynamicAllocNode(table);
1388  if (move == NULL) goto ddGroupSiftingDownOutOfMem;
1389  move->x = x;
1390  move->y = y;
1391  move->flags = MTR_NEWNODE;
1392  move->size = table->keys - table->isolated;
1393  move->next = *moves;
1394  *moves = move;
1395  } else if (table->subtables[x].next == (unsigned) x &&
1396  table->subtables[y].next == (unsigned) y) {
1397  /* x and y are self groups */
1398  /* Update upper bound on node decrease. */
1399  yindex = table->invperm[y];
1400  if (cuddTestInteract(table,xindex,yindex)) {
1401  isolated = table->vars[yindex]->ref == 1;
1402  R -= table->subtables[y].keys - isolated;
1403  }
1404  size = cuddSwapInPlace(table,x,y);
1405 #ifdef DD_DEBUG
1406  assert(table->subtables[x].next == (unsigned) x);
1407  assert(table->subtables[y].next == (unsigned) y);
1408 #endif
1409  if (size == 0) goto ddGroupSiftingDownOutOfMem;
1410 
1411  /* Record move. */
1412  move = (Move *) cuddDynamicAllocNode(table);
1413  if (move == NULL) goto ddGroupSiftingDownOutOfMem;
1414  move->x = x;
1415  move->y = y;
1416  move->flags = MTR_DEFAULT;
1417  move->size = size;
1418  move->next = *moves;
1419  *moves = move;
1420 
1421 #ifdef DD_DEBUG
1422  if (pr > 0) (void) fprintf(table->out,
1423  "ddGroupSiftingDown (2 single groups):\n");
1424 #endif
1425  if ((double) size > (double) limitSize * table->maxGrowth)
1426  return(1);
1427  if (size < limitSize) limitSize = size;
1428 
1429  x = y;
1430  y = cuddNextHigh(table,x);
1431  } else { /* Group move */
1432  /* Update upper bound on node decrease: first phase. */
1433  gxtop = table->subtables[x].next;
1434  z = gxtop + 1;
1435  do {
1436  zindex = table->invperm[z];
1437  if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
1438  isolated = table->vars[zindex]->ref == 1;
1439  R -= table->subtables[z].keys - isolated;
1440  }
1441  z++;
1442  } while (z <= gybot);
1443  size = ddGroupMove(table,x,y,moves);
1444  if (size == 0) goto ddGroupSiftingDownOutOfMem;
1445  if ((double) size > (double) limitSize * table->maxGrowth)
1446  return(1);
1447  if (size < limitSize) limitSize = size;
1448 
1449  /* Update upper bound on node decrease: second phase. */
1450  gxtop = table->subtables[gybot].next;
1451  for (z = gxtop + 1; z <= gybot; z++) {
1452  zindex = table->invperm[z];
1453  if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
1454  isolated = table->vars[zindex]->ref == 1;
1455  R += table->subtables[z].keys - isolated;
1456  }
1457  }
1458  }
1459  x = gybot;
1460  y = cuddNextHigh(table,x);
1461  }
1462 
1463  return(1);
1464 
1465 ddGroupSiftingDownOutOfMem:
1466  while (*moves != NULL) {
1467  move = (*moves)->next;
1468  cuddDeallocMove(table, *moves);
1469  *moves = move;
1470  }
1471 
1472  return(0);
1473 
1474 } /* end of ddGroupSiftingDown */
DdHalfWord ref
Definition: cudd.h:280
unsigned int keys
Definition: cuddInt.h:330
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
Definition: cuddInt.h:492
double maxGrowth
Definition: cuddInt.h:413
DdSubtable * subtables
Definition: cuddInt.h:365
#define MTR_DEFAULT
Definition: mtr.h:99
unsigned int keys
Definition: cuddInt.h:369
FILE * out
Definition: cuddInt.h:441
unsigned int flags
Definition: cuddInt.h:495
DdHalfWord x
Definition: cuddInt.h:493
static int ddGroupMove(DdManager *table, int x, int y, Move **moves)
Definition: cuddGroup.c:1488
#define MTR_NEWNODE
Definition: mtr.h:103
static int size
Definition: cuddSign.c:86
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
int cuddNextHigh(DdManager *table, int x)
Definition: cuddReorder.c:716
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
DdHalfWord y
Definition: cuddInt.h:494
DdNode ** vars
Definition: cuddInt.h:390
unsigned int next
Definition: cuddInt.h:333
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 ddGroupSiftingUp ( DdManager table,
int  y,
int  xLow,
DD_CHKFP  checkFunction,
Move **  moves 
)
static

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

Synopsis [Sifts up a variable until either it reaches position xLow or the size of the DD heap increases too much.]

Description [Sifts up a variable until either it reaches position xLow or the size of the DD heap increases too much. Assumes that y is the top of a group (or a singleton). Checks y for aggregation to the adjacent variables. Records all the moves that are appended to the list of moves received as input and returned as a side effect. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

Definition at line 1154 of file cuddGroup.c.

1160 {
1161  Move *move;
1162  int x;
1163  int size;
1164  int i;
1165  int gxtop,gybot;
1166  int limitSize;
1167  int xindex, yindex;
1168  int zindex;
1169  int z;
1170  int isolated;
1171  int L; /* lower bound on DD size */
1172 #ifdef DD_DEBUG
1173  int checkL;
1174 #endif
1175 
1176  yindex = table->invperm[y];
1177 
1178  /* Initialize the lower bound.
1179  ** The part of the DD below the bottom of y's group will not change.
1180  ** The part of the DD above y that does not interact with any
1181  ** variable of y's group will not change.
1182  ** The rest may vanish in the best case, except for
1183  ** the nodes at level xLow, which will not vanish, regardless.
1184  ** What we use here is not really a lower bound, because we ignore
1185  ** the interactions with all variables except y.
1186  */
1187  limitSize = L = table->keys - table->isolated;
1188  gybot = y;
1189  while ((unsigned) gybot < table->subtables[gybot].next)
1190  gybot = table->subtables[gybot].next;
1191  for (z = xLow + 1; z <= gybot; z++) {
1192  zindex = table->invperm[z];
1193  if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
1194  isolated = table->vars[zindex]->ref == 1;
1195  L -= table->subtables[z].keys - isolated;
1196  }
1197  }
1198 
1199  x = cuddNextLow(table,y);
1200  while (x >= xLow && L <= limitSize) {
1201 #ifdef DD_DEBUG
1202  gybot = y;
1203  while ((unsigned) gybot < table->subtables[gybot].next)
1204  gybot = table->subtables[gybot].next;
1205  checkL = table->keys - table->isolated;
1206  for (z = xLow + 1; z <= gybot; z++) {
1207  zindex = table->invperm[z];
1208  if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
1209  isolated = table->vars[zindex]->ref == 1;
1210  checkL -= table->subtables[z].keys - isolated;
1211  }
1212  }
1213  if (pr > 0 && L != checkL) {
1214  (void) fprintf(table->out,
1215  "Inaccurate lower bound: L = %d checkL = %d\n",
1216  L, checkL);
1217  }
1218 #endif
1219  gxtop = table->subtables[x].next;
1220  if (checkFunction(table,x,y)) {
1221  /* Group found, attach groups */
1222  table->subtables[x].next = y;
1223  i = table->subtables[y].next;
1224  while (table->subtables[i].next != (unsigned) y)
1225  i = table->subtables[i].next;
1226  table->subtables[i].next = gxtop;
1227  move = (Move *)cuddDynamicAllocNode(table);
1228  if (move == NULL) goto ddGroupSiftingUpOutOfMem;
1229  move->x = x;
1230  move->y = y;
1231  move->flags = MTR_NEWNODE;
1232  move->size = table->keys - table->isolated;
1233  move->next = *moves;
1234  *moves = move;
1235  } else if (table->subtables[x].next == (unsigned) x &&
1236  table->subtables[y].next == (unsigned) y) {
1237  /* x and y are self groups */
1238  xindex = table->invperm[x];
1239  size = cuddSwapInPlace(table,x,y);
1240 #ifdef DD_DEBUG
1241  assert(table->subtables[x].next == (unsigned) x);
1242  assert(table->subtables[y].next == (unsigned) y);
1243 #endif
1244  if (size == 0) goto ddGroupSiftingUpOutOfMem;
1245  /* Update the lower bound. */
1246  if (cuddTestInteract(table,xindex,yindex)) {
1247  isolated = table->vars[xindex]->ref == 1;
1248  L += table->subtables[y].keys - isolated;
1249  }
1250  move = (Move *)cuddDynamicAllocNode(table);
1251  if (move == NULL) goto ddGroupSiftingUpOutOfMem;
1252  move->x = x;
1253  move->y = y;
1254  move->flags = MTR_DEFAULT;
1255  move->size = size;
1256  move->next = *moves;
1257  *moves = move;
1258 
1259 #ifdef DD_DEBUG
1260  if (pr > 0) (void) fprintf(table->out,
1261  "ddGroupSiftingUp (2 single groups):\n");
1262 #endif
1263  if ((double) size > (double) limitSize * table->maxGrowth)
1264  return(1);
1265  if (size < limitSize) limitSize = size;
1266  } else { /* Group move */
1267  size = ddGroupMove(table,x,y,moves);
1268  if (size == 0) goto ddGroupSiftingUpOutOfMem;
1269  /* Update the lower bound. */
1270  z = (*moves)->y;
1271  do {
1272  zindex = table->invperm[z];
1273  if (cuddTestInteract(table,zindex,yindex)) {
1274  isolated = table->vars[zindex]->ref == 1;
1275  L += table->subtables[z].keys - isolated;
1276  }
1277  z = table->subtables[z].next;
1278  } while (z != (int) (*moves)->y);
1279  if ((double) size > (double) limitSize * table->maxGrowth)
1280  return(1);
1281  if (size < limitSize) limitSize = size;
1282  }
1283  y = gxtop;
1284  x = cuddNextLow(table,y);
1285  }
1286 
1287  return(1);
1288 
1289 ddGroupSiftingUpOutOfMem:
1290  while (*moves != NULL) {
1291  move = (*moves)->next;
1292  cuddDeallocMove(table, *moves);
1293  *moves = move;
1294  }
1295  return(0);
1296 
1297 } /* end of ddGroupSiftingUp */
DdHalfWord ref
Definition: cudd.h:280
unsigned int keys
Definition: cuddInt.h:330
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:564
Definition: cuddInt.h:492
int cuddNextLow(DdManager *table, int x)
Definition: cuddReorder.c:738
double maxGrowth
Definition: cuddInt.h:413
DdSubtable * subtables
Definition: cuddInt.h:365
#define MTR_DEFAULT
Definition: mtr.h:99
unsigned int keys
Definition: cuddInt.h:369
FILE * out
Definition: cuddInt.h:441
unsigned int flags
Definition: cuddInt.h:495
DdHalfWord x
Definition: cuddInt.h:493
static int ddGroupMove(DdManager *table, int x, int y, Move **moves)
Definition: cuddGroup.c:1488
#define MTR_NEWNODE
Definition: mtr.h:103
static int size
Definition: cuddSign.c:86
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:406
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:761
DdHalfWord y
Definition: cuddInt.h:494
DdNode ** vars
Definition: cuddInt.h:390
unsigned int next
Definition: cuddInt.h:333
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 ddIsVarHandled ( DdManager dd,
int  index 
)
static

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

Synopsis [Checks whether a variables is already handled.]

Description [Checks whether a variables is already handled. This function is used for lazy sifting.]

SideEffects [none]

SeeAlso []

Definition at line 2176 of file cuddGroup.c.

2179 {
2180  if (index >= dd->size || index < 0) return(-1);
2181  return dd->subtables[dd->perm[index]].varHandled;
2182 
2183 } /* end of ddIsVarHandled */
int size
Definition: cuddInt.h:361
DdSubtable * subtables
Definition: cuddInt.h:365
int varHandled
Definition: cuddInt.h:338
int * perm
Definition: cuddInt.h:386
static void ddMergeGroups ( DdManager table,
MtrNode treenode,
int  low,
int  high 
)
static

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

Synopsis [Merges groups in the DD table.]

Description [Creates a single group from low to high and adjusts the index field of the tree node.]

SideEffects [None]

Definition at line 1775 of file cuddGroup.c.

1780 {
1781  int i;
1782  MtrNode *auxnode;
1783  int saveindex;
1784  int newindex;
1785 
1786  /* Merge all variables from low to high in one group, unless
1787  ** this is the topmost group. In such a case we do not merge lest
1788  ** we lose the symmetry information. */
1789  if (treenode != table->tree) {
1790  for (i = low; i < high; i++)
1791  table->subtables[i].next = i+1;
1792  table->subtables[high].next = low;
1793  }
1794 
1795  /* Adjust the index fields of the tree nodes. If a node is the
1796  ** first child of its parent, then the parent may also need adjustment. */
1797  saveindex = treenode->index;
1798  newindex = table->invperm[low];
1799  auxnode = treenode;
1800  do {
1801  auxnode->index = newindex;
1802  if (auxnode->parent == NULL ||
1803  (int) auxnode->parent->index != saveindex)
1804  break;
1805  auxnode = auxnode->parent;
1806  } while (1);
1807  return;
1808 
1809 } /* end of ddMergeGroups */
DdSubtable * subtables
Definition: cuddInt.h:365
struct MtrNode * parent
Definition: mtr.h:136
MtrNode * tree
Definition: cuddInt.h:424
MtrHalfWord index
Definition: mtr.h:135
Definition: mtr.h:131
unsigned int next
Definition: cuddInt.h:333
int * invperm
Definition: cuddInt.h:388
static int ddNoCheck ( DdManager table,
int  x,
int  y 
)
static

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

Synopsis [Pretends to check two variables for aggregation.]

Description [Pretends to check two variables for aggregation. Always returns 0.]

SideEffects [None]

Definition at line 1857 of file cuddGroup.c.

1861 {
1862  return(0);
1863 
1864 } /* end of ddNoCheck */
static int ddReorderChildren ( DdManager table,
MtrNode treenode,
Cudd_ReorderingType  method 
)
static

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

Synopsis [Reorders the children of a group tree node according to the options.]

Description [Reorders the children of a group tree node according to the options. After reordering puts all the variables in the group and/or its descendents in a single group. This allows hierarchical reordering. If the variables in the group do not exist yet, simply does nothing. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

Definition at line 453 of file cuddGroup.c.

457 {
458  int lower;
459  int upper = -1;
460  int result;
461  unsigned int initialSize;
462 
463  ddFindNodeHiLo(table,treenode,&lower,&upper);
464  /* If upper == -1 these variables do not exist yet. */
465  if (upper == -1)
466  return(1);
467 
468  if (treenode->flags == MTR_FIXED) {
469  result = 1;
470  } else {
471 #ifdef DD_STATS
472  (void) fprintf(table->out," ");
473 #endif
474  switch (method) {
475  case CUDD_REORDER_RANDOM:
477  result = cuddSwapping(table,lower,upper,method);
478  break;
479  case CUDD_REORDER_SIFT:
480  result = cuddSifting(table,lower,upper);
481  break;
483  do {
484  initialSize = table->keys - table->isolated;
485  result = cuddSifting(table,lower,upper);
486  if (initialSize <= table->keys - table->isolated)
487  break;
488 #ifdef DD_STATS
489  else
490  (void) fprintf(table->out,"\n");
491 #endif
492  } while (result != 0);
493  break;
495  result = cuddSymmSifting(table,lower,upper);
496  break;
498  result = cuddSymmSiftingConv(table,lower,upper);
499  break;
501  if (table->groupcheck == CUDD_NO_CHECK) {
502  result = ddGroupSifting(table,lower,upper,ddNoCheck,
504  } else if (table->groupcheck == CUDD_GROUP_CHECK5) {
505  result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
507  } else if (table->groupcheck == CUDD_GROUP_CHECK7) {
508  result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
510  } else {
511  (void) fprintf(table->err,
512  "Unknown group ckecking method\n");
513  result = 0;
514  }
515  break;
517  do {
518  initialSize = table->keys - table->isolated;
519  if (table->groupcheck == CUDD_NO_CHECK) {
520  result = ddGroupSifting(table,lower,upper,ddNoCheck,
522  } else if (table->groupcheck == CUDD_GROUP_CHECK5) {
523  result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
525  } else if (table->groupcheck == CUDD_GROUP_CHECK7) {
526  result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
528  } else {
529  (void) fprintf(table->err,
530  "Unknown group ckecking method\n");
531  result = 0;
532  }
533 #ifdef DD_STATS
534  (void) fprintf(table->out,"\n");
535 #endif
536  result = cuddWindowReorder(table,lower,upper,
538  if (initialSize <= table->keys - table->isolated)
539  break;
540 #ifdef DD_STATS
541  else
542  (void) fprintf(table->out,"\n");
543 #endif
544  } while (result != 0);
545  break;
552  result = cuddWindowReorder(table,lower,upper,method);
553  break;
555  result = cuddAnnealing(table,lower,upper);
556  break;
558  result = cuddGa(table,lower,upper);
559  break;
560  case CUDD_REORDER_LINEAR:
561  result = cuddLinearAndSifting(table,lower,upper);
562  break;
564  do {
565  initialSize = table->keys - table->isolated;
566  result = cuddLinearAndSifting(table,lower,upper);
567  if (initialSize <= table->keys - table->isolated)
568  break;
569 #ifdef DD_STATS
570  else
571  (void) fprintf(table->out,"\n");
572 #endif
573  } while (result != 0);
574  break;
575  case CUDD_REORDER_EXACT:
576  result = cuddExact(table,lower,upper);
577  break;
579  result = ddGroupSifting(table,lower,upper,ddVarGroupCheck,
580  DD_LAZY_SIFT);
581  break;
582  default:
583  return(0);
584  }
585  }
586 
587  /* Create a single group for all the variables that were sifted,
588  ** so that they will be treated as a single block by successive
589  ** invocations of ddGroupSifting.
590  */
591  ddMergeGroups(table,treenode,lower,upper);
592 
593 #ifdef DD_DEBUG
594  if (pr > 0) (void) fprintf(table->out,"ddReorderChildren:");
595 #endif
596 
597  return(result);
598 
599 } /* end of ddReorderChildren */
Cudd_AggregationType groupcheck
Definition: cuddInt.h:426
MtrHalfWord flags
Definition: mtr.h:132
int cuddExact(DdManager *table, int lower, int upper)
Definition: cuddExact.c:153
static int ddGroupSifting(DdManager *table, int lower, int upper, DD_CHKFP checkFunction, int lazyFlag)
Definition: cuddGroup.c:720
static int ddNoCheck(DdManager *table, int x, int y)
Definition: cuddGroup.c:1857
int cuddSifting(DdManager *table, int lower, int upper)
Definition: cuddReorder.c:508
FILE * err
Definition: cuddInt.h:442
#define MTR_FIXED
Definition: mtr.h:102
static int ddExtSymmCheck(DdManager *table, int x, int y)
Definition: cuddGroup.c:1938
int cuddGa(DdManager *table, int lower, int upper)
Definition: cuddGenetic.c:192
int cuddSymmSiftingConv(DdManager *table, int lower, int upper)
Definition: cuddSymmetry.c:442
unsigned int keys
Definition: cuddInt.h:369
FILE * out
Definition: cuddInt.h:441
static void ddFindNodeHiLo(DdManager *table, MtrNode *treenode, int *lower, int *upper)
Definition: cuddGroup.c:617
static void ddMergeGroups(DdManager *table, MtrNode *treenode, int low, int high)
Definition: cuddGroup.c:1775
#define DD_NORMAL_SIFT
Definition: cuddGroup.c:91
int cuddWindowReorder(DdManager *table, int low, int high, Cudd_ReorderingType submethod)
Definition: cuddWindow.c:142
int cuddSwapping(DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
Definition: cuddReorder.c:605
static int ddVarGroupCheck(DdManager *table, int x, int y)
Definition: cuddGroup.c:2088
#define DD_LAZY_SIFT
Definition: cuddGroup.c:92
int cuddAnnealing(DdManager *table, int lower, int upper)
Definition: cuddAnneal.c:158
static int result
Definition: cuddGenetic.c:125
int isolated
Definition: cuddInt.h:385
int cuddLinearAndSifting(DdManager *table, int lower, int upper)
Definition: cuddLinear.c:240
int cuddSymmSifting(DdManager *table, int lower, int upper)
Definition: cuddSymmetry.c:322
static int ddResetVarHandled ( DdManager dd,
int  index 
)
static

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

Synopsis [Resets a variable to be processed.]

Description [Resets a variable to be processed. This function is used for lazy sifting.]

SideEffects [none]

SeeAlso []

Definition at line 2152 of file cuddGroup.c.

2155 {
2156  if (index >= dd->size || index < 0) return(0);
2157  dd->subtables[dd->perm[index]].varHandled = 0;
2158  return(1);
2159 
2160 } /* end of ddResetVarHandled */
int size
Definition: cuddInt.h:361
DdSubtable * subtables
Definition: cuddInt.h:365
int varHandled
Definition: cuddInt.h:338
int * perm
Definition: cuddInt.h:386
static int ddSecDiffCheck ( DdManager table,
int  x,
int  y 
)
static

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

Synopsis [Checks two variables for aggregation.]

Description [Checks two variables for aggregation. The check is based on the second difference of the number of nodes as a function of the layer. If the second difference is lower than a given threshold (typically negative) then the two variables should be aggregated. Returns 1 if the two variables pass the test; 0 otherwise.]

SideEffects [None]

Definition at line 1881 of file cuddGroup.c.

1885 {
1886  double Nx,Nx_1;
1887  double Sx;
1888  double threshold;
1889  int xindex,yindex;
1890 
1891  if (x==0) return(0);
1892 
1893 #ifdef DD_STATS
1894  secdiffcalls++;
1895 #endif
1896  Nx = (double) table->subtables[x].keys;
1897  Nx_1 = (double) table->subtables[x-1].keys;
1898  Sx = (table->subtables[y].keys/Nx) - (Nx/Nx_1);
1899 
1900  threshold = table->recomb / 100.0;
1901  if (Sx < threshold) {
1902  xindex = table->invperm[x];
1903  yindex = table->invperm[y];
1904  if (cuddTestInteract(table,xindex,yindex)) {
1905 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
1906  (void) fprintf(table->out,
1907  "Second difference for %d = %g Pos(%d)\n",
1908  table->invperm[x],Sx,x);
1909 #endif
1910 #ifdef DD_STATS
1911  secdiff++;
1912 #endif
1913  return(1);
1914  } else {
1915 #ifdef DD_STATS
1916  secdiffmisfire++;
1917 #endif
1918  return(0);
1919  }
1920 
1921  }
1922  return(0);
1923 
1924 } /* end of ddSecDiffCheck */
unsigned int keys
Definition: cuddInt.h:330
DdSubtable * subtables
Definition: cuddInt.h:365
int recomb
Definition: cuddInt.h:427
FILE * out
Definition: cuddInt.h:441
int * invperm
Definition: cuddInt.h:388
int cuddTestInteract(DdManager *table, int x, int y)
Definition: cuddInteract.c:191
static int ddSetVarHandled ( DdManager dd,
int  index 
)
static

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

Synopsis [Sets a variable to already handled.]

Description [Sets a variable to already handled. This function is used for lazy sifting.]

SideEffects [none]

SeeAlso []

Definition at line 2128 of file cuddGroup.c.

2131 {
2132  if (index >= dd->size || index < 0) return(0);
2133  dd->subtables[dd->perm[index]].varHandled = 1;
2134  return(1);
2135 
2136 } /* end of ddSetVarHandled */
int size
Definition: cuddInt.h:361
DdSubtable * subtables
Definition: cuddInt.h:365
int varHandled
Definition: cuddInt.h:338
int * perm
Definition: cuddInt.h:386
static int ddTreeSiftingAux ( DdManager table,
MtrNode treenode,
Cudd_ReorderingType  method 
)
static

AutomaticStart

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

Synopsis [Visits the group tree and reorders each group.]

Description [Recursively visits the group tree and reorders each group in postorder fashion. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

Definition at line 361 of file cuddGroup.c.

365 {
366  MtrNode *auxnode;
367  int res;
368  Cudd_AggregationType saveCheck;
369 
370 #ifdef DD_DEBUG
371  Mtr_PrintGroups(treenode,1);
372 #endif
373 
374  auxnode = treenode;
375  while (auxnode != NULL) {
376  if (auxnode->child != NULL) {
377  if (!ddTreeSiftingAux(table, auxnode->child, method))
378  return(0);
379  saveCheck = table->groupcheck;
380  table->groupcheck = CUDD_NO_CHECK;
381  if (method != CUDD_REORDER_LAZY_SIFT)
382  res = ddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
383  else
384  res = ddReorderChildren(table, auxnode, CUDD_REORDER_LAZY_SIFT);
385  table->groupcheck = saveCheck;
386 
387  if (res == 0)
388  return(0);
389  } else if (auxnode->size > 1) {
390  if (!ddReorderChildren(table, auxnode, method))
391  return(0);
392  }
393  auxnode = auxnode->younger;
394  }
395 
396  return(1);
397 
398 } /* end of ddTreeSiftingAux */
Cudd_AggregationType groupcheck
Definition: cuddInt.h:426
Cudd_AggregationType
Definition: cudd.h:184
MtrHalfWord size
Definition: mtr.h:134
struct MtrNode * younger
Definition: mtr.h:139
Definition: mtr.h:131
static int ddTreeSiftingAux(DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
Definition: cuddGroup.c:361
void Mtr_PrintGroups(MtrNode *root, int silent)
Definition: mtrGroup.c:537
static int ddReorderChildren(DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
Definition: cuddGroup.c:453
struct MtrNode * child
Definition: mtr.h:137
static int ddUniqueCompareGroup ( int *  ptrX,
int *  ptrY 
)
static

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 692 of file cuddGroup.c.

695 {
696 #if 0
697  if (entry[*ptrY] == entry[*ptrX]) {
698  return((*ptrX) - (*ptrY));
699  }
700 #endif
701  return(entry[*ptrY] - entry[*ptrX]);
702 
703 } /* end of ddUniqueCompareGroup */
static int * entry
Definition: cuddGroup.c:122
static int ddVarGroupCheck ( DdManager table,
int  x,
int  y 
)
static

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

Synopsis [Checks for grouping of x and y.]

Description [Checks for grouping of x and y. Returns 1 in case of grouping; 0 otherwise. This function is used for lazy sifting.]

SideEffects [None]

Definition at line 2088 of file cuddGroup.c.

2092 {
2093  int xindex = table->invperm[x];
2094  int yindex = table->invperm[y];
2095 
2096  if (Cudd_bddIsVarToBeUngrouped(table, xindex)) return(0);
2097 
2098  if (Cudd_bddReadPairIndex(table, xindex) == yindex) {
2099  if (ddIsVarHandled(table, xindex) ||
2100  ddIsVarHandled(table, yindex)) {
2101  if (Cudd_bddIsVarToBeGrouped(table, xindex) ||
2102  Cudd_bddIsVarToBeGrouped(table, yindex) ) {
2103  if (table->keys - table->isolated <= originalSize) {
2104  return(1);
2105  }
2106  }
2107  }
2108  }
2109 
2110  return(0);
2111 
2112 } /* end of ddVarGroupCheck */
static unsigned int originalSize
Definition: cuddGroup.c:136
static int ddIsVarHandled(DdManager *dd, int index)
Definition: cuddGroup.c:2176
unsigned int keys
Definition: cuddInt.h:369
int Cudd_bddIsVarToBeUngrouped(DdManager *dd, int index)
Definition: cuddAPI.c:4301
int Cudd_bddIsVarToBeGrouped(DdManager *dd, int index)
Definition: cuddAPI.c:4249
int Cudd_bddReadPairIndex(DdManager *dd, int index)
Definition: cuddAPI.c:4148
int * invperm
Definition: cuddInt.h:388
int isolated
Definition: cuddInt.h:385

Variable Documentation

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

Definition at line 119 of file cuddGroup.c.

int ddTotalNumberSwapping

Definition at line 107 of file cuddReorder.c.

int* entry
static

Definition at line 122 of file cuddGroup.c.

unsigned int originalSize
static

Definition at line 136 of file cuddGroup.c.