abc/src/bdd/cudd/cuddZddSymm.c
int
cuddZddSymmSiftingConv(
  DdManager * table,
  int  lower,
  int  upper)
{
    int         i;
    int         *var;
    int         nvars;
    int         initialSize;
    int         x;
    int         result;
    int         symvars;
    int         symgroups;
    int         classes;
    int         iteration;
#ifdef DD_STATS
    int         previousSize;
#endif

    initialSize = table->keysZ;

    nvars = table->sizeZ;

    /* Find order in which to sift variables. */
    var = NULL;
    zdd_entry = ABC_ALLOC(int, nvars);
    if (zdd_entry == NULL) {
        table->errorCode = CUDD_MEMORY_OUT;
        goto cuddZddSymmSiftingConvOutOfMem;
    }
    var = ABC_ALLOC(int, nvars);
    if (var == NULL) {
        table->errorCode = CUDD_MEMORY_OUT;
        goto cuddZddSymmSiftingConvOutOfMem;
    }

    for (i = 0; i < nvars; i++) {
        x = table->permZ[i];
        zdd_entry[i] = table->subtableZ[x].keys;
        var[i] = i;
    }

    qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);

    /* Initialize the symmetry of each subtable to itself
    ** for first pass of converging symmetric sifting.
    */
    for (i = lower; i <= upper; i++)
        table->subtableZ[i].next = i;

    iteration = ddMin(table->siftMaxVar, table->sizeZ);
    for (i = 0; i < iteration; i++) {
        if (zddTotalNumberSwapping >= table->siftMaxSwap)
            break;
        x = table->permZ[var[i]];
        if (x < lower || x > upper) continue;
        /* Only sift if not in symmetry group already. */
        if (table->subtableZ[x].next == (unsigned) x) {
#ifdef DD_STATS
            previousSize = table->keysZ;
#endif
            result = cuddZddSymmSiftingAux(table, x, lower, upper);
            if (!result)
                goto cuddZddSymmSiftingConvOutOfMem;
#ifdef DD_STATS
            if (table->keysZ < (unsigned) previousSize) {
                (void) fprintf(table->out,"-");
            } else if (table->keysZ > (unsigned) previousSize) {
                (void) fprintf(table->out,"+");
#ifdef DD_VERBOSE
                (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
#endif
            } else {
                (void) fprintf(table->out,"=");
            }
            fflush(table->out);
#endif
        }
    }

    /* Sifting now until convergence. */
    while ((unsigned) initialSize > table->keysZ) {
        initialSize = table->keysZ;
#ifdef DD_STATS
        (void) fprintf(table->out,"\n");
#endif
        /* Here we consider only one representative for each symmetry class. */
        for (x = lower, classes = 0; x <= upper; x++, classes++) {
            while ((unsigned) x < table->subtableZ[x].next)
                x = table->subtableZ[x].next;
            /* Here x is the largest index in a group.
            ** Groups consists of adjacent variables.
            ** Hence, the next increment of x will move it to a new group.
            */
            i = table->invpermZ[x];
            zdd_entry[i] = table->subtableZ[x].keys;
            var[classes] = i;
        }

        qsort((void *)var,classes,sizeof(int),(DD_QSFP)cuddZddUniqueCompare);

        /* Now sift. */
        iteration = ddMin(table->siftMaxVar, nvars);
        for (i = 0; i < iteration; i++) {
            if (zddTotalNumberSwapping >= table->siftMaxSwap)
                break;
            x = table->permZ[var[i]];
            if ((unsigned) x >= table->subtableZ[x].next) {
#ifdef DD_STATS
                previousSize = table->keysZ;
#endif
                result = cuddZddSymmSiftingConvAux(table, x, lower, upper);
                if (!result)
                    goto cuddZddSymmSiftingConvOutOfMem;
#ifdef DD_STATS
                if (table->keysZ < (unsigned) previousSize) {
                    (void) fprintf(table->out,"-");
                } else if (table->keysZ > (unsigned) previousSize) {
                    (void) fprintf(table->out,"+");
#ifdef DD_VERBOSE
                (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
#endif
                } else {
                    (void) fprintf(table->out,"=");
                }
                fflush(table->out);
#endif
            }
        } /* for */
    }

    cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);

#ifdef DD_STATS
    (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",
                   symvars);
    (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",
                   symgroups);
#endif

    ABC_FREE(var);
    ABC_FREE(zdd_entry);

    return(1+symvars);

cuddZddSymmSiftingConvOutOfMem:

    if (zdd_entry != NULL)
        ABC_FREE(zdd_entry);
    if (var != NULL)
        ABC_FREE(var);

    return(0);

}
/**Function********************************************************************

  Synopsis [Symmetric sifting to convergence algorithm for ZDDs.]

  Description [Symmetric sifting to convergence algorithm for ZDDs.
  Assumes that no dead nodes are present.
    <ol>
    <li> Order all the variables according to the number of entries in
    each unique subtable.
    <li> Sift the variable up and down, remembering each time the total
    size of the ZDD heap and grouping variables that are symmetric.
    <li> Select the best permutation.
    <li> Repeat 3 and 4 for all variables.
    <li> Repeat 1-4 until no further improvement.
    </ol>
  Returns 1 plus the number of symmetric variables if successful; 0
  otherwise.]

  SideEffects [None]

  SeeAlso     [cuddZddSymmSifting]

******************************************************************************/
Function
Synopsis [Symmetric sifting to convergence algorithm for ZDDs.]

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

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

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




