Exemple #1
0
 Saig_ManForEachLi( p, pObj, i )
 {
     bFunc = (DdNode *)pObj->pData;  Cudd_Ref( bFunc );
     Vec_PtrWriteEntry( vBdds, Aig_ObjId(Saig_ObjLiToLo(p, pObj)), bFunc );
 }
/**Function********************************************************************

  Synopsis [Performs the recursive step of Cudd_bddIsop.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_bddIsop]

******************************************************************************/
DdNode	*
cuddBddIsop(
    DdManager * dd,
    DdNode * L,
    DdNode * U)
{
    DdNode	*one = DD_ONE(dd);
    DdNode	*zero = Cudd_Not(one);
    int		v, top_l, top_u;
    DdNode	*Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
    DdNode	*Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
    DdNode	*Isub0, *Isub1, *Id;
    DdNode	*x;
    DdNode	*term0, *term1, *sum;
    DdNode	*Lv, *Uv, *Lnv, *Unv;
    DdNode	*r;
    int		index;

    statLine(dd);
    if (L == zero)
        return(zero);
    if (U == one)
        return(one);

    /* Check cache */
    r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
    if (r)
        return(r);

    top_l = dd->perm[Cudd_Regular(L)->index];
    top_u = dd->perm[Cudd_Regular(U)->index];
    v = ddMin(top_l, top_u);

    /* Compute cofactors */
    if (top_l == v) {
        index = Cudd_Regular(L)->index;
        Lv = Cudd_T(L);
        Lnv = Cudd_E(L);
        if (Cudd_IsComplement(L)) {
            Lv = Cudd_Not(Lv);
            Lnv = Cudd_Not(Lnv);
        }
    }
    else {
        index = Cudd_Regular(U)->index;
        Lv = Lnv = L;
    }

    if (top_u == v) {
        Uv = Cudd_T(U);
        Unv = Cudd_E(U);
        if (Cudd_IsComplement(U)) {
            Uv = Cudd_Not(Uv);
            Unv = Cudd_Not(Unv);
        }
    }
    else {
        Uv = Unv = U;
    }

    Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
    if (Lsub0 == NULL)
        return(NULL);
    Cudd_Ref(Lsub0);
    Usub0 = Unv;
    Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
    if (Lsub1 == NULL) {
        Cudd_RecursiveDeref(dd, Lsub0);
        return(NULL);
    }
    Cudd_Ref(Lsub1);
    Usub1 = Uv;

    Isub0 = cuddBddIsop(dd, Lsub0, Usub0);
    if (Isub0 == NULL) {
        Cudd_RecursiveDeref(dd, Lsub0);
        Cudd_RecursiveDeref(dd, Lsub1);
        return(NULL);
    }
    Cudd_Ref(Isub0);
    Isub1 = cuddBddIsop(dd, Lsub1, Usub1);
    if (Isub1 == NULL) {
        Cudd_RecursiveDeref(dd, Lsub0);
        Cudd_RecursiveDeref(dd, Lsub1);
        Cudd_RecursiveDeref(dd, Isub0);
        return(NULL);
    }
    Cudd_Ref(Isub1);
    Cudd_RecursiveDeref(dd, Lsub0);
    Cudd_RecursiveDeref(dd, Lsub1);

    Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
    if (Lsuper0 == NULL) {
        Cudd_RecursiveDeref(dd, Isub0);
        Cudd_RecursiveDeref(dd, Isub1);
        return(NULL);
    }
    Cudd_Ref(Lsuper0);
    Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
    if (Lsuper1 == NULL) {
        Cudd_RecursiveDeref(dd, Isub0);
        Cudd_RecursiveDeref(dd, Isub1);
        Cudd_RecursiveDeref(dd, Lsuper0);
        return(NULL);
    }
    Cudd_Ref(Lsuper1);
    Usuper0 = Unv;
    Usuper1 = Uv;

    /* Ld = Lsuper0 + Lsuper1 */
    Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
    Ld = Cudd_NotCond(Ld, Ld != NULL);
    if (Ld == NULL) {
        Cudd_RecursiveDeref(dd, Isub0);
        Cudd_RecursiveDeref(dd, Isub1);
        Cudd_RecursiveDeref(dd, Lsuper0);
        Cudd_RecursiveDeref(dd, Lsuper1);
        return(NULL);
    }
    Cudd_Ref(Ld);
    Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
    if (Ud == NULL) {
        Cudd_RecursiveDeref(dd, Isub0);
        Cudd_RecursiveDeref(dd, Isub1);
        Cudd_RecursiveDeref(dd, Lsuper0);
        Cudd_RecursiveDeref(dd, Lsuper1);
        Cudd_RecursiveDeref(dd, Ld);
        return(NULL);
    }
    Cudd_Ref(Ud);
    Cudd_RecursiveDeref(dd, Lsuper0);
    Cudd_RecursiveDeref(dd, Lsuper1);

    Id = cuddBddIsop(dd, Ld, Ud);
    if (Id == NULL) {
        Cudd_RecursiveDeref(dd, Isub0);
        Cudd_RecursiveDeref(dd, Isub1);
        Cudd_RecursiveDeref(dd, Ld);
        Cudd_RecursiveDeref(dd, Ud);
        return(NULL);
    }
    Cudd_Ref(Id);
    Cudd_RecursiveDeref(dd, Ld);
    Cudd_RecursiveDeref(dd, Ud);

    x = cuddUniqueInter(dd, index, one, zero);
    if (x == NULL) {
        Cudd_RecursiveDeref(dd, Isub0);
        Cudd_RecursiveDeref(dd, Isub1);
        Cudd_RecursiveDeref(dd, Id);
        return(NULL);
    }
    Cudd_Ref(x);
    term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
    if (term0 == NULL) {
        Cudd_RecursiveDeref(dd, Isub0);
        Cudd_RecursiveDeref(dd, Isub1);
        Cudd_RecursiveDeref(dd, Id);
        Cudd_RecursiveDeref(dd, x);
        return(NULL);
    }
    Cudd_Ref(term0);
    Cudd_RecursiveDeref(dd, Isub0);
    term1 = cuddBddAndRecur(dd, x, Isub1);
    if (term1 == NULL) {
        Cudd_RecursiveDeref(dd, Isub1);
        Cudd_RecursiveDeref(dd, Id);
        Cudd_RecursiveDeref(dd, x);
        Cudd_RecursiveDeref(dd, term0);
        return(NULL);
    }
    Cudd_Ref(term1);
    Cudd_RecursiveDeref(dd, x);
    Cudd_RecursiveDeref(dd, Isub1);
    /* sum = term0 + term1 */
    sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
    sum = Cudd_NotCond(sum, sum != NULL);
    if (sum == NULL) {
        Cudd_RecursiveDeref(dd, Id);
        Cudd_RecursiveDeref(dd, term0);
        Cudd_RecursiveDeref(dd, term1);
        return(NULL);
    }
    Cudd_Ref(sum);
    Cudd_RecursiveDeref(dd, term0);
    Cudd_RecursiveDeref(dd, term1);
    /* r = sum + Id */
    r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
    r = Cudd_NotCond(r, r != NULL);
    if (r == NULL) {
        Cudd_RecursiveDeref(dd, Id);
        Cudd_RecursiveDeref(dd, sum);
        return(NULL);
    }
    Cudd_Ref(r);
    Cudd_RecursiveDeref(dd, sum);
    Cudd_RecursiveDeref(dd, Id);

    cuddCacheInsert2(dd, cuddBddIsop, L, U, r);

    Cudd_Deref(r);
    return(r);

} /* end of cuddBddIsop */
/**Function*************************************************************

  Synopsis    [Deriving the functionality of the gates.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Mio_GateParseFormula( Mio_Gate_t * pGate )
{
    DdManager * dd = pGate->pLib->dd;
    char * pPinNames[100];
    char * pPinNamesCopy[100];
    Mio_Pin_t * pPin, ** ppPin;
    int nPins, iPin, i;

    // set the maximum delay of the gate; count pins
    pGate->dDelayMax = 0.0;
    nPins = 0;
    Mio_GateForEachPin( pGate, pPin )
    {
        // set the maximum delay of the gate
        if ( pGate->dDelayMax < pPin->dDelayBlockMax )
            pGate->dDelayMax = pPin->dDelayBlockMax;
        // count the pin
        nPins++;
    }

    // check for the gate with const function
    if ( nPins == 0 )
    {
        if ( strcmp( pGate->pForm, MIO_STRING_CONST0 ) == 0 )
        {
            pGate->bFunc = b0;
            pGate->pSop = Abc_SopRegister( pGate->pLib->pMmFlex, " 0\n" );
            pGate->pLib->pGate0 = pGate;
        }
        else if ( strcmp( pGate->pForm, MIO_STRING_CONST1 ) == 0 )
        {
            pGate->bFunc = b1;
            pGate->pSop = Abc_SopRegister( pGate->pLib->pMmFlex, " 1\n" );
            pGate->pLib->pGate1 = pGate;
        }
        else
        {
            printf( "Cannot parse formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName );
            return 1;
        }
        Cudd_Ref( pGate->bFunc );
        return 0;
    }

    // collect the names as they appear in the formula
    nPins = Mio_GateCollectNames( pGate->pForm, pPinNames );
    if ( nPins == 0 )
    {
        printf( "Cannot read formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName );
        return 1;
    }

    // set the number of inputs
    pGate->nInputs = nPins;

    // consider the case when all the pins have identical pin info
    if ( strcmp( pGate->pPins->pName, "*" ) == 0 )
    {
        // get the topmost (generic) pin
        pPin = pGate->pPins;
        FREE( pPin->pName );

        // create individual pins from the generic pin
        ppPin = &pPin->pNext;
        for ( i = 1; i < nPins; i++ )
        {
            // get the new pin
            *ppPin = Mio_PinDup( pPin );
            // set its name
            (*ppPin)->pName = pPinNames[i];
            // prepare the next place in the list
            ppPin = &((*ppPin)->pNext);
        }
        *ppPin = NULL;

        // set the name of the topmost pin
        pPin->pName = pPinNames[0];
    }
    else
    {
        // reorder the variable names to appear the save way as the pins
        iPin = 0;
        Mio_GateForEachPin( pGate, pPin )
        {
            // find the pin with the name pPin->pName
            for ( i = 0; i < nPins; i++ )
            {
                if ( pPinNames[i] && strcmp( pPinNames[i], pPin->pName ) == 0 )
                {
                    // free pPinNames[i] because it is already available as pPin->pName
                    // setting pPinNames[i] to NULL is useful to make sure that
                    // this name is not assigned to two pins in the list
                    FREE( pPinNames[i] );
                    pPinNamesCopy[iPin++] = pPin->pName;
                    break;
                }
                if ( i == nPins )
                {
                    printf( "Cannot find pin name \"%s\" in the formula \"%s\" of gate \"%s\".\n", 
                        pPin->pName, pGate->pForm, pGate->pName );
                    return 1;
                }
            }
        }

        // check for the remaining names
        for ( i = 0; i < nPins; i++ )
            if ( pPinNames[i] )
            {
                printf( "Name \"%s\" appears in the formula \"%s\" of gate \"%s\" but there is no such pin.\n", 
                    pPinNames[i], pGate->pForm, pGate->pName );
                return 1;
            }

        // copy the names back
        memcpy( pPinNames, pPinNamesCopy, nPins * sizeof(char *) );
    }

    // expand the manager if necessary
    if ( dd->size < nPins )
    {
        Cudd_Quit( dd );
        dd = Cudd_Init( nPins + 10, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
        Cudd_zddVarsFromBddVars( dd, 2 );
    }

    // derive the formula as the BDD
    pGate->bFunc = Parse_FormulaParser( stdout, pGate->pForm, nPins, 0, pPinNames, dd, dd->vars );
    Cudd_Ref( pGate->bFunc );

    // derive the cover (SOP)
    pGate->pSop = Abc_ConvertBddToSop( pGate->pLib->pMmFlex, dd, pGate->bFunc, pGate->bFunc, nPins, 0, pGate->pLib->vCube, -1 );
    return 0;
}
Exemple #4
0
/**Function********************************************************************

  Synopsis    [Bellman-Ford algorithm for single-source shortest paths.]

  Description [Bellman-Ford algorithm for single-source shortest
  paths.  Returns the vector of the distances of all states from the
  initial states.  In case of multiple initial states the distance for
  each state is from the nearest initial state.  Negative-weight
  cycles are detected, though only in the naive way.  (Lack of
  convergence after nodes-1 iterations.)  In such a case, a constant
  ADD with value minus infinity is returned.  Bellman-Ford is based on
  matrix-vector multiplication.  The matrix is the distance matrix
  D(x,y), such that D(a,b) is the length of the arc connecting state a
  to state b.  The vector V(x) stores the distances of all states from
  the initial states.  The actual vector used in the matrix-vector
  multiplication is diff(x), that holds those distances that have
  changed during the last update.]

  SideEffects []

  SeeAlso     [ntrWarshall ntrSquare]

******************************************************************************/
static DdNode *
ntrBellman(
  DdManager *dd,
  DdNode *D,
  DdNode *source,
  DdNode **x,
  DdNode **y,
  int vars,
  int pr)
{
    DdNode *u, *w, *V, *min, *diff;
    DdApaNumber i, nodes, one;
    int digits = vars + 1;

    /* To avoid overflow when there are many variables, use APA. */
    nodes = Cudd_NewApaNumber(digits);
    Cudd_ApaPowerOfTwo(digits,nodes,vars);
    i = Cudd_NewApaNumber(digits);
    one = Cudd_NewApaNumber(digits);
    Cudd_ApaSetToLiteral(digits,one,1);

#if 0
    /* Find the distances from the initial state along paths using one
    ** arc. */
    w = Cudd_Cofactor(dd,D,source); /* works only if source is a cube */
    Cudd_Ref(w);
    V = Cudd_addSwapVariables(dd,w,x,y,vars);
    Cudd_Ref(V);
    Cudd_RecursiveDeref(dd,w);
#endif

    /* The initial states are at distance 0. The other states are
    ** initially at infinite distance. */
    V = Cudd_addIte(dd,source,Cudd_ReadZero(dd),Cudd_ReadPlusInfinity(dd));
    Cudd_Ref(V);

    /* Selective trace algorithm.  For the next update, only consider the
    ** nodes whose distance has changed in the last update. */
    diff = V;
    Cudd_Ref(diff);

    for (Cudd_ApaSetToLiteral(digits,i,1);
	 Cudd_ApaCompare(digits,i,digits,nodes) < 0;
	 Cudd_ApaAdd(digits,i,one,i)) {
	if (pr>2) {(void) printf("V"); Cudd_PrintDebug(dd,V,vars,pr);}
	/* Compute the distances via triangulation as a function of x. */
	w = Cudd_addTriangle(dd,diff,D,x,vars);
	Cudd_Ref(w);
	Cudd_RecursiveDeref(dd,diff);
	u = Cudd_addSwapVariables(dd,w,x,y,vars);
	Cudd_Ref(u);
	Cudd_RecursiveDeref(dd,w);
	if (pr>2) {(void) printf("u"); Cudd_PrintDebug(dd,u,vars,pr);}

	/* Take the minimum of the previous distances and those just
	** computed. */
	min = Cudd_addApply(dd,Cudd_addMinimum,V,u);
	Cudd_Ref(min);
	Cudd_RecursiveDeref(dd,u);
	if (pr>2) {(void) printf("min"); Cudd_PrintDebug(dd,min,vars,pr);}

	if (V == min) {		/* convergence */
	    Cudd_RecursiveDeref(dd,min);
	    if (pr>0) {
		(void) printf("Terminating after ");
		Cudd_ApaPrintDecimal(stdout,digits,i);
		(void) printf(" iterations\n");
	    }
	    break;
	}
	/* Find the distances that decreased. */
	diff = Cudd_addApply(dd,Cudd_addDiff,V,min);
	Cudd_Ref(diff);
	if (pr>2) {(void) printf("diff"); Cudd_PrintDebug(dd,diff,vars,pr);}
	Cudd_RecursiveDeref(dd,V);
	V = min;
    }
    /* Negative cycle detection. */
    if (Cudd_ApaCompare(digits,i,digits,nodes) == 0 &&
	diff != Cudd_ReadPlusInfinity(dd)) {
	(void) printf("Negative cycle\n");
	Cudd_RecursiveDeref(dd,diff);
	Cudd_RecursiveDeref(dd,V);
	V = Cudd_ReadMinusInfinity(dd);
	Cudd_Ref(V);
    }

    Cudd_Deref(V);
    FREE(i);
    FREE(nodes);
    FREE(one);
    return(V);

} /* end of ntrBellman */
Exemple #5
0
/**Function********************************************************************

  Synopsis    [Repeated squaring algorithm for all-pairs shortest paths.]

  Description []

  SideEffects []

  SeeAlso     []

******************************************************************************/
static DdNode *
ntrSquare(
  DdManager *dd /* manager */,
  DdNode *D /* D(z,y): distance matrix */,
  DdNode **x /* array of x variables */,
  DdNode **y /* array of y variables */,
  DdNode **z /* array of z variables */,
  int vars /* number of variables in each of the three arrays */,
  int pr /* verbosity level */,
  int st /* use the selective trace algorithm */)
{
    DdNode *zero;
    DdNode *I;              /* identity matirix */
    DdNode *w, *V, *P, *M, *R, *RT;
    DdNode *diff, *min, *minDiag;
    int n;
    int neg;
    long start_time;

    zero = Cudd_ReadZero(dd);
    /* Make a working copy of the original matrix. */
    R = D;
    Cudd_Ref(R);
    I = Cudd_addXeqy(dd,vars,z,y);    /* identity matrix */
    Cudd_Ref(I);

    /* Make a copy of the matrix for the selective trace algorithm. */
    diff = R;
    Cudd_Ref(diff);

    start_time = util_cpu_time();
    for (n = vars; n >= 0; n--) {
	printf("Starting iteration %d at time %s\n",vars-n,
	       util_print_time(util_cpu_time() - start_time));

	/* Check for negative cycles: They are identified by negative
	** elements on the diagonal.
	*/

	/* Extract values from the diagonal. */
        Cudd_Ref(w = Cudd_addIte(dd,I,R,zero));
	minDiag = Cudd_addFindMin(dd,w);	/* no need to ref */
	neg = Cudd_V(minDiag) < 0;
	Cudd_RecursiveDeref(dd,w);
	if (neg) {
	    Cudd_RecursiveDeref(dd,diff);
            (void) printf("Negative cycle after %d iterations!\n",vars-n);
            break;
        }

	/* Prepare the first operand of matrix multiplication:
	**   diff(z,y) -> RT(x,y) -> V(x,z)
	*/

	/* RT(x,y) */
	Cudd_Ref(RT = Cudd_addSwapVariables(dd,diff,x,z,vars));
	Cudd_RecursiveDeref(dd,diff);
	/* V(x,z) */
	Cudd_Ref(V = Cudd_addSwapVariables(dd,RT,y,z,vars));
	Cudd_RecursiveDeref(dd,RT);
	if (pr > 0) {
	    double pathcount;
	    (void) printf("V"); Cudd_PrintDebug(dd,V,2*vars,pr);
	    pathcount = Cudd_CountPath(V);
	    (void) printf("Path count = %g\n", pathcount);
	}

	/* V(x,z) * R(z,y) -> P(x,y) */
	Cudd_Ref(P = Cudd_addTriangle(dd,V,R,z,vars));
	Cudd_RecursiveDeref(dd,V);
	/* P(x,y) => M(z,y) */
	Cudd_Ref(M = Cudd_addSwapVariables(dd,P,x,z,vars));
	Cudd_RecursiveDeref(dd,P);
	if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,2*vars,pr);}

	/* min(z,y) */
	Cudd_Ref(min = Cudd_addApply(dd,Cudd_addMinimum,R,M));
	Cudd_RecursiveDeref(dd,M);

	if (R == min) {
	    Cudd_RecursiveDeref(dd,min);
	    if (pr>0) {printf("Done after %d iterations\n",vars-n+1); }
	    break;
	}
	/* diff(z,y) */
	if (st) {
	    Cudd_Ref(diff = Cudd_addApply(dd,Cudd_addDiff,min,R));
	} else {
	    Cudd_Ref(diff = min);
	}
	Cudd_RecursiveDeref(dd,R);
	R = min;                  /* keep a copy of matrix at current iter. */
	if (pr > 0) {
	    double pathcount;
	    (void) printf("R"); Cudd_PrintDebug(dd,R,2*vars,pr);
	    pathcount = Cudd_CountPath(R);
	    (void) printf("Path count = %g\n", pathcount);
	}

	if (n == 0) {
	    (void) printf("Negative cycle!\n");
	    break;
	}

    }
    Cudd_RecursiveDeref(dd,I);
    Cudd_Deref(R);
    return(R);

} /* end of ntrSquare */
Exemple #6
0
ABC_NAMESPACE_IMPL_START


