/**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 */
/** @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 */
/** @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 */
/**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 */
/**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 */
/**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 */
/**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 */
/**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 */
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; }