SVF
Macros | Functions | Variables
cuddZddSymm.c File Reference
#include "CUDD/util.h"
#include "CUDD/cuddInt.h"

Go to the source code of this file.

Macros

#define ZDD_MV_OOM   (Move *)1
 

Functions

static int cuddZddSymmSiftingAux (DdManager *table, int x, int x_low, int x_high)
 
static int cuddZddSymmSiftingConvAux (DdManager *table, int x, int x_low, int x_high)
 
static MovecuddZddSymmSifting_up (DdManager *table, int x, int x_low, int initial_size)
 
static MovecuddZddSymmSifting_down (DdManager *table, int x, int x_high, int initial_size)
 
static int cuddZddSymmSiftingBackward (DdManager *table, Move *moves, int size)
 
static int zdd_group_move (DdManager *table, int x, int y, Move **moves)
 
static int zdd_group_move_backward (DdManager *table, int x, int y)
 
static void cuddZddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups)
 
void Cudd_zddSymmProfile (DdManager *table, int lower, int upper)
 
int cuddZddSymmCheck (DdManager *table, int x, int y)
 
int cuddZddSymmSifting (DdManager *table, int lower, int upper)
 
int cuddZddSymmSiftingConv (DdManager *table, int lower, int upper)
 

Variables

static char rcsid [] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.31 2012/02/05 01:07:19 fabio Exp $"
 
int * zdd_entry
 
int zddTotalNumberSwapping
 
static DdNodeempty
 

Macro Definition Documentation

◆ ZDD_MV_OOM

#define ZDD_MV_OOM   (Move *)1

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

FileName [cuddZddSymm.c]

PackageName [cudd]

Synopsis [Functions for symmetry-based ZDD variable reordering.]

Description [External procedures included in this module:

Internal procedures included in this module:

Static procedures included in this module:

]

SeeAlso [cuddSymmetry.c]

Author [Hyong-Kyoon Shin, In-Ho Moon]

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

All rights reserved.

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

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

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

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

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

Definition at line 77 of file cuddZddSymm.c.

Function Documentation

◆ Cudd_zddSymmProfile()

void Cudd_zddSymmProfile ( DdManager table,
int  lower,
int  upper 
)

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