////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                    FUNCTION DEFINITIONS                          ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    [This procedure is similar to Cudd_ShuffleHeap() and Cudd_bddPermute().]

  Description [The first argument is the REO manager. The 2nd/3d
  arguments are the function and its CUDD manager. The last argument
  is the permutation to be implemented. The i-th entry of the permutation 
  array contains the index of the variable that should be brought to the 
  i-th level.  The size of the array should be equal or greater to 
  the number of variables currently in use (that is, the size of CUDD
  manager and the size of REO manager).]

  SideEffects [Note that the resulting BDD is not referenced.]

  SeeAlso     []

***********************************************************************/
DdNode * reoShuffle( reo_man * p, DdManager * dd, DdNode * bFunc, int * pPerm, int * pPermInv )
{
    DdNode * bFuncRes = NULL;
    int i, k, v;

    if ( Cudd_IsConstant(bFunc) )
        return bFunc;

	// set the initial parameters
	p->dd    = dd;
    p->nSupp = Cudd_SupportSize( dd, bFunc );
	p->nTops = 1;
//    p->nNodesBeg = Cudd_DagSize( bFunc );

    // set the starting permutation
	for ( i = 0; i < p->nSupp; i++ )
    {
        p->pOrderInt[i] = i;
		p->pMapToPlanes[ dd->invperm[i] ] = i;
		p->pMapToDdVarsFinal[i] = dd->invperm[i];
    }

	// set the initial parameters
	p->nUnitsUsed = 0;
	p->nNodesCur  = 0;
	p->fThisIsAdd = 0;
	p->Signature++;

	// transfer the function from the CUDD package into REO's internal data structure
    p->pTops[0] = reoTransferNodesToUnits_rec( p, bFunc );
//	assert( p->nNodesBeg == p->nNodesCur );

    // reorder one variable at a time
    for ( i = 0; i < p->nSupp; i++ )
    {
        if ( p->pOrderInt[i] == pPerm[i] )
            continue;
        // find where is variable number pPerm[i]
        for ( k = i + 1; k < p->nSupp; k++ )
            if ( pPerm[i] == p->pOrderInt[k] )
                break;
        if ( k == p->nSupp )
        {
            printf( "reoShuffle() Error: Cannot find a variable.\n" );
            goto finish;
        }
        // move the variable up
        for ( v = k - 1; v >= i; v-- )
        {
            reoReorderSwapAdjacentVars( p, v, 1 );
            // check if the number of nodes is not too large
            if ( p->nNodesCur > 10000 )
            {
                printf( "reoShuffle() Error: BDD size is too large.\n" );
                goto finish;
            }
        }
        assert( p->pOrderInt[i] == pPerm[i] );
    }

	// set the initial parameters
	p->nRefNodes  = 0;
	p->nNodesCur  = 0;
	p->Signature++;
	// transfer the BDDs from REO's internal data structure to CUDD
    bFuncRes = reoTransferUnitsToNodes_rec( p, p->pTops[0] ); Cudd_Ref( bFuncRes );
	// undo the DDs referenced for storing in the cache
	for ( i = 0; i < p->nRefNodes; i++ )
		Cudd_RecursiveDeref( dd, p->pRefNodes[i] );

	// verify zero refs of the terminal nodes
//    assert( reoRecursiveDeref( p->pTops[0] ) );
//    assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) );

    // perform verification
	if ( p->fVerify )
	{
		DdNode * bFuncPerm;
		bFuncPerm = Cudd_bddPermute( dd, bFunc, pPermInv );  Cudd_Ref( bFuncPerm );
		if ( bFuncPerm != bFuncRes )
		{
			printf( "REO: Internal verification has failed!\n" );
			fflush( stdout );
		}
		Cudd_RecursiveDeref( dd, bFuncPerm );
	}

	// recycle the data structure
	for ( i = 0; i <= p->nSupp; i++ )
		reoUnitsRecycleUnitList( p, p->pPlanes + i );

finish :
    if ( bFuncRes )
        Cudd_Deref( bFuncRes );
    return bFuncRes;
}
Exemple #7
0
/* traverse a CFG and encode each edge as a BDD */
DdNode* bdd_convert_cfg(DdManager *m, pos* postab, cfg_node* host, int proc,
                        DdNode* current, DdNode* R, int prev) {
    DdNode* branch;                      /* holds branch conditions */
    DdNode* tmp1, *tmp2;                 /* temporary vars for cleanup */
    current = bdd_encode_pc(m, current, postab->pc_, postab->pc_size, proc,
                            host->node->id);
    tmp1 = Cudd_bddOr(m, R, current);    /* add the completed edge to the */
    Cudd_Ref(tmp1);                      /* transistion system by disjuncting */
    Cudd_RecursiveDeref(m, R);
    Cudd_RecursiveDeref(m, current);
    R = tmp1;
    switch (host->node->tag) {
    case _assign_stat:                 /* assignment and skip statements */
    case _skip_stat:                   /* form very similar edges */
        if (host->node->tag == _assign_stat)
            current = bdd_mk_assign(m, postab, host, proc);
        else if (host->node->tag == _skip_stat)
            current = bdd_mk_skip(m, postab, host->node->id,  proc);
        break;
    case _if_then_stat:                /* if a branch is encountered, */
    case _if_else_stat:                /* add the branch condition to the  */
    case _while_stat:                  /* edge's encoding and continue */
        current = bdd_mk_skip(m, postab, host->node->id,  proc);
        tmp1 = bdd_expr(m, postab->vars, host->node->children[EXPR]);
        branch = Cudd_bddAnd(m, tmp1, current);
        Cudd_Ref(branch);                /* conjunct branch condition to branch */
        tmp2 = Cudd_bddAnd(m, Cudd_Not(tmp1), current);
        Cudd_Ref(tmp2);                  /* conjuct complement of the branch */
        Cudd_RecursiveDeref(m, tmp1);    /* condition to current */
        Cudd_RecursiveDeref(m, current);
        current = tmp2;
        if (host->node->id < prev)       /* terminate after back edge */
            return R;
        else {                           /* traverse the 'true' branch */
            tmp1 = bdd_convert_cfg(m, postab, host->succ[CFG_IF | CFG_WHILE], proc,
                                   branch, R, prev);
            Cudd_RecursiveDeref(m, R);
        }
        break;
    case _await_stat:                  /* await is both a branch and a skip */
        tmp1 = bdd_mk_skip(m, postab, host->node->id,  proc);
        tmp2 = bdd_expr(m, postab->vars, host->node->children[EXPR]);
        current = Cudd_bddAnd(m, tmp1, tmp2);
        Cudd_Ref(current);               /* conjunct branch condition to current */
        branch = Cudd_bddAnd(m, tmp1, Cudd_Not(tmp2));
        Cudd_Ref(branch);                /* conjuct complement of the branch */
        Cudd_RecursiveDeref(m, tmp1);    /* condition to branch */
        Cudd_RecursiveDeref(m, tmp2);    /* branch is a self-referential edge */
        branch = bdd_encode_pc(m, branch, postab->pc_, postab->pc_size, proc,
                               host->node->id);
        tmp1 = Cudd_bddOr(m, R, branch);
        Cudd_Ref(tmp1);
        Cudd_RecursiveDeref(m, R);
        Cudd_RecursiveDeref(m, branch);  /* continue edge continues to next node */
        break;
    default:
        printf("Error: invalid statement in CFG\n");
        exit(1);
    }
    if (host->succ[CONTINUE])  {         /* if the node has a successor */
        R = bdd_convert_cfg(m, postab, host->succ[CONTINUE], proc, current,
                            tmp1, host->node->id);
        Cudd_RecursiveDeref(m, tmp1);      /* initiate new edge and call again */
    } else {                             /* if the node terminates a branch */
        current = bdd_encode_pc(m, current, postab->pc_, postab->pc_size, proc,
                                host->node->id);
        R = Cudd_bddOr(m, tmp1, current);
        Cudd_Ref(R);                       /* terminate node with an infinite loop */
        Cudd_RecursiveDeref(m, tmp1);
        Cudd_RecursiveDeref(m, current);
    }
    return R;                            /* return complete transition relation */
}
Exemple #8
0
DdNode *compute_winning_set_BDD( DdManager *manager,
                                 DdNode *etrans, DdNode *strans,
                                 DdNode **egoals, DdNode **sgoals,
                                 unsigned char verbose )
{
    DdNode *X = NULL, *X_prev = NULL;
    DdNode *Y = NULL, *Y_exmod = NULL, *Y_prev = NULL;
    DdNode **Z = NULL, **Z_prev = NULL;
    bool Z_changed;  /* Use to detect occurrence of fixpoint for all Z_i */

    /* Fixpoint iteration counters */
    int num_it_Z, num_it_Y, num_it_X;

    DdNode *tmp, *tmp2;
    int i, j;  /* Generic counters */

    DdNode **vars, **pvars;
    int num_env, num_sys;
    int *cube;  /* length will be twice total number of variables (to
                   account for both variables and their primes). */

    num_env = tree_size( spc.evar_list );
    num_sys = tree_size( spc.svar_list );

    /* Allocate cube array, used later for quantifying over variables. */
    cube = (int *)malloc( sizeof(int)*2*(num_env+num_sys) );
    if (cube == NULL) {
        perror( __FILE__ ",  malloc" );
        exit(-1);
    }

    /* Define a map in the manager to easily swap variables with their
       primed selves. */
    vars = malloc( (num_env+num_sys)*sizeof(DdNode *) );
    pvars = malloc( (num_env+num_sys)*sizeof(DdNode *) );
    for (i = 0; i < num_env+num_sys; i++) {
        *(vars+i) = Cudd_bddIthVar( manager, i );
        *(pvars+i) = Cudd_bddIthVar( manager, i+num_env+num_sys );
    }
    if (!Cudd_SetVarMap( manager, vars, pvars, num_env+num_sys )) {
        fprintf( stderr,
                 "Error: failed to define variable map in CUDD manager.\n" );
        free( cube );
        return NULL;
    }
    free( vars );
    free( pvars );

    if (spc.num_sgoals > 0) {
        Z = malloc( spc.num_sgoals*sizeof(DdNode *) );
        Z_prev = malloc( spc.num_sgoals*sizeof(DdNode *) );
        for (i = 0; i < spc.num_sgoals; i++) {
            *(Z+i) = NULL;
            *(Z_prev+i) = NULL;
        }
    }

    /* Initialize */
    for (i = 0; i < spc.num_sgoals; i++) {
        *(Z+i) = Cudd_ReadOne( manager );
        Cudd_Ref( *(Z+i) );
    }

    num_it_Z = 0;
    do {
        num_it_Z++;
        if (verbose > 1) {
            logprint( "Z iteration %d", num_it_Z );
            logprint( "Cudd_ReadMemoryInUse (bytes): %d",
                      Cudd_ReadMemoryInUse( manager ) );
        }

        for (i = 0; i < spc.num_sgoals; i++) {
            if (*(Z_prev+i) != NULL)
                Cudd_RecursiveDeref( manager, *(Z_prev+i) );
            *(Z_prev+i) = *(Z+i);
        }

        for (i = 0; i < spc.num_sgoals; i++) {
            if (i == spc.num_sgoals-1) {
                *(Z+i) = compute_existsmodal( manager, *Z_prev, etrans, strans,
                                              num_env, num_sys, cube );
            } else {
                *(Z+i) = compute_existsmodal( manager, *(Z_prev+i+1),
                                              etrans, strans, num_env, num_sys,
                                              cube );
            }
            if (*(Z+i) == NULL) {
                /* fatal error */
                return NULL;
            }

            /* (Re)initialize Y */
            if (Y != NULL)
                Cudd_RecursiveDeref( manager, Y );
            Y = Cudd_Not( Cudd_ReadOne( manager ) );
            Cudd_Ref( Y );

            num_it_Y = 0;
            do {
                num_it_Y++;
                if (verbose > 1) {
                    logprint( "\tY iteration %d", num_it_Y );
                    logprint( "\tCudd_ReadMemoryInUse (bytes): %d",
                              Cudd_ReadMemoryInUse( manager ) );
                }

                if (Y_prev != NULL)
                    Cudd_RecursiveDeref( manager, Y_prev );
                Y_prev = Y;
                if (Y_exmod != NULL)
                    Cudd_RecursiveDeref( manager, Y_exmod );
                Y_exmod = compute_existsmodal( manager, Y_prev, etrans, strans,
                                               num_env, num_sys, cube );
                if (Y_exmod == NULL) {
                    /* fatal error */
                    return NULL;
                }

                Y = Cudd_Not( Cudd_ReadOne( manager ) );
                Cudd_Ref( Y );
                for (j = 0; j < spc.num_egoals; j++) {

                    /* (Re)initialize X */
                    if (X != NULL)
                        Cudd_RecursiveDeref( manager, X );
                    X = Cudd_ReadOne( manager );
                    Cudd_Ref( X );

                    /* Greatest fixpoint for X, for this env goal */
                    num_it_X = 0;
                    do {
                        num_it_X++;
                        if (verbose > 1) {
                            logprint( "\t\tX iteration %d", num_it_X );
                            logprint( "\t\tCudd_ReadMemoryInUse (bytes): %d",
                                      Cudd_ReadMemoryInUse( manager ) );
                        }

                        if (X_prev != NULL)
                            Cudd_RecursiveDeref( manager, X_prev );
                        X_prev = X;
                        X = compute_existsmodal( manager, X_prev,
                                                 etrans, strans,
                                                 num_env, num_sys, cube );
                        if (X == NULL) {
                            /* fatal error */
                            return NULL;
                        }

                        tmp = Cudd_bddAnd( manager, *(sgoals+i), *(Z+i) );
                        Cudd_Ref( tmp );
                        tmp2 = Cudd_bddOr( manager, tmp, Y_exmod );
                        Cudd_Ref( tmp2 );
                        Cudd_RecursiveDeref( manager, tmp );

                        tmp = Cudd_bddAnd( manager,
                                           X, Cudd_Not( *(egoals+j) ) );
                        Cudd_Ref( tmp );
                        Cudd_RecursiveDeref( manager, X );

                        X = Cudd_bddOr( manager, tmp2, tmp );
                        Cudd_Ref( X );
                        Cudd_RecursiveDeref( manager, tmp );
                        Cudd_RecursiveDeref( manager, tmp2 );

                        tmp = X;
                        X = Cudd_bddAnd( manager, X, X_prev );
                        Cudd_Ref( X );
                        Cudd_RecursiveDeref( manager, tmp );

                    } while (!Cudd_bddLeq( manager, X, X_prev )
                             || !Cudd_bddLeq( manager, X_prev, X ));

                    tmp = Y;
                    Y = Cudd_bddOr( manager, Y, X );
                    Cudd_Ref( Y );
                    Cudd_RecursiveDeref( manager, tmp );

                    Cudd_RecursiveDeref( manager, X );
                    X = NULL;
                    Cudd_RecursiveDeref( manager, X_prev );
                    X_prev = NULL;
                }

                tmp2 = Y;
                Y = Cudd_bddOr( manager, Y, Y_prev );
                Cudd_Ref( Y );
                Cudd_RecursiveDeref( manager, tmp2 );

            } while (!Cudd_bddLeq( manager, Y, Y_prev )
                     || !Cudd_bddLeq( manager, Y_prev, Y ));

            Cudd_RecursiveDeref( manager, *(Z+i) );
            *(Z+i) = Cudd_bddAnd( manager, Y, *(Z_prev+i) );
            Cudd_Ref( *(Z+i) );

            Cudd_RecursiveDeref( manager, Y );
            Y = NULL;
            Cudd_RecursiveDeref( manager, Y_prev );
            Y_prev = NULL;
            Cudd_RecursiveDeref( manager, Y_exmod );
            Y_exmod = NULL;

        }

        Z_changed = False;
        for (i = 0; i < spc.num_sgoals; i++) {
            if (!Cudd_bddLeq( manager, *(Z+i), *(Z_prev+i) )
                || !Cudd_bddLeq( manager, *(Z_prev+i), *(Z+i) )) {
                Z_changed = True;
                break;
            }
        }
    } while (Z_changed);

    /* Pre-exit clean-up */
    tmp = *Z;
    Cudd_RecursiveDeref( manager, *Z_prev );
    for (i = 1; i < spc.num_sgoals; i++) {
        Cudd_RecursiveDeref( manager, *(Z+i) );
        Cudd_RecursiveDeref( manager, *(Z_prev+i) );
    }
    free( Z );
    free( Z_prev );
    free( cube );

    return tmp;
}
void
I_BDD_new_mutex_domain (DdManager *dd, DdNode *node[], unsigned int size)
{
  unsigned int shbuf, vars, ctr;
  DdNode **ddVar, *one, *newnode, *oldnode, *bitnode;
  int i,j, extra;

  /* base cases */

  if (size == 0)
    {
      return;
    }

  one = Cudd_ReadOne(dd);

  if (size == 1)
    {
      node[0] = one;
      Cudd_Ref (node[0]);
      return;
    }

  for(shbuf = size - 1, vars = 0; shbuf != 0; shbuf >>= 1, vars++);

  extra = (1 << vars) - size;

  ddVar = malloc(vars * sizeof(DdNode *));

  for (j = 0; j < vars; j++)
    {
      ddVar[j] = bitnode = Cudd_bddNewVar (dd);
      Cudd_Ref (bitnode);
    }

  ctr = 0;

  for (i = 0; i < size; i++, ctr++)
    {
      newnode = one;
      Cudd_Ref (newnode);

#ifdef I_BDD_MUTEX_DEBUG
      printf("i%d:", i);
#endif

      for (j = (extra > 0); j < vars; j++)
	{
	  bitnode = (ctr & (1 << j)) ? ddVar[j] : Cudd_Not(ddVar[j]);

	  newnode = Cudd_bddAnd (dd, bitnode, oldnode = newnode);
	  Cudd_Ref (newnode);
	  Cudd_RecursiveDeref (dd, oldnode);

#ifdef I_BDD_MUTEX_DEBUG
	  if (ctr & (1 << j))
	    printf("+ v%d ", j);
	  else
	    printf("+ !v%d ", j);
#endif
	}

#ifdef I_BDD_MUTEX_DEBUG
      printf ("\n");
#endif

      node[i] = newnode;

      if (extra > 0)
	{
	  extra--;
	  ctr++;
	}
    }

#ifdef I_BDD_MUTEX_TEST
  {
    DdNode *test, *old_test;
    int i;
    test = Cudd_ReadLogicZero(dd);
    Cudd_Ref (test);
    for (i = 0; i < size; i++)
      {
	if (Cudd_bddIte (dd, test, node[i], zero) != zero)
	  I_punt("I_BDD_new_mutex_complex: not mutex!");

	test = Cudd_bddIte(dd, node[i], one, old_test = test);
	Cudd_Ref (test);
	Cudd_RecursiveDeref (dd, old_test);
      }
    if (test != one)
      I_punt("I_BDD_new_mutex_complex: not exhaustive!");

    Cudd_RecursiveDeref (dd, test);
    }
#endif

  for (j = 0; j < vars; j++)
    Cudd_RecursiveDeref (dd, ddVar[j]);

  free (ddVar);
  return;
}
/**Function********************************************************************

  Synopsis    [Main function for testcudd.]

  Description []

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
int
main(int argc, char **argv)
{
    FILE *fp;           /* pointer to input file */
    char *file = "";	/* input file name */
    FILE *dfp = NULL;	/* pointer to dump file */
    char *dfile;	/* file for DD dump */
    DdNode *dfunc[2];	/* addresses of the functions to be dumped */
    DdManager *dd;	/* pointer to DD manager */
    DdNode *one, *zero;	/* fast access to constant functions */
    DdNode *M;
    DdNode **x;		/* pointers to variables */
    DdNode **y;		/* pointers to variables */
    DdNode **xn;       	/* complements of row variables */
    DdNode **yn_;      	/* complements of column variables */
    DdNode **xvars;
    DdNode **yvars;
    DdNode *C;		/* result of converting from ADD to BDD */
    DdNode *ess;	/* cube of essential variables */
    DdNode *shortP;	/* BDD cube of shortest path */
    DdNode *largest;	/* BDD of largest cube */
    DdNode *shortA;	/* ADD cube of shortest path */
    DdNode *constN;	/* value returned by evaluation of ADD */
    DdNode *ycube;	/* cube of the negated y vars for c-proj */
    DdNode *CP;		/* C-Projection of C */
    DdNode *CPr;	/* C-Selection of C */
    int    length;	/* length of the shortest path */
    int    nx;			/* number of variables */
    int    ny;
    int    maxnx;
    int    maxny;
    int    m;
    int    n;
    int    N;
    int    cmu;			/* use CMU multiplication */
    int    pr;			/* verbose printout level */
    int    harwell;
    int    multiple;		/* read multiple matrices */
    int    ok;
    int    c;			/* variable to read in options */
    int    approach;		/* reordering approach */
    int    autodyn;		/* automatic reordering */
    int    groupcheck;		/* option for group sifting */
    int    profile;		/* print heap profile if != 0 */
    int    keepperm;		/* keep track of permutation */
    int    clearcache;		/* clear the cache after each matrix */
    int    blifOrDot;		/* dump format: 0 -> dot, 1 -> blif, ... */
    int    retval;		/* return value */
    int    i;			/* loop index */
    long   startTime;		/* initial time */
    long   lapTime;
    int    size;
    unsigned int cacheSize, maxMemory;
    unsigned int nvars,nslots;

    startTime = util_cpu_time();

    approach = CUDD_REORDER_NONE;
    autodyn = 0;
    pr = 0;
    harwell = 0;
    multiple = 0;
    profile = 0;
    keepperm = 0;
    cmu = 0;
    N = 4;
    nvars = 4;
    cacheSize = 127;
    maxMemory = 0;
    nslots = CUDD_UNIQUE_SLOTS;
    clearcache = 0;
    groupcheck = CUDD_GROUP_CHECK7;
    dfile = NULL;
    blifOrDot = 0; /* dot format */

    /* Parse command line. */
    while ((c = util_getopt(argc, argv, "CDHMPS:a:bcd:g:hkmn:p:v:x:X:"))
	   != EOF) {
	switch(c) {
	case 'C':
	    cmu = 1;
	    break;
	case 'D':
	    autodyn = 1;
	    break;
	case 'H':
	    harwell = 1;
	    break;
	case 'M':
#ifdef MNEMOSYNE
	    (void) mnem_setrecording(0);
#endif
	    break;
	case 'P':
	    profile = 1;
	    break;
	case 'S':
	    nslots = atoi(util_optarg);
	    break;
	case 'X':
	    maxMemory = atoi(util_optarg);
	    break;
	case 'a':
	    approach = atoi(util_optarg);
	    break;
	case 'b':
	    blifOrDot = 1; /* blif format */
	    break;
	case 'c':
	    clearcache = 1;
	    break;
	case 'd':
	    dfile = util_optarg;
	    break;
	case 'g':
	    groupcheck = atoi(util_optarg);
	    break;
	case 'k':
	    keepperm = 1;
	    break;
	case 'm':
	    multiple = 1;
	    break;
	case 'n':
	    N = atoi(util_optarg);
	    break;
	case 'p':
	    pr = atoi(util_optarg);
	    break;
	case 'v':
	    nvars = atoi(util_optarg);
	    break;
	case 'x':
	    cacheSize = atoi(util_optarg);
	    break;
	case 'h':
	default:
	    usage(argv[0]);
	    break;
	}
    }

    if (argc - util_optind == 0) {
	file = "-";
    } else if (argc - util_optind == 1) {
	file = argv[util_optind];
    } else {
	usage(argv[0]);
    }
    if ((approach<0) || (approach>17)) {
	(void) fprintf(stderr,"Invalid approach: %d \n",approach);
	usage(argv[0]);
    }

    if (pr >= 0) {
	(void) printf("# %s\n", TESTCUDD_VERSION);
	/* Echo command line and arguments. */
	(void) printf("#");
	for (i = 0; i < argc; i++) {
	    (void) printf(" %s", argv[i]);
	}
	(void) printf("\n");
	(void) fflush(stdout);
    }

    /* Initialize manager and provide easy reference to terminals. */
    dd = Cudd_Init(nvars,0,nslots,cacheSize,maxMemory);
    one = DD_ONE(dd);
    zero = DD_ZERO(dd);
    dd->groupcheck = (Cudd_AggregationType) groupcheck;
    if (autodyn) Cudd_AutodynEnable(dd,CUDD_REORDER_SAME);

    /* Open input file. */
    fp = open_file(file, "r");

    /* Open dump file if requested */
    if (dfile != NULL) {
	dfp = open_file(dfile, "w");
    }

    x = y = xn = yn_ = NULL;
    do {
	/* We want to start anew for every matrix. */
	maxnx = maxny = 0;
	nx = maxnx; ny = maxny;
	if (pr>0) lapTime = util_cpu_time();
	if (harwell) {
	    if (pr >= 0) (void) printf(":name: ");
	    ok = Cudd_addHarwell(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny,
	    &m, &n, 0, 2, 1, 2, pr);
	} else {
	    ok = Cudd_addRead(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny,
	    &m, &n, 0, 2, 1, 2);
	    if (pr >= 0)
		(void) printf(":name: %s: %d rows %d columns\n", file, m, n);
	}
	if (!ok) {
	    (void) fprintf(stderr, "Error reading matrix\n");
	    exit(1);
	}

	if (nx > maxnx) maxnx = nx;
	if (ny > maxny) maxny = ny;

	/* Build cube of negated y's. */
	ycube = DD_ONE(dd);
	Cudd_Ref(ycube);
	for (i = maxny - 1; i >= 0; i--) {
	    DdNode *tmpp;
	    tmpp = Cudd_bddAnd(dd,Cudd_Not(dd->vars[y[i]->index]),ycube);
	    if (tmpp == NULL) exit(2);
	    Cudd_Ref(tmpp);
	    Cudd_RecursiveDeref(dd,ycube);
	    ycube = tmpp;
	}
	/* Initialize vectors of BDD variables used by priority func. */
	xvars = ALLOC(DdNode *, nx);
	if (xvars == NULL) exit(2);
	for (i = 0; i < nx; i++) {
	    xvars[i] = dd->vars[x[i]->index];
	}
	yvars = ALLOC(DdNode *, ny);
	if (yvars == NULL) exit(2);
	for (i = 0; i < ny; i++) {
	    yvars[i] = dd->vars[y[i]->index];
	}

	/* Clean up */
	for (i=0; i < maxnx; i++) {
	    Cudd_RecursiveDeref(dd, x[i]);
	    Cudd_RecursiveDeref(dd, xn[i]);
	}
	FREE(x);
	FREE(xn);
	for (i=0; i < maxny; i++) {
	    Cudd_RecursiveDeref(dd, y[i]);
	    Cudd_RecursiveDeref(dd, yn_[i]);
	}
	FREE(y);
	FREE(yn_);

	if (pr>0) {(void) printf(":1: M"); Cudd_PrintDebug(dd,M,nx+ny,pr);}

	if (pr>0) (void) printf(":2: time to read the matrix = %s\n",
		    util_print_time(util_cpu_time() - lapTime));

	C = Cudd_addBddPattern(dd, M);
	if (C == 0) exit(2);
	Cudd_Ref(C);
	if (pr>0) {(void) printf(":3: C"); Cudd_PrintDebug(dd,C,nx+ny,pr);}

	/* Test iterators. */
	retval = testIterators(dd,M,C,pr);
	if (retval == 0) exit(2);

	cuddCacheProfile(dd,stdout);

	/* Test XOR */
	retval = testXor(dd,C,pr,nx+ny);
	if (retval == 0) exit(2);

	/* Test Hamming distance functions. */
	retval = testHamming(dd,C,pr,nx+ny);
	if (retval == 0) exit(2);

	/* Test selection functions. */
	CP = Cudd_CProjection(dd,C,ycube);
	if (CP == NULL) exit(2);
	Cudd_Ref(CP);
	if (pr>0) {(void) printf("ycube"); Cudd_PrintDebug(dd,ycube,nx+ny,pr);}
	if (pr>0) {(void) printf("CP"); Cudd_PrintDebug(dd,CP,nx+ny,pr);}

	if (nx == ny) {
	    CPr = Cudd_PrioritySelect(dd,C,xvars,yvars,(DdNode **)NULL,
		(DdNode *)NULL,ny,Cudd_Xgty);
	    if (CPr == NULL) exit(2);
	    Cudd_Ref(CPr);
	    if (pr>0) {(void) printf(":4: CPr"); Cudd_PrintDebug(dd,CPr,nx+ny,pr);}
	    if (CP != CPr) {
		(void) printf("CP != CPr!\n");
	    }
	    Cudd_RecursiveDeref(dd, CPr);
	}
	FREE(xvars); FREE(yvars);

	Cudd_RecursiveDeref(dd, CP);
	Cudd_RecursiveDeref(dd, ycube);

	/* Test functions for essential variables. */
	ess = Cudd_FindEssential(dd,C);
	if (ess == NULL) exit(2);
	Cudd_Ref(ess);
	if (pr>0) {(void) printf(":4: ess"); Cudd_PrintDebug(dd,ess,nx+ny,pr);}
	Cudd_RecursiveDeref(dd, ess);

	/* Test functions for shortest paths. */
	shortP = Cudd_ShortestPath(dd, M, NULL, NULL, &length);
	if (shortP == NULL) exit(2);
	Cudd_Ref(shortP);
	if (pr>0) {
	    (void) printf(":5: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr);
	}
	/* Test functions for largest cubes. */
	largest = Cudd_LargestCube(dd, Cudd_Not(C), &length);
	if (largest == NULL) exit(2);
	Cudd_Ref(largest);
	if (pr>0) {
	    (void) printf(":5b: largest");
	    Cudd_PrintDebug(dd,largest,nx+ny,pr);
	}
	Cudd_RecursiveDeref(dd, largest);

	/* Test Cudd_addEvalConst and Cudd_addIteConstant. */
	shortA = Cudd_BddToAdd(dd,shortP);
	if (shortA == NULL) exit(2);
	Cudd_Ref(shortA);
	Cudd_RecursiveDeref(dd, shortP);
	constN = Cudd_addEvalConst(dd,shortA,M);
	if (constN == DD_NON_CONSTANT) exit(2);
	if (Cudd_addIteConstant(dd,shortA,M,constN) != constN) exit(2);
	if (pr>0) {(void) printf("The value of M along the chosen shortest path is %g\n", cuddV(constN));}
	Cudd_RecursiveDeref(dd, shortA);

	shortP = Cudd_ShortestPath(dd, C, NULL, NULL, &length);
	if (shortP == NULL) exit(2);
	Cudd_Ref(shortP);
	if (pr>0) {
	    (void) printf(":6: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr);
	}

	/* Test Cudd_bddIteConstant and Cudd_bddLeq. */
	if (!Cudd_bddLeq(dd,shortP,C)) exit(2);
	if (Cudd_bddIteConstant(dd,Cudd_Not(shortP),one,C) != one) exit(2);
	Cudd_RecursiveDeref(dd, shortP);

	if (profile) {
	    retval = cuddHeapProfile(dd);
	}

	size = dd->size;

	if (pr>0) {
	    (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd));
	}

	/* Reorder if so requested. */
        if (approach != CUDD_REORDER_NONE) {
#ifndef DD_STATS
	    retval = Cudd_EnableReorderingReporting(dd);
	    if (retval == 0) {
		(void) fprintf(stderr,"Error reported by Cudd_EnableReorderingReporting\n");
		exit(3);
	    }
#endif
#ifdef DD_DEBUG
	    retval = Cudd_DebugCheck(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
		exit(3);
	    }
	    retval = Cudd_CheckKeys(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n");
		exit(3);
	    }
#endif
	    retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5);
	    if (retval == 0) {
		(void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n");
		exit(3);
	    }
#ifndef DD_STATS
	    retval = Cudd_DisableReorderingReporting(dd);
	    if (retval == 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DisableReorderingReporting\n");
		exit(3);
	    }
#endif
#ifdef DD_DEBUG
	    retval = Cudd_DebugCheck(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
		exit(3);
	    }
	    retval = Cudd_CheckKeys(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n");
		exit(3);
	    }
#endif
	    if (approach == CUDD_REORDER_SYMM_SIFT ||
	    approach == CUDD_REORDER_SYMM_SIFT_CONV) {
		Cudd_SymmProfile(dd,0,dd->size-1);
	    }

	    if (pr>0) {
		(void) printf("Average distance: %g\n", Cudd_AverageDistance(dd));
	    }

	    if (keepperm) {
		/* Print variable permutation. */
		(void) printf("Variable Permutation:");
		for (i=0; i<size; i++) {
		    if (i%20 == 0) (void) printf("\n");
		    (void) printf("%d ", dd->invperm[i]);
		}
		(void) printf("\n");
		(void) printf("Inverse Permutation:");
		for (i=0; i<size; i++) {
		    if (i%20 == 0) (void) printf("\n");
		    (void) printf("%d ", dd->perm[i]);
		}
		(void) printf("\n");
	    }

	    if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,nx+ny,pr);}

	    if (profile) {
		retval = cuddHeapProfile(dd);
	    }

	}

	/* Dump DDs of C and M if so requested. */
	if (dfile != NULL) {
	    dfunc[0] = C;
	    dfunc[1] = M;
	    if (blifOrDot == 1) {
		/* Only dump C because blif cannot handle ADDs */
		retval = Cudd_DumpBlif(dd,1,dfunc,NULL,onames,NULL,dfp);
	    } else {
		retval = Cudd_DumpDot(dd,2,dfunc,NULL,onames,dfp);
	    }
	    if (retval != 1) {
		(void) fprintf(stderr,"abnormal termination\n");
		exit(2);
	    }
	}

	Cudd_RecursiveDeref(dd, C);
	Cudd_RecursiveDeref(dd, M);

	if (clearcache) {
	    if (pr>0) {(void) printf("Clearing the cache... ");}
	    for (i = dd->cacheSlots - 1; i>=0; i--) {
		dd->cache[i].data = NIL(DdNode);
	    }
	    if (pr>0) {(void) printf("done\n");}
	}
	if (pr>0) {
	    (void) printf("Number of variables = %6d\t",dd->size);
	    (void) printf("Number of slots     = %6d\n",dd->slots);
	    (void) printf("Number of keys      = %6d\t",dd->keys);
	    (void) printf("Number of min dead  = %6d\n",dd->minDead);
	}

    } while (multiple && !feof(fp));

    fclose(fp);
    if (dfile != NULL) {
	fclose(dfp);
    }

    /* Second phase: experiment with Walsh matrices. */
    if (!testWalsh(dd,N,cmu,approach,pr)) {
	exit(2);
    }

    /* Check variable destruction. */
    assert(cuddDestroySubtables(dd,3));
    assert(Cudd_DebugCheck(dd) == 0);
    assert(Cudd_CheckKeys(dd) == 0);

    retval = Cudd_CheckZeroRef(dd);
    ok = retval != 0;  /* ok == 0 means O.K. */
    if (retval != 0) {
	(void) fprintf(stderr,
	    "%d non-zero DD reference counts after dereferencing\n", retval);
    }

    if (pr >= 0) {
	(void) Cudd_PrintInfo(dd,stdout);
    }

    Cudd_Quit(dd);

