You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1581 lines
56 KiB

  1. /**CFile***********************************************************************
  2. FileName [ntrMflow.c]
  3. PackageName [ntr]
  4. Synopsis [Symbolic maxflow algorithm.]
  5. Description [This file contains the functions that implement the
  6. symbolic version of Dinits's maxflow algorithm described in the
  7. ICCAD93 paper. The present implementation differs from the algorithm
  8. described in the paper in that more than one matching techniques is
  9. used. The technique of the paper is the one applied to
  10. hourglass-type bilayers here.]
  11. Author [Fabio Somenzi, Gary Hachtel]
  12. Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
  13. All rights reserved.
  14. Redistribution and use in source and binary forms, with or without
  15. modification, are permitted provided that the following conditions
  16. are met:
  17. Redistributions of source code must retain the above copyright
  18. notice, this list of conditions and the following disclaimer.
  19. Redistributions in binary form must reproduce the above copyright
  20. notice, this list of conditions and the following disclaimer in the
  21. documentation and/or other materials provided with the distribution.
  22. Neither the name of the University of Colorado nor the names of its
  23. contributors may be used to endorse or promote products derived from
  24. this software without specific prior written permission.
  25. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  26. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  27. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  28. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  29. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  30. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  31. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  32. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  33. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  35. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. POSSIBILITY OF SUCH DAMAGE.]
  37. ******************************************************************************/
  38. #include "ntr.h"
  39. /*---------------------------------------------------------------------------*/
  40. /* Constant declarations */
  41. /*---------------------------------------------------------------------------*/
  42. #define MAXPHASE 1000
  43. #define MAXLAYER 1000
  44. #define MAXFPIT 100000
  45. #define MANY_TIMES 3.0
  46. #define PRUNE /* If defined, enables pruning of E */
  47. /*---------------------------------------------------------------------------*/
  48. /* Stucture declarations */
  49. /*---------------------------------------------------------------------------*/
  50. /*---------------------------------------------------------------------------*/
  51. /* Type declarations */
  52. /*---------------------------------------------------------------------------*/
  53. typedef struct flowStatsStruct {
  54. int pr; /* level of verbosity */
  55. long start_time; /* cpu time when the covering started */
  56. int phases; /* number of phases */
  57. int layers; /* number of layers */
  58. int fpit; /* number of fixed point iterations */
  59. } flowStats;
  60. /*---------------------------------------------------------------------------*/
  61. /* Variable declarations */
  62. /*---------------------------------------------------------------------------*/
  63. #ifndef lint
  64. static char rcsid[] UTIL_UNUSED = "$Id: ntrMflow.c,v 1.8 2012/02/05 01:53:01 fabio Exp fabio $";
  65. #endif
  66. static DdNode *xcube, *ycube, *zcube;
  67. /*---------------------------------------------------------------------------*/
  68. /* Macro declarations */
  69. /*---------------------------------------------------------------------------*/
  70. /**AutomaticStart*************************************************************/
  71. /*---------------------------------------------------------------------------*/
  72. /* Static function prototypes */
  73. /*---------------------------------------------------------------------------*/
  74. static void maximal_pull (DdManager *bdd, int l, DdNode *ty, DdNode **neW, DdNode **U, DdNode *E, DdNode **F, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats);
  75. static void propagate_maximal_flow (DdManager *bdd, int m, DdNode **neW, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats);
  76. static void trellis (DdManager *bdd, int m, DdNode **neW, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats);
  77. static void rhombus (DdManager *bdd, int m, DdNode **neW, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats);
  78. static void hourglass (DdManager *bdd, int m, DdNode **neW, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats);
  79. static void maximal_push (DdManager *bdd, int l, DdNode **U, DdNode **F, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats);
  80. static void trellisPush (DdManager *bdd, int m, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats);
  81. static void rhombusPush (DdManager *bdd, int m, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats);
  82. static void hourglassPush (DdManager *bdd, int m, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats);
  83. /**AutomaticEnd***************************************************************/
  84. /*---------------------------------------------------------------------------*/
  85. /* Definition of exported functions */
  86. /*---------------------------------------------------------------------------*/
  87. /**Function********************************************************************
  88. Synopsis []
  89. Description [This function implements Dinits's algorithm for (0-1)
  90. max flow, using BDDs and a symbolic technique to trace multiple
  91. edge-disjoint augmenting paths to complete a phase. The outer
  92. forever loop is over phases, and the inner forever loop is to
  93. propagate a (not yet) maximal flow of edge-disjoint augmenting paths
  94. from one layer to the previous. The subprocedure call implements a
  95. least fixed point iteration to compute a (not yet) maximal flow
  96. update between layers. At the end of each phase (except the last
  97. one) the flow is actually pushed from the source to the sink.
  98. Data items:
  99. <ul>
  100. <li> sx(ty) BDD representations of s(t).
  101. <li> x(y) The variables encoding the from(to)-node u(v) of an
  102. edge (u,v) in the given digraph.
  103. <li> z Another set of variables.
  104. <li> E(x,y) The edge relation.
  105. <li> F(x,y) BDD representation of the current flow, initialized to 0
  106. for each arc, and updated by +1, -1, or 0 at the
  107. end of each phase.
  108. <li> Ms Mt The maximum flow, that is, the cardinality of a minimum cut,
  109. measured at the source and at the sink, respectively.
  110. The two values should be identical.
  111. <li> reached The set of nodes already visited in the BFS of the digraph.
  112. <li> fos fanout of the source node s.
  113. <li> fit fanin of the sink node t.
  114. </ul>
  115. ]
  116. SideEffects [The flow realtion F and the cutset relation cut are returned
  117. as side effects.]
  118. SeeAlso []
  119. ******************************************************************************/
  120. double
  121. Ntr_maximum01Flow(
  122. DdManager * bdd /* manager */,
  123. DdNode * sx /* source node */,
  124. DdNode * ty /* sink node */,
  125. DdNode * E /* edge relation */,
  126. DdNode ** F /* flow relation */,
  127. DdNode ** cut /* cutset relation */,
  128. DdNode ** x /* array of row variables */,
  129. DdNode ** y /* array of column variables */,
  130. DdNode ** z /* arrays of auxiliary variables */,
  131. int n /* number of variables in each array */,
  132. int pr /* verbosity level */)
  133. {
  134. flowStats stats;
  135. DdNode *one, *zero,
  136. #ifdef PRUNE
  137. *EDC, /* Edge don't care set */
  138. #endif
  139. *reached, /* states reached through useful edges */
  140. *fos, *fit, /* fanout of source, fanin of sink */
  141. *rF, *rB, *tx,
  142. *I, *P,
  143. *w, *p, *q, *r,/* intemediate results */
  144. *pryz, *prxz, /* priority functions for disjoint path tracing */
  145. **neW, **U; /* arrays of BDDs for flow propagation */
  146. int i, j, l;
  147. double Ms, Mt;
  148. /* Initialize debugging structure. */
  149. stats.pr = pr;
  150. stats.start_time = util_cpu_time();
  151. stats.phases = 0;
  152. stats.layers = 0;
  153. stats.fpit = 0;
  154. /* Allocate arrays for new (just reached vertex sets)
  155. ** and U (useful edge sets).
  156. */
  157. U = ALLOC(DdNode *, ((unsigned) MAXLAYER));
  158. neW = ALLOC(DdNode *, ((unsigned) MAXLAYER));
  159. one = Cudd_ReadOne(bdd);
  160. zero = Cudd_Not(one);
  161. /* Initialize xcube, ycube, and zcube (for abstractions). */
  162. Cudd_Ref(xcube = Cudd_bddComputeCube(bdd,x,NULL,n));
  163. Cudd_Ref(ycube = Cudd_bddComputeCube(bdd,y,NULL,n));
  164. Cudd_Ref(zcube = Cudd_bddComputeCube(bdd,z,NULL,n));
  165. /* Build the BDD for the priority functions. */
  166. Cudd_Ref(pryz = Cudd_Dxygtdxz(bdd, n, x, y, z));
  167. Cudd_Ref(prxz = Cudd_Dxygtdyz(bdd, n, x, y, z));
  168. /* Now "randomize" by shuffling the x variables in pryz and the y
  169. ** variables in prxz.
  170. */
  171. Cudd_Ref(p = Cudd_bddAdjPermuteX(bdd,pryz,x,n));
  172. Cudd_RecursiveDeref(bdd,pryz);
  173. pryz = p;
  174. if(pr>2){(void) fprintf(stdout,"pryz");Cudd_PrintDebug(bdd,pryz,n*3,pr);}
  175. Cudd_Ref(p = Cudd_bddAdjPermuteX(bdd,prxz,y,n));
  176. Cudd_RecursiveDeref(bdd,prxz);
  177. prxz = p;
  178. if(pr>2){(void) fprintf(stdout,"prxz");Cudd_PrintDebug(bdd,prxz,n*3,pr);}
  179. #ifdef PRUNE
  180. /* Build the edge don't care set and prune E. The edge don't care
  181. ** set consists of the edges into the source(s), the edges out of the
  182. ** sink(s), and the self-loops. These edges cannot contribute to the
  183. ** maximum flow.
  184. */
  185. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, sx, x, y, n));
  186. Cudd_Ref(q = Cudd_bddSwapVariables(bdd, ty, x, y, n));
  187. Cudd_Ref(r = Cudd_bddOr(bdd, p, q));
  188. Cudd_RecursiveDeref(bdd,p);
  189. Cudd_RecursiveDeref(bdd,q);
  190. Cudd_Ref(p = Cudd_Xeqy(bdd, n, x, y));
  191. Cudd_Ref(EDC = Cudd_bddOr(bdd, p, r));
  192. Cudd_RecursiveDeref(bdd,p);
  193. Cudd_RecursiveDeref(bdd,r);
  194. if(pr>2){(void) fprintf(stdout,"EDC");Cudd_PrintDebug(bdd,EDC,n<<1,pr);}
  195. Cudd_Ref(p = Cudd_bddAnd(bdd, E, Cudd_Not(EDC)));
  196. Cudd_RecursiveDeref(bdd,EDC);
  197. if(pr>0){(void) fprintf(stdout,"Given E");Cudd_PrintDebug(bdd,E,n<<1,pr);}
  198. E = p;
  199. if(pr>0){(void) fprintf(stdout,"Pruned E");Cudd_PrintDebug(bdd,E,n<<1,pr);}
  200. #endif
  201. /* Compute fanin of sink node t: it is an upper bound for the flow. */
  202. Cudd_Ref(fit = Cudd_bddAnd(bdd, E, ty));
  203. if (pr>2) {
  204. /* Compute fanout of source node s. */
  205. Cudd_Ref(fos = Cudd_bddAnd(bdd, E, sx));
  206. (void) fprintf(stdout,"fos");Cudd_PrintDebug(bdd,fos,n<<1,pr);
  207. Cudd_RecursiveDeref(bdd,fos);
  208. (void) fprintf(stdout,"fit");Cudd_PrintDebug(bdd,fit,n<<1,pr);
  209. }
  210. /* t(x) is used to check for termination of forward traversal. */
  211. Cudd_Ref(tx = Cudd_bddSwapVariables(bdd, ty, x, y, n));
  212. /* \KW{Procedure}\ \ \PC{maximum\_flow}$(s,t,E(x,y)) */
  213. Cudd_Ref(*F = zero);
  214. for (i = 1; i < MAXPHASE; i++) {
  215. stats.phases++;
  216. if(pr>0){(void) fprintf(stdout,"## Starting Phase %d at time = %s\n",i,
  217. util_print_time(util_cpu_time() - stats.start_time));}
  218. /* new[0](x) = s(x);U^0(x,y)=E(x,y)\cdot s(x) \cdot \overline{F(x,y)};
  219. ** reached=s; new[1](x)=\exists_xU^0(x,y);
  220. */
  221. Cudd_Ref(neW[0] = sx);
  222. Cudd_Ref(p = Cudd_bddAnd(bdd, sx, Cudd_Not(*F)));
  223. Cudd_Ref(U[0] = Cudd_bddAnd(bdd, p, E));
  224. Cudd_RecursiveDeref(bdd,p);
  225. Cudd_Ref(reached = sx);
  226. Cudd_Ref(r = Cudd_bddExistAbstract(bdd, U[0], xcube));
  227. Cudd_RecursiveDeref(bdd,U[0]);
  228. Cudd_Ref(q = Cudd_bddSwapVariables(bdd, r, x, y, n));
  229. Cudd_RecursiveDeref(bdd,r);
  230. Cudd_Ref(neW[1] = Cudd_bddAnd(bdd, q, Cudd_Not(reached)));
  231. Cudd_RecursiveDeref(bdd,q);
  232. if(pr>0) {
  233. (void) fprintf(stdout,"neW[1]");Cudd_PrintDebug(bdd,neW[1],n,pr);
  234. }
  235. for (l = 1; l < MAXLAYER; l++) {
  236. if (neW[l] == zero) { /* flow is maximum */
  237. /* cut=reached(x) \cdot E(x,y) \cdot \overline{reached(y)} */
  238. Cudd_Ref(p = Cudd_bddAnd(bdd, reached, E));
  239. Cudd_Ref(q = Cudd_bddSwapVariables(bdd, reached, x, y, n));
  240. Cudd_Ref(*cut = Cudd_bddAnd(bdd, p, Cudd_Not(q)));
  241. Cudd_RecursiveDeref(bdd,p);
  242. Cudd_RecursiveDeref(bdd,q);
  243. Cudd_RecursiveDeref(bdd,reached);
  244. for (j = 0; j <= l; j++)
  245. Cudd_RecursiveDeref(bdd,neW[j]);
  246. goto endPhases;
  247. }
  248. /* As soon as we touch one sink node we stop traversal.
  249. ** \KW{if} ($t\cdot new^{l} \neq 0$)
  250. */
  251. if (!Cudd_bddLeq(bdd, tx, Cudd_Not(neW[l]))) {
  252. Cudd_RecursiveDeref(bdd,reached);
  253. maximal_pull(bdd,l-1,ty,neW,U,E,F,x,y,z,n,pryz,prxz,&stats);
  254. goto endLayers;
  255. }
  256. stats.layers++;
  257. if(pr>2){(void) fprintf(stdout,"===== Layer %d =====\n",l);}
  258. /* reached(x) = reached(x) + new^l(x) */
  259. Cudd_Ref(w = Cudd_bddOr(bdd, reached, neW[l]));
  260. Cudd_RecursiveDeref(bdd,reached);
  261. reached = w;
  262. /* I(y) = \exists_x((E(x,y) \cdot \overline{F(x,y)})
  263. ** \cdot new^l(x))
  264. */
  265. Cudd_Ref(p = Cudd_bddAnd(bdd, E, Cudd_Not(*F)));
  266. Cudd_Ref(I = Cudd_bddAndAbstract(bdd, p, neW[l], xcube));
  267. if(pr>3){(void) fprintf(stdout,"I");Cudd_PrintDebug(bdd,I,n,pr);}
  268. Cudd_RecursiveDeref(bdd,p);
  269. /* rF(x)= I(x) \cdot \overline{reached(x)}) */
  270. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, I, x, y, n));
  271. Cudd_RecursiveDeref(bdd,I);
  272. Cudd_Ref(rF = Cudd_bddAnd(bdd, p, Cudd_Not(reached)));
  273. Cudd_RecursiveDeref(bdd,p);
  274. if(pr>2){(void) fprintf(stdout,"rF");Cudd_PrintDebug(bdd,rF,n,pr);}
  275. /* P(x) = \exists_{y}(F(x,y) \cdot new^l(y)) */
  276. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, neW[l], x, y, n));
  277. Cudd_Ref(P = Cudd_bddAndAbstract(bdd, *F, p, ycube));
  278. Cudd_RecursiveDeref(bdd,p);
  279. /* rB(x) = P(x) \cdot \overline{reached(x)}) */
  280. Cudd_Ref(rB = Cudd_bddAnd(bdd, P, Cudd_Not(reached)));
  281. Cudd_RecursiveDeref(bdd,P);
  282. if(pr>2){(void) fprintf(stdout,"rB");Cudd_PrintDebug(bdd,rB,n,pr);}
  283. /* new^{l+1}(x) = rF(x) + rB(x) */
  284. Cudd_Ref(neW[l+1] = Cudd_bddOr(bdd, rF, rB));
  285. Cudd_RecursiveDeref(bdd,rB);
  286. Cudd_RecursiveDeref(bdd,rF);
  287. if(pr>0) {
  288. (void) fprintf(stdout,"new[%d]",l+1);
  289. Cudd_PrintDebug(bdd,neW[l+1],n,pr);
  290. }
  291. } /* start next layer */
  292. if (l==MAXLAYER) (void) fprintf(stderr,"ERROR! MAXLAYER exceeded.\n");
  293. exit(3);
  294. endLayers:
  295. maximal_push(bdd, l-1, U, F, x, y, z, n, pryz, prxz, &stats);
  296. for (j = 0; j < l; j++) {
  297. Cudd_RecursiveDeref(bdd,U[j]);
  298. Cudd_RecursiveDeref(bdd,neW[j]);
  299. }
  300. Cudd_RecursiveDeref(bdd,neW[l]);
  301. if (pr > 0) {
  302. Cudd_Ref(p = Cudd_bddAnd(bdd, sx, *F));
  303. Ms=Cudd_CountMinterm(bdd, p, n<<1);
  304. (void) fprintf(stdout,"# Flow out of s: %g\n", Ms);
  305. Cudd_RecursiveDeref(bdd,p);
  306. }
  307. if (Cudd_bddLeq(bdd, fit, *F)) {
  308. Cudd_Ref(*cut = fit);
  309. goto endPhases;
  310. }
  311. } /* start next phase */
  312. if (i == MAXPHASE) (void) fprintf(stderr,"ERROR! MAXPHASE exceeded.\n");
  313. /* Last phase is completed --- print flow results. */
  314. endPhases:
  315. Cudd_RecursiveDeref(bdd,tx);
  316. Cudd_Ref(q = Cudd_bddAnd(bdd, *F, sx));
  317. Ms = Cudd_CountMinterm(bdd, q, n<<1);
  318. Cudd_RecursiveDeref(bdd,q);
  319. Cudd_Ref(q = Cudd_bddAnd(bdd, *F, ty));
  320. Mt = Cudd_CountMinterm(bdd, q, n<<1);
  321. Cudd_RecursiveDeref(bdd,q);
  322. if (pr>1) (void) fprintf(stdout,"Mt= %g, Ms= %g \n", Mt, Ms);
  323. if (pr>3){(void) fprintf(stdout,"pryz");Cudd_PrintDebug(bdd,pryz,n*3,pr);}
  324. if (pr>3){(void) fprintf(stdout,"prxz");Cudd_PrintDebug(bdd,prxz,n*3,pr);}
  325. if (pr>0) {
  326. (void) fprintf(stdout,"#### Stats for maximum_flow ####\n");
  327. (void) fprintf(stdout,"%d variables %d of which x[i]\n", Cudd_ReadSize(bdd), n);
  328. (void) fprintf(stdout,"time = %s\n",
  329. util_print_time(util_cpu_time() - stats.start_time));
  330. (void) fprintf(stdout,"phases = %d\n", stats.phases);
  331. (void) fprintf(stdout,"layers = %d\n", stats.layers);
  332. (void) fprintf(stdout,"FP iter. = %d\n", stats.fpit);
  333. }
  334. Cudd_RecursiveDeref(bdd,fit);
  335. Cudd_RecursiveDeref(bdd,pryz);
  336. Cudd_RecursiveDeref(bdd,prxz);
  337. Cudd_RecursiveDeref(bdd,xcube);
  338. Cudd_RecursiveDeref(bdd,ycube);
  339. Cudd_RecursiveDeref(bdd,zcube);
  340. #ifdef PRUNE
  341. Cudd_RecursiveDeref(bdd,E);
  342. #endif
  343. FREE(U);
  344. FREE(neW);
  345. return(Ms);
  346. } /* end of Ntr_maximum01Flow */
  347. /*---------------------------------------------------------------------------*/
  348. /* Definition of internal functions */
  349. /*---------------------------------------------------------------------------*/
  350. /*---------------------------------------------------------------------------*/
  351. /* Definition of static functions */
  352. /*---------------------------------------------------------------------------*/
  353. /**Function********************************************************************
  354. Synopsis [Selects set of edge-disjoint paths from layered network.]
  355. Description [Selects set of edge-disjoint paths from layered
  356. network. maximal_pull is called when the BFS constructing the
  357. layered graph reaches a sink. At this point the new sets of the
  358. BFS have been formed, and we know every vertex in these sets is
  359. reachable from the source vertex (or vertices) s. The new sets are
  360. used to compute the set of useful edges exiting each layer to the
  361. right. In each layer, propagate_maximal_flow is called to select a
  362. maximal subset of these useful edges. This subset is then used to
  363. prune new and U.]
  364. SideEffects [None]
  365. SeeAlso [maximal_push]
  366. ******************************************************************************/
  367. static void
  368. maximal_pull(
  369. DdManager * bdd /* manager */,
  370. int l /* depth of layered network for current phase */,
  371. DdNode * ty /* sink node */,
  372. DdNode ** neW /* array of BFS layers */,
  373. DdNode ** U /* array of useful edges */,
  374. DdNode * E /* edge relation */,
  375. DdNode ** F /* flow relation */,
  376. DdNode ** x,
  377. DdNode ** y,
  378. DdNode ** z /* arrays of variables for rows and columns */,
  379. int n /* number of x variables */,
  380. DdNode * pryz,
  381. DdNode * prxz /* priority functions */,
  382. flowStats * stats)
  383. {
  384. DdNode *p, *q, *r,
  385. *UF, *UB;
  386. int m,
  387. pr; /* Print control */
  388. pr = stats->pr;
  389. /* The useful edges of the last layer are all the empty edges into
  390. ** the sink(s) from new[l].
  391. ** U^{l}(x,y) = t(y)\cdot \overline{F(x,y)}\cdot E(x,y)\cdot new^{l}(x)
  392. */
  393. Cudd_Ref(p = Cudd_bddAnd(bdd, E, Cudd_Not(*F)));
  394. Cudd_Ref(q = Cudd_bddAnd(bdd, neW[l], p));
  395. Cudd_RecursiveDeref(bdd,p);
  396. Cudd_Ref(U[l] = Cudd_bddAnd(bdd, ty, q));
  397. Cudd_RecursiveDeref(bdd,q);
  398. if(pr>1){(void) fprintf(stdout,"U[%d]",l);Cudd_PrintDebug(bdd,U[l],n<<1,pr);}
  399. /* Eliminate from new[l] the states with no paths to the sink(s).
  400. ** new^{l}(x)=\exists_y U^{l}(x,y)
  401. */
  402. Cudd_RecursiveDeref(bdd,neW[l]);
  403. Cudd_Ref(neW[l] = Cudd_bddExistAbstract(bdd, U[l], ycube));
  404. for (m = l; m >= 1; m--) {
  405. /* Find usable backward edges from level m-1 to level m.
  406. ** UB(x,y) = new^{m}(x) \cdot F(x,y) \cdot new^{m-1}(y)
  407. */
  408. Cudd_Ref(r = Cudd_bddSwapVariables(bdd, neW[m-1], x, y, n));
  409. Cudd_Ref(q = Cudd_bddAnd(bdd, r, *F));
  410. Cudd_RecursiveDeref(bdd,r);
  411. Cudd_Ref(UB = Cudd_bddAnd(bdd, neW[m], q));
  412. Cudd_RecursiveDeref(bdd,q);
  413. if(pr>2){(void) fprintf(stdout,"UB");Cudd_PrintDebug(bdd,UB,n<<1,pr);}
  414. /* Find usable forward edges.
  415. ** UF(x,y) = new^{m}(y) \cdot \overline{F(x,y)} \cdot E(x,y)
  416. ** \cdot new^{m-1}(x)
  417. */
  418. Cudd_Ref(p = Cudd_bddAnd(bdd, E, Cudd_Not(*F)));
  419. Cudd_Ref(q = Cudd_bddAnd(bdd, neW[m-1], p));
  420. Cudd_RecursiveDeref(bdd,p);
  421. Cudd_Ref(r = Cudd_bddSwapVariables(bdd, neW[m], x, y, n));
  422. Cudd_Ref(UF = Cudd_bddAnd(bdd, r, q));
  423. Cudd_RecursiveDeref(bdd,q);
  424. Cudd_RecursiveDeref(bdd,r);
  425. if(pr>2){(void) fprintf(stdout,"UF");Cudd_PrintDebug(bdd,UF,n<<1,pr);}
  426. /* U^{m-1}(x,y) = UB(y,x) + UF(x,y) */
  427. Cudd_Ref(r = Cudd_bddSwapVariables(bdd, UB, x, y, n));
  428. Cudd_RecursiveDeref(bdd,UB);
  429. Cudd_Ref(U[m-1] = Cudd_bddOr(bdd, UF, r));
  430. Cudd_RecursiveDeref(bdd,UF);
  431. Cudd_RecursiveDeref(bdd,r);
  432. if(pr>2){(void)fprintf(stdout,"U[%d]",m-1);
  433. Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);}
  434. /* new[m-1](x) = \exists_{y}U^{m-1}(x,y) */
  435. Cudd_RecursiveDeref(bdd,neW[m-1]);
  436. Cudd_Ref(neW[m-1] = Cudd_bddExistAbstract(bdd, U[m-1], ycube));
  437. /* Compute maximal disjoint interlayer edge set. */
  438. propagate_maximal_flow(bdd, m, neW, U, x, y, z, n, pryz, prxz, stats);
  439. if(pr>0) {
  440. (void)fprintf(stdout,"U[%d]",m-1);
  441. Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);
  442. }
  443. } /* prune next layer */
  444. return;
  445. } /* end of maximal_pull */
  446. /**Function********************************************************************
  447. Synopsis [Pulls flow though a layer.]
  448. Description [Pulls flow though a layer. propagate_maximal_flow only
  449. affects U[m-1] and new[m-1]. At the end of this function, the edges
  450. in U[m] are guaranteed to drain all the flow supplied by the edges
  451. in U[m-1]. This effect is obtained by pruning U[m-1]. After the
  452. pruned U[m-1] is computed, new[m-1] is updated to keep track of what
  453. nodes are still useful.
  454. The pruning is performed without actually measuring the in-potential
  455. and the out-potential of each node. Instead, pairs of nodes from U[m-1]
  456. and U[m] are matched. To avoid counting, the procedure computes sets of
  457. paths that connect layer m-1 to layer m+1 and are edge-disjoint.
  458. Two paths from layer m-1 to layer m+1 are disjoint if they have distinct
  459. end-point or if they have distinct middle points. What condition to
  460. enforce depends on the "shape" of the layers.]
  461. SideEffects [Changes U[m-1] and new[m-1]]
  462. SeeAlso [trellis rhombus hourglass]
  463. ******************************************************************************/
  464. static void
  465. propagate_maximal_flow(
  466. DdManager * bdd,
  467. int m /* center of current bilayer */,
  468. DdNode ** neW /* array of reachable or useful nodes */,
  469. DdNode ** U /* array of usable or useful edges */,
  470. DdNode ** x,
  471. DdNode ** y,
  472. DdNode ** z /* arrays of variables for rows and columns */,
  473. int n /* number of x variables */,
  474. DdNode * pryz,
  475. DdNode * prxz /* priority functions */,
  476. flowStats * stats)
  477. {
  478. DdNode *rN;
  479. double mtl, mtc, mtr; /* minterms for left, center, right levels */
  480. int pr; /* print control */
  481. pr = stats->pr;
  482. mtl = Cudd_CountMinterm(bdd, neW[m-1], n);
  483. mtc = Cudd_CountMinterm(bdd, neW[m], n);
  484. /* rN(y) = \exists_x U^{m}(x,y) */
  485. Cudd_Ref(rN = Cudd_bddExistAbstract(bdd, U[m], xcube));
  486. mtr = Cudd_CountMinterm(bdd, rN, n);
  487. Cudd_RecursiveDeref(bdd,rN);
  488. if (pr > 0) {
  489. (void) fprintf(stdout, "layer = %d mtl = %g mtc = %g mtr = %g",
  490. m, mtl, mtc, mtr);
  491. }
  492. if ((mtc > MANY_TIMES * mtl) || (mtc > MANY_TIMES * mtr)) {
  493. if (pr>0) (void) fprintf(stdout, " R\n");
  494. rhombus(bdd, m, neW, U, x, y, z, n, pryz, prxz, stats);
  495. } else if (mtr > MANY_TIMES * mtc) {
  496. if (pr>0) (void) fprintf(stdout, " H\n");
  497. hourglass(bdd, m, neW, U, x, y, z, n, pryz, prxz, stats);
  498. } else {
  499. if (pr>0) (void) fprintf(stdout, " T\n");
  500. trellis(bdd, m, neW, U, x, y, z, n, pryz, prxz, stats);
  501. }
  502. return;
  503. } /* end of propagate_maximal_flow */
  504. /**Function********************************************************************
  505. Synopsis [Selects edges from a trellis-type bilayer.]
  506. Description [Selects edges from a trellis-type bilayer. Used to pull flow.
  507. First a matching is found in the left layer. Then the paths are extended
  508. (if possible) through the right layer. This process is repeated until a
  509. maximal flow is found.]
  510. SideEffects [None]
  511. SeeAlso [rhombus hourglass trellisPush]
  512. ******************************************************************************/
  513. static void
  514. trellis(
  515. DdManager * bdd,
  516. int m /* center level of current bilayer */,
  517. DdNode ** neW /* array of node levels */,
  518. DdNode ** U /* array of edge layers */,
  519. DdNode ** x,
  520. DdNode ** y,
  521. DdNode ** z /* arrays of variables for rows and columns */,
  522. int n /* number of x variables */,
  523. DdNode * pryz,
  524. DdNode * prxz /* priority functions */,
  525. flowStats * stats)
  526. {
  527. DdNode *one, *zero,
  528. *p, *q, *r,
  529. *Uin, /* edges to be matched from U[m-1] */
  530. *Uout, /* edges to be matched from U[m] */
  531. *P,
  532. *LU, *RU, /* left-unique and right-unique sets of edges */
  533. *D,
  534. *Ml, *Mr; /* nodes matched from left and right */
  535. int k,
  536. pr; /* print control */
  537. pr = stats->pr;
  538. one = Cudd_ReadOne(bdd);
  539. zero = Cudd_Not(one);
  540. /*Uout(x,y)=U^m(x,y)*/
  541. Cudd_Ref(Uout = U[m]);
  542. if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
  543. /*Uin(x,y)=U^{m-1}(x,y)*/
  544. Cudd_Ref(Uin = U[m-1]);
  545. if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
  546. for(k = 0; k < MAXFPIT; k++) {
  547. stats->fpit++;
  548. /*LU(x,y)=Uin(x,y)\cdot\overline{\exists_{z}(Uin(z,y)\cdot\Pi(x,z))}*/
  549. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uin, x, z, n));
  550. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, prxz, zcube));
  551. Cudd_RecursiveDeref(bdd,p);
  552. Cudd_Ref(LU = Cudd_bddAnd(bdd, Uin, Cudd_Not(r)));
  553. Cudd_RecursiveDeref(bdd,r);
  554. if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);}
  555. /*D(x,y)= LU(x,y)\cdot \overline{\exists_{z}(LU(x,z)\cdot \Pi(y,z))}*/
  556. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, LU, y, z, n));
  557. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube));
  558. Cudd_RecursiveDeref(bdd,p);
  559. Cudd_Ref(D = Cudd_bddAnd(bdd, LU, Cudd_Not(r)));
  560. Cudd_RecursiveDeref(bdd,r);
  561. Cudd_RecursiveDeref(bdd,LU);
  562. if(pr>3){(void)fprintf(stdout,"D");Cudd_PrintDebug(bdd,D,n<<1,pr);}
  563. /*Ml(y)=\exists_{x}D(x,y)*/
  564. Cudd_Ref(Ml = Cudd_bddExistAbstract(bdd, D, xcube));
  565. if(pr>3){(void)fprintf(stdout,"Ml");Cudd_PrintDebug(bdd,Ml,n,pr);}
  566. /*P(x,y)=Ml(x)\cdot Uout(x,y)*/
  567. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Ml, x, y, n));
  568. Cudd_Ref(P = Cudd_bddAnd(bdd, p, Uout));
  569. Cudd_RecursiveDeref(bdd,p);
  570. Cudd_RecursiveDeref(bdd,Ml);
  571. if(pr>3){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n<<1,pr);}
  572. /*RU(x,y)= P(x,y)\cdot \overline{\exists_{z}(P(x,z)\cdot \Pi(y,z))}*/
  573. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, y, z, n));
  574. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube));
  575. Cudd_RecursiveDeref(bdd,p);
  576. Cudd_Ref(RU = Cudd_bddAnd(bdd, P, Cudd_Not(r)));
  577. Cudd_RecursiveDeref(bdd,r);
  578. Cudd_RecursiveDeref(bdd,P);
  579. if(pr>3){(void)fprintf(stdout,"RU");Cudd_PrintDebug(bdd,RU,n<<1,pr);}
  580. /*Mr(x)=\exists_{y}RU(x,y)*/
  581. Cudd_Ref(Mr = Cudd_bddExistAbstract(bdd, RU, ycube));
  582. if(pr>3){(void)fprintf(stdout,"Mr");Cudd_PrintDebug(bdd,Mr,n,pr);}
  583. /*D(x,y)=D(x,y)\cdot Mr(y)*/
  584. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Mr, x, y, n));
  585. Cudd_RecursiveDeref(bdd,Mr);
  586. Cudd_Ref(q = Cudd_bddAnd(bdd, D, p));
  587. Cudd_RecursiveDeref(bdd,p);
  588. Cudd_RecursiveDeref(bdd,D);
  589. D = q;
  590. if(pr>3){(void)fprintf(stdout,"D");Cudd_PrintDebug(bdd,D,n<<1,pr);}
  591. /*Uin(x,y)=Uin(x,y)-D(x,y)*/
  592. Cudd_Ref(p = Cudd_bddAnd(bdd, Uin, Cudd_Not(D)));
  593. Cudd_RecursiveDeref(bdd,Uin);
  594. Uin = p;
  595. if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
  596. /*Uout(x,y)=Uout(x,y)-RU(x,y)*/
  597. Cudd_Ref(p = Cudd_bddAnd(bdd, Uout, Cudd_Not(RU)));
  598. Cudd_RecursiveDeref(bdd,Uout);
  599. Cudd_RecursiveDeref(bdd,RU);
  600. Uout = p;
  601. if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
  602. /*\KW{if}(($D(x,y)=zero$)~~\KW{or}~~($Uin(x,y)=zero$)~~\KW{or}
  603. ($Uout(x,y)=zero$))~~KW{break}*/
  604. if ((D == zero)||(Uin == zero)||(Uout == zero)) {
  605. Cudd_RecursiveDeref(bdd,D);
  606. break;
  607. }
  608. Cudd_RecursiveDeref(bdd,D);
  609. } /* Next least fixed point iteration with smaller Uin and Uout */
  610. if (k == MAXFPIT) (void) fprintf(stderr,
  611. "Trellis: WARNING! MAXFPIT (%d) exceeded processing Layer %d.\n",
  612. MAXFPIT, m);
  613. if (Uin != zero) {
  614. /* $U^{m-1}(x,y) = U^{m-1}(x,y)-Uin(x,y)$*/
  615. Cudd_Ref(p = Cudd_bddAnd(bdd, U[m-1], Cudd_Not(Uin)));
  616. Cudd_RecursiveDeref(bdd,U[m-1]);
  617. U[m-1] = p;
  618. /* $new^{m-1}(x,y) = \esists_yU^{m-1}(x,y)$*/
  619. Cudd_RecursiveDeref(bdd,neW[m-1]);
  620. Cudd_Ref(neW[m-1] = Cudd_bddExistAbstract(bdd, U[m-1], ycube));
  621. }
  622. if(pr>2){(void)fprintf(stdout,"U[%d]",m-1); Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);}
  623. if(pr>2){(void)fprintf(stdout,"new[%d]",m-1);
  624. Cudd_PrintDebug(bdd,neW[m-1],n,pr);}
  625. Cudd_RecursiveDeref(bdd,Uin);
  626. Cudd_RecursiveDeref(bdd,Uout);
  627. return;
  628. } /* end of trellis */
  629. /**Function********************************************************************
  630. Synopsis [Selects edges from a rhombus-type bilayer.]
  631. Description [Selects edges from a rhombus-type bilayer. Used to pull flow.
  632. Makes the left layer left-unique and the right layer right-unique. Prunes
  633. and repeats until convergence to a maximal flow. It makes sure that all
  634. intermediate points of the two-arc paths are disjoint at each iteration.]
  635. SideEffects [None]
  636. SeeAlso [trellis hourglass rhombusPush]
  637. ******************************************************************************/
  638. static void
  639. rhombus(
  640. DdManager * bdd,
  641. int m /* center of current bilayer */,
  642. DdNode ** neW,
  643. DdNode ** U /* arrays for flow propagation */,
  644. DdNode ** x,
  645. DdNode ** y,
  646. DdNode ** z /* arrays of variables for rows and columns */,
  647. int n /* number of x variables */,
  648. DdNode * pryz,
  649. DdNode * prxz /* priority functions */,
  650. flowStats * stats)
  651. {
  652. DdNode *one, *zero,
  653. *p, *q, *r,
  654. *Uin, /* edges to be matched from U[m-1] */
  655. *Uout, /* edges to be matched from U[m] */
  656. *P,
  657. *LU, *RU, /* left-unique and right-unique sets of edges */
  658. *Ml, *Mr; /* nodes matched from left and right */
  659. int k,
  660. pr; /* print control */
  661. pr = stats->pr;
  662. one = Cudd_ReadOne(bdd);
  663. zero = Cudd_Not(one);
  664. /*Uout(x,y)=U^m(x,y)*/
  665. Cudd_Ref(Uout = U[m]);
  666. if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
  667. /*Uin(x,y)=U^{m-1}(x,y)*/
  668. Cudd_Ref(Uin = U[m-1]);
  669. if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
  670. for(k = 0; k < MAXFPIT; k++) {
  671. stats->fpit++;
  672. /*LU(x,y)=Uin(x,y)\cdot\overline{\exists_{z}(Uin(z,y)\cdot\Pi(x,z))}*/
  673. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uin, x, z, n));
  674. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, prxz, zcube));
  675. Cudd_RecursiveDeref(bdd,p);
  676. Cudd_Ref(LU = Cudd_bddAnd(bdd, Uin, Cudd_Not(r)));
  677. Cudd_RecursiveDeref(bdd,r);
  678. if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);}
  679. /*Ml(y)=\exists_{x}LU(x,y)*/
  680. Cudd_Ref(Ml = Cudd_bddExistAbstract(bdd, LU, xcube));
  681. if(pr>3){(void)fprintf(stdout,"Ml");Cudd_PrintDebug(bdd,Ml,n,pr);}
  682. /*P(x,y)=Ml(x)\cdot Uout(x,y)*/
  683. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Ml, x, y, n));
  684. Cudd_Ref(P = Cudd_bddAnd(bdd, p, Uout));
  685. Cudd_RecursiveDeref(bdd,p);
  686. Cudd_RecursiveDeref(bdd,Ml);
  687. if(pr>3){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n<<1,pr);}
  688. /*RU(x,y)= P(x,y)\cdot \overline{\exists_{z}(P(x,z)\cdot \Pi(y,z))}*/
  689. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, y, z, n));
  690. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube));
  691. Cudd_RecursiveDeref(bdd,p);
  692. Cudd_Ref(RU = Cudd_bddAnd(bdd, P, Cudd_Not(r)));
  693. Cudd_RecursiveDeref(bdd,r);
  694. Cudd_RecursiveDeref(bdd,P);
  695. if(pr>3){(void)fprintf(stdout,"RU");Cudd_PrintDebug(bdd,RU,n<<1,pr);}
  696. /*Mr(x)=\exists_{y}RU(x,y)*/
  697. Cudd_Ref(Mr = Cudd_bddExistAbstract(bdd, RU, ycube));
  698. if(pr>3){(void)fprintf(stdout,"Mr");Cudd_PrintDebug(bdd,Mr,n,pr);}
  699. /*LU(x,y)=LU(x,y)\cdot Mr(y)*/
  700. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Mr, x, y, n));
  701. Cudd_RecursiveDeref(bdd,Mr);
  702. Cudd_Ref(q = Cudd_bddAnd(bdd, LU, p));
  703. Cudd_RecursiveDeref(bdd,p);
  704. Cudd_RecursiveDeref(bdd,LU);
  705. LU = q;
  706. if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);}
  707. /*Uin(x,y)=Uin(x,y)-LU(x,y)*/
  708. Cudd_Ref(p = Cudd_bddAnd(bdd, Uin, Cudd_Not(LU)));
  709. Cudd_RecursiveDeref(bdd,Uin);
  710. Uin = p;
  711. if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
  712. /*Uout(x,y)=Uout(x,y)-RU(x,y)*/
  713. Cudd_Ref(p = Cudd_bddAnd(bdd, Uout, Cudd_Not(RU)));
  714. Cudd_RecursiveDeref(bdd,Uout);
  715. Cudd_RecursiveDeref(bdd,RU);
  716. Uout = p;
  717. if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
  718. /*\KW{if}(($LU(x,y)=zero$)~~\KW{or}~~($Uin(x,y)=zero$)~~\KW{or}
  719. ($Uout(x,y)=zero$))~~KW{break}*/
  720. if((LU == zero)||(Uin == zero)||(Uout == zero)) {
  721. Cudd_RecursiveDeref(bdd,LU);
  722. break;
  723. }
  724. Cudd_RecursiveDeref(bdd,LU);
  725. } /* Next least fixed point iteration with smaller Uin and Uout */
  726. if (k == MAXFPIT) (void) fprintf(stderr,
  727. "Rhombus: WARNING! MAXFPIT (%d) exceeded processing Layer %d.\n",
  728. MAXFPIT, m);
  729. if (Uin != zero) {
  730. /* $U^{m-1}(x,y) = U^{m-1}(x,y)-Uin(x,y)$*/
  731. Cudd_Ref(p = Cudd_bddAnd(bdd, U[m-1], Cudd_Not(Uin)));
  732. Cudd_RecursiveDeref(bdd,U[m-1]);
  733. U[m-1] = p;
  734. /* $new^{m-1}(x,y) = \esists_yU^{m-1}(x,y)$*/
  735. Cudd_RecursiveDeref(bdd,neW[m-1]);
  736. Cudd_Ref(neW[m-1] = Cudd_bddExistAbstract(bdd, U[m-1], ycube));
  737. }
  738. if(pr>2){(void)fprintf(stdout,"U[%d]",m-1); Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);}
  739. if(pr>2){
  740. (void)fprintf(stdout,"new[%d]",m-1);
  741. Cudd_PrintDebug(bdd,neW[m-1],n,pr);
  742. }
  743. Cudd_RecursiveDeref(bdd,Uin);
  744. Cudd_RecursiveDeref(bdd,Uout);
  745. return;
  746. } /* end of rhombus */
  747. /**Function********************************************************************
  748. Synopsis [Selects edges from a hourglass-type bilayer.]
  749. Description [Selects edges from a hourglass-type bilayer. Used to
  750. pull flow. Method described in paper. More general, but more
  751. expensive than the others.]
  752. SideEffects [None]
  753. SeeAlso [trellis rhombus hourglassPush]
  754. ******************************************************************************/
  755. static void
  756. hourglass(
  757. DdManager * bdd,
  758. int m /* center level of current bilayer */,
  759. DdNode ** neW,
  760. DdNode ** U /* arrays for flow propagation */,
  761. DdNode ** x,
  762. DdNode ** y,
  763. DdNode ** z /* arrays of variables for rows and columns */,
  764. int n /* number of x variables */,
  765. DdNode * pryz,
  766. DdNode * prxz /* priority functions */,
  767. flowStats * stats)
  768. {
  769. DdNode *one, *zero,
  770. *przy,
  771. *p, *q, *r,
  772. *Uin, /* edges to be matched from U[m-1] */
  773. *Uout, /* edges to be matched from U[m] */
  774. *P, *Q,
  775. *PA, *D;
  776. int k,
  777. pr; /* print control */
  778. pr = stats->pr;
  779. one = Cudd_ReadOne(bdd);
  780. zero = Cudd_Not(one);
  781. /* Build priority function. */
  782. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, pryz, y, z, n));
  783. Cudd_Ref(przy = Cudd_bddAdjPermuteX(bdd,p,x,n));
  784. Cudd_RecursiveDeref(bdd,p);
  785. if(pr>2){(void)fprintf(stdout,"przy");Cudd_PrintDebug(bdd,przy,n*3,pr);}
  786. /*Uout(x,y)=U^m(x,y)*/
  787. Cudd_Ref(Uout = U[m]);
  788. if(pr>1){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
  789. /*Uin(x,y)=U^{m-1}(x,y)*/
  790. Cudd_Ref(Uin = U[m-1]);
  791. if(pr>1){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
  792. for(k = 0; k < MAXFPIT; k++) {
  793. stats->fpit++;
  794. /*P(x,y,z)=Uin(x,y)\cdot Uout(y,z)*/
  795. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uout, y, z, n));
  796. if(pr>2){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);}
  797. Cudd_Ref(q = Cudd_bddSwapVariables(bdd, p, x, y, n));
  798. Cudd_RecursiveDeref(bdd,p);
  799. if(pr>2){(void)fprintf(stdout,"q");Cudd_PrintDebug(bdd,q,n<<1,pr);}
  800. Cudd_Ref(P = Cudd_bddAnd(bdd, Uin, q));
  801. Cudd_RecursiveDeref(bdd,q);
  802. if(pr>1){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n*3,pr);}
  803. /*PA(x,z)=\exists_yP(x,y,z)*/
  804. Cudd_Ref(PA = Cudd_bddExistAbstract(bdd, P, ycube));
  805. if(pr>2){(void)fprintf(stdout,"PA");Cudd_PrintDebug(bdd,PA,n<<1,pr);}
  806. if(pr>3) {
  807. Cudd_Ref(p = Cudd_bddExistAbstract(bdd, PA, xcube));
  808. (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr);
  809. Cudd_RecursiveDeref(bdd,p);
  810. Cudd_Ref(p = Cudd_bddExistAbstract(bdd, PA, zcube));
  811. (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr);
  812. Cudd_RecursiveDeref(bdd,p);
  813. }
  814. /*Q(x,z)= PA(x,z)\cdot \overline{\exists_{y}(PA(x,y)\cdot \Pi(z,y))}*/
  815. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, PA, y, z, n));
  816. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, przy, ycube));
  817. Cudd_RecursiveDeref(bdd,p);
  818. Cudd_Ref(Q = Cudd_bddAnd(bdd, PA, Cudd_Not(r)));
  819. Cudd_RecursiveDeref(bdd,r);
  820. Cudd_RecursiveDeref(bdd,PA);
  821. if(pr>2){(void)fprintf(stdout,"Q");Cudd_PrintDebug(bdd,Q,n<<1,pr);}
  822. if(pr>3) {
  823. Cudd_Ref(p = Cudd_bddExistAbstract(bdd, Q, xcube));
  824. (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr);
  825. Cudd_RecursiveDeref(bdd,p);
  826. }
  827. /*D(x,z)= Q(x,z)\cdot \overline{\exists_{y}(Q(y,z)\cdot \Pi(x,y))}*/
  828. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Q, x, y, n));
  829. Cudd_Ref(q = Cudd_bddSwapVariables(bdd, prxz, y, z, n));
  830. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, q, ycube));
  831. Cudd_RecursiveDeref(bdd,p);
  832. Cudd_RecursiveDeref(bdd,q);
  833. Cudd_Ref(D = Cudd_bddAnd(bdd, Q, Cudd_Not(r)));
  834. Cudd_RecursiveDeref(bdd,r);
  835. Cudd_RecursiveDeref(bdd,Q);
  836. if(pr>1){(void)fprintf(stdout,"D");Cudd_PrintDebug(bdd,D,n<<1,pr);}
  837. /*P(x,y,z)=P(x,y,z)\cdot D(x,z)*/
  838. Cudd_Ref(p = Cudd_bddAnd(bdd, P, D));
  839. Cudd_RecursiveDeref(bdd,D);
  840. Cudd_RecursiveDeref(bdd,P);
  841. P = p;
  842. if(pr>2){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n*3,pr);}
  843. /*Uin(x,y)=Uin(x,y)-\exists_zP(x,y,z)*/
  844. Cudd_Ref(p = Cudd_bddExistAbstract(bdd, P, zcube));
  845. if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);}
  846. Cudd_Ref(q = Cudd_bddAnd(bdd, Uin, Cudd_Not(p)));
  847. Cudd_RecursiveDeref(bdd,p);
  848. Cudd_RecursiveDeref(bdd,Uin);
  849. Uin = q;
  850. if(pr>1){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
  851. /*Uout(x,y)=Uout(x,y)-\exists_zP(z,x,y)*/
  852. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, x, y, n));
  853. if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n*3,pr);}
  854. Cudd_Ref(r = Cudd_bddSwapVariables(bdd, p, y, z, n));
  855. Cudd_RecursiveDeref(bdd,p);
  856. if(pr>3){(void)fprintf(stdout,"r");Cudd_PrintDebug(bdd,r,n*3,pr);}
  857. Cudd_Ref(p = Cudd_bddExistAbstract(bdd, r, zcube));
  858. Cudd_RecursiveDeref(bdd,r);
  859. if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);}
  860. Cudd_Ref(q = Cudd_bddAnd(bdd, Uout, Cudd_Not(p)));
  861. Cudd_RecursiveDeref(bdd,p);
  862. Cudd_RecursiveDeref(bdd,Uout);
  863. Uout = q;
  864. if(pr>1){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
  865. /*\KW{if}(($P(x,y,z)=zero$)~~\KW{or}~~($Uin(x,y)=zero$)~~\KW{or}
  866. ($Uout(x,y)=zero$))~~KW{break}*/
  867. if((P == zero)||(Uin == zero)||(Uout == zero)) {
  868. Cudd_RecursiveDeref(bdd,P);
  869. break;
  870. }
  871. Cudd_RecursiveDeref(bdd,P);
  872. } /* Next least fixed point iteration with smaller P */
  873. if (k == MAXFPIT) (void) fprintf(stderr,
  874. "Hourglass: WARNING! MAXFPIT (%d) exceeded processing Layer %d.\n",
  875. MAXFPIT, m);
  876. if (Uin != zero) {
  877. /* $U^{m-1}(x,y) = U^{m-1}(x,y)-Uin(x,y)$*/
  878. Cudd_Ref(p = Cudd_bddAnd(bdd, U[m-1], Cudd_Not(Uin)));
  879. Cudd_RecursiveDeref(bdd,U[m-1]);
  880. U[m-1] = p;
  881. /* $new^{m-1}(x,y) = \esists_yU^{m-1}(x,y)$*/
  882. Cudd_RecursiveDeref(bdd,neW[m-1]);
  883. Cudd_Ref(neW[m-1] = Cudd_bddExistAbstract(bdd, U[m-1], ycube));
  884. }
  885. if(pr>1){(void)fprintf(stdout,"U[%d]",m-1); Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);}
  886. if(pr>1){(void)fprintf(stdout,"new[%d]",m-1);
  887. Cudd_PrintDebug(bdd,neW[m-1],n,pr);}
  888. Cudd_RecursiveDeref(bdd,Uin);
  889. Cudd_RecursiveDeref(bdd,Uout);
  890. Cudd_RecursiveDeref(bdd,przy);
  891. return;
  892. } /* end of hourglass */
  893. /**Function********************************************************************
  894. Synopsis [Pushes flow through useful edges.]
  895. Description [Pushes flow from the source(s) to the sink(s) through
  896. useful edges.]
  897. SideEffects [None]
  898. SeeAlso []
  899. ******************************************************************************/
  900. static void
  901. maximal_push(
  902. DdManager * bdd,
  903. int l /* Depth of layered network for current phase */,
  904. DdNode ** U /* array of edge sets for flow propagation */,
  905. DdNode ** F /* edge and flow relations */,
  906. DdNode ** x,
  907. DdNode ** y,
  908. DdNode ** z /* arrays of variables for rows and columns */,
  909. int n /* number of x variables */,
  910. DdNode * pryz,
  911. DdNode * prxz /* priority functions */,
  912. flowStats * stats)
  913. {
  914. DdNode *p, *q, *r,
  915. *UT,
  916. *lN, *cN, *rN; /* left, center, right nodes of bilayer */
  917. double mtl, mtc, mtr;
  918. int m,
  919. pr; /* print control */
  920. pr = stats->pr;
  921. if (l == 0) {
  922. /* F(x,y) = F(x,y) + U^{0}(x,y) */
  923. Cudd_Ref(q = Cudd_bddOr(bdd, *F, U[0]));
  924. Cudd_RecursiveDeref(bdd,*F);
  925. *F = q;
  926. if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
  927. return;
  928. }
  929. for (m = 1; m < l; m++) {
  930. /* lN(x) = \exists_y U^{m-1}(x,y) */
  931. Cudd_Ref(lN = Cudd_bddExistAbstract(bdd, U[m-1], ycube));
  932. mtl = Cudd_CountMinterm(bdd, lN, n);
  933. Cudd_RecursiveDeref(bdd,lN);
  934. /* cN(y) = \exists_x U^{m-1}(x,y) */
  935. Cudd_Ref(cN = Cudd_bddExistAbstract(bdd, U[m-1], xcube));
  936. mtc = Cudd_CountMinterm(bdd, cN, n);
  937. Cudd_RecursiveDeref(bdd,cN);
  938. /* rN(y) = \exists_x U^{m}(x,y) */
  939. Cudd_Ref(rN = Cudd_bddExistAbstract(bdd, U[m], xcube));
  940. mtr = Cudd_CountMinterm(bdd, rN, n);
  941. Cudd_RecursiveDeref(bdd,rN);
  942. if (pr > 0) {
  943. (void) fprintf(stdout, "layer = %d mtl = %g mtc = %g mtr = %g",
  944. m, mtl, mtc, mtr);
  945. }
  946. if ((mtc > MANY_TIMES * mtl) && !(mtr > MANY_TIMES * mtl)) {
  947. if (pr>0) (void) fprintf(stdout, " R\n");
  948. rhombusPush(bdd, m, U, x, y, z, n, pryz, prxz, stats);
  949. } else if (mtl > MANY_TIMES * mtc) {
  950. if (pr>0) (void) fprintf(stdout, " H\n");
  951. hourglassPush(bdd, m, U, x, y, z, n, pryz, prxz, stats);
  952. } else {
  953. if (pr>0) (void) fprintf(stdout, " T\n");
  954. trellisPush(bdd, m, U, x, y, z, n, pryz, prxz, stats);
  955. }
  956. /* F(x,y) = F(x,y) + U^{m-1}(x,y) \cdot \overline{F(y,x)} */
  957. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, *F, x, y, n));
  958. Cudd_Ref(q = Cudd_bddAnd(bdd, Cudd_Not(p), U[m-1]));
  959. Cudd_RecursiveDeref(bdd,p);
  960. Cudd_Ref(r = Cudd_bddOr(bdd, *F, q));
  961. Cudd_RecursiveDeref(bdd,q);
  962. Cudd_RecursiveDeref(bdd,*F);
  963. *F = r;
  964. if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
  965. /* F(x,y) = F(x,y) - U^{m-1}(y,x) */
  966. Cudd_Ref(r = Cudd_bddSwapVariables(bdd, U[m-1], x, y, n));
  967. Cudd_Ref(q = Cudd_bddAnd(bdd, *F, Cudd_Not(r)));
  968. Cudd_RecursiveDeref(bdd,r);
  969. Cudd_RecursiveDeref(bdd,*F);
  970. *F = q;
  971. if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
  972. } /* Push maximal flow to next layer */
  973. /*F(x,y)=F(x,y)+U^{l-1}(x,y)\cdot\overline{F(y,x)}*/
  974. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, *F, x, y, n));
  975. Cudd_Ref(q = Cudd_bddAnd(bdd, Cudd_Not(p), U[l-1]));
  976. Cudd_RecursiveDeref(bdd,p);
  977. Cudd_Ref(r = Cudd_bddOr(bdd, *F, q));
  978. Cudd_RecursiveDeref(bdd,q);
  979. Cudd_RecursiveDeref(bdd,*F);
  980. *F = r;
  981. if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
  982. /*F(y,x)=F(y,x)-U^{l-1}(x,y)*/
  983. Cudd_Ref(r = Cudd_bddSwapVariables(bdd, U[l-1], x, y, n));
  984. Cudd_Ref(q = Cudd_bddAnd(bdd, *F, Cudd_Not(r)));
  985. Cudd_RecursiveDeref(bdd,r);
  986. Cudd_RecursiveDeref(bdd,*F);
  987. *F = q;
  988. if(pr>1){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
  989. /*UT(x,y)=\exists_y(U^{l-1}(y,x))\cdot U^{l}(x,y)*/
  990. Cudd_Ref(p = Cudd_bddExistAbstract(bdd, U[l-1], xcube));
  991. if(pr>4){(void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr);}
  992. Cudd_Ref(q = Cudd_bddSwapVariables(bdd, p, x, y, n));
  993. Cudd_RecursiveDeref(bdd,p);
  994. if(pr>4){(void) fprintf(stdout,"q");Cudd_PrintDebug(bdd,q,n,pr);}
  995. Cudd_Ref(UT = Cudd_bddAnd(bdd, U[l], q));
  996. Cudd_RecursiveDeref(bdd,q);
  997. if(pr>2){(void) fprintf(stdout,"UT");Cudd_PrintDebug(bdd,UT,n<<1,pr);}
  998. /*F(x,y)=F(x,y)+UT(x,y)\cdot\overline{F(y,x)}*/
  999. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, *F, x, y, n));
  1000. Cudd_Ref(q = Cudd_bddAnd(bdd, Cudd_Not(p), UT));
  1001. Cudd_RecursiveDeref(bdd,p);
  1002. Cudd_Ref(r = Cudd_bddOr(bdd, *F, q));
  1003. Cudd_RecursiveDeref(bdd,q);
  1004. Cudd_RecursiveDeref(bdd,*F);
  1005. *F = r;
  1006. if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
  1007. /*F(y,x)=F(y,x)-UT(x,y)*/
  1008. Cudd_Ref(r = Cudd_bddSwapVariables(bdd, UT, x, y, n));
  1009. Cudd_RecursiveDeref(bdd,UT);
  1010. Cudd_Ref(q = Cudd_bddAnd(bdd, *F, Cudd_Not(r)));
  1011. Cudd_RecursiveDeref(bdd,r);
  1012. Cudd_RecursiveDeref(bdd,*F);
  1013. *F = q;
  1014. if(pr>1){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
  1015. return;
  1016. } /* end of maximal_push */
  1017. /**Function********************************************************************
  1018. Synopsis []
  1019. Description []
  1020. SideEffects [None]
  1021. SeeAlso []
  1022. ******************************************************************************/
  1023. static void
  1024. trellisPush(
  1025. DdManager * bdd,
  1026. int m /* Current layer */,
  1027. DdNode ** U /* Array of edge sets for flow propagation */,
  1028. DdNode ** x,
  1029. DdNode ** y,
  1030. DdNode ** z /* Arrays of variables for rows and columns */,
  1031. int n /* Number of x variables */,
  1032. DdNode * pryz,
  1033. DdNode * prxz /* Priority functions */,
  1034. flowStats * stats)
  1035. {
  1036. DdNode *one, *zero,
  1037. *p, *r,
  1038. *Uin, /* Edges to be matched from U[m-1] */
  1039. *Uout, /* Edges to be matched from U[m] */
  1040. *RU, *LU,
  1041. *P,
  1042. *Ml;
  1043. int i,
  1044. pr; /* Print control */
  1045. pr = stats->pr;
  1046. one = Cudd_ReadOne(bdd);
  1047. zero = Cudd_Not(one);
  1048. /*Uout(x,y)=U^m(x,y)*/
  1049. Cudd_Ref(Uout = U[m]);
  1050. if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
  1051. /*Uin(x,y)=U^{m-1}(x,y)*/
  1052. Cudd_Ref(Uin = U[m-1]);
  1053. if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
  1054. for(i=0; i<MAXFPIT; i++) {
  1055. stats->fpit++;
  1056. /*LU(x,y)=Uin(x,y)\cdot\overline{\exists_{z}(Uin(z,y)\cdot\Pi(x,z))}*/
  1057. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uin, x, z, n));
  1058. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, prxz, zcube));
  1059. Cudd_RecursiveDeref(bdd,p);
  1060. Cudd_Ref(LU = Cudd_bddAnd(bdd, Uin, Cudd_Not(r)));
  1061. Cudd_RecursiveDeref(bdd,r);
  1062. if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);}
  1063. /*Ml(y)=\exists_{x}LU(x,y)*/
  1064. Cudd_Ref(Ml = Cudd_bddExistAbstract(bdd, LU, xcube));
  1065. if(pr>3){(void)fprintf(stdout,"Ml");Cudd_PrintDebug(bdd,Ml,n,pr);}
  1066. /*P(x,y)=Ml(x)\cdot Uout(x,y)*/
  1067. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Ml, x, y, n));
  1068. Cudd_Ref(P = Cudd_bddAnd(bdd, p, Uout));
  1069. Cudd_RecursiveDeref(bdd,p);
  1070. Cudd_RecursiveDeref(bdd,Ml);
  1071. if(pr>3){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n<<1,pr);}
  1072. /*RU(x,y)= P(x,y)\cdot \overline{\exists_{z}(P(x,z)\cdot \Pi(y,z))}*/
  1073. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, y, z, n));
  1074. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube));
  1075. Cudd_RecursiveDeref(bdd,p);
  1076. Cudd_Ref(RU = Cudd_bddAnd(bdd, P, Cudd_Not(r)));
  1077. Cudd_RecursiveDeref(bdd,r);
  1078. Cudd_RecursiveDeref(bdd,P);
  1079. if(pr>3){(void)fprintf(stdout,"RU");Cudd_PrintDebug(bdd,RU,n<<1,pr);}
  1080. /*Uin(x,y)=Uin(x,y)-LU(x,y)*/
  1081. Cudd_Ref(p = Cudd_bddAnd(bdd, Uin, Cudd_Not(LU)));
  1082. Cudd_RecursiveDeref(bdd,Uin);
  1083. Uin = p;
  1084. if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
  1085. /*Uout(x,y)=Uout(x,y)-RU(x,y)*/
  1086. Cudd_Ref(p = Cudd_bddAnd(bdd, Uout, Cudd_Not(RU)));
  1087. Cudd_RecursiveDeref(bdd,Uout);
  1088. Cudd_RecursiveDeref(bdd,RU);
  1089. Uout = p;
  1090. if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
  1091. /*\KW{if}(($LU(x,y)=zero$)~~\KW{or}~~($Uin(x,y)=zero$))~~KW{break}*/
  1092. if((LU == zero)||(Uin == zero)) {
  1093. Cudd_RecursiveDeref(bdd,LU);
  1094. break;
  1095. }
  1096. Cudd_RecursiveDeref(bdd,LU);
  1097. } /* Next least fixed point iteration with smaller Uin and Uout */
  1098. if (i == MAXFPIT) (void) fprintf(stderr,
  1099. "TrellisPush: ERROR! MAXFPIT (%d) exceeded at layer %d.\n",
  1100. MAXFPIT, m);
  1101. /* $U^{m}(x,y) = U^{m}(x,y)-Uout(x,y)$*/
  1102. if (Uout != zero) {
  1103. Cudd_Ref(p = Cudd_bddAnd(bdd, U[m], Cudd_Not(Uout)));
  1104. Cudd_RecursiveDeref(bdd,U[m]);
  1105. U[m] = p;
  1106. if(pr>3){(void)fprintf(stdout,"U[%d]",m);
  1107. Cudd_PrintDebug(bdd,U[m],n<<1,pr);}
  1108. }
  1109. Cudd_RecursiveDeref(bdd,Uin);
  1110. Cudd_RecursiveDeref(bdd,Uout);
  1111. } /* end of trellisPush */
  1112. /**Function********************************************************************
  1113. Synopsis []
  1114. Description []
  1115. SideEffects [None]
  1116. SeeAlso []
  1117. ******************************************************************************/
  1118. static void
  1119. rhombusPush(
  1120. DdManager * bdd,
  1121. int m /* Current layer */,
  1122. DdNode ** U /* Array of edge sets for flow propagation */,
  1123. DdNode ** x,
  1124. DdNode ** y,
  1125. DdNode ** z /* Arrays of variables for rows and columns */,
  1126. int n /* Number of x variables */,
  1127. DdNode * pryz,
  1128. DdNode * prxz /* Priority functions */,
  1129. flowStats * stats)
  1130. {
  1131. DdNode *one, *zero,
  1132. *p, *r,
  1133. *Uin, /* Edges to be matched from U[m-1] */
  1134. *Uout, /* Edges to be matched from U[m] */
  1135. *RU, *LU,
  1136. *P,
  1137. *Ml;
  1138. int i,
  1139. pr; /* Print control */
  1140. pr = stats->pr;
  1141. one = Cudd_ReadOne(bdd);
  1142. zero = Cudd_Not(one);
  1143. /*Uout(x,y)=U^m(x,y)*/
  1144. Cudd_Ref(Uout = U[m]);
  1145. if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
  1146. /*Uin(x,y)=U^{m-1}(x,y)*/
  1147. Cudd_Ref(Uin = U[m-1]);
  1148. if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
  1149. for(i = 0; i < MAXFPIT; i++) {
  1150. stats->fpit++;
  1151. /*RU(x,y)=Uin(x,y)\cdot\overline{\exists_{z}(Uin(x,z)\cdot\Pi(y,z))}*/
  1152. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uin, y, z, n));
  1153. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube));
  1154. Cudd_RecursiveDeref(bdd,p);
  1155. Cudd_Ref(RU = Cudd_bddAnd(bdd, Uin, Cudd_Not(r)));
  1156. Cudd_RecursiveDeref(bdd,r);
  1157. if(pr>3){(void)fprintf(stdout,"RU");Cudd_PrintDebug(bdd,RU,n<<1,pr);}
  1158. /*Ml(y)=\exists_{x}RU(x,y)*/
  1159. Cudd_Ref(Ml = Cudd_bddExistAbstract(bdd, RU, xcube));
  1160. if(pr>3){(void)fprintf(stdout,"Ml");Cudd_PrintDebug(bdd,Ml,n,pr);}
  1161. /*P(x,y)=Ml(x)\cdot Uout(x,y)*/
  1162. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Ml, x, y, n));
  1163. Cudd_Ref(P = Cudd_bddAnd(bdd, p, Uout));
  1164. Cudd_RecursiveDeref(bdd,p);
  1165. Cudd_RecursiveDeref(bdd,Ml);
  1166. if(pr>3){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n<<1,pr);}
  1167. /*LU(x,y)= P(x,y)\cdot \overline{\exists_{z}(P(z,y)\cdot \Pi(x,z))}*/
  1168. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, x, z, n));
  1169. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, prxz, zcube));
  1170. Cudd_RecursiveDeref(bdd,p);
  1171. Cudd_Ref(LU = Cudd_bddAnd(bdd, P, Cudd_Not(r)));
  1172. Cudd_RecursiveDeref(bdd,r);
  1173. Cudd_RecursiveDeref(bdd,P);
  1174. if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);}
  1175. /*Uin(x,y)=Uin(x,y)-RU(x,y)*/
  1176. Cudd_Ref(p = Cudd_bddAnd(bdd, Uin, Cudd_Not(RU)));
  1177. Cudd_RecursiveDeref(bdd,Uin);
  1178. Uin = p;
  1179. if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
  1180. /*Uout(x,y)=Uout(x,y)-LU(x,y)*/
  1181. Cudd_Ref(p = Cudd_bddAnd(bdd, Uout, Cudd_Not(LU)));
  1182. Cudd_RecursiveDeref(bdd,Uout);
  1183. Cudd_RecursiveDeref(bdd,LU);
  1184. Uout = p;
  1185. if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
  1186. /*\KW{if}(($RU(x,y)=zero$)~~\KW{or}~~($Uin(x,y)=zero$))~~KW{break}*/
  1187. if((RU == zero)||(Uin == zero)) {
  1188. Cudd_RecursiveDeref(bdd,RU);
  1189. break;
  1190. }
  1191. Cudd_RecursiveDeref(bdd,RU);
  1192. } /* Next least fixed point iteration with smaller Uin and Uout */
  1193. if (i == MAXFPIT) (void) fprintf(stderr,
  1194. "RhombusPush: ERROR! MAXFPIT (%d) exceeded at layer %d.\n",
  1195. MAXFPIT, m);
  1196. /* $U^{m}(x,y) = U^{m}(x,y)-Uout(x,y)$*/
  1197. if (Uout != zero) {
  1198. Cudd_Ref(p = Cudd_bddAnd(bdd, U[m], Cudd_Not(Uout)));
  1199. Cudd_RecursiveDeref(bdd,U[m]);
  1200. U[m] = p;
  1201. if(pr>3){(void)fprintf(stdout,"U[%d]",m);
  1202. Cudd_PrintDebug(bdd,U[m],n<<1,pr);}
  1203. }
  1204. Cudd_RecursiveDeref(bdd,Uin);
  1205. Cudd_RecursiveDeref(bdd,Uout);
  1206. return;
  1207. } /* end of rhombusPush */
  1208. /**Function********************************************************************
  1209. Synopsis []
  1210. Description []
  1211. SideEffects [None]
  1212. SeeAlso []
  1213. ******************************************************************************/
  1214. static void
  1215. hourglassPush(
  1216. DdManager * bdd,
  1217. int m /* Current layer */,
  1218. DdNode ** U /* Array of edge sets for flow propagation */,
  1219. DdNode ** x,
  1220. DdNode ** y,
  1221. DdNode ** z /* Arrays of variables for rows and columns */,
  1222. int n /* Number of x variables */,
  1223. DdNode * pryz,
  1224. DdNode * prxz /* Priority functions */,
  1225. flowStats * stats)
  1226. {
  1227. DdNode *one, *zero,
  1228. *przy,
  1229. *p, *q, *r,
  1230. *Uin, /* Edges to be matched from U[m-1] */
  1231. *Uout, /* Edges to be matched from U[m] */
  1232. *P, *Q,
  1233. *PA, *D;
  1234. int i,
  1235. pr; /* Print control */
  1236. pr = stats->pr;
  1237. one = Cudd_ReadOne(bdd);
  1238. zero = Cudd_Not(one);
  1239. /* Build priority function. */
  1240. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, pryz, y, z, n));
  1241. Cudd_Ref(przy = Cudd_bddAdjPermuteX(bdd,p,x,n));
  1242. Cudd_RecursiveDeref(bdd,p);
  1243. if(pr>2){(void)fprintf(stdout,"przy");Cudd_PrintDebug(bdd,przy,n*3,pr);}
  1244. /*Uout(x,y)=U^m(x,y)*/
  1245. Cudd_Ref(Uout = U[m]);
  1246. if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
  1247. /*Uin(x,y)=U^{m-1}(x,y)*/
  1248. Cudd_Ref(Uin = U[m-1]);
  1249. if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
  1250. for(i = 0; i < MAXFPIT; i++) {
  1251. stats->fpit++;
  1252. /*P(x,y,z)=Uin(x,y)\cdot Uout(y,z)*/
  1253. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uout, y, z, n));
  1254. if(pr>2){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);}
  1255. Cudd_Ref(q = Cudd_bddSwapVariables(bdd, p, x, y, n));
  1256. Cudd_RecursiveDeref(bdd,p);
  1257. if(pr>2){(void)fprintf(stdout,"q");Cudd_PrintDebug(bdd,q,n<<1,pr);}
  1258. Cudd_Ref(P = Cudd_bddAnd(bdd, Uin, q));
  1259. Cudd_RecursiveDeref(bdd,q);
  1260. if(pr>1){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n*3,pr);}
  1261. /*PA(x,z)=\exists_yP(x,y,z)*/
  1262. Cudd_Ref(PA = Cudd_bddExistAbstract(bdd, P, ycube));
  1263. if(pr>2){(void)fprintf(stdout,"PA");Cudd_PrintDebug(bdd,PA,n<<1,pr);}
  1264. if(pr>3) {
  1265. Cudd_Ref(p = Cudd_bddExistAbstract(bdd, PA, xcube));
  1266. (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr);
  1267. Cudd_RecursiveDeref(bdd,p);
  1268. Cudd_Ref(p = Cudd_bddExistAbstract(bdd, PA, zcube));
  1269. (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr);
  1270. Cudd_RecursiveDeref(bdd,p);
  1271. }
  1272. /*Q(x,z)= PA(x,z)\cdot \overline{\exists_{y}(PA(x,y)\cdot \Pi(z,y))}*/
  1273. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, PA, y, z, n));
  1274. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, przy, ycube));
  1275. Cudd_RecursiveDeref(bdd,p);
  1276. Cudd_Ref(Q = Cudd_bddAnd(bdd, PA, Cudd_Not(r)));
  1277. Cudd_RecursiveDeref(bdd,r);
  1278. Cudd_RecursiveDeref(bdd,PA);
  1279. if(pr>2){(void)fprintf(stdout,"Q");Cudd_PrintDebug(bdd,Q,n<<1,pr);}
  1280. if(pr>3) {
  1281. Cudd_Ref(p = Cudd_bddExistAbstract(bdd, Q, xcube));
  1282. (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr);
  1283. Cudd_RecursiveDeref(bdd,p);
  1284. }
  1285. /*D(x,z)= Q(x,z)\cdot \overline{\exists_{y}(Q(y,z)\cdot \Pi(x,y))}*/
  1286. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Q, x, y, n));
  1287. Cudd_Ref(q = Cudd_bddSwapVariables(bdd, prxz, y, z, n));
  1288. Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, q, ycube));
  1289. Cudd_RecursiveDeref(bdd,p);
  1290. Cudd_RecursiveDeref(bdd,q);
  1291. Cudd_Ref(D = Cudd_bddAnd(bdd, Q, Cudd_Not(r)));
  1292. Cudd_RecursiveDeref(bdd,r);
  1293. Cudd_RecursiveDeref(bdd,Q);
  1294. if(pr>1){(void)fprintf(stdout,"D");Cudd_PrintDebug(bdd,D,n<<1,pr);}
  1295. /*P(x,y,z)=P(x,y,z)\cdot D(x,z)*/
  1296. Cudd_Ref(p = Cudd_bddAnd(bdd, P, D));
  1297. Cudd_RecursiveDeref(bdd,D);
  1298. Cudd_RecursiveDeref(bdd,P);
  1299. P = p;
  1300. if(pr>2){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n*3,pr);}
  1301. /*Uin(x,y)=Uin(x,y)-\exists_zP(x,y,z)*/
  1302. Cudd_Ref(p = Cudd_bddExistAbstract(bdd, P, zcube));
  1303. if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);}
  1304. Cudd_Ref(q = Cudd_bddAnd(bdd, Uin, Cudd_Not(p)));
  1305. Cudd_RecursiveDeref(bdd,p);
  1306. Cudd_RecursiveDeref(bdd,Uin);
  1307. Uin = q;
  1308. if(pr>1){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
  1309. /*Uout(x,y)=Uout(x,y)-\exists_zP(z,x,y)*/
  1310. Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, x, y, n));
  1311. if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n*3,pr);}
  1312. Cudd_Ref(r = Cudd_bddSwapVariables(bdd, p, y, z, n));
  1313. Cudd_RecursiveDeref(bdd,p);
  1314. if(pr>3){(void)fprintf(stdout,"r");Cudd_PrintDebug(bdd,r,n*3,pr);}
  1315. Cudd_Ref(p = Cudd_bddExistAbstract(bdd, r, zcube));
  1316. Cudd_RecursiveDeref(bdd,r);
  1317. if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);}
  1318. Cudd_Ref(q = Cudd_bddAnd(bdd, Uout, Cudd_Not(p)));
  1319. Cudd_RecursiveDeref(bdd,p);
  1320. Cudd_RecursiveDeref(bdd,Uout);
  1321. Uout = q;
  1322. if(pr>1){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
  1323. /*\KW{if}(($P(x,y,z)=zero$)~~\KW{or}~~($Uin(x,y)=zero$)~~\KW{or}
  1324. ($Uout(x,y)=zero$))~~KW{break}*/
  1325. if((P == zero)||(Uin == zero)||(Uout == zero)) {
  1326. Cudd_RecursiveDeref(bdd,P);
  1327. break;
  1328. }
  1329. Cudd_RecursiveDeref(bdd,P);
  1330. } /* Next least fixed point iteration with smaller P */
  1331. if (i == MAXFPIT) (void) fprintf(stderr,
  1332. "HourglassPush: ERROR! MAXFPIT (%d) exceeded at layer %d.\n",
  1333. MAXFPIT, m);
  1334. /* $U^{m}(x,y) = U^{m}(x,y)-Uout(x,y)$*/
  1335. if (Uout != zero) {
  1336. Cudd_Ref(p = Cudd_bddAnd(bdd, U[m], Cudd_Not(Uout)));
  1337. Cudd_RecursiveDeref(bdd,U[m]);
  1338. U[m] = p;
  1339. }
  1340. if(pr>1){(void)fprintf(stdout,"U[%d]",m); Cudd_PrintDebug(bdd,U[m],n<<1,pr);}
  1341. Cudd_RecursiveDeref(bdd,Uin);
  1342. Cudd_RecursiveDeref(bdd,Uout);
  1343. Cudd_RecursiveDeref(bdd,przy);
  1344. return;
  1345. } /* end of hourglassPush */