SVF
Macros | Typedefs | Functions | Variables
cuddGroup.c File Reference
#include "CUDD/util.h"
#include "CUDD/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.49 2012/02/05 01:07:18 fabio Exp $"
 
static int * entry
 
int ddTotalNumberSwapping
 
static unsigned int originalSize
 

Macro Definition Documentation

◆ DD_LAZY_SIFT

#define DD_LAZY_SIFT   1

Definition at line 89 of file cuddGroup.c.

◆ DD_NORMAL_SIFT

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

◆ DD_SIFT_DOWN

#define DD_SIFT_DOWN   0

Definition at line 92 of file cuddGroup.c.

◆ DD_SIFT_UP

#define DD_SIFT_UP   1

Definition at line 93 of file cuddGroup.c.

Typedef Documentation

◆ DD_CHKFP

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

Definition at line 106 of file cuddGroup.c.

Function Documentation

◆ Cudd_MakeTreeNode()

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

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

◆ cuddTreeSifting()

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

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

◆ ddCreateGroup()

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

924 {
925  int gybot;
926 
927 #ifdef DD_DEBUG
928  assert(y == x+1);
929 #endif
930 
931  /* Find bottom of second group. */
932  gybot = y;
933  while ((unsigned) gybot < table->subtables[gybot].next)
934  gybot = table->subtables[gybot].next;
935 
936  /* Link groups. */
937  table->subtables[x].next = y;
938  table->subtables[gybot].next = x;
939 
940  return;
941 
942 } /* ddCreateGroup */
#define assert(ex)
Definition: util.h:141
DdSubtable * subtables
Definition: cuddInt.h:349
unsigned int next
Definition: cuddInt.h:317

◆ ddDissolveGroup()

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

1832 {
1833  int topx;
1834  int boty;
1835 
1836  /* find top and bottom of the two groups */
1837  boty = y;
1838  while ((unsigned) boty < table->subtables[boty].next)
1839  boty = table->subtables[boty].next;
1840 
1841  topx = table->subtables[boty].next;
1842 
1843  table->subtables[boty].next = y;
1844  table->subtables[x].next = topx;
1845 
1846  return;
1847 
1848 } /* end of ddDissolveGroup */
DdSubtable * subtables
Definition: cuddInt.h:349
unsigned int next
Definition: cuddInt.h:317

◆ ddExtSymmCheck()

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

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

◆ ddFindNodeHiLo()

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:129
#define assert(ex)
Definition: util.h:141
int size
Definition: cuddInt.h:345
struct MtrNode * younger
Definition: mtr.h:134
MtrHalfWord index
Definition: mtr.h:130
MtrHalfWord low
Definition: mtr.h:128
Definition: mtr.h:126
struct MtrNode * child
Definition: mtr.h:132
int * perm
Definition: cuddInt.h:369

◆ ddGroupMove()

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

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

◆ ddGroupMoveBackward()

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

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