#ifdef MNEMOSYNE
    mnem_writestats();
#endif

    if (pr>0) (void) printf("total time = %s\n",
		util_print_time(util_cpu_time() - startTime));

    if (pr >= 0) util_print_cpu_stats(stdout);
    exit(ok);
    /* NOTREACHED */

} /* end of main */
ABC_NAMESPACE_IMPL_START


/*---------------------------------------------------------------------------*/
/* Constant declarations                                                     */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Stucture declarations                                                     */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Type declarations                                                         */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Variable declarations                                                     */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Macro declarations                                                        */
/*---------------------------------------------------------------------------*/


/**AutomaticStart*************************************************************/

/*---------------------------------------------------------------------------*/
/* Static function prototypes                                                */
/*---------------------------------------------------------------------------*/

/**AutomaticEnd***************************************************************/


/*
    LinearSpace(f) = Space(f,f)

    Space(f,g)
	{
		if ( f = const )
		{ 
		    if ( f = g )  return 1;
			else          return 0;
		}
		if ( g = const )  return 0;
		return x' * Space(fx',gx') * Space(fx,gx) + x * Space(fx',gx) * Space(fx,gx');
	}

	Equations(s) = Pos(s) + Neg(s);

	Pos(s)
	{
		if ( s  = 0 )   return 1;
		if ( s  = 1 )   return 0;
		if ( sx'= 0 )   return Pos(sx) + x;
		if ( sx = 0 )   return Pos(sx');
		return 1 * [Pos(sx') & Pos(sx)] + x * [Pos(sx') & Neg(sx)];
	}

	Neg(s)
	{
		if ( s  = 0 )   return 1;
		if ( s  = 1 )   return 0;
		if ( sx'= 0 )   return Neg(sx);
		if ( sx = 0 )   return Neg(sx') + x;
		return 1 * [Neg(sx') & Neg(sx)] + x * [Neg(sx') & Pos(sx)];
	}


    SpaceP(A)
	{
		if ( A = 0 )    return 1;
		if ( A = 1 )    return 1;
		return x' * SpaceP(Ax') * SpaceP(Ax) + x * SpaceP(Ax') * SpaceN(Ax);
	}

    SpaceN(A)
	{
		if ( A = 0 )    return 1;
		if ( A = 1 )    return 0;
		return x' * SpaceN(Ax') * SpaceN(Ax) + x * SpaceN(Ax') * SpaceP(Ax);
	}


    LinInd(A)
	{
		if ( A = const )     return 1;
		if ( !LinInd(Ax') )  return 0;
		if ( !LinInd(Ax)  )  return 0;
		if (  LinSumOdd(Ax')  & LinSumEven(Ax) != 0 )  return 0;
		if (  LinSumEven(Ax') & LinSumEven(Ax) != 0 )  return 0;
		return 1;
	}

	LinSumOdd(A)
	{
		if ( A = 0 )    return 0;                 // Odd0  ---e-- Odd1
		if ( A = 1 )    return 1;                 //       \   o
		Odd0  = LinSumOdd(Ax');  // x is absent   //         \ 
		Even0 = LinSumEven(Ax'); // x is absent   //       /   o  
		Odd1  = LinSumOdd(Ax);   // x is present  // Even0 ---e-- Even1 
		Even1 = LinSumEven(Ax);  // x is absent
		return 1 * [Odd0 + ExorP(Odd0, Even1)] + x * [Odd1 + ExorP(Odd1, Even0)];
	}

	LinSumEven(A)
	{
		if ( A = 0 )    return 0;
		if ( A = 1 )    return 0;
		Odd0  = LinSumOdd(Ax');  // x is absent
		Even0 = LinSumEven(Ax'); // x is absent
		Odd1  = LinSumOdd(Ax);   // x is present
		Even1 = LinSumEven(Ax);  // x is absent
		return 1 * [Even0 + Even1 + ExorP(Even0, Even1)] + x * [ExorP(Odd0, Odd1)];
	}
	
*/

