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.

1555 lines
55 KiB

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