/** * @brief Basic test of arbitrary-precision arithmetic. * @return 0 if successful; -1 otherwise. */ static int testApa(int verbosity) { if (verbosity) { printf("DD_APA_BITS = %" PRIszt "\n", sizeof(DdApaDigit) * 8); } DdApaNumber an = Cudd_NewApaNumber(3); Cudd_ApaSetToLiteral(3, an, (DdApaDigit) 0x0fa5); Cudd_ApaAdd(3, an, an, an); if (verbosity) { Cudd_ApaPrintHex(stdout, 3, an); printf("\n"); } DdApaDigit numbers[] = {1283805, 1283815, 15983557, 1598354, 15999999}; size_t i; for (i = 0; i < sizeof(numbers)/sizeof(DdApaDigit); i++) { Cudd_ApaSetToLiteral(3, an, numbers[i]); if (verbosity) { Cudd_ApaPrintDecimal(stdout, 3, an); printf(" -> "); Cudd_ApaPrintExponential(stdout, 3, an, 6); printf("\n"); } } Cudd_FreeApaNumber(an); return 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 */