/*---------------------------------------------------------------------------*/
/* Definition of exported functions                                          */
/*---------------------------------------------------------------------------*/

/**Function*************************************************************

  Synopsis    []

  Description []

  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc )
{
	int * pSupport;
	int * pPermute;
	int * pPermuteBack;
	DdNode ** pCompose;
	DdNode * bCube, * bTemp;
	DdNode * bSpace, * bFunc1, * bFunc2, * bSpaceShift;
	int nSupp, Counter;
	int i, lev;

	// get the support
	pSupport = ABC_ALLOC( int, ddMax(dd->size,dd->sizeZ) );
	Extra_SupportArray( dd, bFunc, pSupport );
	nSupp = 0;
	for ( i = 0; i < dd->size; i++ )
		if ( pSupport[i] )
			nSupp++;

	// make sure the manager has enough variables
	if ( 2*nSupp > dd->size )
	{
		printf( "Cannot derive linear space, because DD manager does not have enough variables.\n" );
		fflush( stdout );
		ABC_FREE( pSupport );
		return NULL;
	}

	// create the permutation arrays
	pPermute     = ABC_ALLOC( int, dd->size );
	pPermuteBack = ABC_ALLOC( int, dd->size );
	pCompose     = ABC_ALLOC( DdNode *, dd->size );
	for ( i = 0; i < dd->size; i++ )
	{
		pPermute[i]     = i;
		pPermuteBack[i] = i;
		pCompose[i]     = dd->vars[i];   Cudd_Ref( pCompose[i] );
	}

	// remap the function in such a way that the variables are interleaved
	Counter = 0;
	bCube = b1;  Cudd_Ref( bCube );
	for ( lev = 0; lev < dd->size; lev++ )
		if ( pSupport[ dd->invperm[lev] ] )
		{   // var "dd->invperm[lev]" on level "lev" should go to level 2*Counter;
			pPermute[ dd->invperm[lev] ] = dd->invperm[2*Counter];
			// var from level 2*Counter+1 should go back to the place of this var
			pPermuteBack[ dd->invperm[2*Counter+1] ] = dd->invperm[lev];
			// the permutation should be defined in such a way that variable
			// on level 2*Counter is replaced by an EXOR of itself and var on the next level
			Cudd_Deref( pCompose[ dd->invperm[2*Counter] ] );
			pCompose[ dd->invperm[2*Counter] ] = 
				Cudd_bddXor( dd, dd->vars[ dd->invperm[2*Counter] ], dd->vars[ dd->invperm[2*Counter+1] ] );  
			Cudd_Ref( pCompose[ dd->invperm[2*Counter] ] );
			// add this variable to the cube
			bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[ dd->invperm[2*Counter] ] );  Cudd_Ref( bCube );
			Cudd_RecursiveDeref( dd, bTemp );
			// increment the counter
			Counter ++;
		}

	// permute the functions
	bFunc1 = Cudd_bddPermute( dd, bFunc, pPermute );         Cudd_Ref( bFunc1 );
	// compose to gate the function depending on both vars
	bFunc2 = Cudd_bddVectorCompose( dd, bFunc1, pCompose );  Cudd_Ref( bFunc2 );
	// gate the vector space
	// L(a) = ForAll x [ F(x) = F(x+a) ] = Not( Exist x [ F(x) (+) F(x+a) ] )
	bSpaceShift = Cudd_bddXorExistAbstract( dd, bFunc1, bFunc2, bCube );  Cudd_Ref( bSpaceShift );
	bSpaceShift = Cudd_Not( bSpaceShift );
	// permute the space back into the original mapping
	bSpace = Cudd_bddPermute( dd, bSpaceShift, pPermuteBack ); Cudd_Ref( bSpace );
	Cudd_RecursiveDeref( dd, bFunc1 );
	Cudd_RecursiveDeref( dd, bFunc2 );
	Cudd_RecursiveDeref( dd, bSpaceShift );
	Cudd_RecursiveDeref( dd, bCube );

	for ( i = 0; i < dd->size; i++ )
		Cudd_RecursiveDeref( dd, pCompose[i] );
	ABC_FREE( pPermute );
	ABC_FREE( pPermuteBack );
	ABC_FREE( pCompose );
    ABC_FREE( pSupport );

	Cudd_Deref( bSpace );
	return bSpace;
}
/**Function********************************************************************

  Synopsis    [Tests Walsh matrix multiplication.]

  Description [Tests Walsh matrix multiplication.  Return 1 if successful;
  0 otherwise.]

  SideEffects [May create new variables in the manager.]

  SeeAlso     []

******************************************************************************/
static int
testWalsh(
  DdManager *dd /* manager */,
  int N /* number of variables */,
  int cmu /* use CMU approach to matrix multiplication */,
  int approach /* reordering approach */,
  int pr /* verbosity level */)
{
    DdNode *walsh1, *walsh2, *wtw;
    DdNode **x, **v, **z;
    int i, retval;
    DdNode *one = DD_ONE(dd);
    DdNode *zero = DD_ZERO(dd);

    if (N > 3) {
	x = ALLOC(DdNode *,N);
	v = ALLOC(DdNode *,N);
	z = ALLOC(DdNode *,N);

	for (i = N-1; i >= 0; i--) {
	    Cudd_Ref(x[i]=cuddUniqueInter(dd,3*i,one,zero));
	    Cudd_Ref(v[i]=cuddUniqueInter(dd,3*i+1,one,zero));
	    Cudd_Ref(z[i]=cuddUniqueInter(dd,3*i+2,one,zero));
	}
	Cudd_Ref(walsh1 = Cudd_addWalsh(dd,v,z,N));
	if (pr>0) {(void) printf("walsh1"); Cudd_PrintDebug(dd,walsh1,2*N,pr);}
	Cudd_Ref(walsh2 = Cudd_addWalsh(dd,x,v,N));
	if (cmu) {
	    Cudd_Ref(wtw = Cudd_addTimesPlus(dd,walsh2,walsh1,v,N));
	} else {
	    Cudd_Ref(wtw = Cudd_addMatrixMultiply(dd,walsh2,walsh1,v,N));
	}
	if (pr>0) {(void) printf("wtw"); Cudd_PrintDebug(dd,wtw,2*N,pr);}

	if (approach != CUDD_REORDER_NONE) {
#ifdef DD_DEBUG
	    retval = Cudd_DebugCheck(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
		return(0);
	    }
#endif
	    retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5);
	    if (retval == 0) {
		(void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n");
		return(0);
	    }
#ifdef DD_DEBUG
	    retval = Cudd_DebugCheck(dd);
	    if (retval != 0) {
		(void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n");
		return(0);
	    }
#endif
	    if (approach == CUDD_REORDER_SYMM_SIFT ||
	    approach == CUDD_REORDER_SYMM_SIFT_CONV) {
		Cudd_SymmProfile(dd,0,dd->size-1);
	    }
	}
	/* Clean up. */
	Cudd_RecursiveDeref(dd, wtw);
	Cudd_RecursiveDeref(dd, walsh1);
	Cudd_RecursiveDeref(dd, walsh2);
	for (i=0; i < N; i++) {
	    Cudd_RecursiveDeref(dd, x[i]);
	    Cudd_RecursiveDeref(dd, v[i]);
	    Cudd_RecursiveDeref(dd, z[i]);
	}
	FREE(x);
	FREE(v);
	FREE(z);
    }
/**Function*************************************************************

  Synopsis    [Returns the local function of the DSD node. ]

  Description [The local function is computed using the global function 
  of the node and the global functions of the formal inputs. The resulting
  local function is mapped using the topmost N variables of the manager.
  The number of variables N is equal to the number of formal inputs.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ) 
{
    int * pForm2Var;   // the mapping of each formal input into its first var
    int * pVar2Form;   // the mapping of each var into its formal inputs
    int i, iVar, iLev, * pPermute;
    DdNode ** pbCube0, ** pbCube1;
    DdNode * bFunc, * bRes, * bTemp;
    st_table * pCache;
    
    pPermute  = ALLOC( int, dd->size );
    pVar2Form = ALLOC( int, dd->size );
    pForm2Var = ALLOC( int, dd->size );

    pbCube0 = ALLOC( DdNode *, dd->size );
    pbCube1 = ALLOC( DdNode *, dd->size );

    // remap the global function in such a way that
    // the support variables of each formal input are adjacent
    iLev = 0;
	for ( i = 0; i < pNode->nDecs; i++ )
    {
        pForm2Var[i] = dd->invperm[i];
        for ( bTemp = pNode->pDecs[i]->S; bTemp != b1; bTemp = cuddT(bTemp) )
        {
            iVar = dd->invperm[iLev];
            pPermute[bTemp->index] = iVar;
            pVar2Form[iVar] = i;
            iLev++;
        }

        // collect the cubes representing each assignment
        pbCube0[i] = Extra_bddGetOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) );
        Cudd_Ref( pbCube0[i] );
        pbCube1[i] = Extra_bddGetOneCube( dd, pNode->pDecs[i]->G );
        Cudd_Ref( pbCube1[i] );
    }

    // remap the function
    bFunc = Cudd_bddPermute( dd, pNode->G, pPermute ); Cudd_Ref( bFunc );
    // remap the cube
	for ( i = 0; i < pNode->nDecs; i++ )
    {
        pbCube0[i] = Cudd_bddPermute( dd, bTemp = pbCube0[i], pPermute ); Cudd_Ref( pbCube0[i] );
        Cudd_RecursiveDeref( dd, bTemp );
        pbCube1[i] = Cudd_bddPermute( dd, bTemp = pbCube1[i], pPermute ); Cudd_Ref( pbCube1[i] );
        Cudd_RecursiveDeref( dd, bTemp );
    }

    // remap the function
    pCache = st_init_table(st_ptrcmp,st_ptrhash);
    bRes = Extra_dsdRemap( dd, bFunc, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 );  Cudd_Ref( bRes );
    st_free_table( pCache );

    Cudd_RecursiveDeref( dd, bFunc );
	for ( i = 0; i < pNode->nDecs; i++ )
    {
        Cudd_RecursiveDeref( dd, pbCube0[i] );
        Cudd_RecursiveDeref( dd, pbCube1[i] );
    }
/*
////////////
    // permute the function once again
    // in such a way that i-th var stood for i-th formal input
	for ( i = 0; i < dd->size; i++ )
        pPermute[i] = -1;
	for ( i = 0; i < pNode->nDecs; i++ )
        pPermute[dd->invperm[i]] = i;
    bRes = Cudd_bddPermute( dd, bTemp = bRes, pPermute ); Cudd_Ref( bRes );
    Cudd_RecursiveDeref( dd, bTemp );
////////////
*/
    FREE(pPermute);
    FREE(pVar2Form);
    FREE(pForm2Var);
    FREE(pbCube0);
    FREE(pbCube1);

    Cudd_Deref( bRes );
    return bRes;
}
/**Function*************************************************************

  Synopsis    [Creates the DD from the internal reordering data structure.]

  Description [It is important that the hash table is lossless.]

  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit )
{
	DdManager * dd = p->dd;
	DdNode * bRes, * E, * T;
	int HKey, fComp;

	fComp = Cudd_IsComplement(pUnit);
	pUnit = Unit_Regular(pUnit);

	// check the hash-table
	if ( pUnit->n != 1 )
	{
		for ( HKey = hashKey2(p->Signature,pUnit,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize )
			if ( p->HTable[HKey].Arg1 == pUnit )
			{
				bRes = (DdNode*) p->HTable[HKey].Arg2;  
				assert( bRes );
				return Cudd_NotCond( bRes, fComp );
			}
	}

	// treat the case of constants
	if ( Unit_IsConstant(pUnit) )
	{
		bRes = cuddUniqueConst( dd, ((double)((int)(pUnit->pE))) );
		cuddRef( bRes );
	}
	else
	{
		// split and recur on children of this node
		E = reoTransferUnitsToNodes_rec( p, pUnit->pE );
		if ( E == NULL )
			return NULL;
		cuddRef(E);

		T = reoTransferUnitsToNodes_rec( p, pUnit->pT );
		if ( T == NULL )
		{
			Cudd_RecursiveDeref(dd, E);
			return NULL;
		}
		cuddRef(T);
		
		// consider the case when Res0 and Res1 are the same node
		assert( E != T );
		assert( !Cudd_IsComplement(T) );

		bRes = cuddUniqueInter( dd, p->pMapToDdVarsFinal[pUnit->lev], T, E );
		if ( bRes == NULL ) 
		{
			Cudd_RecursiveDeref(dd,E);
			Cudd_RecursiveDeref(dd,T);
			return NULL;
		}
		cuddRef( bRes );
		cuddDeref( E );
		cuddDeref( T );
	}

	// do not keep the result if the ref count is only 1, since it will not be visited again
	if ( pUnit->n != 1 )
	{
		 // while we traversed the diagram, the hash entry to which HKey points,
		 // might have been used. Make sure that its signature is different.
		 for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize );
		 p->HTable[HKey].Sign = p->Signature;
		 p->HTable[HKey].Arg1 = pUnit;
		 p->HTable[HKey].Arg2 = (reo_unit *)bRes;  

		 // add the DD to the referenced DD list in order to be able to store it in cache
		 p->pRefNodes[p->nRefNodes++] = bRes;  Cudd_Ref( bRes ); 
		 // no need to do this, because the garbage collection will not take bRes away
		 // it is held by the diagram in the making
	}
	// increment the counter of nodes
	p->nNodesCur++;
	cuddDeref( bRes );
	return Cudd_NotCond( bRes, fComp );
}
Exemple #15
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_zddWeakDivF.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddWeakDivF]

******************************************************************************/
DdNode  *
cuddZddWeakDivF(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    int         v, top_f, top_g, vf, vg;
    DdNode      *one = DD_ONE(dd);
    DdNode      *zero = DD_ZERO(dd);
    DdNode      *f0, *f1, *fd, *g0, *g1, *gd;
    DdNode      *q, *tmp;
    DdNode      *r;
    DdNode      *term1, *term0, *termd;
    int         flag;
    int         pv, nv;

    statLine(dd);
    if (g == one)
        return(f);
    if (f == zero || f == one)
        return(zero);
    if (f == g)
        return(one);

    /* Check cache. */
    r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g);
    if (r)
        return(r);

    top_f = dd->permZ[f->index];
    top_g = dd->permZ[g->index];
    vf = top_f >> 1;
    vg = top_g >> 1;
    v = ddMin(top_f, top_g);

    if (v == top_f && vf < vg) {
        v = f->index;
        flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
        if (flag == 1)
            return(NULL);
        Cudd_Ref(f1);
        Cudd_Ref(f0);
        Cudd_Ref(fd);

        pv = cuddZddGetPosVarIndex(dd, v);
        nv = cuddZddGetNegVarIndex(dd, v);

        term1 = cuddZddWeakDivF(dd, f1, g);
        if (term1 == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, f0);
            Cudd_RecursiveDerefZdd(dd, fd);
            return(NULL);
        }
        Cudd_Ref(term1);
        Cudd_RecursiveDerefZdd(dd, f1);
        term0 = cuddZddWeakDivF(dd, f0, g);
        if (term0 == NULL) {
            Cudd_RecursiveDerefZdd(dd, f0);
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, term1);
            return(NULL);
        }
        Cudd_Ref(term0);
        Cudd_RecursiveDerefZdd(dd, f0);
        termd = cuddZddWeakDivF(dd, fd, g);
        if (termd == NULL) {
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, term1);
            Cudd_RecursiveDerefZdd(dd, term0);
            return(NULL);
        }
        Cudd_Ref(termd);
        Cudd_RecursiveDerefZdd(dd, fd);

        tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */
        if (tmp == NULL) {
            Cudd_RecursiveDerefZdd(dd, term1);
            Cudd_RecursiveDerefZdd(dd, term0);
            Cudd_RecursiveDerefZdd(dd, termd);
            return(NULL);
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDerefZdd(dd, term0);
        Cudd_RecursiveDerefZdd(dd, termd);
        q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */
        if (q == NULL) {
            Cudd_RecursiveDerefZdd(dd, term1);
            Cudd_RecursiveDerefZdd(dd, tmp);
            return(NULL);
        }
        Cudd_Ref(q);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, tmp);

        cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q);
        Cudd_Deref(q);
        return(q);
    }

    if (v == top_f)
        v = f->index;
    else
        v = g->index;

    flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
    if (flag == 1)
        return(NULL);
    Cudd_Ref(f1);
    Cudd_Ref(f0);
    Cudd_Ref(fd);
    flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
    if (flag == 1) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        return(NULL);
    }
    Cudd_Ref(g1);
    Cudd_Ref(g0);
    Cudd_Ref(gd);

    q = g;

    if (g0 != zero) {
        q = cuddZddWeakDivF(dd, f0, g0);
        if (q == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, f0);
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, g1);
            Cudd_RecursiveDerefZdd(dd, g0);
            Cudd_RecursiveDerefZdd(dd, gd);
            return(NULL);
        }
        Cudd_Ref(q);
    }
    else
        Cudd_Ref(q);
    Cudd_RecursiveDerefZdd(dd, f0);
    Cudd_RecursiveDerefZdd(dd, g0);

    if (q == zero) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
        cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero);
        Cudd_Deref(q);
        return(zero);
    }

    if (g1 != zero) {
        Cudd_RecursiveDerefZdd(dd, q);
        tmp = cuddZddWeakDivF(dd, f1, g1);
        if (tmp == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, g1);
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, gd);
            return(NULL);
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, g1);
        if (q == g)
            q = tmp;
        else {
            q = cuddZddIntersect(dd, q, tmp);
            if (q == NULL) {
                Cudd_RecursiveDerefZdd(dd, fd);
                Cudd_RecursiveDerefZdd(dd, gd);
                return(NULL);
            }
            Cudd_Ref(q);
            Cudd_RecursiveDerefZdd(dd, tmp);
        }
    }
    else {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, g1);
    }

    if (q == zero) {
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
        cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero);
        Cudd_Deref(q);
        return(zero);
    }

    if (gd != zero) {
        Cudd_RecursiveDerefZdd(dd, q);
        tmp = cuddZddWeakDivF(dd, fd, gd);
        if (tmp == NULL) {
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, gd);
            return(NULL);
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
        if (q == g)
            q = tmp;
        else {
            q = cuddZddIntersect(dd, q, tmp);
            if (q == NULL) {
                Cudd_RecursiveDerefZdd(dd, tmp);
                return(NULL);
            }
            Cudd_Ref(q);
            Cudd_RecursiveDerefZdd(dd, tmp);
        }
    }
    else {
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
    }

    cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q);
    Cudd_Deref(q);
    return(q);

} /* end of cuddZddWeakDivF */
Exemple #16
0
/**
 * @brief Basic test of long double and EPD minterm computation.
 * @return 0 if successful; -1 otherwise.
 */
