Exemplo n.º 1
0
/**Function********************************************************************

  Synopsis    [Calculates the product of two matrices represented as
  ADDs.]

  Description [Calculates the product of two matrices, A and B,
  represented as ADDs, using the CMU matrix by matrix multiplication
  procedure by Clarke et al..  Matrix A has x's as row variables and z's
  as column variables, while matrix B has z's as row variables and y's
  as column variables. Returns the pointer to the result if successful;
  NULL otherwise. The resulting matrix has x's as row variables and y's
  as column variables.]

  SideEffects [None]

  SeeAlso     [Cudd_addMatrixMultiply]

******************************************************************************/
DdNode *
Cudd_addTimesPlus(
  DdManager * dd,
  DdNode * A,
  DdNode * B,
  DdNode ** z,
  int  nz)
{
    DdNode *w, *cube, *tmp, *res; 
    int i;
    tmp = Cudd_addApply(dd,Cudd_addTimes,A,B);
    if (tmp == NULL) return(NULL);
    Cudd_Ref(tmp);
    Cudd_Ref(cube = DD_ONE(dd));
    for (i = nz-1; i >= 0; i--) {
	 w = Cudd_addIte(dd,z[i],cube,DD_ZERO(dd));
	 if (w == NULL) {
	    Cudd_RecursiveDeref(dd,tmp);
	    return(NULL);
	 }
	 Cudd_Ref(w);
	 Cudd_RecursiveDeref(dd,cube);
	 cube = w;
    }
    res = Cudd_addExistAbstract(dd,tmp,cube);
    if (res == NULL) {
	Cudd_RecursiveDeref(dd,tmp);
	Cudd_RecursiveDeref(dd,cube);
	return(NULL);
    }
    Cudd_Ref(res);
    Cudd_RecursiveDeref(dd,cube);
    Cudd_RecursiveDeref(dd,tmp);
    Cudd_Deref(res);
    return(res);

} /* end of Cudd_addTimesPlus */
Exemplo n.º 2
0
/**
  @brief Implements the recursive step of Cudd_addWalsh.

  @return a pointer to the matrixi if successful; NULL otherwise.

  @sideeffect None

  @see Cudd_addWalsh

*/
static DdNode *
addWalshInt(
  DdManager * dd,
  DdNode ** x,
  DdNode ** y,
  int  n)
{
    DdNode *one, *minusone;
    DdNode *t = NULL, *u, *t1, *u1, *v, *w;
    int     i;

    one = DD_ONE(dd);
    if (n == 0) return(one);

    /* Build bottom part of ADD outside loop */
    minusone = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) -1);
    if (minusone == NULL) return(NULL);
    cuddRef(minusone);
    v = Cudd_addIte(dd, y[n-1], minusone, one);
    if (v == NULL) {
	Cudd_RecursiveDeref(dd, minusone);
	return(NULL);
    }
    cuddRef(v);
    u = Cudd_addIte(dd, x[n-1], v, one);
    if (u == NULL) {
	Cudd_RecursiveDeref(dd, minusone);
	Cudd_RecursiveDeref(dd, v);
	return(NULL);
    }
    cuddRef(u);
    Cudd_RecursiveDeref(dd, v);
    if (n>1) {
	w = Cudd_addIte(dd, y[n-1], one, minusone);
	if (w == NULL) {
	    Cudd_RecursiveDeref(dd, minusone);
	    Cudd_RecursiveDeref(dd, u);
	    return(NULL);
	}
	cuddRef(w);
	t = Cudd_addIte(dd, x[n-1], w, minusone);
	if (t == NULL) {
	    Cudd_RecursiveDeref(dd, minusone);
	    Cudd_RecursiveDeref(dd, u);
	    Cudd_RecursiveDeref(dd, w);
	    return(NULL);
	}
	cuddRef(t);
	Cudd_RecursiveDeref(dd, w);
    }
    cuddDeref(minusone); /* minusone is in the result; it won't die */

    /* Loop to build the rest of the ADD */
    for (i=n-2; i>=0; i--) {
	t1 = t; u1 = u;
	v = Cudd_addIte(dd, y[i], t1, u1);
	if (v == NULL) {
	    Cudd_RecursiveDeref(dd, u1);
	    Cudd_RecursiveDeref(dd, t1);
	    return(NULL);
	}
	cuddRef(v);
	u = Cudd_addIte(dd, x[i], v, u1);
	if (u == NULL) {
	    Cudd_RecursiveDeref(dd, u1);
	    Cudd_RecursiveDeref(dd, t1);
	    Cudd_RecursiveDeref(dd, v);
	    return(NULL);
	}
	cuddRef(u);
	Cudd_RecursiveDeref(dd, v);
	if (i>0) {
	    w = Cudd_addIte(dd, y[i], u1, t1);
	    if (w == NULL) {
		Cudd_RecursiveDeref(dd, u1);
		Cudd_RecursiveDeref(dd, t1);
		Cudd_RecursiveDeref(dd, u);
		return(NULL);
	    }
	    cuddRef(w);
	    t = Cudd_addIte(dd, x[i], w, t1);
	    if (u == NULL) {
		Cudd_RecursiveDeref(dd, u1);
		Cudd_RecursiveDeref(dd, t1);
		Cudd_RecursiveDeref(dd, u);
		Cudd_RecursiveDeref(dd, w);
		return(NULL);
	    }
	    cuddRef(t);
	    Cudd_RecursiveDeref(dd, w);
	}
	Cudd_RecursiveDeref(dd, u1);
	Cudd_RecursiveDeref(dd, t1);
    }

    cuddDeref(u);
    return(u);

} /* end of addWalshInt */
Exemplo n.º 3
0
/**
  @brief Builds an %ADD for the residue modulo m of an n-bit
  number.

  @details The modulus must be at least 2, and the number of bits at
  least 1. Parameter options specifies whether the MSB should be on top
  or the LSB; and whther the number whose residue is computed is in
  two's complement notation or not. The macro CUDD_RESIDUE_DEFAULT
  specifies LSB on top and unsigned number. The macro CUDD_RESIDUE_MSB
  specifies MSB on top, and the macro CUDD_RESIDUE_TC specifies two's
  complement residue. To request MSB on top and two's complement residue
  simultaneously, one can OR the two macros:
  CUDD_RESIDUE_MSB | CUDD_RESIDUE_TC.

  @return a pointer to the resulting %ADD if successful; NULL
  otherwise.

  @sideeffect None

*/
DdNode *
Cudd_addResidue(
  DdManager * dd /**< manager */,
  int  n /**< number of bits */,
  int  m /**< modulus */,
  int  options /**< options */,
  int  top /**< index of top variable */)
{
    int msbLsb;	/* MSB on top (1) or LSB on top (0) */
    int tc;	/* two's complement (1) or unsigned (0) */
    int i, j, k, t, residue, thisOne, previous, index;
    DdNode **array[2], *var, *tmp, *res;

    /* Sanity check. */
    if (n < 1 && m < 2) return(NULL);

    msbLsb = options & CUDD_RESIDUE_MSB;
    tc = options & CUDD_RESIDUE_TC;

    /* Allocate and initialize working arrays. */
    array[0] = ALLOC(DdNode *,m);
    if (array[0] == NULL) {
	dd->errorCode = CUDD_MEMORY_OUT;
	return(NULL);
    }
    array[1] = ALLOC(DdNode *,m);
    if (array[1] == NULL) {
	FREE(array[0]);
	dd->errorCode = CUDD_MEMORY_OUT;
	return(NULL);
    }
    for (i = 0; i < m; i++) {
	array[0][i] = array[1][i] = NULL;
    }

    /* Initialize residues. */
    for (i = 0; i < m; i++) {
	tmp = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) i);
	if (tmp == NULL) {
	    for (j = 0; j < i; j++) {
		Cudd_RecursiveDeref(dd,array[1][j]);
	    }
	    FREE(array[0]);
	    FREE(array[1]);
	    return(NULL);
	}
	cuddRef(tmp);
	array[1][i] = tmp;
    }

    /* Main iteration. */
    residue = 1;	/* residue of 2**0 */
    for (k = 0; k < n; k++) {
	/* Choose current and previous arrays. */
	thisOne = k & 1;
	previous = thisOne ^ 1;
	/* Build an ADD projection function. */
	if (msbLsb) {
	    index = top+n-k-1;
	} else {
	    index = top+k;
	}
	var = cuddUniqueInter(dd,index,DD_ONE(dd),DD_ZERO(dd));
	if (var == NULL) {
	    for (j = 0; j < m; j++) {
		Cudd_RecursiveDeref(dd,array[previous][j]);
	    }
	    FREE(array[0]);
	    FREE(array[1]);
	    return(NULL);
	}
	cuddRef(var);
	for (i = 0; i < m; i ++) {
	    t = (i + residue) % m;
	    tmp = Cudd_addIte(dd,var,array[previous][t],array[previous][i]);
	    if (tmp == NULL) {
		for (j = 0; j < i; j++) {
		    Cudd_RecursiveDeref(dd,array[thisOne][j]);
		}
		for (j = 0; j < m; j++) {
		    Cudd_RecursiveDeref(dd,array[previous][j]);
		}
		FREE(array[0]);
		FREE(array[1]);
		return(NULL);
	    }
	    cuddRef(tmp);
	    array[thisOne][i] = tmp;
	}
	/* One layer completed. Free the other array for the next iteration. */
	for (i = 0; i < m; i++) {
	    Cudd_RecursiveDeref(dd,array[previous][i]);
	}
	Cudd_RecursiveDeref(dd,var);
	/* Update residue of 2**k. */
	residue = (2 * residue) % m;
	/* Adjust residue for MSB, if this is a two's complement number. */
	if (tc && (k == n - 1)) {
	    residue = (m - residue) % m;
	}
    }

    /* We are only interested in the 0-residue node of the top layer. */
    for (i = 1; i < m; i++) {
	Cudd_RecursiveDeref(dd,array[(n - 1) & 1][i]);
    }
    res = array[(n - 1) & 1][0];

    FREE(array[0]);
    FREE(array[1]);

    cuddDeref(res);
    return(res);

} /* end of Cudd_addResidue */
Exemplo n.º 4
0
/**Function********************************************************************

  Synopsis    [Generates an ADD for the function x==y.]

  Description [This function generates an ADD for the function x==y.
  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
  The ADD is built bottom-up.
  It has 3*N-1 internal nodes, if the variables are ordered as follows: 
  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ]

  SideEffects [None]

  SeeAlso     [Cudd_Xeqy]

******************************************************************************/
DdNode *
Cudd_addXeqy(
  DdManager * dd /* DD manager */,
  int  N /* number of x and y variables */,
  DdNode ** x /* array of x variables */,
  DdNode ** y /* array of y variables */)
{
    DdNode *one, *zero;
    DdNode *u, *v, *w;
    int     i;

    one = DD_ONE(dd);
    zero = DD_ZERO(dd);

    /* Build bottom part of ADD outside loop. */
    v = Cudd_addIte(dd, y[N-1], one, zero);
    if (v == NULL) return(NULL);
    cuddRef(v);
    w = Cudd_addIte(dd, y[N-1], zero, one);
    if (w == NULL) {
	Cudd_RecursiveDeref(dd, v);
	return(NULL);
    }
    cuddRef(w);
    u = Cudd_addIte(dd, x[N-1], v, w);
    if (w == NULL) {
	Cudd_RecursiveDeref(dd, v);
	Cudd_RecursiveDeref(dd, w);
	return(NULL);
    }
    cuddRef(u);
    Cudd_RecursiveDeref(dd, v);
    Cudd_RecursiveDeref(dd, w);

    /* Loop to build the rest of the ADD. */
    for (i = N-2; i >= 0; i--) {
	v = Cudd_addIte(dd, y[i], u, zero);
	if (v == NULL) {
	    Cudd_RecursiveDeref(dd, u);
	    return(NULL);
	}
	cuddRef(v);
	w = Cudd_addIte(dd, y[i], zero, u);
	if (w == NULL) {
	    Cudd_RecursiveDeref(dd, u);
	    Cudd_RecursiveDeref(dd, v);
	    return(NULL);
	}
	cuddRef(w);
	Cudd_RecursiveDeref(dd, u);
	u = Cudd_addIte(dd, x[i], v, w);
	if (w == NULL) {
	    Cudd_RecursiveDeref(dd, v);
	    Cudd_RecursiveDeref(dd, w);
	    return(NULL);
	}
	cuddRef(u);
	Cudd_RecursiveDeref(dd, v);
	Cudd_RecursiveDeref(dd, w);
    }
    cuddDeref(u);
    return(u);

} /* end of Cudd_addXeqy */
Exemplo n.º 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 */
Exemplo n.º 6
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 */
Exemplo n.º 7
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 */
Exemplo n.º 8
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 */
Exemplo n.º 9
0
ref_t shadow_ite(shadow_mgr mgr, ref_t iref, ref_t tref, ref_t eref) {
    DdNode *in = get_ddnode(mgr, iref);
    DdNode *tn = get_ddnode(mgr, tref);
    DdNode *en = get_ddnode(mgr, eref);
    DdNode *n = NULL;
    ref_t r = REF_INVALID;
    dd_type_t dtype = IS_BDD;

    if (mgr->do_local) {
	r = ref_ite(mgr->ref_mgr, iref, tref, eref);
    }
    if (mgr->do_dist) {
	ref_t rdist = dist_ite(mgr->ref_mgr, iref, tref, eref);
	if (mgr->do_local) {
	    if (!check_refs(mgr, r, rdist)) {
		return REF_INVALID;
	    }
	} else {
	    r = rdist;
	}
    }

    if (mgr->do_cudd) {

	if (mgr->nzvars > 0) {
	    bool zi = is_zdd(mgr, iref);
	    bool zt = is_zdd(mgr, tref);
	    bool ze = is_zdd(mgr, eref);
	    if (zi || zt || ze) {
		dtype = IS_ZDD;
		if (is_add(mgr, iref) || is_add(mgr, tref) || is_add(mgr, eref)) {
		    err(false, "Can't mix ADDs with ZDDs");
		}
		if (!zi) {
		    in = zconvert(mgr, in);
		}
		if (!zt) {
		    tn = zconvert(mgr, tn);
		}
		if (!ze) {
		    en = zconvert(mgr, en);
		}
		n = Cudd_zddIte(mgr->bdd_manager, in, tn, en);
		reference_dd(mgr, n);
		if (!zi)
		    unreference_dd(mgr, in, IS_ZDD);
		if (!zt)
		    unreference_dd(mgr, tn, IS_ZDD);
		if (!ze)
		    unreference_dd(mgr, en, IS_ZDD);
	    }
	}
	{
	    bool ai = is_add(mgr, iref);
	    bool at = is_add(mgr, tref);
	    bool ae = is_add(mgr, eref);

	    if (ai || at || ae) {
		dtype = IS_ADD;
		if (!ai) {
		    in = aconvert(mgr, in);
		}
		if (!at) {
		    tn = aconvert(mgr, tn);
		}
		if (!ae) {
		    en = aconvert(mgr, en);
		}
		n = Cudd_addIte(mgr->bdd_manager, in, tn, en);
		reference_dd(mgr, n);
		if (!ai)
		    unreference_dd(mgr, in, IS_ADD);
		if (!at)
		    unreference_dd(mgr, tn, IS_ADD);
		if (!ae)
		    unreference_dd(mgr, en, IS_ADD);
	    }
	}
	if (dtype == IS_BDD) {
	    n = Cudd_bddIte(mgr->bdd_manager, in, tn, en);
	    reference_dd(mgr, n);
	}
    } else {
	n = ref2dd(mgr, r);
    }
    if (!do_ref(mgr))
	r = dd2ref(n, dtype);
    add_ref(mgr, r, n);
    return r;
}