◆ ddGroupSifting()

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 = ALLOC(int,nvars);
746  if (var == NULL) {
747  table->errorCode = CUDD_MEMORY_OUT;
748  goto ddGroupSiftingOutOfMem;
749  }
750  entry = ALLOC(int,nvars);
751  if (entry == NULL) {
752  table->errorCode = CUDD_MEMORY_OUT;
753  goto ddGroupSiftingOutOfMem;
754  }
755  sifted = 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  if (util_cpu_time() - table->startTime + table->reordTime
786  > table->timeLimit) {
787  table->autoDyn = 0; /* prevent further reordering */
788  break;
789  }
790  xindex = var[i];
791  if (sifted[xindex] == 1) /* variable already sifted as part of group */
792  continue;
793  x = table->perm[xindex]; /* find current level of this variable */
794 
795  if (x < lower || x > upper || table->subtables[x].bindVar == 1)
796  continue;
797 #ifdef DD_STATS
798  previousSize = table->keys - table->isolated;
799 #endif
800 #ifdef DD_DEBUG
801  /* x is bottom of group */
802  assert((unsigned) x >= table->subtables[x].next);
803 #endif
804  if ((unsigned) x == table->subtables[x].next) {
805  dissolve = 1;
806  result = ddGroupSiftingAux(table,x,lower,upper,checkFunction,
807  lazyFlag);
808  } else {
809  dissolve = 0;
810  result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
811  }
812  if (!result) goto ddGroupSiftingOutOfMem;
813 
814  /* check for aggregation */
815  merged = 0;
816  if (lazyFlag == 0 && table->groupcheck == CUDD_GROUP_CHECK7) {
817  x = table->perm[xindex]; /* find current level */
818  if ((unsigned) x == table->subtables[x].next) { /* not part of a group */
819  if (x != upper && sifted[table->invperm[x+1]] == 0 &&
820  (unsigned) x+1 == table->subtables[x+1].next) {
821  if (ddSecDiffCheck(table,x,x+1)) {
822  merged =1;
823  ddCreateGroup(table,x,x+1);
824  }
825  }
826  if (x != lower && sifted[table->invperm[x-1]] == 0 &&
827  (unsigned) x-1 == table->subtables[x-1].next) {
828  if (ddSecDiffCheck(table,x-1,x)) {
829  merged =1;
830  ddCreateGroup(table,x-1,x);
831  }
832  }
833  }
834  }
835 
836  if (merged) { /* a group was created */
837  /* move x to bottom of group */
838  while ((unsigned) x < table->subtables[x].next)
839  x = table->subtables[x].next;
840  /* sift */
841  result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
842  if (!result) goto ddGroupSiftingOutOfMem;
843 #ifdef DD_STATS
844  if (table->keys < previousSize + table->isolated) {
845  (void) fprintf(table->out,"_");
846  } else if (table->keys > previousSize + table->isolated) {
847  (void) fprintf(table->out,"^");
848  } else {
849  (void) fprintf(table->out,"*");
850  }
851  fflush(table->out);
852  } else {
853  if (table->keys < previousSize + table->isolated) {
854  (void) fprintf(table->out,"-");
855  } else if (table->keys > previousSize + table->isolated) {
856  (void) fprintf(table->out,"+");
857  } else {
858  (void) fprintf(table->out,"=");
859  }
860  fflush(table->out);
861 #endif
862  }
863 
864  /* Mark variables in the group just sifted. */
865  x = table->perm[xindex];
866  if ((unsigned) x != table->subtables[x].next) {
867  xInit = x;
868  do {
869  j = table->invperm[x];
870  sifted[j] = 1;
871  x = table->subtables[x].next;
872  } while (x != xInit);
873 
874  /* Dissolve the group if it was created. */
875  if (lazyFlag == 0 && dissolve) {
876  do {
877  j = table->subtables[x].next;
878  table->subtables[x].next = x;
879  x = j;
880  } while (x != xInit);
881  }
882  }
883 
884 #ifdef DD_DEBUG
885  if (pr > 0) (void) fprintf(table->out,"ddGroupSifting:");
886 #endif
887 
888  if (lazyFlag) ddSetVarHandled(table, xindex);
889  } /* for */
890 
891  FREE(sifted);
892  FREE(var);
893  FREE(entry);
894 
895  return(1);
896 
897 ddGroupSiftingOutOfMem:
898  if (entry != NULL) FREE(entry);
899  if (var != NULL) FREE(var);
900  if (sifted != NULL) FREE(sifted);
901 
902  return(0);
903 
904 } /* end of ddGroupSifting */
Cudd_AggregationType groupcheck
Definition: cuddInt.h:410
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
#define assert(ex)
Definition: util.h:141
int size
Definition: cuddInt.h:345
static int ddNoCheck(DdManager *table, int x, int y)
Definition: cuddGroup.c:1862
static int ddSetVarHandled(DdManager *dd, int index)
Definition: cuddGroup.c:2133
int bindVar
Definition: cuddInt.h:318
DdSubtable * subtables
Definition: cuddInt.h:349
static int * entry
Definition: cuddGroup.c:119
static int ddResetVarHandled(DdManager *dd, int index)
Definition: cuddGroup.c:2157
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
#define ddMin(x, y)
Definition: cuddInt.h:771
long util_cpu_time(void)
Definition: cpu_time.c:34
static int ddSecDiffCheck(DdManager *table, int x, int y)
Definition: cuddGroup.c:1886
static void ddCreateGroup(DdManager *table, int x, int y)
Definition: cuddGroup.c:920
int siftMaxVar
Definition: cuddInt.h:395
unsigned int next
Definition: cuddInt.h:317
static int ddGroupSiftingAux(DdManager *table, int x, int xLow, int xHigh, DD_CHKFP checkFunction, int lazyFlag)
Definition: cuddGroup.c:961
static int ddUniqueCompareGroup(int *ptrX, int *ptrY)
Definition: cuddGroup.c:692
int * invperm
Definition: cuddInt.h:371
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