static int
testLdbl(int verbosity)
{
    DdManager *dd;
    DdNode *f, *g;
    int i, ret;
    int const N = 12; /* half the number of variables */
    long double cnt;

    dd = Cudd_Init(2*N, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0);
    if (!dd) {
        if (verbosity) {
            printf("initialization failed\n");
        }
        return -1;
    }
    f = g = Cudd_ReadOne(dd);
    Cudd_Ref(f);
    Cudd_Ref(g);
    for (i = 0; i < N; i++) {
        DdNode *var1, *var2, *clause, *tmp;
        var1 = Cudd_bddIthVar(dd, i);
        var2 = Cudd_bddIthVar(dd, i+N);
        clause = Cudd_bddOr(dd, var1, var2);
        if (!clause) {
            Cudd_Quit(dd);
            return -1;
        }
        Cudd_Ref(clause);
        tmp = Cudd_bddAnd(dd, f, clause);
        if (!tmp) {
            Cudd_Quit(dd);
            return -1;
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDeref(dd, clause);
        Cudd_RecursiveDeref(dd, f);
        f = tmp;
        clause = Cudd_bddOr(dd, Cudd_Not(var1), Cudd_Not(var2));
        if (!clause) {
            Cudd_Quit(dd);
            return -1;
        }
        Cudd_Ref(clause);
        tmp = Cudd_bddAnd(dd, g, clause);
        if (!tmp) {
            Cudd_Quit(dd);
            return -1;
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDeref(dd, clause);
        Cudd_RecursiveDeref(dd, g);
        g = tmp;
    }
    if (verbosity) {
        printf("f");
        Cudd_PrintSummary(dd, f, 2*N, 0);
    }
    cnt = Cudd_LdblCountMinterm(dd, f, 2*N);
    if (verbosity) {
        printf("f has %Lg minterms\n", cnt);
    }
    if (verbosity) {
        printf("EPD count for f = ");
        ret = Cudd_EpdPrintMinterm(dd, f, 2*N);
        printf("\n");
        if (!ret) {
            printf("problem with EPD\n");
        }
    }
    Cudd_RecursiveDeref(dd, f);
    if (verbosity) {
        printf("g");
        Cudd_PrintSummary(dd, g, 2*N, 0);
    }
    cnt = Cudd_LdblCountMinterm(dd, g, 2*N);
    if (verbosity) {
        printf("g has %Lg minterms\n", cnt);
    }
    if (verbosity) {
        printf("EPD count for g = ");
        ret = Cudd_EpdPrintMinterm(dd, g, 2*N);
        printf("\n");
        if (!ret) {
            printf("problem with EPD\n");
        }
    }
    Cudd_RecursiveDeref(dd, g);
    ret = Cudd_CheckZeroRef(dd);
    if (verbosity && ret != 0) {
        printf("%d non-zero references\n", ret);
    }
    Cudd_Quit(dd);
    return 0;
}
Exemple #17
0
/**Function*************************************************************

  Synopsis    [Reorders the DD using REO and CUDD.]

  Description [This function can be used to test the performance of the reordering package.]

  SideEffects []

  SeeAlso     []

***********************************************************************/
void Extra_ShuffleTest( reo_man * pReo, DdManager * dd, DdNode * Func )
{
//    extern int runtime1, runtime2;

	DdNode * Temp, * bRemap;
    int nSuppSize, OffSet, Num, i;
    clock_t clk;
	int pOrder[1000], pOrderInv[1000];
    assert( dd->size < 1000 );

    srand( 0x12341234 );
    nSuppSize = Cudd_SupportSize( dd, Func );
    if ( nSuppSize < 2 )
        return;

    for ( i = 0; i < nSuppSize; i++ )
        pOrder[i] = i;
    for ( i = 0; i < 120; i++ )
    {
        OffSet = rand() % (nSuppSize - 1);
        Num = pOrder[OffSet];
        pOrder[OffSet] = pOrder[OffSet+1];
        pOrder[OffSet+1] = Num;
    }
    for ( i = 0; i < nSuppSize; i++ )
        pOrderInv[pOrder[i]] = i;

/*
    printf( "Permutation: " );
    for ( i = 0; i < nSuppSize; i++ )
        printf( "%d ", pOrder[i] );
    printf( "\n" );
    printf( "Inverse permutation: " );
    for ( i = 0; i < nSuppSize; i++ )
        printf( "%d ", pOrderInv[i] );
    printf( "\n" );
*/

    // create permutation
//    Extra_ReorderSetVerification( pReo, 1 );
    bRemap = Extra_bddRemapUp( dd, Func );  Cudd_Ref( bRemap );

clk = clock();
	Temp  = reoShuffle( pReo, dd, bRemap, pOrder, pOrderInv );  Cudd_Ref( Temp );
//runtime1 += clock() - clk;

//printf( "Initial = %d. Final = %d.\n", Cudd_DagSize(bRemap), Cudd_DagSize(Temp)  );

	{
		DdNode * bFuncPerm;
clk = clock();
		bFuncPerm = Cudd_bddPermute( dd, bRemap, pOrderInv );  Cudd_Ref( bFuncPerm );
//runtime2 += clock() - clk;
		if ( bFuncPerm != Temp )
		{
			printf( "REO: Internal verification has failed!\n" );
			fflush( stdout );
		}
		Cudd_RecursiveDeref( dd, bFuncPerm );
	}

	Cudd_RecursiveDeref( dd, Temp );
	Cudd_RecursiveDeref( dd, bRemap );
}
Exemple #18
0
/**
 * @brief Basic test of timeout handler.
 *
 * @details Sets a short timeout and then tries to build a function
 * with a large BDD.  Strives to avoid leaking nodes.
 *
 * @return 0 if successful; -1 otherwise.
 */
static int
testTimeout(int verbosity)
{
    DdManager *dd;
    /* Declare these "volatile" to prevent clobbering by longjmp. */
    DdNode * volatile f;
    DdNode * volatile clause = NULL;
    DdNode * var1, * var2;
    int i, ret, count;
    int const N = 20; /* half the number of variables in f */
    unsigned long timeout = 100UL; /* in milliseconds */
    jmp_buf timeoutEnv;

    dd = Cudd_Init(0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0);
    if (!dd) {
        if (verbosity) {
            printf("initialization failed\n");
        }
        return -1;
    }

    /* Set up timeout handling. */
    if (setjmp(timeoutEnv) > 0) {
        if (verbosity) {
            printf("caught timeout\n");
        }
        /* The nodes of clause may be leaked if the timeout was
         * detected while conjoining the clause to f.  We set
         * clause to NULL when it's not in use to be able to
         * detect this case.
         */
        if (clause)
            Cudd_RecursiveDeref(dd, clause);
        goto finally;
    }
    (void) Cudd_RegisterTimeoutHandler(dd, timeoutHandler, (void *) &timeoutEnv);
    (void) Cudd_SetTimeLimit(dd, timeout);

    /* Try to build function.  This is expected to run out of time. */
    f = Cudd_ReadOne(dd);
    Cudd_Ref(f);
    for (i = 0; i < N; i++) {
        DdNode * tmp;
        var1 = Cudd_bddIthVar(dd, i);
        if (!var1) {
            if (verbosity) {
                printf("computation failed\n");
                return -1;
            }
        }
        var2 = Cudd_bddIthVar(dd, i+N);
        if (!var2) {
            if (verbosity) {
                printf("computation failed\n");
                return -1;
            }
        }
        clause = Cudd_bddOr(dd, var1, var2);
        if (!clause) {
            if (verbosity) {
                printf("computation failed\n");
            }
            return -1;
        }
        Cudd_Ref(clause);
        tmp = Cudd_bddAnd(dd, f, clause);
        if (!tmp) {
            if (verbosity) {
                printf("computation failed\n");
            }
            return -1;
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDeref(dd, clause);
        clause = NULL;
        Cudd_RecursiveDeref(dd, f);
        f = tmp;
    }
    if (verbosity > 1) {
        Cudd_bddPrintCover(dd, f, f);
    }

finally:
    if (verbosity) {
        printf("so far");
        Cudd_PrintSummary(dd, f, 2*N, 0);
    }
    count = 0;
    for (i = 0; i < N-1; i += 2) {
        var1 = Cudd_bddIthVar(dd, i);
        if (!var1) {
            printf("computation failed\n");
            return -1;
        }
        var2 = Cudd_bddIthVar(dd, i+1);
        if (!var2) {
            printf("computation failed\n");
            return -1;
        }
        clause = Cudd_bddOr(dd, var1, var2);
        if (!clause) {
            printf("computation failed\n");
            return -1;
        }
        Cudd_Ref(clause);
        if (Cudd_bddLeq(dd, f, clause)) {
            count++;
        }
        Cudd_RecursiveDeref(dd, clause);
    }
    if (verbosity) {
        printf("f implies %d clauses\n", count);
    }
    Cudd_RecursiveDeref(dd, f);
    ret = Cudd_CheckZeroRef(dd);
    if (verbosity) {
        Cudd_PrintInfo(dd, stdout);
        if (ret != 0) {
            printf("%d non-zero references\n", ret);
        }
    }
    Cudd_Quit(dd);
    return 0;
}
Exemple #19
0
anode_t *synthesize( DdManager *manager,  unsigned char init_flags,
                     unsigned char verbose )
{
    anode_t *strategy = NULL;
    anode_t *this_node_stack = NULL;
    anode_t *node, *new_node;
    bool initial;
    vartype *state;
    vartype **env_moves;
    int emoves_len;

    ptree_t *var_separator;
    DdNode *W;
    DdNode *strans_into_W;

    DdNode *einit, *sinit, *etrans, *strans, **egoals, **sgoals;

    DdNode *ddval;  /* Store result of evaluating a BDD */
    DdNode ***Y = NULL;
    DdNode *Y_i_primed;
    int *num_sublevels;
    DdNode ****X_ijr = NULL;

    DdNode *tmp, *tmp2;
    int i, j, r, k;  /* Generic counters */
    int offset;
    bool env_nogoal_flag = False;  /* Indicate environment has no goals */
    int loop_mode;
    int next_mode;

    int num_env, num_sys;
    int *cube;  /* length will be twice total number of variables (to
                   account for both variables and their primes). */

    /* Variables used during CUDD generation (state enumeration). */
    DdGen *gen;
    CUDD_VALUE_TYPE gvalue;
    int *gcube;

    /* Set environment goal to True (i.e., any state) if none was
       given. This simplifies the implementation below. */
    if (spc.num_egoals == 0) {
        env_nogoal_flag = True;
        spc.num_egoals = 1;
        spc.env_goals = malloc( sizeof(ptree_t *) );
        *spc.env_goals = init_ptree( PT_CONSTANT, NULL, 1 );
    }

    num_env = tree_size( spc.evar_list );
    num_sys = tree_size( spc.svar_list );

    /* State vector (i.e., valuation of the variables) */
    state = malloc( sizeof(vartype)*(num_env+num_sys) );
    if (state == NULL) {
        perror( __FILE__ ",  malloc" );
        exit(-1);
    }

    /* Allocate cube array, used later for quantifying over variables. */
    cube = (int *)malloc( sizeof(int)*2*(num_env+num_sys) );
    if (cube == NULL) {
        perror( __FILE__ ",  malloc" );
        exit(-1);
    }

    /* Chain together environment and system variable lists for
       working with BDD library. */
    if (spc.evar_list == NULL) {
        var_separator = NULL;
        spc.evar_list = spc.svar_list;  /* that this is the deterministic case
                                           is indicated by var_separator = NULL. */
    } else {
        var_separator = get_list_item( spc.evar_list, -1 );
        if (var_separator == NULL) {
            fprintf( stderr,
                     "Error: get_list_item failed on environment variables"
                     " list.\n" );
            free( state );
            free( cube );
            return NULL;
        }
        var_separator->left = spc.svar_list;
    }

    /* Generate BDDs for the various parse trees from the problem spec. */
    if (spc.env_init != NULL) {
        einit = ptree_BDD( spc.env_init, spc.evar_list, manager );
    } else {
        einit = Cudd_ReadOne( manager );
        Cudd_Ref( einit );
    }
    if (spc.sys_init != NULL) {
        sinit = ptree_BDD( spc.sys_init, spc.evar_list, manager );
    } else {
        sinit = Cudd_ReadOne( manager );
        Cudd_Ref( sinit );
    }
    if (verbose > 1)
        logprint( "Building environment transition BDD..." );
    etrans = ptree_BDD( spc.env_trans, spc.evar_list, manager );
    if (verbose > 1) {
        logprint( "Done." );
        logprint( "Building system transition BDD..." );
    }
    strans = ptree_BDD( spc.sys_trans, spc.evar_list, manager );
    if (verbose > 1)
        logprint( "Done." );

    /* Build goal BDDs, if present. */
    if (spc.num_egoals > 0) {
        egoals = malloc( spc.num_egoals*sizeof(DdNode *) );
        for (i = 0; i < spc.num_egoals; i++)
            *(egoals+i) = ptree_BDD( *(spc.env_goals+i), spc.evar_list, manager );
    } else {
        egoals = NULL;
    }
    if (spc.num_sgoals > 0) {
        sgoals = malloc( spc.num_sgoals*sizeof(DdNode *) );
        for (i = 0; i < spc.num_sgoals; i++)
            *(sgoals+i) = ptree_BDD( *(spc.sys_goals+i), spc.evar_list, manager );
    } else {
        sgoals = NULL;
    }

    if (var_separator == NULL) {
        spc.evar_list = NULL;
    } else {
        var_separator->left = NULL;
    }

    W = compute_winning_set_BDD( manager, etrans, strans, egoals, sgoals,
                                 verbose );
    if (W == NULL) {
        fprintf( stderr,
                 "Error synthesize: failed to construct winning set.\n" );
        free( state );
        free( cube );
        return NULL;
    }
    Y = compute_sublevel_sets( manager, W, etrans, strans,
                               egoals, spc.num_egoals,
                               sgoals, spc.num_sgoals,
                               &num_sublevels, &X_ijr, verbose );
    if (Y == NULL) {
        fprintf( stderr,
                 "Error synthesize: failed to construct sublevel sets.\n" );
        free( state );
        free( cube );
        return NULL;
    }

    /* The sublevel sets are exactly as resulting from the vanilla
       fixed point formula.  Thus for each system goal i, Y_0 = \emptyset,
       and Y_1 is a union of i-goal states and environment-blocking states.

       For the purpose of synthesis, it is enough to delete Y_0 and
       replace Y_1 with the intersection of i-goal states and the
       winning set, and then shift the indices down (so that Y_1 is
       now called Y_0, Y_2 is now called Y_1, etc.) */
    for (i = 0; i < spc.num_sgoals; i++) {
        Cudd_RecursiveDeref( manager, *(*(Y+i)) );
        Cudd_RecursiveDeref( manager, *(*(Y+i)+1) );
        for (r = 0; r < spc.num_egoals; r++)
            Cudd_RecursiveDeref( manager, *(*(*(X_ijr+i))+r) );
        free( *(*(X_ijr+i)) );

        *(*(Y+i)+1) = Cudd_bddAnd( manager, *(sgoals+i), W );
        Cudd_Ref( *(*(Y+i)+1) );

        (*(num_sublevels+i))--;
        for (j = 0; j < *(num_sublevels+i); j++) {
            *(*(Y+i)+j) = *(*(Y+i)+j+1);
            *(*(X_ijr+i)+j) = *(*(X_ijr+i)+j+1);
        }

        assert( *(num_sublevels+i) > 0 );
        *(Y+i) = realloc( *(Y+i), (*(num_sublevels+i))*sizeof(DdNode *) );
        *(X_ijr+i) = realloc( *(X_ijr+i),
                              (*(num_sublevels+i))*sizeof(DdNode **) );
        if (*(Y+i) == NULL || *(X_ijr+i) == NULL) {
            perror( __FILE__ ",  realloc" );
            exit(-1);
        }
    }

    /* Make primed form of W and take conjunction with system
       transition (safety) formula, for use while stepping down Y_i
       sets.  Note that we assume the variable map has been
       appropriately defined in the CUDD manager, after the call to
       compute_winning_set_BDD above. */
    tmp = Cudd_bddVarMap( manager, W );
    if (tmp == NULL) {
        fprintf( stderr,
                 "Error synthesize: Error in swapping variables with primed"
                 " forms.\n" );
        free( state );
        free( cube );
        return NULL;
    }
    Cudd_Ref( tmp );
    strans_into_W = Cudd_bddAnd( manager, strans, tmp );
    Cudd_Ref( strans_into_W );
    Cudd_RecursiveDeref( manager, tmp );

    /* From each initial state, build strategy by propagating forward
       toward the next goal (current target goal specified by "mode"
       of a state), and iterating until every reached state and mode
       combination has already been encountered (whence the
       strategy already built). */
    if (init_flags == ALL_INIT
        || (init_flags == ONE_SIDE_INIT && spc.sys_init == NULL)) {
        if (init_flags == ALL_INIT) {
            if (verbose > 1)
                logprint( "Enumerating initial states, given init_flags ="
                          " ALL_INIT" );
            tmp = Cudd_bddAnd( manager, einit, sinit );
        } else {
            if (verbose > 1)
                logprint( "Enumerating initial states, given init_flags ="
                          " ONE_SIDE_INIT and empty SYSINIT" );
            tmp = einit;
            Cudd_Ref( tmp );
        }
        Cudd_Ref( tmp );
        Cudd_AutodynDisable( manager );
        Cudd_ForeachCube( manager, tmp, gen, gcube, gvalue ) {
            initialize_cube( state, gcube, num_env+num_sys );
            while (!saturated_cube( state, gcube, num_env+num_sys )) {
                this_node_stack = insert_anode( this_node_stack, 0, -1, False,
                                                state, num_env+num_sys );
                if (this_node_stack == NULL) {
                    fprintf( stderr,
                             "Error synthesize: building list of initial"
                             " states.\n" );
                    return NULL;
                }
                increment_cube( state, gcube, num_env+num_sys );
            }
            this_node_stack = insert_anode( this_node_stack, 0, -1, False,
                                            state, num_env+num_sys );
            if (this_node_stack == NULL) {
                fprintf( stderr,
                         "Error synthesize: building list of initial"
                         " states.\n" );
                return NULL;
            }
        }
        Cudd_AutodynEnable( manager, CUDD_REORDER_SAME );
        Cudd_RecursiveDeref( manager, tmp );

    } else if (init_flags == ALL_ENV_EXIST_SYS_INIT) {
Exemple #20
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_zddDivideF.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddDivideF]

******************************************************************************/
DdNode  *
cuddZddDivideF(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    int         v;
    DdNode      *one = DD_ONE(dd);
    DdNode      *zero = DD_ZERO(dd);
    DdNode      *f0, *f1, *g0, *g1;
    DdNode      *q, *r, *tmp;
    int         flag;

    statLine(dd);
    if (g == one)
        return(f);
    if (f == zero || f == one)
        return(zero);
    if (f == g)
        return(one);

    /* Check cache. */
    r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g);
    if (r)
        return(r);

    v = g->index;

    flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
    if (flag == 1)
        return(NULL);
    Cudd_Ref(f1);
    Cudd_Ref(f0);
    flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);    /* g1 != zero */
    if (flag == 1) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        return(NULL);
    }
    Cudd_Ref(g1);
    Cudd_Ref(g0);

    r = cuddZddDivideF(dd, f1, g1);
    if (r == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        return(NULL);
    }
    Cudd_Ref(r);

    if (r != zero && g0 != zero) {
        tmp = r;
        q = cuddZddDivideF(dd, f0, g0);
        if (q == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, f0);
            Cudd_RecursiveDerefZdd(dd, g1);
            Cudd_RecursiveDerefZdd(dd, g0);
            return(NULL);
        }
        Cudd_Ref(q);
        r = cuddZddIntersect(dd, r, q);
        if (r == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, f0);
            Cudd_RecursiveDerefZdd(dd, g1);
            Cudd_RecursiveDerefZdd(dd, g0);
            Cudd_RecursiveDerefZdd(dd, q);
            return(NULL);
        }
        Cudd_Ref(r);
        Cudd_RecursiveDerefZdd(dd, q);
        Cudd_RecursiveDerefZdd(dd, tmp);
    }

    Cudd_RecursiveDerefZdd(dd, f1);
    Cudd_RecursiveDerefZdd(dd, f0);
    Cudd_RecursiveDerefZdd(dd, g1);
    Cudd_RecursiveDerefZdd(dd, g0);
    
    cuddCacheInsert2(dd, cuddZddDivideF, f, g, r);
    Cudd_Deref(r);
    return(r);

} /* end of cuddZddDivideF */
Exemple #21
0
/**Function********************************************************************

  Synopsis    [Computes shortest paths in a state graph.]

  Description [Computes shortest paths in the state transition graph of
  a network.  Three methods are availabe:
  <ul>
  <li> Bellman-Ford algorithm for single-source shortest paths; the
  algorithm computes the distance (number of transitions) from the initial
  states to all states.
  <li> Floyd-Warshall algorithm for all-pair shortest paths.
  <li> Repeated squaring algorithm for all-pair shortest paths.
  </ul>
  The function returns 1 in case of success; 0 otherwise.
  ]

  SideEffects [ADD variables are created in the manager.]

  SeeAlso     []

******************************************************************************/
int
Ntr_ShortestPaths(
  DdManager * dd,
  BnetNetwork * net,
  NtrOptions * option)
{
    NtrPartTR *TR;
    DdNode *edges, *source, *res, *r, *q, *bddSource;
    DdNode **xadd, **yadd, **zadd;
    int i;
    int pr = option->verb;
    int algorithm = option->shortPath;
    int selectiveTrace = option->selectiveTrace;
    int nvars = net->nlatches;

    /* Set background to infinity for shortest paths. */
    Cudd_SetBackground(dd,Cudd_ReadPlusInfinity(dd));

    /* Build the monolithic TR. */
    TR = Ntr_buildTR(dd,net,option,NTR_IMAGE_MONO);

    /* Build the ADD variable vectors for x and y. */
    xadd = ALLOC(DdNode *, nvars);
    yadd = ALLOC(DdNode *, nvars);
    for(i = 0; i < nvars; i++) {
	q = Cudd_addIthVar(dd,TR->x[i]->index);
	Cudd_Ref(q);
	xadd[i] = q;
	q = Cudd_addIthVar(dd,TR->y[i]->index);
	Cudd_Ref(q);
	yadd[i] = q;
    }

    /* Convert the transition relation BDD into an ADD... */
    q = Cudd_BddToAdd(dd,TR->part[0]);
    Cudd_Ref(q);
    /* ...replacing zeroes with infinities... */
    r = Cudd_addIte(dd,q,Cudd_ReadOne(dd),Cudd_ReadPlusInfinity(dd));
    Cudd_Ref(r);
    Cudd_RecursiveDeref(dd,q);
    /* ...and zeroing the diagonal. */
    q = Cudd_addXeqy(dd,nvars,xadd,yadd);
    Cudd_Ref(q);
    edges = Cudd_addIte(dd,q,Cudd_ReadZero(dd),r);
    Cudd_Ref(edges);
    Cudd_RecursiveDeref(dd,r);
    Cudd_RecursiveDeref(dd,q);

    switch(algorithm) {
    case NTR_SHORT_BELLMAN:
	bddSource = Ntr_initState(dd,net,option);
	source = Cudd_BddToAdd(dd,bddSource);
	Cudd_Ref(source);
	res = ntrBellman(dd,edges,source,xadd,yadd,nvars,pr);
	if (res == NULL) return(0);
	Cudd_Ref(res);
	Cudd_RecursiveDeref(dd,source);
	Cudd_RecursiveDeref(dd,bddSource);
	if (pr >= 0) {
	    (void) fprintf(stdout,"Distance Matrix");
	    Cudd_PrintDebug(dd,res,nvars,pr);
	}
	break;
    case NTR_SHORT_FLOYD:
	res = ntrWarshall(dd,edges,xadd,yadd,nvars,pr);
	if (res == NULL) return(0);
	Cudd_Ref(res);
	if (pr >= 0) {
	    (void) fprintf(stdout,"Distance Matrix");
	    Cudd_PrintDebug(dd,res,2*nvars,pr);
	}
	break;
    case NTR_SHORT_SQUARE:
	/* Create a third set of ADD variables. */
	zadd = ALLOC(DdNode *, nvars);
	for(i = 0; i < nvars; i++) {
	    int level;
	    level = Cudd_ReadIndex(dd,TR->x[i]->index);
	    q = Cudd_addNewVarAtLevel(dd,level);
	    Cudd_Ref(q);
	    zadd[i] = q;
	}
	/* Compute the shortest paths. */
	res = ntrSquare(dd,edges,zadd,yadd,xadd,nvars,pr,selectiveTrace);
	if (res == NULL) return(0);
	Cudd_Ref(res);
	/* Dispose of the extra variables. */
	for(i = 0; i < nvars; i++) {
	    Cudd_RecursiveDeref(dd,zadd[i]);
	}
	FREE(zadd);
	if (pr >= 0) {
	    (void) fprintf(stdout,"Distance Matrix");
	    Cudd_PrintDebug(dd,res,2*nvars,pr);
	}
	break;
    default:
	(void) printf("Unrecognized method. Try again.\n");
	return(0);
    }

    /* Here we should compute the paths. */

    /* Clean up. */
    Ntr_freeTR(dd,TR);
    Cudd_RecursiveDeref(dd,edges);
    Cudd_RecursiveDeref(dd,res);
    for(i = 0; i < nvars; i++) {
	Cudd_RecursiveDeref(dd,xadd[i]);
	Cudd_RecursiveDeref(dd,yadd[i]);
    }
    FREE(xadd);
    FREE(yadd);

    if (option->autoDyn & 1) {
	(void) printf("Order after short path computation\n");
	if (!Bnet_PrintOrder(net,dd)) return(0);
    }

    return(1);

} /* end of Ntr_ShortestPaths */
Exemple #22
0
/**Function********************************************************************

  Synopsis    [Computes the three-way decomposition of f w.r.t. v.]

  Description [Computes the three-way decomposition of function f (represented
  by a ZDD) wit respect to variable v.  Returns 0 if successful; 1 otherwise.]

  SideEffects [The results are returned in f1, f0, and fd.]

  SeeAlso     [cuddZddGetCofactors2]

******************************************************************************/
int
cuddZddGetCofactors3(
  DdManager * dd,
  DdNode * f,
  int  v,
  DdNode ** f1,
  DdNode ** f0,
  DdNode ** fd)
{
    DdNode      *pc, *nc;
    DdNode      *zero = DD_ZERO(dd);
    int         top, hv, ht, pv, nv;
    int         level;

    top = dd->permZ[f->index];
    level = dd->permZ[v];
    hv = level >> 1;
    ht = top >> 1;

    if (hv < ht) {
        *f1 = zero;
        *f0 = zero;
        *fd = f;
    }
    else {
        pv = cuddZddGetPosVarIndex(dd, v);
        nv = cuddZddGetNegVarIndex(dd, v);

        /* not to create intermediate ZDD node */
        if (cuddZddGetPosVarLevel(dd, v) < cuddZddGetNegVarLevel(dd, v)) {
            pc = cuddZddSubset1(dd, f, pv);
            if (pc == NULL)
                return(1);
            Cudd_Ref(pc);
            nc = cuddZddSubset0(dd, f, pv);
            if (nc == NULL) {
                Cudd_RecursiveDerefZdd(dd, pc);
                return(1);
            }
            Cudd_Ref(nc);

            *f1 = cuddZddSubset0(dd, pc, nv);
            if (*f1 == NULL) {
                Cudd_RecursiveDerefZdd(dd, pc);
                Cudd_RecursiveDerefZdd(dd, nc);
                return(1);
            }
            Cudd_Ref(*f1);
            *f0 = cuddZddSubset1(dd, nc, nv);
            if (*f0 == NULL) {
                Cudd_RecursiveDerefZdd(dd, pc);
                Cudd_RecursiveDerefZdd(dd, nc);
                Cudd_RecursiveDerefZdd(dd, *f1);
                return(1);
            }
            Cudd_Ref(*f0);

            *fd = cuddZddSubset0(dd, nc, nv);
            if (*fd == NULL) {
                Cudd_RecursiveDerefZdd(dd, pc);
                Cudd_RecursiveDerefZdd(dd, nc);
                Cudd_RecursiveDerefZdd(dd, *f1);
                Cudd_RecursiveDerefZdd(dd, *f0);
                return(1);
            }
            Cudd_Ref(*fd);
        } else {
            pc = cuddZddSubset1(dd, f, nv);
            if (pc == NULL)
                return(1);
            Cudd_Ref(pc);
            nc = cuddZddSubset0(dd, f, nv);
            if (nc == NULL) {
                Cudd_RecursiveDerefZdd(dd, pc);
                return(1);
            }
            Cudd_Ref(nc);

            *f0 = cuddZddSubset0(dd, pc, pv);
            if (*f0 == NULL) {
                Cudd_RecursiveDerefZdd(dd, pc);
                Cudd_RecursiveDerefZdd(dd, nc);
                return(1);
            }
            Cudd_Ref(*f0);
            *f1 = cuddZddSubset1(dd, nc, pv);
            if (*f1 == NULL) {
                Cudd_RecursiveDerefZdd(dd, pc);
                Cudd_RecursiveDerefZdd(dd, nc);
                Cudd_RecursiveDerefZdd(dd, *f0);
                return(1);
            }
            Cudd_Ref(*f1);

            *fd = cuddZddSubset0(dd, nc, pv);
            if (*fd == NULL) {
                Cudd_RecursiveDerefZdd(dd, pc);
                Cudd_RecursiveDerefZdd(dd, nc);
                Cudd_RecursiveDerefZdd(dd, *f1);
                Cudd_RecursiveDerefZdd(dd, *f0);
                return(1);
            }
            Cudd_Ref(*fd);
        }

        Cudd_RecursiveDerefZdd(dd, pc);
        Cudd_RecursiveDerefZdd(dd, nc);
        Cudd_Deref(*f1);
        Cudd_Deref(*f0);
        Cudd_Deref(*fd);
    }
    return(0);

} /* end of cuddZddGetCofactors3 */
Exemple #23
0
/**Function********************************************************************

  Synopsis    [Floyd-Warshall algorithm for all-pair shortest paths.]

  Description []

  SideEffects []

  SeeAlso     []

******************************************************************************/
static DdNode *
ntrWarshall(
  DdManager *dd,
  DdNode *D,
  DdNode **x,
  DdNode **y,
  int vars,
  int pr)
{
    DdNode *one, *zero;
    DdNode *xminterm,  *w, *V, *V2;
    DdNode *P, *R;
    int i;
    int nodes;
    int k,u;
    long start_time;
    if (vars > 30)
	nodes = 1000000000;
    else
	nodes = 1 << vars;

    one = DD_ONE(dd);
    zero = DD_ZERO(dd);
    Cudd_Ref(R = D);                        /* make copy of original matrix */

    /* Extract pivot row and column from D */
    start_time = util_cpu_time();
    for (k = 0; k < nodes; k++) {
        if (k % 10000 == 0) {
	    (void) printf("Starting iteration  %d  at time %s\n",
			  k,util_print_time(util_cpu_time() - start_time));
        }
        Cudd_Ref(xminterm = one);
        u = k;
	for (i = vars-1; i >= 0; i--) {
	    if (u&1) {
	        Cudd_Ref(w = Cudd_addIte(dd,x[i],xminterm,zero));
	    } else {
	        Cudd_Ref(w = Cudd_addIte(dd,x[i],zero,xminterm));
	    }
	    Cudd_RecursiveDeref(dd,xminterm);
	    xminterm = w;
	    u >>= 1;
	}

	Cudd_Ref(V = Cudd_Cofactor(dd,R,xminterm));
	Cudd_RecursiveDeref(dd,xminterm);
	if (pr>2) {(void) printf("V"); Cudd_PrintDebug(dd,V,vars,pr);}


	Cudd_Ref(xminterm = one);
	u = k;
	for (i = vars-1; i >= 0; i--) {
	    if (u&1) {
	        Cudd_Ref(w = Cudd_addIte(dd,y[i],xminterm,zero));
	    } else {
	        Cudd_Ref(w = Cudd_addIte(dd,y[i],zero,xminterm));
	    }
	    Cudd_RecursiveDeref(dd,xminterm);
	    xminterm = w;
	    u >>= 1;
	}

	Cudd_Ref(V2 = Cudd_Cofactor(dd,R,xminterm));
	Cudd_RecursiveDeref(dd,xminterm);
	if (pr>2) {(void) printf("V2"); Cudd_PrintDebug(dd,V2,vars,pr);}

	Cudd_Ref(P = Cudd_addOuterSum(dd,R,V,V2));

	Cudd_RecursiveDeref(dd,V);
	Cudd_RecursiveDeref(dd,V2);
	Cudd_RecursiveDeref(dd,R);
	R = P;
	if (pr>2) {(void) printf("R"); Cudd_PrintDebug(dd,R,vars,pr);}
    }

    Cudd_Deref(R);
    return(R);

} /* end of ntrWarshall */
Exemple #24
0
/**Function********************************************************************

  Synopsis [Performs the recursive step of Cudd_zddProduct.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddProduct]

******************************************************************************/
DdNode  *
cuddZddProduct(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    int         v, top_f, top_g;
    DdNode      *tmp, *term1, *term2, *term3;
    DdNode      *f0, *f1, *fd, *g0, *g1, *gd;
    DdNode      *R0, *R1, *Rd, *N0, *N1;
    DdNode      *r;
    DdNode      *one = DD_ONE(dd);
    DdNode      *zero = DD_ZERO(dd);
    int         flag;
    int         pv, nv;

    statLine(dd);
    if (f == zero || g == zero)
        return(zero);
    if (f == one)
        return(g);
    if (g == one)
        return(f);

    top_f = dd->permZ[f->index];
    top_g = dd->permZ[g->index];

    if (top_f > top_g)
        return(cuddZddProduct(dd, g, f));

    /* Check cache */
    r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g);
    if (r)
        return(r);

    v = f->index;       /* either yi or zi */
    flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
    if (flag == 1)
        return(NULL);
    Cudd_Ref(f1);
    Cudd_Ref(f0);
    Cudd_Ref(fd);
    flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
    if (flag == 1) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        return(NULL);
    }
    Cudd_Ref(g1);
    Cudd_Ref(g0);
    Cudd_Ref(gd);
    pv = cuddZddGetPosVarIndex(dd, v);
    nv = cuddZddGetNegVarIndex(dd, v);

    Rd = cuddZddProduct(dd, fd, gd);
    if (Rd == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, gd);
        return(NULL);
    }
    Cudd_Ref(Rd);

    term1 = cuddZddProduct(dd, f0, g0);
    if (term1 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, Rd);
        return(NULL);
    }
    Cudd_Ref(term1);
    term2 = cuddZddProduct(dd, f0, gd);
    if (term2 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, Rd);
        Cudd_RecursiveDerefZdd(dd, term1);
        return(NULL);
    }
    Cudd_Ref(term2);
    term3 = cuddZddProduct(dd, fd, g0);
    if (term3 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, Rd);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        return(NULL);
    }
    Cudd_Ref(term3);
    Cudd_RecursiveDerefZdd(dd, f0);
    Cudd_RecursiveDerefZdd(dd, g0);
    tmp = cuddZddUnion(dd, term1, term2);
    if (tmp == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, Rd);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        Cudd_RecursiveDerefZdd(dd, term3);
        return(NULL);
    }
    Cudd_Ref(tmp);
    Cudd_RecursiveDerefZdd(dd, term1);
    Cudd_RecursiveDerefZdd(dd, term2);
    R0 = cuddZddUnion(dd, tmp, term3);
    if (R0 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, Rd);
        Cudd_RecursiveDerefZdd(dd, term3);
        Cudd_RecursiveDerefZdd(dd, tmp);
        return(NULL);
    }
    Cudd_Ref(R0);
    Cudd_RecursiveDerefZdd(dd, tmp);
    Cudd_RecursiveDerefZdd(dd, term3);
    N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */
    if (N0 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, Rd);
        Cudd_RecursiveDerefZdd(dd, R0);
        return(NULL);
    }
    Cudd_Ref(N0);
    Cudd_RecursiveDerefZdd(dd, R0);
    Cudd_RecursiveDerefZdd(dd, Rd);

    term1 = cuddZddProduct(dd, f1, g1);
    if (term1 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, N0);
        return(NULL);
    }
    Cudd_Ref(term1);
    term2 = cuddZddProduct(dd, f1, gd);
    if (term2 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, N0);
        Cudd_RecursiveDerefZdd(dd, term1);
        return(NULL);
    }
    Cudd_Ref(term2);
    term3 = cuddZddProduct(dd, fd, g1);
    if (term3 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, N0);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        return(NULL);
    }
    Cudd_Ref(term3);
    Cudd_RecursiveDerefZdd(dd, f1);
    Cudd_RecursiveDerefZdd(dd, g1);
    Cudd_RecursiveDerefZdd(dd, fd);
    Cudd_RecursiveDerefZdd(dd, gd);
    tmp = cuddZddUnion(dd, term1, term2);
    if (tmp == NULL) {
        Cudd_RecursiveDerefZdd(dd, N0);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        Cudd_RecursiveDerefZdd(dd, term3);
        return(NULL);
    }
    Cudd_Ref(tmp);
    Cudd_RecursiveDerefZdd(dd, term1);
    Cudd_RecursiveDerefZdd(dd, term2);
    R1 = cuddZddUnion(dd, tmp, term3);
    if (R1 == NULL) {
        Cudd_RecursiveDerefZdd(dd, N0);
        Cudd_RecursiveDerefZdd(dd, term3);
        Cudd_RecursiveDerefZdd(dd, tmp);
        return(NULL);
    }
    Cudd_Ref(R1);
    Cudd_RecursiveDerefZdd(dd, tmp);
    Cudd_RecursiveDerefZdd(dd, term3);
    N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */
    if (N1 == NULL) {
        Cudd_RecursiveDerefZdd(dd, N0);
        Cudd_RecursiveDerefZdd(dd, R1);
        return(NULL);
    }
    Cudd_Ref(N1);
    Cudd_RecursiveDerefZdd(dd, R1);
    Cudd_RecursiveDerefZdd(dd, N0);

    cuddCacheInsert2(dd, cuddZddProduct, f, g, N1);
    Cudd_Deref(N1);
    return(N1);

} /* end of cuddZddProduct */
int main(int argc, char** argv) {
  unsigned int i;
  Biddy_Boolean complete;
  Biddy_Edge tmp;
  Biddy_Edge r1,r2;
  unsigned int n1,n2;
  char *userinput;

#ifdef USA_YES
  unsigned int usaSize = 0;
  unsigned int **usaEdge;
  unsigned int *usaOrder;
  char *usaCodes;
  Biddy_Edge *usaState;
  Biddy_Edge *usaGraph;
#endif

#ifdef EUROPE_YES
  unsigned int europeSize = 0;
  unsigned int **europeEdge;
  unsigned int *europeOrder;
  char *europeCodes;
  Biddy_Edge *europeState;
  Biddy_Edge *europeGraph;
#endif

  setbuf(stdout, NULL);

#ifdef USA_YES
  setDataUSA(&usaSize,&usaEdge,&usaOrder,&usaCodes);
#endif

#ifdef EUROPE_YES
  setDataEurope(&europeSize,&europeEdge,&europeOrder,&europeCodes);
#endif

#ifdef USE_BIDDY
  /* There is only one unique table in Biddy */
  /* There are three caches in Biddy */
  /* Unique table grows over the time */
  /* The max number of variables is hardcoded in biddyInt. h */
  /* biddyVariableTable.usaSize = BIDDYVARMAX = 2048 */
  /* The following constants are hardcoded in biddyMain.c */
  /* biddyIteCache.usaSize = MEDIUM_TABLE = 262143 */
  /* biddyEACache.usaSize = SMALL_TABLE = 65535 */
  /* biddyRCCache.usaSize = SMALL_TABLE = 65535 */
  /* DEFAULT INIT CALL: Biddy_Init() */
  Biddy_Init();
#endif

#ifdef USE_CUDD
  /* In CUDD each variable has its own subtable in the unique table */
  /* There is only one cache in CUDD */
  /* Subtables grow over the time, you can set limit for fast unique table growth */
  /* Cudd_SetLooseUpTo(manager,1048576) */
  /* Cache can grow over the time, you can set the max usaSize */
  /* Cudd_SetMaxCacheHard(manager,262144) */
  /* These two constants are hardcoded in v3.0.0 */
  /* CUDD_UNIQUE_SLOTS = 256 (default initial usaSize of each subtable) */
  /* CUDD_CACHE_SLOTS = 262144 (default initial usaSize of cache table) */
  /* DEFAULT INIT CALL: Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0) */
  manager = Cudd_Init(0,0,CUDD_UNIQUE_SLOTS,CUDD_CACHE_SLOTS,0);
  Cudd_SetMaxCacheHard(manager,262144);
#endif

#ifdef USA_YES
  usaGraph = (Biddy_Edge *) malloc(usaSize*sizeof(Biddy_Edge *));
  usaState = (Biddy_Edge *) malloc(usaSize*sizeof(Biddy_Edge *));
#endif

#ifdef EUROPE_YES
  europeGraph = (Biddy_Edge *) malloc(europeSize*sizeof(Biddy_Edge *));
  europeState = (Biddy_Edge *) malloc(europeSize*sizeof(Biddy_Edge *));
#endif

  i = 0;
  complete = FALSE;
  while (!complete) {
    complete = TRUE;
    tmp = Biddy_AddVariable();
#ifdef USA_YES
    if (i < usaSize) {
      usaState[usaOrder[i]] = tmp;
    }
    complete = complete && (i >= (usaSize-1));
#endif
#ifdef EUROPE_YES
    if (i < europeSize) {
      europeState[europeOrder[i]] = tmp;
    }
    complete = complete && (i >= (europeSize-1));
#endif
    i++;
  }

#ifdef USA_YES
  createGraph(usaSize,usaEdge,usaState,usaGraph);
#endif

#ifdef EUROPE_YES
  createGraph(europeSize,europeEdge,europeState,europeGraph);
#endif

#ifdef USE_BIDDY
  Biddy_Clean();
#endif

  r1 = Biddy_GetConstantZero();
  r2 = Biddy_GetConstantZero();
#ifdef USE_CUDD
  Cudd_Ref(r1);
  Cudd_Ref(r2);
#endif

#ifdef USA_YES
  if (!CALCULATE_KERNELS) {
    /* CALCULATING INDEPENDENCE SETS FOR USA */
#ifdef USE_CUDD
    Cudd_RecursiveDeref(manager,r1);
#endif
    r1 = calculateIndependence(usaSize,usaState,usaGraph);
  } else {
    /* CALCULATING KERNELS (MAXIMUM INDEPENDENCE SETS) FOR USA */
#ifdef USE_CUDD
    Cudd_RecursiveDeref(manager,r1);
#endif
    r1 = calculateKernels(usaSize,usaState,usaGraph);
  }
#ifdef USE_BIDDY
  Biddy_AddPersistentFormula((Biddy_String)"usa",r1);
  Biddy_Clean();
#endif
#ifdef USE_CUDD
  for (i=0; i<usaSize; i++) {
    Cudd_RecursiveDeref(manager,usaGraph[i]);
  }
#endif
#endif

#ifdef EUROPE_YES
  if (!CALCULATE_KERNELS) {
    /* CALCULATING INDEPENDENCE SETS FOR EUROPE */
#ifdef USE_CUDD
    Cudd_RecursiveDeref(manager,r2);
#endif
    r2 = calculateIndependence(europeSize,europeState,europeGraph);
  } else {
    /* CALCULATING KERNELS (MAXIMUM INDEPENDENCE SETS) FOR EUROPE */
#ifdef USE_CUDD
    Cudd_RecursiveDeref(manager,r2);
#endif
    r2 = calculateKernels(europeSize,europeState,europeGraph);
  }
#ifdef USE_BIDDY
  Biddy_AddPersistentFormula((Biddy_String)"europe",r2);
  Biddy_Clean();
#endif
#ifdef USE_CUDD
  for (i=0; i<europeSize; i++) {
    Cudd_RecursiveDeref(manager,europeGraph[i]);
  }
#endif
#endif

  userinput = strdup("...");
  while (userinput[0] != 'x') {

    /* We have problems with passing stdout in the case you compile this file */
    /* with MINGW and use biddy.dll generated with Visual Studio. */
    /* In such cases, please, use Biddy_PrintInfo(NULL) */
    if (userinput[0] == 'r') Biddy_PrintInfo(stdout);

    /* SIFTING  */
#ifdef USE_BIDDY
#ifdef CONVERGE
    if (userinput[0] == 's') Biddy_PurgeAndReorder(NULL,TRUE);
#ifdef USA_YES
    if (userinput[0] == 'u') Biddy_PurgeAndReorder(r1,TRUE);
#endif
#ifdef EUROPE_YES
    if (userinput[0] == 'e') Biddy_PurgeAndReorder(r2,TRUE);
#endif
#else
    if (userinput[0] == 's') Biddy_PurgeAndReorder(NULL,FALSE);
#ifdef USA_YES
    if (userinput[0] == 'u') Biddy_PurgeAndReorder(r1,FALSE);
#endif
#ifdef EUROPE_YES
    if (userinput[0] == 'e') Biddy_PurgeAndReorder(r2,FALSE);
#endif
#endif
#endif
#ifdef USE_CUDD
#ifdef CONVERGE
    if (userinput[0] == 's') Cudd_ReduceHeap(manager,CUDD_REORDER_SIFT_CONVERGE,0);
#else
    if (userinput[0] == 's') Cudd_ReduceHeap(manager,CUDD_REORDER_SIFT,0);
#endif
#endif
    n1 = Biddy_VariableNumber(r1);
    n2 = Biddy_VariableNumber(r2);
    if ((userinput[0] == 's')
#ifdef USA_YES
        || (userinput[0] == 'u')
#endif
#ifdef EUROPE_YES
        || (userinput[0] == 'e')
#endif
    ) {
#ifdef CONVERGE
      printf("(CONVERGING SIFTING");
#ifdef USE_BIDDY
      if (userinput[0] == 'u') {
        printf(" ON FUNCTION FOR USA");
      }
      if (userinput[0] == 'e') {
        printf(" ON FUNCTION FOR EUROPE");
      }
#endif
      printf(") ");
#else
      printf("(SIFTING");
#ifdef USE_BIDDY
      if (userinput[0] == 'u') {
        printf(" ON FUNCTION FOR USA");
      }
      if (userinput[0] == 'e') {
        printf(" ON FUNCTION FOR EUROPE");
      }
#endif
      printf(") ");
#endif
    }

    printf("Resulting function r1/r2 depends on %u/%u variables.\n",n1,n2);
    printf("Resulting function r1/r2 has %.0f/%.0f minterms.\n",Biddy_CountMinterm(r1,n1),Biddy_CountMinterm(r2,n2));
#ifdef USE_BIDDY
    printf("BDD for resulting function r1/r2 has %u/%u nodes (%u/%u nodes if using complement edges).\n",
           Biddy_NodeNumberPlain(r1),Biddy_NodeNumberPlain(r2),Biddy_NodeNumber(r1),Biddy_NodeNumber(r2));
#endif
#ifdef USE_CUDD
    printf("BDD for resulting function r1/r2 has %u/%u nodes (using complement edges).\n",Biddy_NodeNumber(r1),Biddy_NodeNumber(r2));
#endif
#ifdef USE_BIDDY
    printf("Variable swaps performed so far: %u\n",Biddy_NodeTableSwapNumber());
#endif
#ifdef USE_CUDD
    printf("Variable swaps performed so far: %.0f\n",Cudd_ReadSwapSteps(manager));
#endif
#ifdef USA_YES
    printf("Order for USA: ");
    writeOrder(r1,usaCodes,usaOrder,usaSize);
#endif
#ifdef EUROPE_YES
    printf("Order for Europe: ");
    writeOrder(r2,europeCodes,europeOrder,europeSize);
#endif
#ifdef USE_BIDDY
    printf("E[x]it or [r]eport or ");
#ifdef CONVERGE
    printf("Converging sifting ");
#else
    printf("Sifting ");
#endif
#if (defined USA_YES) || (defined EUROPE_YES)
    printf("on [s]ystem or Sifting on function for");
#ifdef USA_YES
    printf(" [u]SA");
#endif
#ifdef EUROPE_YES
    printf(" [e]urope");
#endif
#endif
    printf(": ");
    if (!scanf("%s",userinput)) printf("ERROR\n");
#endif
#ifdef USE_CUDD
    printf("E[x]it or [r]eport or ");
#ifdef CONVERGE
    printf("Converging sifting ");
#else
    printf("Sifting ");
#endif
    printf("on [s]ystem: ");
    if (!scanf("%s",userinput)) printf("ERROR\n");
#endif
  }

  free(userinput);

  /* EXIT */
#ifdef USE_BIDDY
  Biddy_Exit();
#endif
#ifdef USE_CUDD
  Cudd_RecursiveDeref(manager,r1);
  Cudd_RecursiveDeref(manager,r2);
  printf("CUDD: nodes with non-zero reference counts: %d\n",Cudd_CheckZeroRef(manager));
  Cudd_Quit(manager);
#endif

  return 0;
}
Exemple #26
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_zddUnateProduct.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddUnateProduct]