Synopsis [Prints statistics on symmetric ZDD variables.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 141 of file cuddZddSymm.c.

145 {
146  int i, x, gbot;
147  int TotalSymm = 0;
148  int TotalSymmGroups = 0;
149 
150  for (i = lower; i < upper; i++) {
151  if (table->subtableZ[i].next != (unsigned) i) {
152  x = i;
153  (void) fprintf(table->out,"Group:");
154  do {
155  (void) fprintf(table->out," %d", table->invpermZ[x]);
156  TotalSymm++;
157  gbot = x;
158  x = table->subtableZ[x].next;
159  } while (x != i);
160  TotalSymmGroups++;
161 #ifdef DD_DEBUG
162  assert(table->subtableZ[gbot].next == (unsigned) i);
163 #endif
164  i = gbot;
165  (void) fprintf(table->out,"\n");
166  }
167  }
168  (void) fprintf(table->out,"Total Symmetric = %d\n", TotalSymm);
169  (void) fprintf(table->out,"Total Groups = %d\n", TotalSymmGroups);
170 
171 } /* end of Cudd_zddSymmProfile */
int * invpermZ
Definition: cuddInt.h:372
#define assert(ex)
Definition: util.h:141
FILE * out
Definition: cuddInt.h:423
unsigned int next
Definition: cuddInt.h:317
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddSymmCheck()

int cuddZddSymmCheck ( DdManager table,
int  x,
int  y 
)

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

Synopsis [Checks for symmetry of x and y.]

Description [Checks for symmetry of x and y. Ignores projection functions, unless they are isolated. Returns 1 in case of symmetry; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 193 of file cuddZddSymm.c.

197 {
198  int i;
199  DdNode *f, *f0, *f1, *f01, *f00, *f11, *f10;
200  int yindex;
201  int xsymmy = 1;
202  int xsymmyp = 1;
203  int arccount = 0;
204  int TotalRefCount = 0;
205  int symm_found;
206 
207  empty = table->zero;
208 
209  yindex = table->invpermZ[y];
210  for (i = table->subtableZ[x].slots - 1; i >= 0; i--) {
211  f = table->subtableZ[x].nodelist[i];
212  while (f != NULL) {
213  /* Find f1, f0, f11, f10, f01, f00 */
214  f1 = cuddT(f);
215  f0 = cuddE(f);
216  if ((int) f1->index == yindex) {
217  f11 = cuddT(f1);
218  f10 = cuddE(f1);
219  if (f10 != empty)
220  arccount++;
221  } else {
222  if ((int) f0->index != yindex) {
223  return(0); /* f bypasses layer y */
224  }
225  f11 = empty;
226  f10 = f1;
227  }
228  if ((int) f0->index == yindex) {
229  f01 = cuddT(f0);
230  f00 = cuddE(f0);
231  if (f00 != empty)
232  arccount++;
233  } else {
234  f01 = empty;
235  f00 = f0;
236  }
237  if (f01 != f10)
238  xsymmy = 0;
239  if (f11 != f00)
240  xsymmyp = 0;
241  if ((xsymmy == 0) && (xsymmyp == 0))
242  return(0);
243 
244  f = f->next;
245  } /* for each element of the collision list */
246  } /* for each slot of the subtable */
247 
248  /* Calculate the total reference counts of y
249  ** whose else arc is not empty.
250  */
251  for (i = table->subtableZ[y].slots - 1; i >= 0; i--) {
252  f = table->subtableZ[y].nodelist[i];
253  while (f != NIL(DdNode)) {
254  if (cuddE(f) != empty)
255  TotalRefCount += f->ref;
256  f = f->next;
257  }
258  }
259 
260  symm_found = (arccount == TotalRefCount);
261 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
262  if (symm_found) {
263  int xindex = table->invpermZ[x];
264  (void) fprintf(table->out,
265  "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
266  xindex,yindex,x,y);
267  }
268 #endif
269 
270  return(symm_found);
271 
272 } /* end cuddZddSymmCheck */
DdHalfWord ref
Definition: cudd.h:272
Definition: cudd.h:270
int * invpermZ
Definition: cuddInt.h:372
DdNode * zero
Definition: cuddInt.h:330
#define NIL(type)
Definition: util.h:44
static DdNode * empty
Definition: cuddZddSymm.c:99
FILE * out
Definition: cuddInt.h:423
DdNode * next
Definition: cudd.h:273
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
#define cuddE(node)
Definition: cuddInt.h:625
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddSymmSifting()

int cuddZddSymmSifting ( DdManager table,
int  lower,
int  upper 
)

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

Synopsis [Symmetric sifting algorithm for ZDDs.]

Description [Symmetric sifting algorithm. Assumes that no dead nodes are present.

  1. Order all the variables according to the number of entries in each unique subtable.
  2. Sift the variable up and down, remembering each time the total size of the ZDD heap and grouping variables that are symmetric.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.

Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddZddSymmSiftingConv]

Definition at line 298 of file cuddZddSymm.c.

302 {
303  int i;
304  int *var;
305  int nvars;
306  int x;
307  int result;
308  int symvars;
309  int symgroups;
310  int iteration;
311 #ifdef DD_STATS
312  int previousSize;
313 #endif
314 
315  nvars = table->sizeZ;
316 
317  /* Find order in which to sift variables. */
318  var = NULL;
319  zdd_entry = ALLOC(int, nvars);
320  if (zdd_entry == NULL) {
321  table->errorCode = CUDD_MEMORY_OUT;
322  goto cuddZddSymmSiftingOutOfMem;
323  }
324  var = ALLOC(int, nvars);
325  if (var == NULL) {
326  table->errorCode = CUDD_MEMORY_OUT;
327  goto cuddZddSymmSiftingOutOfMem;
328  }
329 
330  for (i = 0; i < nvars; i++) {
331  x = table->permZ[i];
332  zdd_entry[i] = table->subtableZ[x].keys;
333  var[i] = i;
334  }
335 
336  qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
337 
338  /* Initialize the symmetry of each subtable to itself. */
339  for (i = lower; i <= upper; i++)
340  table->subtableZ[i].next = i;
341 
342  iteration = ddMin(table->siftMaxVar, nvars);
343  for (i = 0; i < iteration; i++) {
344  if (zddTotalNumberSwapping >= table->siftMaxSwap)
345  break;
346  if (util_cpu_time() - table->startTime > table->timeLimit) {
347  table->autoDynZ = 0; /* prevent further reordering */
348  break;
349  }
350  x = table->permZ[var[i]];
351 #ifdef DD_STATS
352  previousSize = table->keysZ;
353 #endif
354  if (x < lower || x > upper) continue;
355  if (table->subtableZ[x].next == (unsigned) x) {
356  result = cuddZddSymmSiftingAux(table, x, lower, upper);
357  if (!result)
358  goto cuddZddSymmSiftingOutOfMem;
359 #ifdef DD_STATS
360  if (table->keysZ < (unsigned) previousSize) {
361  (void) fprintf(table->out,"-");
362  } else if (table->keysZ > (unsigned) previousSize) {
363  (void) fprintf(table->out,"+");
364 #ifdef DD_VERBOSE
365  (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
366 #endif
367  } else {
368  (void) fprintf(table->out,"=");
369  }
370  fflush(table->out);
371 #endif
372  }
373  }
374 
375  FREE(var);
376  FREE(zdd_entry);
377 
378  cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
379 
380 #ifdef DD_STATS
381  (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars);
382  (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups);
383 #endif
384 
385  return(1+symvars);
386 
387 cuddZddSymmSiftingOutOfMem:
388 
389  if (zdd_entry != NULL)
390  FREE(zdd_entry);
391  if (var != NULL)
392  FREE(var);
393 
394  return(0);
395 
396 } /* end of cuddZddSymmSifting */
unsigned int keys
Definition: cuddInt.h:314
#define FREE(obj)
Definition: util.h:80
int siftMaxSwap
Definition: cuddInt.h:396
int(* DD_QSFP)(const void *, const void *)
Definition: cudd.h:313
unsigned long startTime
Definition: cuddInt.h:426
int * zdd_entry
Definition: cuddZddReord.c:104
int * permZ
Definition: cuddInt.h:370
int zddTotalNumberSwapping
Definition: cuddZddReord.c:106
#define ALLOC(type, num)
Definition: util.h:76
FILE * out
Definition: cuddInt.h:423
#define ddMin(x, y)
Definition: cuddInt.h:771
long util_cpu_time(void)
Definition: cpu_time.c:34
int siftMaxVar
Definition: cuddInt.h:395
static void cuddZddSymmSummary(DdManager *table, int lower, int upper, int *symvars, int *symgroups)
Definition: cuddZddSymm.c:1679
int sizeZ
Definition: cuddInt.h:346
unsigned int next
Definition: cuddInt.h:317
int autoDynZ
Definition: cuddInt.h:401
static int result
Definition: cuddGenetic.c:121
unsigned int keysZ
Definition: cuddInt.h:354
static int cuddZddSymmSiftingAux(DdManager *table, int x, int x_low, int x_high)
Definition: cuddZddSymm.c:609
unsigned long timeLimit
Definition: cuddInt.h:427
int cuddZddUniqueCompare(int *ptr_x, int *ptr_y)
Definition: cuddZddReord.c:455
Cudd_ErrorType errorCode
Definition: cuddInt.h:425
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddSymmSifting_down()

static Move * cuddZddSymmSifting_down ( DdManager table,
int  x,
int  x_high,
int  initial_size 
)
static

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

Synopsis [Moves x down until either it reaches the bound (x_high) or the size of the ZDD heap increases too much.]

Description [Moves x down until either it reaches the bound (x_high) or the size of the ZDD heap increases too much. Assumes that x is the bottom of a symmetry group. Checks x for symmetry to the adjacent variables. If symmetry is found, the symmetry group of x is merged with the symmetry group of the other variable. Returns the set of moves in case of success; ZDD_MV_OOM if memory is full.]

SideEffects [None]

SeeAlso []

Definition at line 1346 of file cuddZddSymm.c.

1351 {
1352  Move *moves;
1353  Move *move;
1354  int y;
1355  int size;
1356  int limit_size = initial_size;
1357  int i, gxtop, gybot;
1358 
1359  moves = NULL;
1360  y = cuddZddNextHigh(table, x);
1361  while (y <= x_high) {
1362  gybot = table->subtableZ[y].next;
1363  while (table->subtableZ[gybot].next != (unsigned) y)
1364  gybot = table->subtableZ[gybot].next;
1365  if (cuddZddSymmCheck(table, x, y)) {
1366  /* Symmetry found, attach symm groups */
1367  gxtop = table->subtableZ[x].next;
1368  table->subtableZ[x].next = y;
1369  i = table->subtableZ[y].next;
1370  while (table->subtableZ[i].next != (unsigned) y)
1371  i = table->subtableZ[i].next;
1372  table->subtableZ[i].next = gxtop;
1373  }
1374  else if ((table->subtableZ[x].next == (unsigned) x) &&
1375  (table->subtableZ[y].next == (unsigned) y)) {
1376  /* x and y have self symmetry */
1377  size = cuddZddSwapInPlace(table, x, y);
1378  if (size == 0)
1379  goto cuddZddSymmSifting_downOutOfMem;
1380  move = (Move *)cuddDynamicAllocNode(table);
1381  if (move == NULL)
1382  goto cuddZddSymmSifting_downOutOfMem;
1383  move->x = x;
1384  move->y = y;
1385  move->size = size;
1386  move->next = moves;
1387  moves = move;
1388  if ((double)size >
1389  (double)limit_size * table->maxGrowth)
1390  return(moves);
1391  if (size < limit_size)
1392  limit_size = size;
1393  x = y;
1394  y = cuddZddNextHigh(table, x);
1395  }
1396  else { /* Group move */
1397  size = zdd_group_move(table, x, y, &moves);
1398  if ((double)size >
1399  (double)limit_size * table->maxGrowth)
1400  return(moves);
1401  if (size < limit_size)
1402  limit_size = size;
1403  }
1404  x = gybot;
1405  y = cuddZddNextHigh(table, x);
1406  }
1407 
1408  return(moves);
1409 
1410 cuddZddSymmSifting_downOutOfMem:
1411  while (moves != NULL) {
1412  move = moves->next;
1413  cuddDeallocMove(table, moves);
1414  moves = move;
1415  }
1416  return(ZDD_MV_OOM);
1417 
1418 } /* end of cuddZddSymmSifting_down */
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
Definition: cuddInt.h:469
int cuddZddSymmCheck(DdManager *table, int x, int y)
Definition: cuddZddSymm.c:193
double maxGrowth
Definition: cuddInt.h:397
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:480
DdHalfWord x
Definition: cuddInt.h:470
static int zdd_group_move(DdManager *table, int x, int y, Move **moves)
Definition: cuddZddSymm.c:1489
int cuddZddNextHigh(DdManager *table, int x)
Definition: cuddZddReord.c:409
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:405
DdHalfWord y
Definition: cuddInt.h:471
unsigned int next
Definition: cuddInt.h:317
struct Move * next
Definition: cuddInt.h:474
#define ZDD_MV_OOM
Definition: cuddZddSymm.c:77
int size
Definition: cuddInt.h:473
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddSymmSifting_up()

static Move * cuddZddSymmSifting_up ( DdManager table,
int  x,
int  x_low,
int  initial_size 
)
static

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

Synopsis [Moves x up until either it reaches the bound (x_low) or the size of the ZDD heap increases too much.]

Description [Moves x up until either it reaches the bound (x_low) or the size of the ZDD heap increases too much. Assumes that x is the top of a symmetry group. Checks x for symmetry to the adjacent variables. If symmetry is found, the symmetry group of x is merged with the symmetry group of the other variable. Returns the set of moves in case of success; ZDD_MV_OOM if memory is full.]

SideEffects [None]

SeeAlso []

Definition at line 1258 of file cuddZddSymm.c.

1263 {
1264  Move *moves;
1265  Move *move;
1266  int y;
1267  int size;
1268  int limit_size = initial_size;
1269  int i, gytop;
1270 
1271  moves = NULL;
1272  y = cuddZddNextLow(table, x);
1273  while (y >= x_low) {
1274  gytop = table->subtableZ[y].next;
1275  if (cuddZddSymmCheck(table, y, x)) {
1276  /* Symmetry found, attach symm groups */
1277  table->subtableZ[y].next = x;
1278  i = table->subtableZ[x].next;
1279  while (table->subtableZ[i].next != (unsigned) x)
1280  i = table->subtableZ[i].next;
1281  table->subtableZ[i].next = gytop;
1282  }
1283  else if ((table->subtableZ[x].next == (unsigned) x) &&
1284  (table->subtableZ[y].next == (unsigned) y)) {
1285  /* x and y have self symmetry */
1286  size = cuddZddSwapInPlace(table, y, x);
1287  if (size == 0)
1288  goto cuddZddSymmSifting_upOutOfMem;
1289  move = (Move *)cuddDynamicAllocNode(table);
1290  if (move == NULL)
1291  goto cuddZddSymmSifting_upOutOfMem;
1292  move->x = y;
1293  move->y = x;
1294  move->size = size;
1295  move->next = moves;
1296  moves = move;
1297  if ((double)size >
1298  (double)limit_size * table->maxGrowth)
1299  return(moves);
1300  if (size < limit_size)
1301  limit_size = size;
1302  }
1303  else { /* Group move */
1304  size = zdd_group_move(table, y, x, &moves);
1305  if ((double)size >
1306  (double)limit_size * table->maxGrowth)
1307  return(moves);
1308  if (size < limit_size)
1309  limit_size = size;
1310  }
1311  x = gytop;
1312  y = cuddZddNextLow(table, x);
1313  }
1314 
1315  return(moves);
1316 
1317 cuddZddSymmSifting_upOutOfMem:
1318  while (moves != NULL) {
1319  move = moves->next;
1320  cuddDeallocMove(table, moves);
1321  moves = move;
1322  }
1323  return(ZDD_MV_OOM);
1324 
1325 } /* end of cuddZddSymmSifting_up */
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
Definition: cuddInt.h:469
int cuddZddSymmCheck(DdManager *table, int x, int y)
Definition: cuddZddSymm.c:193
double maxGrowth
Definition: cuddInt.h:397
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:480
DdHalfWord x
Definition: cuddInt.h:470
static int zdd_group_move(DdManager *table, int x, int y, Move **moves)
Definition: cuddZddSymm.c:1489
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:405
DdHalfWord y
Definition: cuddInt.h:471
unsigned int next
Definition: cuddInt.h:317
struct Move * next
Definition: cuddInt.h:474
#define ZDD_MV_OOM
Definition: cuddZddSymm.c:77
int cuddZddNextLow(DdManager *table, int x)
Definition: cuddZddReord.c:431
int size
Definition: cuddInt.h:473
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddSymmSiftingAux()

static int cuddZddSymmSiftingAux ( DdManager table,
int  x,
int  x_low,
int  x_high 
)
static

AutomaticStart

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

Synopsis [Given x_low <= x <= x_high moves x up and down between the boundaries.]

Description [Given x_low <= x <= x_high moves x up and down between the boundaries. Finds the best position and does the required changes. Assumes that x is not part of a symmetry group. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 609 of file cuddZddSymm.c.

614 {
615  Move *move;
616  Move *move_up; /* list of up move */
617  Move *move_down; /* list of down move */
618  int initial_size;
619  int result;
620  int i;
621  int topbot; /* index to either top or bottom of symmetry group */
622  int init_group_size, final_group_size;
623 
624  initial_size = table->keysZ;
625 
626  move_down = NULL;
627  move_up = NULL;
628 
629  /* Look for consecutive symmetries above x. */
630  for (i = x; i > x_low; i--) {
631  if (!cuddZddSymmCheck(table, i - 1, i))
632  break;
633  /* find top of i-1's symmetry */
634  topbot = table->subtableZ[i - 1].next;
635  table->subtableZ[i - 1].next = i;
636  table->subtableZ[x].next = topbot;
637  /* x is bottom of group so its symmetry is top of i-1's
638  group */
639  i = topbot + 1; /* add 1 for i--, new i is top of symm group */
640  }
641  /* Look for consecutive symmetries below x. */
642  for (i = x; i < x_high; i++) {
643  if (!cuddZddSymmCheck(table, i, i + 1))
644  break;
645  /* find bottom of i+1's symm group */
646  topbot = i + 1;
647  while ((unsigned) topbot < table->subtableZ[topbot].next)
648  topbot = table->subtableZ[topbot].next;
649 
650  table->subtableZ[topbot].next = table->subtableZ[i].next;
651  table->subtableZ[i].next = i + 1;
652  i = topbot - 1; /* add 1 for i++,
653  new i is bottom of symm group */
654  }
655 
656  /* Now x maybe in the middle of a symmetry group. */
657  if (x == x_low) { /* Sift down */
658  /* Find bottom of x's symm group */
659  while ((unsigned) x < table->subtableZ[x].next)
660  x = table->subtableZ[x].next;
661 
662  i = table->subtableZ[x].next;
663  init_group_size = x - i + 1;
664 
665  move_down = cuddZddSymmSifting_down(table, x, x_high,
666  initial_size);
667  /* after that point x --> x_high, unless early term */
668  if (move_down == ZDD_MV_OOM)
669  goto cuddZddSymmSiftingAuxOutOfMem;
670 
671  if (move_down == NULL ||
672  table->subtableZ[move_down->y].next != move_down->y) {
673  /* symmetry detected may have to make another complete
674  pass */
675  if (move_down != NULL)
676  x = move_down->y;
677  else
678  x = table->subtableZ[x].next;
679  i = x;
680  while ((unsigned) i < table->subtableZ[i].next) {
681  i = table->subtableZ[i].next;
682  }
683  final_group_size = i - x + 1;
684 
685  if (init_group_size == final_group_size) {
686  /* No new symmetry groups detected,
687  return to best position */
688  result = cuddZddSymmSiftingBackward(table,
689  move_down, initial_size);
690  }
691  else {
692  initial_size = table->keysZ;
693  move_up = cuddZddSymmSifting_up(table, x, x_low,
694  initial_size);
695  result = cuddZddSymmSiftingBackward(table, move_up,
696  initial_size);
697  }
698  }
699  else {
700  result = cuddZddSymmSiftingBackward(table, move_down,
701  initial_size);
702  /* move backward and stop at best position */
703  }
704  if (!result)
705  goto cuddZddSymmSiftingAuxOutOfMem;
706  }
707  else if (x == x_high) { /* Sift up */
708  /* Find top of x's symm group */
709  while ((unsigned) x < table->subtableZ[x].next)
710  x = table->subtableZ[x].next;
711  x = table->subtableZ[x].next;
712 
713  i = x;
714  while ((unsigned) i < table->subtableZ[i].next) {
715  i = table->subtableZ[i].next;
716  }
717  init_group_size = i - x + 1;
718 
719  move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
720  /* after that point x --> x_low, unless early term */
721  if (move_up == ZDD_MV_OOM)
722  goto cuddZddSymmSiftingAuxOutOfMem;
723 
724  if (move_up == NULL ||
725  table->subtableZ[move_up->x].next != move_up->x) {
726  /* symmetry detected may have to make another complete
727  pass */
728  if (move_up != NULL)
729  x = move_up->x;
730  else {
731  while ((unsigned) x < table->subtableZ[x].next)
732  x = table->subtableZ[x].next;
733  }
734  i = table->subtableZ[x].next;
735  final_group_size = x - i + 1;
736 
737  if (init_group_size == final_group_size) {
738  /* No new symmetry groups detected,
739  return to best position */
740  result = cuddZddSymmSiftingBackward(table, move_up,
741  initial_size);
742  }
743  else {
744  initial_size = table->keysZ;
745  move_down = cuddZddSymmSifting_down(table, x, x_high,
746  initial_size);
747  result = cuddZddSymmSiftingBackward(table, move_down,
748  initial_size);
749  }
750  }
751  else {
752  result = cuddZddSymmSiftingBackward(table, move_up,
753  initial_size);
754  /* move backward and stop at best position */
755  }
756  if (!result)
757  goto cuddZddSymmSiftingAuxOutOfMem;
758  }
759  else if ((x - x_low) > (x_high - x)) { /* must go down first:
760  shorter */
761  /* Find bottom of x's symm group */
762  while ((unsigned) x < table->subtableZ[x].next)
763  x = table->subtableZ[x].next;
764 
765  move_down = cuddZddSymmSifting_down(table, x, x_high,
766  initial_size);
767  /* after that point x --> x_high, unless early term */
768  if (move_down == ZDD_MV_OOM)
769  goto cuddZddSymmSiftingAuxOutOfMem;
770 
771  if (move_down != NULL) {
772  x = move_down->y;
773  }
774  else {
775  x = table->subtableZ[x].next;
776  }
777  i = x;
778  while ((unsigned) i < table->subtableZ[i].next) {
779  i = table->subtableZ[i].next;
780  }
781  init_group_size = i - x + 1;
782 
783  move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
784  if (move_up == ZDD_MV_OOM)
785  goto cuddZddSymmSiftingAuxOutOfMem;
786 
787  if (move_up == NULL ||
788  table->subtableZ[move_up->x].next != move_up->x) {
789  /* symmetry detected may have to make another complete
790  pass */
791  if (move_up != NULL) {
792  x = move_up->x;
793  }
794  else {
795  while ((unsigned) x < table->subtableZ[x].next)
796  x = table->subtableZ[x].next;
797  }
798  i = table->subtableZ[x].next;
799  final_group_size = x - i + 1;
800 
801  if (init_group_size == final_group_size) {
802  /* No new symmetry groups detected,
803  return to best position */
804  result = cuddZddSymmSiftingBackward(table, move_up,
805  initial_size);
806  }
807  else {
808  while (move_down != NULL) {
809  move = move_down->next;
810  cuddDeallocMove(table, move_down);
811  move_down = move;
812  }
813  initial_size = table->keysZ;
814  move_down = cuddZddSymmSifting_down(table, x, x_high,
815  initial_size);
816  result = cuddZddSymmSiftingBackward(table, move_down,
817  initial_size);
818  }
819  }
820  else {
821  result = cuddZddSymmSiftingBackward(table, move_up,
822  initial_size);
823  /* move backward and stop at best position */
824  }
825  if (!result)
826  goto cuddZddSymmSiftingAuxOutOfMem;
827  }
828  else { /* moving up first:shorter */
829  /* Find top of x's symmetry group */
830  while ((unsigned) x < table->subtableZ[x].next)
831  x = table->subtableZ[x].next;
832  x = table->subtableZ[x].next;
833 
834  move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
835  /* after that point x --> x_high, unless early term */
836  if (move_up == ZDD_MV_OOM)
837  goto cuddZddSymmSiftingAuxOutOfMem;
838 
839  if (move_up != NULL) {
840  x = move_up->x;
841  }
842  else {
843  while ((unsigned) x < table->subtableZ[x].next)
844  x = table->subtableZ[x].next;
845  }
846  i = table->subtableZ[x].next;
847  init_group_size = x - i + 1;
848 
849  move_down = cuddZddSymmSifting_down(table, x, x_high,
850  initial_size);
851  if (move_down == ZDD_MV_OOM)
852  goto cuddZddSymmSiftingAuxOutOfMem;
853 
854  if (move_down == NULL ||
855  table->subtableZ[move_down->y].next != move_down->y) {
856  /* symmetry detected may have to make another complete
857  pass */
858  if (move_down != NULL) {
859  x = move_down->y;
860  }
861  else {
862  x = table->subtableZ[x].next;
863  }
864  i = x;
865  while ((unsigned) i < table->subtableZ[i].next) {
866  i = table->subtableZ[i].next;
867  }
868  final_group_size = i - x + 1;
869 
870  if (init_group_size == final_group_size) {
871  /* No new symmetries detected,
872  go back to best position */
873  result = cuddZddSymmSiftingBackward(table, move_down,
874  initial_size);
875  }
876  else {
877  while (move_up != NULL) {
878  move = move_up->next;
879  cuddDeallocMove(table, move_up);
880  move_up = move;
881  }
882  initial_size = table->keysZ;
883  move_up = cuddZddSymmSifting_up(table, x, x_low,
884  initial_size);
885  result = cuddZddSymmSiftingBackward(table, move_up,
886  initial_size);
887  }
888  }
889  else {
890  result = cuddZddSymmSiftingBackward(table, move_down,
891  initial_size);
892  /* move backward and stop at best position */
893  }
894  if (!result)
895  goto cuddZddSymmSiftingAuxOutOfMem;
896  }
897 
898  while (move_down != NULL) {
899  move = move_down->next;
900  cuddDeallocMove(table, move_down);
901  move_down = move;
902  }
903  while (move_up != NULL) {
904  move = move_up->next;
905  cuddDeallocMove(table, move_up);
906  move_up = move;
907  }
908 
909  return(1);
910 
911 cuddZddSymmSiftingAuxOutOfMem:
912  if (move_down != ZDD_MV_OOM) {
913  while (move_down != NULL) {
914  move = move_down->next;
915  cuddDeallocMove(table, move_down);
916  move_down = move;
917  }
918  }
919  if (move_up != ZDD_MV_OOM) {
920  while (move_up != NULL) {
921  move = move_up->next;
922  cuddDeallocMove(table, move_up);
923  move_up = move;
924  }
925  }
926 
927  return(0);
928 
929 } /* end of cuddZddSymmSiftingAux */
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
Definition: cuddInt.h:469
int cuddZddSymmCheck(DdManager *table, int x, int y)
Definition: cuddZddSymm.c:193
static Move * cuddZddSymmSifting_down(DdManager *table, int x, int x_high, int initial_size)
Definition: cuddZddSymm.c:1346
static int cuddZddSymmSiftingBackward(DdManager *table, Move *moves, int size)
Definition: cuddZddSymm.c:1437
DdHalfWord x
Definition: cuddInt.h:470
DdHalfWord y
Definition: cuddInt.h:471
unsigned int next
Definition: cuddInt.h:317
struct Move * next
Definition: cuddInt.h:474
#define ZDD_MV_OOM
Definition: cuddZddSymm.c:77
static int result
Definition: cuddGenetic.c:121
static Move * cuddZddSymmSifting_up(DdManager *table, int x, int x_low, int initial_size)
Definition: cuddZddSymm.c:1258
unsigned int keysZ
Definition: cuddInt.h:354
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddSymmSiftingBackward()

static int cuddZddSymmSiftingBackward ( DdManager table,
Move moves,
int  size 
)
static

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

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

Description [Given a set of moves, returns the ZDD heap to the position giving the minimum size. In case of ties, returns to the closest position giving the minimum size. Returns 1 in case of success; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 1437 of file cuddZddSymm.c.

1441 {
1442  int i;
1443  int i_best;
1444  Move *move;
1445  int res;
1446 
1447  i_best = -1;
1448  for (move = moves, i = 0; move != NULL; move = move->next, i++) {
1449  if (move->size < size) {
1450  i_best = i;
1451  size = move->size;
1452  }
1453  }
1454 
1455  for (move = moves, i = 0; move != NULL; move = move->next, i++) {
1456  if (i == i_best) break;
1457  if ((table->subtableZ[move->x].next == move->x) &&
1458  (table->subtableZ[move->y].next == move->y)) {
1459  res = cuddZddSwapInPlace(table, move->x, move->y);
1460  if (!res) return(0);
1461  }
1462  else { /* Group move necessary */
1463  res = zdd_group_move_backward(table, move->x, move->y);
1464  }
1465  if (i_best == -1 && res == size)
1466  break;
1467  }
1468 
1469  return(1);
1470 
1471 } /* end of cuddZddSymmSiftingBackward */
Definition: cuddInt.h:469
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:480
DdHalfWord x
Definition: cuddInt.h:470
DdHalfWord y
Definition: cuddInt.h:471
unsigned int next
Definition: cuddInt.h:317
struct Move * next
Definition: cuddInt.h:474
int size
Definition: cuddInt.h:473
static int zdd_group_move_backward(DdManager *table, int x, int y)
Definition: cuddZddSymm.c:1596
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddSymmSiftingConv()

int cuddZddSymmSiftingConv ( DdManager table,
int  lower,
int  upper 
)

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

Synopsis [Symmetric sifting to convergence algorithm for ZDDs.]

Description [Symmetric sifting to convergence algorithm for ZDDs. Assumes that no dead nodes are present.

  1. Order all the variables according to the number of entries in each unique subtable.
  2. Sift the variable up and down, remembering each time the total size of the ZDD heap and grouping variables that are symmetric.
  3. Select the best permutation.
  4. Repeat 3 and 4 for all variables.
  5. Repeat 1-4 until no further improvement.

Returns 1 plus the number of symmetric variables if successful; 0 otherwise.]

SideEffects [None]

SeeAlso [cuddZddSymmSifting]

Definition at line 423 of file cuddZddSymm.c.

427 {
428  int i;
429  int *var;
430  int nvars;
431  int initialSize;
432  int x;
433  int result;
434  int symvars;
435  int symgroups;
436  int classes;
437  int iteration;
438 #ifdef DD_STATS
439  int previousSize;
440 #endif
441 
442  initialSize = table->keysZ;
443 
444  nvars = table->sizeZ;
445 
446  /* Find order in which to sift variables. */
447  var = NULL;
448  zdd_entry = ALLOC(int, nvars);
449  if (zdd_entry == NULL) {
450  table->errorCode = CUDD_MEMORY_OUT;
451  goto cuddZddSymmSiftingConvOutOfMem;
452  }
453  var = ALLOC(int, nvars);
454  if (var == NULL) {
455  table->errorCode = CUDD_MEMORY_OUT;
456  goto cuddZddSymmSiftingConvOutOfMem;
457  }
458 
459  for (i = 0; i < nvars; i++) {
460  x = table->permZ[i];
461  zdd_entry[i] = table->subtableZ[x].keys;
462  var[i] = i;
463  }
464 
465  qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
466 
467  /* Initialize the symmetry of each subtable to itself
468  ** for first pass of converging symmetric sifting.
469  */
470  for (i = lower; i <= upper; i++)
471  table->subtableZ[i].next = i;
472 
473  iteration = ddMin(table->siftMaxVar, table->sizeZ);
474  for (i = 0; i < iteration; i++) {
475  if (zddTotalNumberSwapping >= table->siftMaxSwap)
476  break;
477  if (util_cpu_time() - table->startTime > table->timeLimit) {
478  table->autoDynZ = 0; /* prevent further reordering */
479  break;
480  }
481  x = table->permZ[var[i]];
482  if (x < lower || x > upper) continue;
483  /* Only sift if not in symmetry group already. */
484  if (table->subtableZ[x].next == (unsigned) x) {
485 #ifdef DD_STATS
486  previousSize = table->keysZ;
487 #endif
488  result = cuddZddSymmSiftingAux(table, x, lower, upper);
489  if (!result)
490  goto cuddZddSymmSiftingConvOutOfMem;
491 #ifdef DD_STATS
492  if (table->keysZ < (unsigned) previousSize) {
493  (void) fprintf(table->out,"-");
494  } else if (table->keysZ > (unsigned) previousSize) {
495  (void) fprintf(table->out,"+");
496 #ifdef DD_VERBOSE
497  (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
498 #endif
499  } else {
500  (void) fprintf(table->out,"=");
501  }
502  fflush(table->out);
503 #endif
504  }
505  }
506 
507  /* Sifting now until convergence. */
508  while ((unsigned) initialSize > table->keysZ) {
509  initialSize = table->keysZ;
510 #ifdef DD_STATS
511  (void) fprintf(table->out,"\n");
512 #endif
513  /* Here we consider only one representative for each symmetry class. */
514  for (x = lower, classes = 0; x <= upper; x++, classes++) {
515  while ((unsigned) x < table->subtableZ[x].next)
516  x = table->subtableZ[x].next;
517  /* Here x is the largest index in a group.
518  ** Groups consists of adjacent variables.
519  ** Hence, the next increment of x will move it to a new group.
520  */
521  i = table->invpermZ[x];
522  zdd_entry[i] = table->subtableZ[x].keys;
523  var[classes] = i;
524  }
525 
526  qsort((void *)var,classes,sizeof(int),(DD_QSFP)cuddZddUniqueCompare);
527 
528  /* Now sift. */
529  iteration = ddMin(table->siftMaxVar, nvars);
530  for (i = 0; i < iteration; i++) {
531  if (zddTotalNumberSwapping >= table->siftMaxSwap)
532  break;
533  if (util_cpu_time() - table->startTime > table->timeLimit) {
534  table->autoDynZ = 0; /* prevent further reordering */
535  break;
536  }
537  x = table->permZ[var[i]];
538  if ((unsigned) x >= table->subtableZ[x].next) {
539 #ifdef DD_STATS
540  previousSize = table->keysZ;
541 #endif
542  result = cuddZddSymmSiftingConvAux(table, x, lower, upper);
543  if (!result)
544  goto cuddZddSymmSiftingConvOutOfMem;
545 #ifdef DD_STATS
546  if (table->keysZ < (unsigned) previousSize) {
547  (void) fprintf(table->out,"-");
548  } else if (table->keysZ > (unsigned) previousSize) {
549  (void) fprintf(table->out,"+");
550 #ifdef DD_VERBOSE
551  (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
552 #endif
553  } else {
554  (void) fprintf(table->out,"=");
555  }
556  fflush(table->out);
557 #endif
558  }
559  } /* for */
560  }
561 
562  cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
563 
564 #ifdef DD_STATS
565  (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",
566  symvars);
567  (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",
568  symgroups);
569 #endif
570 
571  FREE(var);
572  FREE(zdd_entry);
573 
574  return(1+symvars);
575 
576 cuddZddSymmSiftingConvOutOfMem:
577 
578  if (zdd_entry != NULL)
579  FREE(zdd_entry);
580  if (var != NULL)
581  FREE(var);
582 
583  return(0);
584 
585 } /* end of cuddZddSymmSiftingConv */
unsigned int keys
Definition: cuddInt.h:314
#define FREE(obj)
Definition: util.h:80
int siftMaxSwap
Definition: cuddInt.h:396
int(* DD_QSFP)(const void *, const void *)
Definition: cudd.h:313
unsigned long startTime
Definition: cuddInt.h:426
int * invpermZ
Definition: cuddInt.h:372
int * zdd_entry
Definition: cuddZddReord.c:104
int * permZ
Definition: cuddInt.h:370
int zddTotalNumberSwapping
Definition: cuddZddReord.c:106
#define ALLOC(type, num)
Definition: util.h:76
FILE * out
Definition: cuddInt.h:423
#define ddMin(x, y)
Definition: cuddInt.h:771
long util_cpu_time(void)
Definition: cpu_time.c:34
int siftMaxVar
Definition: cuddInt.h:395
static void cuddZddSymmSummary(DdManager *table, int lower, int upper, int *symvars, int *symgroups)
Definition: cuddZddSymm.c:1679
int sizeZ
Definition: cuddInt.h:346
unsigned int next
Definition: cuddInt.h:317
int autoDynZ
Definition: cuddInt.h:401
static int result
Definition: cuddGenetic.c:121
unsigned int keysZ
Definition: cuddInt.h:354
static int cuddZddSymmSiftingAux(DdManager *table, int x, int x_low, int x_high)
Definition: cuddZddSymm.c:609
static int cuddZddSymmSiftingConvAux(DdManager *table, int x, int x_low, int x_high)
Definition: cuddZddSymm.c:949
unsigned long timeLimit
Definition: cuddInt.h:427
int cuddZddUniqueCompare(int *ptr_x, int *ptr_y)
Definition: cuddZddReord.c:455
Cudd_ErrorType errorCode
Definition: cuddInt.h:425
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddSymmSiftingConvAux()

static int cuddZddSymmSiftingConvAux ( DdManager table,
int  x,
int  x_low,
int  x_high 
)
static

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

Synopsis [Given x_low <= x <= x_high moves x up and down between the boundaries.]

Description [Given x_low <= x <= x_high moves x up and down between the boundaries. Finds the best position and does the required changes. Assumes that x is either an isolated variable, or it is the bottom of a symmetry group. All symmetries may not have been found, because of exceeded growth limit. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 949 of file cuddZddSymm.c.

954 {
955  Move *move;
956  Move *move_up; /* list of up move */
957  Move *move_down; /* list of down move */
958  int initial_size;
959  int result;
960  int i;
961  int init_group_size, final_group_size;
962 
963  initial_size = table->keysZ;
964 
965  move_down = NULL;
966  move_up = NULL;
967 
968  if (x == x_low) { /* Sift down */
969  i = table->subtableZ[x].next;
970  init_group_size = x - i + 1;
971 
972  move_down = cuddZddSymmSifting_down(table, x, x_high,
973  initial_size);
974  /* after that point x --> x_high, unless early term */
975  if (move_down == ZDD_MV_OOM)
976  goto cuddZddSymmSiftingConvAuxOutOfMem;
977 
978  if (move_down == NULL ||
979  table->subtableZ[move_down->y].next != move_down->y) {
980  /* symmetry detected may have to make another complete
981  pass */
982  if (move_down != NULL)
983  x = move_down->y;
984  else {
985  while ((unsigned) x < table->subtableZ[x].next)
986  x = table->subtableZ[x].next;
987  x = table->subtableZ[x].next;
988  }
989  i = x;
990  while ((unsigned) i < table->subtableZ[i].next) {
991  i = table->subtableZ[i].next;
992  }
993  final_group_size = i - x + 1;
994 
995  if (init_group_size == final_group_size) {
996  /* No new symmetries detected,
997  go back to best position */
998  result = cuddZddSymmSiftingBackward(table, move_down,
999  initial_size);
1000  }
1001  else {
1002  initial_size = table->keysZ;
1003  move_up = cuddZddSymmSifting_up(table, x, x_low,
1004  initial_size);
1005  result = cuddZddSymmSiftingBackward(table, move_up,
1006  initial_size);
1007  }
1008  }
1009  else {
1010  result = cuddZddSymmSiftingBackward(table, move_down,
1011  initial_size);
1012  /* move backward and stop at best position */
1013  }
1014  if (!result)
1015  goto cuddZddSymmSiftingConvAuxOutOfMem;
1016  }
1017  else if (x == x_high) { /* Sift up */
1018  /* Find top of x's symm group */
1019  while ((unsigned) x < table->subtableZ[x].next)
1020  x = table->subtableZ[x].next;
1021  x = table->subtableZ[x].next;
1022 
1023  i = x;
1024  while ((unsigned) i < table->subtableZ[i].next) {
1025  i = table->subtableZ[i].next;
1026  }
1027  init_group_size = i - x + 1;
1028 
1029  move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
1030  /* after that point x --> x_low, unless early term */
1031  if (move_up == ZDD_MV_OOM)
1032  goto cuddZddSymmSiftingConvAuxOutOfMem;
1033 
1034  if (move_up == NULL ||
1035  table->subtableZ[move_up->x].next != move_up->x) {
1036  /* symmetry detected may have to make another complete
1037  pass */
1038  if (move_up != NULL)
1039  x = move_up->x;
1040  else {
1041  while ((unsigned) x < table->subtableZ[x].next)
1042  x = table->subtableZ[x].next;
1043  }
1044  i = table->subtableZ[x].next;
1045  final_group_size = x - i + 1;
1046 
1047  if (init_group_size == final_group_size) {
1048  /* No new symmetry groups detected,
1049  return to best position */
1050  result = cuddZddSymmSiftingBackward(table, move_up,
1051  initial_size);
1052  }
1053  else {
1054  initial_size = table->keysZ;
1055  move_down = cuddZddSymmSifting_down(table, x, x_high,
1056  initial_size);
1057  result = cuddZddSymmSiftingBackward(table, move_down,
1058  initial_size);
1059  }
1060  }
1061  else {
1062  result = cuddZddSymmSiftingBackward(table, move_up,
1063  initial_size);
1064  /* move backward and stop at best position */
1065  }
1066  if (!result)
1067  goto cuddZddSymmSiftingConvAuxOutOfMem;
1068  }
1069  else if ((x - x_low) > (x_high - x)) { /* must go down first:
1070  shorter */
1071  move_down = cuddZddSymmSifting_down(table, x, x_high,
1072  initial_size);
1073  /* after that point x --> x_high */
1074  if (move_down == ZDD_MV_OOM)
1075  goto cuddZddSymmSiftingConvAuxOutOfMem;
1076 
1077  if (move_down != NULL) {
1078  x = move_down->y;
1079  }
1080  else {
1081  while ((unsigned) x < table->subtableZ[x].next)
1082  x = table->subtableZ[x].next;
1083  x = table->subtableZ[x].next;
1084  }
1085  i = x;
1086  while ((unsigned) i < table->subtableZ[i].next) {
1087  i = table->subtableZ[i].next;
1088  }
1089  init_group_size = i - x + 1;
1090 
1091  move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
1092  if (move_up == ZDD_MV_OOM)
1093  goto cuddZddSymmSiftingConvAuxOutOfMem;
1094 
1095  if (move_up == NULL ||
1096  table->subtableZ[move_up->x].next != move_up->x) {
1097  /* symmetry detected may have to make another complete
1098  pass */
1099  if (move_up != NULL) {
1100  x = move_up->x;
1101  }
1102  else {
1103  while ((unsigned) x < table->subtableZ[x].next)
1104  x = table->subtableZ[x].next;
1105  }
1106  i = table->subtableZ[x].next;
1107  final_group_size = x - i + 1;
1108 
1109  if (init_group_size == final_group_size) {
1110  /* No new symmetry groups detected,
1111  return to best position */
1112  result = cuddZddSymmSiftingBackward(table, move_up,
1113  initial_size);
1114  }
1115  else {
1116  while (move_down != NULL) {
1117  move = move_down->next;
1118  cuddDeallocMove(table, move_down);
1119  move_down = move;
1120  }
1121  initial_size = table->keysZ;
1122  move_down = cuddZddSymmSifting_down(table, x, x_high,
1123  initial_size);
1124  result = cuddZddSymmSiftingBackward(table, move_down,
1125  initial_size);
1126  }
1127  }
1128  else {
1129  result = cuddZddSymmSiftingBackward(table, move_up,
1130  initial_size);
1131  /* move backward and stop at best position */
1132  }
1133  if (!result)
1134  goto cuddZddSymmSiftingConvAuxOutOfMem;
1135  }
1136  else { /* moving up first:shorter */
1137  /* Find top of x's symmetry group */
1138  x = table->subtableZ[x].next;
1139 
1140  move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
1141  /* after that point x --> x_high, unless early term */
1142  if (move_up == ZDD_MV_OOM)
1143  goto cuddZddSymmSiftingConvAuxOutOfMem;
1144 
1145  if (move_up != NULL) {
1146  x = move_up->x;
1147  }
1148  else {
1149  while ((unsigned) x < table->subtableZ[x].next)
1150  x = table->subtableZ[x].next;
1151  }
1152  i = table->subtableZ[x].next;
1153  init_group_size = x - i + 1;
1154 
1155  move_down = cuddZddSymmSifting_down(table, x, x_high,
1156  initial_size);
1157  if (move_down == ZDD_MV_OOM)
1158  goto cuddZddSymmSiftingConvAuxOutOfMem;
1159 
1160  if (move_down == NULL ||
1161  table->subtableZ[move_down->y].next != move_down->y) {
1162  /* symmetry detected may have to make another complete
1163  pass */
1164  if (move_down != NULL) {
1165  x = move_down->y;
1166  }
1167  else {
1168  while ((unsigned) x < table->subtableZ[x].next)
1169  x = table->subtableZ[x].next;
1170  x = table->subtableZ[x].next;
1171  }
1172  i = x;
1173  while ((unsigned) i < table->subtableZ[i].next) {
1174  i = table->subtableZ[i].next;
1175  }
1176  final_group_size = i - x + 1;
1177 
1178  if (init_group_size == final_group_size) {
1179  /* No new symmetries detected,
1180  go back to best position */
1181  result = cuddZddSymmSiftingBackward(table, move_down,
1182  initial_size);
1183  }
1184  else {
1185  while (move_up != NULL) {
1186  move = move_up->next;
1187  cuddDeallocMove(table, move_up);
1188  move_up = move;
1189  }
1190  initial_size = table->keysZ;
1191  move_up = cuddZddSymmSifting_up(table, x, x_low,
1192  initial_size);
1193  result = cuddZddSymmSiftingBackward(table, move_up,
1194  initial_size);
1195  }
1196  }
1197  else {
1198  result = cuddZddSymmSiftingBackward(table, move_down,
1199  initial_size);
1200  /* move backward and stop at best position */
1201  }
1202  if (!result)
1203  goto cuddZddSymmSiftingConvAuxOutOfMem;
1204  }
1205 
1206  while (move_down != NULL) {
1207  move = move_down->next;
1208  cuddDeallocMove(table, move_down);
1209  move_down = move;
1210  }
1211  while (move_up != NULL) {
1212  move = move_up->next;
1213  cuddDeallocMove(table, move_up);
1214  move_up = move;
1215  }
1216 
1217  return(1);
1218 
1219 cuddZddSymmSiftingConvAuxOutOfMem:
1220  if (move_down != ZDD_MV_OOM) {
1221  while (move_down != NULL) {
1222  move = move_down->next;
1223  cuddDeallocMove(table, move_down);
1224  move_down = move;
1225  }
1226  }
1227  if (move_up != ZDD_MV_OOM) {
1228  while (move_up != NULL) {
1229  move = move_up->next;
1230  cuddDeallocMove(table, move_up);
1231  move_up = move;
1232  }
1233  }
1234 
1235  return(0);
1236 
1237 } /* end of cuddZddSymmSiftingConvAux */
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
Definition: cuddInt.h:469
static Move * cuddZddSymmSifting_down(DdManager *table, int x, int x_high, int initial_size)
Definition: cuddZddSymm.c:1346
static int cuddZddSymmSiftingBackward(DdManager *table, Move *moves, int size)
Definition: cuddZddSymm.c:1437
DdHalfWord x
Definition: cuddInt.h:470
DdHalfWord y
Definition: cuddInt.h:471
unsigned int next
Definition: cuddInt.h:317
struct Move * next
Definition: cuddInt.h:474
#define ZDD_MV_OOM
Definition: cuddZddSymm.c:77
static int result
Definition: cuddGenetic.c:121
static Move * cuddZddSymmSifting_up(DdManager *table, int x, int x_low, int initial_size)
Definition: cuddZddSymm.c:1258
unsigned int keysZ
Definition: cuddInt.h:354
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ cuddZddSymmSummary()

static void cuddZddSymmSummary ( DdManager table,
int  lower,
int  upper,
int *  symvars,
int *  symgroups 
)
static

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

Synopsis [Counts numbers of symmetric variables and symmetry groups.]

Description []

SideEffects [None]

Definition at line 1679 of file cuddZddSymm.c.

1685 {
1686  int i,x,gbot;
1687  int TotalSymm = 0;
1688  int TotalSymmGroups = 0;
1689 
1690  for (i = lower; i <= upper; i++) {
1691  if (table->subtableZ[i].next != (unsigned) i) {
1692  TotalSymmGroups++;
1693  x = i;
1694  do {
1695  TotalSymm++;
1696  gbot = x;
1697  x = table->subtableZ[x].next;
1698  } while (x != i);
1699 #ifdef DD_DEBUG
1700  assert(table->subtableZ[gbot].next == (unsigned) i);
1701 #endif
1702  i = gbot;
1703  }
1704  }
1705  *symvars = TotalSymm;
1706  *symgroups = TotalSymmGroups;
1707 
1708  return;
1709 
1710 } /* end of cuddZddSymmSummary */
#define assert(ex)
Definition: util.h:141
unsigned int next
Definition: cuddInt.h:317
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ zdd_group_move()

static int zdd_group_move ( DdManager table,
int  x,
int  y,
Move **  moves 
)
static

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

Synopsis [Swaps two groups.]

Description [Swaps two groups. x is assumed to be the bottom variable of the first group. y is assumed to be the top variable of the second group. Updates the list of moves. Returns the number of keys in the table if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 1489 of file cuddZddSymm.c.

1494 {
1495  Move *move;
1496  int size;
1497  int i, temp, gxtop, gxbot, gybot, yprev;
1498  int swapx, swapy;
1499 
1500 #ifdef DD_DEBUG
1501  assert(x < y); /* we assume that x < y */
1502 #endif
1503  /* Find top and bottom for the two groups. */
1504  gxtop = table->subtableZ[x].next;
1505  gxbot = x;
1506  gybot = table->subtableZ[y].next;
1507  while (table->subtableZ[gybot].next != (unsigned) y)
1508  gybot = table->subtableZ[gybot].next;
1509  yprev = gybot;
1510 
1511  while (x <= y) {
1512  while (y > gxtop) {
1513  /* Set correct symmetries. */
1514  temp = table->subtableZ[x].next;
1515  if (temp == x)
1516  temp = y;
1517  i = gxtop;
1518  for (;;) {
1519  if (table->subtableZ[i].next == (unsigned) x) {
1520  table->subtableZ[i].next = y;
1521  break;
1522  } else {
1523  i = table->subtableZ[i].next;
1524  }
1525  }
1526  if (table->subtableZ[y].next != (unsigned) y) {
1527  table->subtableZ[x].next = table->subtableZ[y].next;
1528  } else {
1529  table->subtableZ[x].next = x;
1530  }
1531 
1532  if (yprev != y) {
1533  table->subtableZ[yprev].next = x;
1534  } else {
1535  yprev = x;
1536  }
1537  table->subtableZ[y].next = temp;
1538 
1539  size = cuddZddSwapInPlace(table, x, y);
1540  if (size == 0)
1541  goto zdd_group_moveOutOfMem;
1542  swapx = x;
1543  swapy = y;
1544  y = x;
1545  x--;
1546  } /* while y > gxtop */
1547 
1548  /* Trying to find the next y. */
1549  if (table->subtableZ[y].next <= (unsigned) y) {
1550  gybot = y;
1551  } else {
1552  y = table->subtableZ[y].next;
1553  }
1554 
1555  yprev = gxtop;
1556  gxtop++;
1557  gxbot++;
1558  x = gxbot;
1559  } /* while x <= y, end of group movement */
1560  move = (Move *)cuddDynamicAllocNode(table);
1561  if (move == NULL)
1562  goto zdd_group_moveOutOfMem;
1563  move->x = swapx;
1564  move->y = swapy;
1565  move->size = table->keysZ;
1566  move->next = *moves;
1567  *moves = move;
1568 
1569  return(table->keysZ);
1570 
1571 zdd_group_moveOutOfMem:
1572  while (*moves != NULL) {
1573  move = (*moves)->next;
1574  cuddDeallocMove(table, *moves);
1575  *moves = move;
1576  }
1577  return(0);
1578 
1579 } /* end of zdd_group_move */
#define cuddDeallocMove(unique, node)
Definition: cuddInt.h:537
#define assert(ex)
Definition: util.h:141
Definition: cuddInt.h:469
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:480
DdHalfWord x
Definition: cuddInt.h:470
DdNode * cuddDynamicAllocNode(DdManager *table)
Definition: cuddReorder.c:405
DdHalfWord y
Definition: cuddInt.h:471
unsigned int next
Definition: cuddInt.h:317
struct Move * next
Definition: cuddInt.h:474
unsigned int keysZ
Definition: cuddInt.h:354
int size
Definition: cuddInt.h:473
DdSubtable * subtableZ
Definition: cuddInt.h:350

◆ zdd_group_move_backward()

static int zdd_group_move_backward ( DdManager table,
int  x,
int  y 
)
static

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

Synopsis [Undoes the swap of two groups.]

Description [Undoes the swap of two groups. x is assumed to be the bottom variable of the first group. y is assumed to be the top variable of the second group. Returns 1 if successful; 0 otherwise.]

SideEffects [None]

SeeAlso []

Definition at line 1596 of file cuddZddSymm.c.

1600 {
1601  int size;
1602  int i, temp, gxtop, gxbot, gybot, yprev;
1603 
1604 #ifdef DD_DEBUG
1605  assert(x < y); /* we assume that x < y */
1606 #endif
1607  /* Find top and bottom of the two groups. */
1608  gxtop = table->subtableZ[x].next;
1609  gxbot = x;
1610  gybot = table->subtableZ[y].next;
1611  while (table->subtableZ[gybot].next != (unsigned) y)
1612  gybot = table->subtableZ[gybot].next;
1613  yprev = gybot;
1614 
1615  while (x <= y) {
1616  while (y > gxtop) {
1617  /* Set correct symmetries. */
1618  temp = table->subtableZ[x].next;
1619  if (temp == x)
1620  temp = y;
1621  i = gxtop;
1622  for (;;) {
1623  if (table->subtableZ[i].next == (unsigned) x) {
1624  table->subtableZ[i].next = y;
1625  break;
1626  } else {
1627  i = table->subtableZ[i].next;
1628  }
1629  }
1630  if (table->subtableZ[y].next != (unsigned) y) {
1631  table->subtableZ[x].next = table->subtableZ[y].next;
1632  } else {
1633  table->subtableZ[x].next = x;
1634  }
1635 
1636  if (yprev != y) {
1637  table->subtableZ[yprev].next = x;
1638  } else {
1639  yprev = x;
1640  }
1641  table->subtableZ[y].next = temp;
1642 
1643  size = cuddZddSwapInPlace(table, x, y);
1644  if (size == 0)
1645  return(0);
1646  y = x;
1647  x--;
1648  } /* while y > gxtop */
1649 
1650  /* Trying to find the next y. */
1651  if (table->subtableZ[y].next <= (unsigned) y) {
1652  gybot = y;
1653  } else {
1654  y = table->subtableZ[y].next;
1655  }
1656 
1657  yprev = gxtop;
1658  gxtop++;
1659  gxbot++;
1660  x = gxbot;
1661  } /* while x <= y, end of group movement backward */
1662 
1663  return(size);
1664 
1665 } /* end of zdd_group_move_backward */
#define assert(ex)
Definition: util.h:141
int cuddZddSwapInPlace(DdManager *table, int x, int y)
Definition: cuddZddReord.c:480
unsigned int next
Definition: cuddInt.h:317
DdSubtable * subtableZ
Definition: cuddInt.h:350

Variable Documentation

◆ DD_UNUSED

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

Definition at line 92 of file cuddZddSymm.c.

◆ empty

DdNode* empty
static

Definition at line 99 of file cuddZddSymm.c.

◆ zdd_entry

int* zdd_entry

Definition at line 104 of file cuddZddReord.c.

◆ zddTotalNumberSwapping

int zddTotalNumberSwapping

Definition at line 106 of file cuddZddReord.c.