◆ ddGroupSiftingAux()

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

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

◆ ddGroupSiftingBackward()

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

1679 {
1680  Move *move;
1681  int res;
1682  Move *end_move;
1683  int diff, tmp_diff;
1684  int index;
1685  unsigned int pairlev;
1686 
1687  if (lazyFlag) {
1688  end_move = NULL;
1689 
1690  /* Find the minimum size, and the earliest position at which it
1691  ** was achieved. */
1692  for (move = moves; move != NULL; move = move->next) {
1693  if (move->size < size) {
1694  size = move->size;
1695  end_move = move;
1696  } else if (move->size == size) {
1697  if (end_move == NULL) end_move = move;
1698  }
1699  }
1700 
1701  /* Find among the moves that give minimum size the one that
1702  ** minimizes the distance from the corresponding variable. */
1703  if (moves != NULL) {
1704  diff = Cudd_ReadSize(table) + 1;
1705  index = (upFlag == 1) ?
1706  table->invperm[moves->x] : table->invperm[moves->y];
1707  pairlev =
1708  (unsigned) table->perm[Cudd_bddReadPairIndex(table, index)];
1709 
1710  for (move = moves; move != NULL; move = move->next) {
1711  if (move->size == size) {
1712  if (upFlag == 1) {
1713  tmp_diff = (move->x > pairlev) ?
1714  move->x - pairlev : pairlev - move->x;
1715  } else {
1716  tmp_diff = (move->y > pairlev) ?
1717  move->y - pairlev : pairlev - move->y;
1718  }
1719  if (tmp_diff < diff) {
1720  diff = tmp_diff;
1721  end_move = move;
1722  }
1723  }
1724  }
1725  }
1726  } else {
1727  /* Find the minimum size. */
1728  for (move = moves; move != NULL; move = move->next) {
1729  if (move->size < size) {
1730  size = move->size;
1731  }
1732  }
1733  }
1734 
1735  /* In case of lazy sifting, end_move identifies the position at
1736  ** which we want to stop. Otherwise, we stop as soon as we meet
1737  ** the minimum size. */
1738  for (move = moves; move != NULL; move = move->next) {
1739  if (lazyFlag) {
1740  if (move == end_move) return(1);
1741  } else {
1742  if (move->size == size) return(1);
1743  }
1744  if ((table->subtables[move->x].next == move->x) &&
1745  (table->subtables[move->y].next == move->y)) {
1746  res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
1747  if (!res) return(0);
1748 #ifdef DD_DEBUG
1749  if (pr > 0) (void) fprintf(table->out,"ddGroupSiftingBackward:\n");
1750  assert(table->subtables[move->x].next == move->x);
1751  assert(table->subtables[move->y].next == move->y);
1752 #endif
1753  } else { /* Group move necessary */
1754  if (move->flags == MTR_NEWNODE) {
1755  ddDissolveGroup(table,(int)move->x,(int)move->y);
1756  } else {
1757  res = ddGroupMoveBackward(table,(int)move->x,(int)move->y);
1758  if (!res) return(0);
1759  }
1760  }
1761 
1762  }
1763 
1764  return(1);
1765 
1766 } /* end of ddGroupSiftingBackward */
#define assert(ex)
Definition: util.h:141
Definition: cuddInt.h:469
static int ddGroupMoveBackward(DdManager *table, int x, int y)
Definition: cuddGroup.c:1599
DdSubtable * subtables
Definition: cuddInt.h:349
int Cudd_ReadSize(DdManager *dd)
Definition: cuddAPI.c:1681
FILE * out
Definition: cuddInt.h:423
unsigned int flags
Definition: cuddInt.h:472
DdHalfWord x
Definition: cuddInt.h:470
#define MTR_NEWNODE
Definition: mtr.h:98
int cuddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddReorder.c:760
DdHalfWord y
Definition: cuddInt.h:471
static void ddDissolveGroup(DdManager *table, int x, int y)
Definition: cuddGroup.c:1828
unsigned int next
Definition: cuddInt.h:317
int Cudd_bddReadPairIndex(DdManager *dd, int index)
Definition: cuddAPI.c:4601
struct Move * next
Definition: cuddInt.h:474
int * invperm
Definition: cuddInt.h:371
int * perm
Definition: cuddInt.h:369
int size
Definition: cuddInt.h:473