******************************************************************************/
DdNode  *
cuddZddUnateProduct(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    int         v, top_f, top_g;
    DdNode      *term1, *term2, *term3, *term4;
    DdNode      *sum1, *sum2;
    DdNode      *f0, *f1, *g0, *g1;
    DdNode      *r;
    DdNode      *one = DD_ONE(dd);
    DdNode      *zero = DD_ZERO(dd);
    int         flag;

    statLine(dd);
    if (f == zero || g == zero)
        return(zero);
    if (f == one)
        return(g);
    if (g == one)
        return(f);

    top_f = dd->permZ[f->index];
    top_g = dd->permZ[g->index];

    if (top_f > top_g)
        return(cuddZddUnateProduct(dd, g, f));

    /* Check cache */
    r = cuddCacheLookup2Zdd(dd, cuddZddUnateProduct, f, g);
    if (r)
        return(r);

    v = f->index;       /* either yi or zi */
    flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
    if (flag == 1)
        return(NULL);
    Cudd_Ref(f1);
    Cudd_Ref(f0);
    flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);
    if (flag == 1) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        return(NULL);
    }
    Cudd_Ref(g1);
    Cudd_Ref(g0);

    term1 = cuddZddUnateProduct(dd, f1, g1);
    if (term1 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        return(NULL);
    }
    Cudd_Ref(term1);
    term2 = cuddZddUnateProduct(dd, f1, g0);
    if (term2 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, term1);
        return(NULL);
    }
    Cudd_Ref(term2);
    term3 = cuddZddUnateProduct(dd, f0, g1);
    if (term3 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        return(NULL);
    }
    Cudd_Ref(term3);
    term4 = cuddZddUnateProduct(dd, f0, g0);
    if (term4 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        Cudd_RecursiveDerefZdd(dd, term3);
        return(NULL);
    }
    Cudd_Ref(term4);
    Cudd_RecursiveDerefZdd(dd, f1);
    Cudd_RecursiveDerefZdd(dd, f0);
    Cudd_RecursiveDerefZdd(dd, g1);
    Cudd_RecursiveDerefZdd(dd, g0);
    sum1 = cuddZddUnion(dd, term1, term2);
    if (sum1 == NULL) {
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        Cudd_RecursiveDerefZdd(dd, term3);
        Cudd_RecursiveDerefZdd(dd, term4);
        return(NULL);
    }
    Cudd_Ref(sum1);
    Cudd_RecursiveDerefZdd(dd, term1);
    Cudd_RecursiveDerefZdd(dd, term2);
    sum2 = cuddZddUnion(dd, sum1, term3);
    if (sum2 == NULL) {
        Cudd_RecursiveDerefZdd(dd, term3);
        Cudd_RecursiveDerefZdd(dd, term4);
        Cudd_RecursiveDerefZdd(dd, sum1);
        return(NULL);
    }
    Cudd_Ref(sum2);
    Cudd_RecursiveDerefZdd(dd, sum1);
    Cudd_RecursiveDerefZdd(dd, term3);
    r = cuddZddGetNode(dd, v, sum2, term4);
    if (r == NULL) {
        Cudd_RecursiveDerefZdd(dd, term4);
        Cudd_RecursiveDerefZdd(dd, sum2);
        return(NULL);
    }
    Cudd_Ref(r);
    Cudd_RecursiveDerefZdd(dd, sum2);
    Cudd_RecursiveDerefZdd(dd, term4);

    cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r);
    Cudd_Deref(r);
    return(r);

} /* end of cuddZddUnateProduct */
Exemple #27
0
/**Function********************************************************************

  Synopsis [Converts a ZDD cover to a BDD graph.]

  Description [Converts a ZDD cover to a BDD graph. If successful, it
  returns a BDD node, otherwise it returns NULL. It is a recursive
  algorithm as the following. First computes 3 cofactors of a ZDD cover;
  f1, f0 and fd. Second, compute BDDs(b1, b0 and bd) of f1, f0 and fd.
  Third, compute T=b1+bd and E=b0+bd. Fourth, compute ITE(v,T,E) where v
  is the variable which has the index of the top node of the ZDD cover.
  In this case, since the index of v can be larger than either one of T or
  one of E, cuddUniqueInterIVO is called, here IVO stands for
  independent variable ordering.]

  SideEffects []

  SeeAlso     [Cudd_MakeBddFromZddCover]

******************************************************************************/
DdNode	*
cuddMakeBddFromZddCover(
    DdManager * dd,
    DdNode * node)
{
    DdNode	*neW;
    int		v;
    DdNode	*f1, *f0, *fd;
    DdNode	*b1, *b0, *bd;
    DdNode	*T, *E;

    statLine(dd);
    if (node == dd->one)
        return(dd->one);
    if (node == dd->zero)
        return(Cudd_Not(dd->one));

    /* Check cache */
    neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node);
    if (neW)
        return(neW);

    v = Cudd_Regular(node)->index;	/* either yi or zi */
    cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd);
    Cudd_Ref(f1);
    Cudd_Ref(f0);
    Cudd_Ref(fd);

    b1 = cuddMakeBddFromZddCover(dd, f1);
    if (!b1) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        return(NULL);
    }
    Cudd_Ref(b1);
    b0 = cuddMakeBddFromZddCover(dd, f0);
    if (!b1) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDeref(dd, b1);
        return(NULL);
    }
    Cudd_Ref(b0);
    Cudd_RecursiveDerefZdd(dd, f1);
    Cudd_RecursiveDerefZdd(dd, f0);
    if (fd != dd->zero) {
        bd = cuddMakeBddFromZddCover(dd, fd);
        if (!bd) {
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDeref(dd, b1);
            Cudd_RecursiveDeref(dd, b0);
            return(NULL);
        }
        Cudd_Ref(bd);
        Cudd_RecursiveDerefZdd(dd, fd);

        T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd));
        if (!T) {
            Cudd_RecursiveDeref(dd, b1);
            Cudd_RecursiveDeref(dd, b0);
            Cudd_RecursiveDeref(dd, bd);
            return(NULL);
        }
        T = Cudd_NotCond(T, T != NULL);
        Cudd_Ref(T);
        Cudd_RecursiveDeref(dd, b1);
        E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd));
        if (!E) {
            Cudd_RecursiveDeref(dd, b0);
            Cudd_RecursiveDeref(dd, bd);
            Cudd_RecursiveDeref(dd, T);
            return(NULL);
        }
        E = Cudd_NotCond(E, E != NULL);
        Cudd_Ref(E);
        Cudd_RecursiveDeref(dd, b0);
        Cudd_RecursiveDeref(dd, bd);
    }
    else {
        Cudd_RecursiveDerefZdd(dd, fd);
        T = b1;
        E = b0;
    }

    if (Cudd_IsComplement(T)) {
        neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E));
        if (!neW) {
            Cudd_RecursiveDeref(dd, T);
            Cudd_RecursiveDeref(dd, E);
            return(NULL);
        }
        neW = Cudd_Not(neW);
    }
    else {
        neW = cuddUniqueInterIVO(dd, v / 2, T, E);
        if (!neW) {
            Cudd_RecursiveDeref(dd, T);
            Cudd_RecursiveDeref(dd, E);
            return(NULL);
        }
    }
    Cudd_Ref(neW);
    Cudd_RecursiveDeref(dd, T);
    Cudd_RecursiveDeref(dd, E);

    cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW);
    Cudd_Deref(neW);
    return(neW);

} /* end of cuddMakeBddFromZddCover */
Exemple #28
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_zddWeakDiv.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddWeakDiv]