Function Synopsis [ Symmetric sifting to convergence algorithm for ZDDs . ] Description [ Symmetric sifting to convergence algorithm for ZDDs . Assumes that no dead nodes are present . Order all the variables according to the number of entries in each unique subtable . Sift the variable up and down remembering each time the total size of the ZDD heap and grouping variables that are symmetric . Select the best permutation . Repeat 3 and 4 for all variables . Repeat 1 - 4 until no further improvement . Returns 1 plus the number of symmetric variables if successful ; 0 otherwise . ]
int
cuddZddSymmSiftingConv(
  DdManager * table,
  int  lower,
  int  upper)
{
    int         i;
    int         *var;
    int         nvars;
    int         initialSize;
    int         x;
    int         result;
    int         symvars;
    int         symgroups;
    int         classes;
    int         iteration;
#ifdef DD_STATS
    int         previousSize;
#endif
    initialSize = table->keysZ;
    nvars = table->sizeZ;
    var = NULL;
    zdd_entry = ABC_ALLOC(int, nvars);
    if (zdd_entry == NULL) {
        table->errorCode = CUDD_MEMORY_OUT;
        goto cuddZddSymmSiftingConvOutOfMem;
    }
    var = ABC_ALLOC(int, nvars);
    if (var == NULL) {
        table->errorCode = CUDD_MEMORY_OUT;
        goto cuddZddSymmSiftingConvOutOfMem;
    }
    for (i = 0; i < nvars; i++) {
        x = table->permZ[i];
        zdd_entry[i] = table->subtableZ[x].keys;
        var[i] = i;
    }
    qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
    for (i = lower; i <= upper; i++)
        table->subtableZ[i].next = i;
    iteration = ddMin(table->siftMaxVar, table->sizeZ);
    for (i = 0; i < iteration; i++) {
        if (zddTotalNumberSwapping >= table->siftMaxSwap)
            break;
        x = table->permZ[var[i]];
        if (x < lower || x > upper) continue;
        if (table->subtableZ[x].next == (unsigned) x) {
#ifdef DD_STATS
            previousSize = table->keysZ;
#endif
            result = cuddZddSymmSiftingAux(table, x, lower, upper);
            if (!result)
                goto cuddZddSymmSiftingConvOutOfMem;
#ifdef DD_STATS
            if (table->keysZ < (unsigned) previousSize) {
                (void) fprintf(table->out,"-");
            } else if (table->keysZ > (unsigned) previousSize) {
                (void) fprintf(table->out,"+");
#ifdef DD_VERBOSE
                (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
#endif
            } else {
                (void) fprintf(table->out,"=");
            }
            fflush(table->out);
#endif
        }
    }
    while ((unsigned) initialSize > table->keysZ) {
        initialSize = table->keysZ;
#ifdef DD_STATS
        (void) fprintf(table->out,"\n");
#endif
        for (x = lower, classes = 0; x <= upper; x++, classes++) {
            while ((unsigned) x < table->subtableZ[x].next)
                x = table->subtableZ[x].next;
            i = table->invpermZ[x];
            zdd_entry[i] = table->subtableZ[x].keys;
            var[classes] = i;
        }
        qsort((void *)var,classes,sizeof(int),(DD_QSFP)cuddZddUniqueCompare);
        iteration = ddMin(table->siftMaxVar, nvars);
        for (i = 0; i < iteration; i++) {
            if (zddTotalNumberSwapping >= table->siftMaxSwap)
                break;
            x = table->permZ[var[i]];
            if ((unsigned) x >= table->subtableZ[x].next) {
#ifdef DD_STATS
                previousSize = table->keysZ;
#endif
                result = cuddZddSymmSiftingConvAux(table, x, lower, upper);
                if (!result)
                    goto cuddZddSymmSiftingConvOutOfMem;
#ifdef DD_STATS
                if (table->keysZ < (unsigned) previousSize) {
                    (void) fprintf(table->out,"-");
                } else if (table->keysZ > (unsigned) previousSize) {
                    (void) fprintf(table->out,"+");
#ifdef DD_VERBOSE
                (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
#endif
                } else {
                    (void) fprintf(table->out,"=");
                }
                fflush(table->out);
#endif
            }
        } 
    }
    cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
#ifdef DD_STATS
    (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",
                   symvars);
    (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",
                   symgroups);
#endif
    ABC_FREE(var);
    ABC_FREE(zdd_entry);
    return(1+symvars);
cuddZddSymmSiftingConvOutOfMem:
    if (zdd_entry != NULL)
        ABC_FREE(zdd_entry);
    if (var != NULL)
        ABC_FREE(var);
    return(0);
}
int cuddZddSymmSiftingConv ( DdManager * table , int lower , int upper ) { int i ; int * var ; int nvars ; int initialSize ; int x ; int result ; int symvars ; int symgroups ; int classes ; int iteration ; #ifdef DD_STATS int previousSize ; #endif initialSize = table -> keysZ ; nvars = table -> sizeZ ; var = NULL ; zdd_entry = ABC_ALLOC ( int , nvars ) ; if ( zdd_entry == NULL ) { table -> errorCode = CUDD_MEMORY_OUT ; goto cuddZddSymmSiftingConvOutOfMem ; } var = ABC_ALLOC ( int , nvars ) ; if ( var == NULL ) { table -> errorCode = CUDD_MEMORY_OUT ; goto cuddZddSymmSiftingConvOutOfMem ; } for ( i = 0 ; i < nvars ; i ++ ) { x = table -> permZ [ i ] ; zdd_entry [ i ] = table -> subtableZ [ x ] . keys ; var [ i ] = i ; } qsort ( ( void * ) var , nvars , sizeof ( int ) , ( DD_QSFP ) cuddZddUniqueCompare ) ; for ( i = lower ; i <= upper ; i ++ ) table -> subtableZ [ i ] . next = i ; iteration = ddMin ( table -> siftMaxVar , table -> sizeZ ) ; for ( i = 0 ; i < iteration ; i ++ ) { if ( zddTotalNumberSwapping >= table -> siftMaxSwap ) break ; x = table -> permZ [ var [ i ] ] ; if ( x < lower || x > upper ) continue ; if ( table -> subtableZ [ x ] . next == ( unsigned ) x ) { #ifdef DD_STATS previousSize = table -> keysZ ; #endif result = cuddZddSymmSiftingAux ( table , x , lower , upper ) ; if ( ! result ) goto cuddZddSymmSiftingConvOutOfMem ; #ifdef DD_STATS if ( table -> keysZ < ( unsigned ) previousSize ) { ( void ) fprintf ( table -> out , " " ) ; } else if ( table -> keysZ > ( unsigned ) previousSize ) { ( void ) fprintf ( table -> out , " " ) ; #ifdef DD_VERBOSE ( void ) fprintf ( table -> out , " \n \n " , previousSize , table -> keysZ , var [ i ] ) ; #endif } else { ( void ) fprintf ( table -> out , " " ) ; } fflush ( table -> out ) ; #endif } } while ( ( unsigned ) initialSize > table -> keysZ ) { initialSize = table -> keysZ ; #ifdef DD_STATS ( void ) fprintf ( table -> out , " \n " ) ; #endif for ( x = lower , classes = 0 ; x <= upper ; x ++ , classes ++ ) { while ( ( unsigned ) x < table -> subtableZ [ x ] . next ) x = table -> subtableZ [ x ] . next ; i = table -> invpermZ [ x ] ; zdd_entry [ i ] = table -> subtableZ [ x ] . keys ; var [ classes ] = i ; } qsort ( ( void * ) var , classes , sizeof ( int ) , ( DD_QSFP ) cuddZddUniqueCompare ) ; iteration = ddMin ( table -> siftMaxVar , nvars ) ; for ( i = 0 ; i < iteration ; i ++ ) { if ( zddTotalNumberSwapping >= table -> siftMaxSwap ) break ; x = table -> permZ [ var [ i ] ] ; if ( ( unsigned ) x >= table -> subtableZ [ x ] . next ) { #ifdef DD_STATS previousSize = table -> keysZ ; #endif result = cuddZddSymmSiftingConvAux ( table , x , lower , upper ) ; if ( ! result ) goto cuddZddSymmSiftingConvOutOfMem ; #ifdef DD_STATS if ( table -> keysZ < ( unsigned ) previousSize ) { ( void ) fprintf ( table -> out , " " ) ; } else if ( table -> keysZ > ( unsigned ) previousSize ) { ( void ) fprintf ( table -> out , " " ) ; #ifdef DD_VERBOSE ( void ) fprintf ( table -> out , " \n \n " , previousSize , table -> keysZ , var [ i ] ) ; #endif } else { ( void ) fprintf ( table -> out , " " ) ; } fflush ( table -> out ) ; #endif } } } cuddZddSymmSummary ( table , lower , upper , & symvars , & symgroups ) ; #ifdef DD_STATS ( void ) fprintf ( table -> out , " \n \n " , symvars ) ; ( void ) fprintf ( table -> out , " \n " , symgroups ) ; #endif ABC_FREE ( var ) ; ABC_FREE ( zdd_entry ) ; return ( 1 + symvars ) ; cuddZddSymmSiftingConvOutOfMem : if ( zdd_entry != NULL ) ABC_FREE ( zdd_entry ) ; if ( var != NULL ) ABC_FREE ( var ) ; return ( 0 ) ; }
Function
Synopsis [Symmetric sifting to convergence algorithm for ZDDs.]
Function Synopsis [ Symmetric sifting to convergence algorithm for ZDDs . ]
/* Find order in which to sift variables. */ /* Initialize the symmetry of each subtable to itself
    ** for first pass of converging symmetric sifting.
    */ /* Only sift if not in symmetry group already. */ /* Sifting now until convergence. */ /* Here we consider only one representative for each symmetry class. */ /* Here x is the largest index in a group.
            ** Groups consists of adjacent variables.
            ** Hence, the next increment of x will move it to a new group.
            */ /* Now sift. */ /* for */