◆ ddGroupSiftingDown()

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

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

◆ ddGroupSiftingUp()

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

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

◆ ddIsVarHandled()

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

2184 {
2185  if (index >= dd->size || index < 0) return(-1);
2186  return dd->subtables[dd->perm[index]].varHandled;
2187 
2188 } /* end of ddIsVarHandled */
int size
Definition: cuddInt.h:345
DdSubtable * subtables
Definition: cuddInt.h:349
int varHandled
Definition: cuddInt.h:322
int * perm
Definition: cuddInt.h:369

◆ ddMergeGroups()

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

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

◆ ddNoCheck()

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

1866 {
1867  return(0);
1868 
1869 } /* end of ddNoCheck */

◆ ddReorderChildren()

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;
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:410
MtrHalfWord flags
Definition: mtr.h:127
static int ddGroupSifting(DdManager *table, int lower, int upper, DD_CHKFP checkFunction, int lazyFlag)
Definition: cuddGroup.c:720
int cuddAnnealing(DdManager *table, int lower, int upper)
Definition: cuddAnneal.c:154
static int ddNoCheck(DdManager *table, int x, int y)
Definition: cuddGroup.c:1862
int cuddSifting(DdManager *table, int lower, int upper)
Definition: cuddReorder.c:502
FILE * err
Definition: cuddInt.h:424
#define MTR_FIXED
Definition: mtr.h:97
static int ddExtSymmCheck(DdManager *table, int x, int y)
Definition: cuddGroup.c:1943
int cuddExact(DdManager *table, int lower, int upper)
Definition: cuddExact.c:149
int cuddSymmSiftingConv(DdManager *table, int lower, int upper)
Definition: cuddSymmetry.c:439
unsigned int keys
Definition: cuddInt.h:353
FILE * out
Definition: cuddInt.h:423
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:1780
#define DD_NORMAL_SIFT
Definition: cuddGroup.c:88
int cuddWindowReorder(DdManager *table, int low, int high, Cudd_ReorderingType submethod)
Definition: cuddWindow.c:138
int cuddSwapping(DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)
Definition: cuddReorder.c:604
int cuddGa(DdManager *table, int lower, int upper)
Definition: cuddGenetic.c:188
static int ddVarGroupCheck(DdManager *table, int x, int y)
Definition: cuddGroup.c:2093
#define DD_LAZY_SIFT
Definition: cuddGroup.c:89
static int result
Definition: cuddGenetic.c:121
int isolated
Definition: cuddInt.h:368
int cuddLinearAndSifting(DdManager *table, int lower, int upper)
Definition: cuddLinear.c:236
int cuddSymmSifting(DdManager *table, int lower, int upper)
Definition: cuddSymmetry.c:318