******************************************************************************/
DdNode  *
cuddZddWeakDiv(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    int         v;
    DdNode      *one = DD_ONE(dd);
    DdNode      *zero = DD_ZERO(dd);
    DdNode      *f0, *f1, *fd, *g0, *g1, *gd;
    DdNode      *q, *tmp;
    DdNode      *r;
    int         flag;

    statLine(dd);
    if (g == one)
        return(f);
    if (f == zero || f == one)
        return(zero);
    if (f == g)
        return(one);

    /* Check cache. */
    r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g);
    if (r)
        return(r);

    v = g->index;

    flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
    if (flag == 1)
        return(NULL);
    Cudd_Ref(f1);
    Cudd_Ref(f0);
    Cudd_Ref(fd);
    flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
    if (flag == 1) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        return(NULL);
    }
    Cudd_Ref(g1);
    Cudd_Ref(g0);
    Cudd_Ref(gd);

    q = g;

    if (g0 != zero) {
        q = cuddZddWeakDiv(dd, f0, g0);
        if (q == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, f0);
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, g1);
            Cudd_RecursiveDerefZdd(dd, g0);
            Cudd_RecursiveDerefZdd(dd, gd);
            return(NULL);
        }
        Cudd_Ref(q);
    }
    else
        Cudd_Ref(q);
    Cudd_RecursiveDerefZdd(dd, f0);
    Cudd_RecursiveDerefZdd(dd, g0);

    if (q == zero) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
        cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero);
        Cudd_Deref(q);
        return(zero);
    }

    if (g1 != zero) {
        Cudd_RecursiveDerefZdd(dd, q);
        tmp = cuddZddWeakDiv(dd, f1, g1);
        if (tmp == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, g1);
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, gd);
            return(NULL);
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, g1);
        if (q == g)
            q = tmp;
        else {
            q = cuddZddIntersect(dd, q, tmp);
            if (q == NULL) {
                Cudd_RecursiveDerefZdd(dd, fd);
                Cudd_RecursiveDerefZdd(dd, gd);
                return(NULL);
            }
            Cudd_Ref(q);
            Cudd_RecursiveDerefZdd(dd, tmp);
        }
    }
    else {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, g1);
    }

    if (q == zero) {
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
        cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero);
        Cudd_Deref(q);
        return(zero);
    }

    if (gd != zero) {
        Cudd_RecursiveDerefZdd(dd, q);
        tmp = cuddZddWeakDiv(dd, fd, gd);
        if (tmp == NULL) {
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, gd);
            return(NULL);
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
        if (q == g)
            q = tmp;
        else {
            q = cuddZddIntersect(dd, q, tmp);
            if (q == NULL) {
                Cudd_RecursiveDerefZdd(dd, tmp);
                return(NULL);
            }
            Cudd_Ref(q);
            Cudd_RecursiveDerefZdd(dd, tmp);
        }
    }
    else {
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
    }

    cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q);
    Cudd_Deref(q);
    return(q);

} /* end of cuddZddWeakDiv */
Exemple #29
0
/**Function********************************************************************

  Synopsis [Performs the recursive step of Cudd_zddIsop.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddIsop]

******************************************************************************/
DdNode	*
cuddZddIsop(
  DdManager * dd,
  DdNode * L,
  DdNode * U,
  DdNode ** zdd_I)
{
    DdNode	*one = DD_ONE(dd);
    DdNode	*zero = Cudd_Not(one);
    DdNode	*zdd_one = DD_ONE(dd);
    DdNode	*zdd_zero = DD_ZERO(dd);
    int		v, top_l, top_u;
    DdNode	*Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
    DdNode	*Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
    DdNode	*Isub0, *Isub1, *Id;
    DdNode	*zdd_Isub0, *zdd_Isub1, *zdd_Id;
    DdNode	*x;
    DdNode	*term0, *term1, *sum;
    DdNode	*Lv, *Uv, *Lnv, *Unv;
    DdNode	*r, *y, *z;
    int		index;
    DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *);

    statLine(dd);
    if (L == zero) {
	*zdd_I = zdd_zero;
    	return(zero);
    }
    if (U == one) {
	*zdd_I = zdd_one;
    	return(one);
    }

    if (U == zero || L == one) {
	printf("*** ERROR : illegal condition for ISOP (U < L).\n");
	exit(1);
    }

    /* Check the cache. We store two results for each recursive call.
    ** One is the BDD, and the other is the ZDD. Both are needed.
    ** Hence we need a double hit in the cache to terminate the
    ** recursion. Clearly, collisions may evict only one of the two
    ** results. */
    cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) cuddZddIsop;
    r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
    if (r) {
	*zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U);
	if (*zdd_I)
	    return(r);
	else {
	    /* The BDD result may have been dead. In that case
	    ** cuddCacheLookup2 would have called cuddReclaim,
	    ** whose effects we now have to undo. */
	    cuddRef(r);
	    Cudd_RecursiveDeref(dd, r);
	}
    }

    top_l = dd->perm[Cudd_Regular(L)->index];
    top_u = dd->perm[Cudd_Regular(U)->index];
    v = ddMin(top_l, top_u);

    /* Compute cofactors. */
    if (top_l == v) {
	index = Cudd_Regular(L)->index;
    	Lv = Cudd_T(L);
    	Lnv = Cudd_E(L);
    	if (Cudd_IsComplement(L)) {
    	    Lv = Cudd_Not(Lv);
    	    Lnv = Cudd_Not(Lnv);
    	}
    }
    else {
	index = Cudd_Regular(U)->index;
        Lv = Lnv = L;
    }

    if (top_u == v) {
    	Uv = Cudd_T(U);
    	Unv = Cudd_E(U);
    	if (Cudd_IsComplement(U)) {
    	    Uv = Cudd_Not(Uv);
    	    Unv = Cudd_Not(Unv);
    	}
    }
    else {
        Uv = Unv = U;
    }

    Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
    if (Lsub0 == NULL)
	return(NULL);
    Cudd_Ref(Lsub0);
    Usub0 = Unv;
    Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
    if (Lsub1 == NULL) {
	Cudd_RecursiveDeref(dd, Lsub0);
	return(NULL);
    }
    Cudd_Ref(Lsub1);
    Usub1 = Uv;

    Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0);
    if (Isub0 == NULL) {
	Cudd_RecursiveDeref(dd, Lsub0);
	Cudd_RecursiveDeref(dd, Lsub1);
	return(NULL);
    }
    /*
    if ((!cuddIsConstant(Cudd_Regular(Isub0))) &&
	(Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 ||
	dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) {
	printf("*** ERROR : illegal permutation in ZDD. ***\n");
    }
    */
    Cudd_Ref(Isub0);
    Cudd_Ref(zdd_Isub0);
    Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1);
    if (Isub1 == NULL) {
	Cudd_RecursiveDeref(dd, Lsub0);
	Cudd_RecursiveDeref(dd, Lsub1);
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	return(NULL);
    }
    /*
    if ((!cuddIsConstant(Cudd_Regular(Isub1))) &&
	(Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 ||
	dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) {
	printf("*** ERROR : illegal permutation in ZDD. ***\n");
    }
    */
    Cudd_Ref(Isub1);
    Cudd_Ref(zdd_Isub1);
    Cudd_RecursiveDeref(dd, Lsub0);
    Cudd_RecursiveDeref(dd, Lsub1);

    Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
    if (Lsuper0 == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	return(NULL);
    }
    Cudd_Ref(Lsuper0);
    Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
    if (Lsuper1 == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Lsuper0);
	return(NULL);
    }
    Cudd_Ref(Lsuper1);
    Usuper0 = Unv;
    Usuper1 = Uv;

    /* Ld = Lsuper0 + Lsuper1 */
    Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
    if (Ld == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Lsuper0);
	Cudd_RecursiveDeref(dd, Lsuper1);
	return(NULL);
    }
    Ld = Cudd_Not(Ld);
    Cudd_Ref(Ld);
    /* Ud = Usuper0 * Usuper1 */
    Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
    if (Ud == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Lsuper0);
	Cudd_RecursiveDeref(dd, Lsuper1);
	Cudd_RecursiveDeref(dd, Ld);
	return(NULL);
    }
    Cudd_Ref(Ud);
    Cudd_RecursiveDeref(dd, Lsuper0);
    Cudd_RecursiveDeref(dd, Lsuper1);

    Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id);
    if (Id == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Ld);
	Cudd_RecursiveDeref(dd, Ud);
	return(NULL);
    }
    /*
    if ((!cuddIsConstant(Cudd_Regular(Id))) &&
	(Cudd_Regular(Id)->index != zdd_Id->index / 2 ||
	dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) {
	printf("*** ERROR : illegal permutation in ZDD. ***\n");
    }
    */
    Cudd_Ref(Id);
    Cudd_Ref(zdd_Id);
    Cudd_RecursiveDeref(dd, Ld);
    Cudd_RecursiveDeref(dd, Ud);

    x = cuddUniqueInter(dd, index, one, zero);
    if (x == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	return(NULL);
    }
    Cudd_Ref(x);
    /* term0 = x * Isub0 */
    term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
    if (term0 == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	Cudd_RecursiveDeref(dd, x);
	return(NULL);
    }
    Cudd_Ref(term0);
    Cudd_RecursiveDeref(dd, Isub0);
    /* term1 = x * Isub1 */
    term1 = cuddBddAndRecur(dd, x, Isub1);
    if (term1 == NULL) {
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	Cudd_RecursiveDeref(dd, x);
	Cudd_RecursiveDeref(dd, term0);
	return(NULL);
    }
    Cudd_Ref(term1);
    Cudd_RecursiveDeref(dd, x);
    Cudd_RecursiveDeref(dd, Isub1);
    /* sum = term0 + term1 */
    sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
    if (sum == NULL) {
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	Cudd_RecursiveDeref(dd, term0);
	Cudd_RecursiveDeref(dd, term1);
	return(NULL);
    }
    sum = Cudd_Not(sum);
    Cudd_Ref(sum);
    Cudd_RecursiveDeref(dd, term0);
    Cudd_RecursiveDeref(dd, term1);
    /* r = sum + Id */
    r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
    r = Cudd_NotCond(r, r != NULL);
    if (r == NULL) {
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	Cudd_RecursiveDeref(dd, sum);
	return(NULL);
    }
    Cudd_Ref(r);
    Cudd_RecursiveDeref(dd, sum);
    Cudd_RecursiveDeref(dd, Id);

    if (zdd_Isub0 != zdd_zero) {
	z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id);
	if (z == NULL) {
	    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	    Cudd_RecursiveDerefZdd(dd, zdd_Id);
	    Cudd_RecursiveDeref(dd, r);
	    return(NULL);
	}
    }
    else {
	z = zdd_Id;
    }
    Cudd_Ref(z);
    if (zdd_Isub1 != zdd_zero) {
	y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z);
	if (y == NULL) {
	    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	    Cudd_RecursiveDerefZdd(dd, zdd_Id);
	    Cudd_RecursiveDeref(dd, r);
	    Cudd_RecursiveDerefZdd(dd, z);
	    return(NULL);
	}
    }
    else
	y = z;
    Cudd_Ref(y);

    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
    Cudd_RecursiveDerefZdd(dd, zdd_Id);
    Cudd_RecursiveDerefZdd(dd, z);

    cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
    cuddCacheInsert2(dd, cacheOp, L, U, y);

    Cudd_Deref(r);
    Cudd_Deref(y);
    *zdd_I = y;
    /*
    if (Cudd_Regular(r)->index != y->index / 2) {
	printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n");
    }
    */
    return(r);

} /* end of cuddZddIsop */
Exemple #30
0
ABC_NAMESPACE_IMPL_START


