/**Function******************************************************************** Synopsis [Finds the minimum discriminant of f.] Description [Returns a pointer to a constant ADD.] SideEffects [None] ******************************************************************************/ DdNode * Cudd_addFindMin( DdManager * dd, DdNode * f) { DdNode *t, *e, *res; statLine(dd); if (cuddIsConstant(f)) { return(f); } res = cuddCacheLookup1(dd,Cudd_addFindMin,f); if (res != NULL) { return(res); } t = Cudd_addFindMin(dd,cuddT(f)); if (t == DD_MINUS_INFINITY(dd)) return(t); e = Cudd_addFindMin(dd,cuddE(f)); res = (cuddV(t) <= cuddV(e)) ? t : e; cuddCacheInsert1(dd,Cudd_addFindMin,f,res); return(res); } /* end of Cudd_addFindMin */
/**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 */