◆ ddResetVarHandled()

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

2160 {
2161  if (index >= dd->size || index < 0) return(0);
2162  dd->subtables[dd->perm[index]].varHandled = 0;
2163  return(1);
2164 
2165 } /* end of ddResetVarHandled */
int size
Definition: cuddInt.h:345
DdSubtable * subtables
Definition: cuddInt.h:349
int varHandled
Definition: cuddInt.h:322
int * perm
Definition: cuddInt.h:369

◆ ddSecDiffCheck()

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

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

◆ ddSetVarHandled()

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

2136 {
2137  if (index >= dd->size || index < 0) return(0);
2138  dd->subtables[dd->perm[index]].varHandled = 1;
2139  return(1);
2140 
2141 } /* end of ddSetVarHandled */
int size
Definition: cuddInt.h:345
DdSubtable * subtables
Definition: cuddInt.h:349
int varHandled
Definition: cuddInt.h:322
int * perm
Definition: cuddInt.h:369

◆ ddTreeSiftingAux()

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:410
Cudd_AggregationType
Definition: cudd.h:180
MtrHalfWord size
Definition: mtr.h:129
struct MtrNode * younger
Definition: mtr.h:134
Definition: mtr.h:126
static int ddTreeSiftingAux(DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
Definition: cuddGroup.c:361
void Mtr_PrintGroups(MtrNode *root, int silent)
Definition: mtrGroup.c:595
static int ddReorderChildren(DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)
Definition: cuddGroup.c:453
struct MtrNode * child
Definition: mtr.h:132

◆ ddUniqueCompareGroup()

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:119

◆ ddVarGroupCheck()

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

2097 {
2098  int xindex = table->invperm[x];
2099  int yindex = table->invperm[y];
2100 
2101  if (Cudd_bddIsVarToBeUngrouped(table, xindex)) return(0);
2102 
2103  if (Cudd_bddReadPairIndex(table, xindex) == yindex) {
2104  if (ddIsVarHandled(table, xindex) ||
2105  ddIsVarHandled(table, yindex)) {
2106  if (Cudd_bddIsVarToBeGrouped(table, xindex) ||
2107  Cudd_bddIsVarToBeGrouped(table, yindex) ) {
2108  if (table->keys - table->isolated <= originalSize) {
2109  return(1);
2110  }
2111  }
2112  }
2113  }
2114 
2115  return(0);
2116 
2117 } /* end of ddVarGroupCheck */
static unsigned int originalSize
Definition: cuddGroup.c:133
static int ddIsVarHandled(DdManager *dd, int index)
Definition: cuddGroup.c:2181
unsigned int keys
Definition: cuddInt.h:353
int Cudd_bddIsVarToBeUngrouped(DdManager *dd, int index)
Definition: cuddAPI.c:4754
int Cudd_bddIsVarToBeGrouped(DdManager *dd, int index)
Definition: cuddAPI.c:4702
int Cudd_bddReadPairIndex(DdManager *dd, int index)
Definition: cuddAPI.c:4601
int * invperm
Definition: cuddInt.h:371
int isolated
Definition: cuddInt.h:368

Variable Documentation

◆ DD_UNUSED

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

Definition at line 116 of file cuddGroup.c.

◆ ddTotalNumberSwapping

int ddTotalNumberSwapping

Definition at line 103 of file cuddReorder.c.

◆ entry

int* entry
static

Definition at line 119 of file cuddGroup.c.

◆ originalSize

unsigned int originalSize
static

Definition at line 133 of file cuddGroup.c.