/*---------------------------------------------------------------------------*/
/* Constant declarations                                                     */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Stucture declarations                                                     */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Type declarations                                                         */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Variable declarations                                                     */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Macro declarations                                                        */
/*---------------------------------------------------------------------------*/

#define DD_GET_SYMM_VARS_TAG          0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */

/**AutomaticStart*************************************************************/

/*---------------------------------------------------------------------------*/
/* Static function prototypes                                                */
/*---------------------------------------------------------------------------*/

/**AutomaticEnd***************************************************************/

/*---------------------------------------------------------------------------*/
/* Definition of exported functions                                          */
/*---------------------------------------------------------------------------*/

/**Function********************************************************************

  Synopsis    [Computes the classical symmetry information for the function.]

  Description [Returns the symmetry information in the form of Extra_SymmInfo_t structure.]

  SideEffects [If the ZDD variables are not derived from BDD variables with
  multiplicity 2, this function may derive them in a wrong way.]

  SeeAlso     []

******************************************************************************/
Extra_SymmInfo_t * Extra_SymmPairsCompute( 
  DdManager * dd,   /* the manager */
  DdNode * bFunc)   /* the function whose symmetries are computed */
{
    DdNode * bSupp;
    DdNode * zRes;
    Extra_SymmInfo_t * p;

    bSupp = Cudd_Support( dd, bFunc );                      Cudd_Ref( bSupp );
    zRes  = Extra_zddSymmPairsCompute( dd, bFunc, bSupp );  Cudd_Ref( zRes );

    p = Extra_SymmPairsCreateFromZdd( dd, zRes, bSupp );

    Cudd_RecursiveDeref( dd, bSupp );
    Cudd_RecursiveDerefZdd( dd, zRes );

    return p;

} /* end of Extra_SymmPairsCompute */