|
|
/**
@file
@ingroup nanotrav
@brief Symbolic maxflow algorithm.
@details This file contains the functions that implement the symbolic version of Dinits's maxflow algorithm described in the ICCAD93 paper. The present implementation differs from the algorithm described in the paper in that more than one matching techniques is used. The technique of the paper is the one applied to hourglass-type bilayers here.
@author Fabio Somenzi, Gary Hachtel
@copyright@parblock Copyright (c) 1995-2015, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @endparblock
*/
#include "ntr.h"
/*---------------------------------------------------------------------------*/ /* Constant declarations */ /*---------------------------------------------------------------------------*/
#define MAXPHASE 1000
#define MAXLAYER 1000
#define MAXFPIT 100000
#define MANY_TIMES 3.0
#define PRUNE /* If defined, enables pruning of E */
/*---------------------------------------------------------------------------*/ /* Stucture declarations */ /*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/ /* Type declarations */ /*---------------------------------------------------------------------------*/
/**
@brief Structure to hold statistics. */ typedef struct flowStatsStruct { int pr; /**< level of verbosity */ long start_time; /**< cpu time when the covering started */ int phases; /**< number of phases */ int layers; /**< number of layers */ int fpit; /**< number of fixed point iterations */ } flowStats;
/*---------------------------------------------------------------------------*/ /* Variable declarations */ /*---------------------------------------------------------------------------*/
static DdNode *xcube, *ycube, *zcube;
/*---------------------------------------------------------------------------*/ /* Macro declarations */ /*---------------------------------------------------------------------------*/
/** \cond */
/*---------------------------------------------------------------------------*/ /* Static function prototypes */ /*---------------------------------------------------------------------------*/
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); 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); 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); 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); 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); 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); static void trellisPush (DdManager *bdd, int m, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats); static void rhombusPush (DdManager *bdd, int m, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats); static void hourglassPush (DdManager *bdd, int m, DdNode **U, DdNode **x, DdNode **y, DdNode **z, int n, DdNode *pryz, DdNode *prxz, flowStats *stats);
/** \endcond */
/*---------------------------------------------------------------------------*/ /* Definition of exported functions */ /*---------------------------------------------------------------------------*/
/**
@brief Symbolic Dinit's algorithm.
@details@parblock This function implements Dinits's algorithm for (0-1) max flow, using BDDs and a symbolic technique to trace multiple edge-disjoint augmenting paths to complete a phase. The outer forever loop is over phases, and the inner forever loop is to propagate a (not yet) maximal flow of edge-disjoint augmenting paths from one layer to the previous. The subprocedure call implements a least fixed point iteration to compute a (not yet) maximal flow update between layers. At the end of each phase (except the last one) the flow is actually pushed from the source to the sink.
Data items: <ul> <li> sx(ty) BDD representations of s(t). <li> x(y) The variables encoding the from(to)-node u(v) of an edge (u,v) in the given digraph. <li> z Another set of variables. <li> E(x,y) The edge relation. <li> F(x,y) %BDD representation of the current flow, initialized to 0 for each arc, and updated by +1, -1, or 0 at the end of each phase. <li> Ms Mt The maximum flow, that is, the cardinality of a minimum cut, measured at the source and at the sink, respectively. The two values should be identical. <li> reached The set of nodes already visited in the BFS of the digraph. <li> fos fanout of the source node s. <li> fit fanin of the sink node t. </ul> @endparblock
@sideeffect The flow realtion F and the cutset relation cut are returned as side effects.
*/ double Ntr_maximum01Flow( DdManager * bdd /**< manager */, DdNode * sx /**< source node */, DdNode * ty /**< sink node */, DdNode * E /**< edge relation */, DdNode ** F /**< flow relation */, DdNode ** cut /**< cutset relation */, DdNode ** x /**< array of row variables */, DdNode ** y /**< array of column variables */, DdNode ** z /**< arrays of auxiliary variables */, int n /**< number of variables in each array */, int pr /**< verbosity level */) { flowStats stats; DdNode *one, *zero, #ifdef PRUNE
*EDC, /* Edge don't care set */ #endif
*reached, /* states reached through useful edges */ *fos, *fit, /* fanout of source, fanin of sink */ *rF, *rB, *tx, *I, *P, *w, *p, *q, *r,/* intemediate results */ *pryz, *prxz, /* priority functions for disjoint path tracing */ **neW, **U; /* arrays of BDDs for flow propagation */ int i, j, l; double Ms, Mt;
/* Initialize debugging structure. */ stats.pr = pr; stats.start_time = util_cpu_time(); stats.phases = 0; stats.layers = 0; stats.fpit = 0;
/* Allocate arrays for new (just reached vertex sets)
** and U (useful edge sets). */ U = ALLOC(DdNode *, ((unsigned) MAXLAYER)); neW = ALLOC(DdNode *, ((unsigned) MAXLAYER));
one = Cudd_ReadOne(bdd); zero = Cudd_Not(one);
/* Initialize xcube, ycube, and zcube (for abstractions). */ Cudd_Ref(xcube = Cudd_bddComputeCube(bdd,x,NULL,n)); Cudd_Ref(ycube = Cudd_bddComputeCube(bdd,y,NULL,n)); Cudd_Ref(zcube = Cudd_bddComputeCube(bdd,z,NULL,n));
/* Build the BDD for the priority functions. */ Cudd_Ref(pryz = Cudd_Dxygtdxz(bdd, n, x, y, z)); Cudd_Ref(prxz = Cudd_Dxygtdyz(bdd, n, x, y, z)); /* Now "randomize" by shuffling the x variables in pryz and the y
** variables in prxz. */ Cudd_Ref(p = Cudd_bddAdjPermuteX(bdd,pryz,x,n)); Cudd_RecursiveDeref(bdd,pryz); pryz = p; if(pr>2){(void) fprintf(stdout,"pryz");Cudd_PrintDebug(bdd,pryz,n*3,pr);} Cudd_Ref(p = Cudd_bddAdjPermuteX(bdd,prxz,y,n)); Cudd_RecursiveDeref(bdd,prxz); prxz = p; if(pr>2){(void) fprintf(stdout,"prxz");Cudd_PrintDebug(bdd,prxz,n*3,pr);}
#ifdef PRUNE
/* Build the edge don't care set and prune E. The edge don't care
** set consists of the edges into the source(s), the edges out of the ** sink(s), and the self-loops. These edges cannot contribute to the ** maximum flow. */ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, sx, x, y, n)); Cudd_Ref(q = Cudd_bddSwapVariables(bdd, ty, x, y, n)); Cudd_Ref(r = Cudd_bddOr(bdd, p, q)); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,q); Cudd_Ref(p = Cudd_Xeqy(bdd, n, x, y)); Cudd_Ref(EDC = Cudd_bddOr(bdd, p, r)); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,r); if(pr>2){(void) fprintf(stdout,"EDC");Cudd_PrintDebug(bdd,EDC,n<<1,pr);} Cudd_Ref(p = Cudd_bddAnd(bdd, E, Cudd_Not(EDC))); Cudd_RecursiveDeref(bdd,EDC); if(pr>0){(void) fprintf(stdout,"Given E");Cudd_PrintDebug(bdd,E,n<<1,pr);} E = p; if(pr>0){(void) fprintf(stdout,"Pruned E");Cudd_PrintDebug(bdd,E,n<<1,pr);} #endif
/* Compute fanin of sink node t: it is an upper bound for the flow. */ Cudd_Ref(fit = Cudd_bddAnd(bdd, E, ty)); if (pr>2) { /* Compute fanout of source node s. */ Cudd_Ref(fos = Cudd_bddAnd(bdd, E, sx)); (void) fprintf(stdout,"fos");Cudd_PrintDebug(bdd,fos,n<<1,pr); Cudd_RecursiveDeref(bdd,fos);
(void) fprintf(stdout,"fit");Cudd_PrintDebug(bdd,fit,n<<1,pr); } /* t(x) is used to check for termination of forward traversal. */ Cudd_Ref(tx = Cudd_bddSwapVariables(bdd, ty, x, y, n));
/* \KW{Procedure}\ \ \PC{maximum\_flow}$(s,t,E(x,y)) */ Cudd_Ref(*F = zero);
for (i = 1; i < MAXPHASE; i++) { stats.phases++; if(pr>0){(void) fprintf(stdout,"## Starting Phase %d at time = %s\n",i, util_print_time(util_cpu_time() - stats.start_time));} /* new[0](x) = s(x);U^0(x,y)=E(x,y)\cdot s(x) \cdot \overline{F(x,y)};
** reached=s; new[1](x)=\exists_xU^0(x,y); */ Cudd_Ref(neW[0] = sx); Cudd_Ref(p = Cudd_bddAnd(bdd, sx, Cudd_Not(*F))); Cudd_Ref(U[0] = Cudd_bddAnd(bdd, p, E)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(reached = sx); Cudd_Ref(r = Cudd_bddExistAbstract(bdd, U[0], xcube)); Cudd_RecursiveDeref(bdd,U[0]); Cudd_Ref(q = Cudd_bddSwapVariables(bdd, r, x, y, n)); Cudd_RecursiveDeref(bdd,r); Cudd_Ref(neW[1] = Cudd_bddAnd(bdd, q, Cudd_Not(reached))); Cudd_RecursiveDeref(bdd,q); if(pr>0) { (void) fprintf(stdout,"neW[1]");Cudd_PrintDebug(bdd,neW[1],n,pr); } for (l = 1; l < MAXLAYER; l++) { if (neW[l] == zero) { /* flow is maximum */ /* cut=reached(x) \cdot E(x,y) \cdot \overline{reached(y)} */ Cudd_Ref(p = Cudd_bddAnd(bdd, reached, E)); Cudd_Ref(q = Cudd_bddSwapVariables(bdd, reached, x, y, n)); Cudd_Ref(*cut = Cudd_bddAnd(bdd, p, Cudd_Not(q))); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,q); Cudd_RecursiveDeref(bdd,reached); for (j = 0; j <= l; j++) Cudd_RecursiveDeref(bdd,neW[j]); goto endPhases; } /* As soon as we touch one sink node we stop traversal.
** \KW{if} ($t\cdot new^{l} \neq 0$) */ if (!Cudd_bddLeq(bdd, tx, Cudd_Not(neW[l]))) { Cudd_RecursiveDeref(bdd,reached); maximal_pull(bdd,l-1,ty,neW,U,E,F,x,y,z,n,pryz,prxz,&stats); goto endLayers; } stats.layers++; if(pr>2){(void) fprintf(stdout,"===== Layer %d =====\n",l);} /* reached(x) = reached(x) + new^l(x) */ Cudd_Ref(w = Cudd_bddOr(bdd, reached, neW[l])); Cudd_RecursiveDeref(bdd,reached); reached = w; /* I(y) = \exists_x((E(x,y) \cdot \overline{F(x,y)})
** \cdot new^l(x)) */ Cudd_Ref(p = Cudd_bddAnd(bdd, E, Cudd_Not(*F))); Cudd_Ref(I = Cudd_bddAndAbstract(bdd, p, neW[l], xcube)); if(pr>3){(void) fprintf(stdout,"I");Cudd_PrintDebug(bdd,I,n,pr);} Cudd_RecursiveDeref(bdd,p); /* rF(x)= I(x) \cdot \overline{reached(x)}) */ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, I, x, y, n)); Cudd_RecursiveDeref(bdd,I); Cudd_Ref(rF = Cudd_bddAnd(bdd, p, Cudd_Not(reached))); Cudd_RecursiveDeref(bdd,p); if(pr>2){(void) fprintf(stdout,"rF");Cudd_PrintDebug(bdd,rF,n,pr);} /* P(x) = \exists_{y}(F(x,y) \cdot new^l(y)) */ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, neW[l], x, y, n)); Cudd_Ref(P = Cudd_bddAndAbstract(bdd, *F, p, ycube)); Cudd_RecursiveDeref(bdd,p); /* rB(x) = P(x) \cdot \overline{reached(x)}) */ Cudd_Ref(rB = Cudd_bddAnd(bdd, P, Cudd_Not(reached))); Cudd_RecursiveDeref(bdd,P); if(pr>2){(void) fprintf(stdout,"rB");Cudd_PrintDebug(bdd,rB,n,pr);} /* new^{l+1}(x) = rF(x) + rB(x) */ Cudd_Ref(neW[l+1] = Cudd_bddOr(bdd, rF, rB)); Cudd_RecursiveDeref(bdd,rB); Cudd_RecursiveDeref(bdd,rF); if(pr>0) { (void) fprintf(stdout,"new[%d]",l+1); Cudd_PrintDebug(bdd,neW[l+1],n,pr); } } /* start next layer */ if (l==MAXLAYER) (void) fprintf(stderr,"ERROR! MAXLAYER exceeded.\n"); exit(3); endLayers: maximal_push(bdd, l-1, U, F, x, y, z, n, pryz, prxz, &stats); for (j = 0; j < l; j++) { Cudd_RecursiveDeref(bdd,U[j]); Cudd_RecursiveDeref(bdd,neW[j]); } Cudd_RecursiveDeref(bdd,neW[l]); if (pr > 0) { Cudd_Ref(p = Cudd_bddAnd(bdd, sx, *F)); Ms=Cudd_CountMinterm(bdd, p, n<<1); (void) fprintf(stdout,"# Flow out of s: %g\n", Ms); Cudd_RecursiveDeref(bdd,p); } if (Cudd_bddLeq(bdd, fit, *F)) { Cudd_Ref(*cut = fit); goto endPhases; } } /* start next phase */ if (i == MAXPHASE) (void) fprintf(stderr,"ERROR! MAXPHASE exceeded.\n");
/* Last phase is completed --- print flow results. */ endPhases: Cudd_RecursiveDeref(bdd,tx);
Cudd_Ref(q = Cudd_bddAnd(bdd, *F, sx)); Ms = Cudd_CountMinterm(bdd, q, n<<1); Cudd_RecursiveDeref(bdd,q);
Cudd_Ref(q = Cudd_bddAnd(bdd, *F, ty)); Mt = Cudd_CountMinterm(bdd, q, n<<1); Cudd_RecursiveDeref(bdd,q);
if (pr>1) (void) fprintf(stdout,"Mt= %g, Ms= %g \n", Mt, Ms);
if (pr>3){(void) fprintf(stdout,"pryz");Cudd_PrintDebug(bdd,pryz,n*3,pr);} if (pr>3){(void) fprintf(stdout,"prxz");Cudd_PrintDebug(bdd,prxz,n*3,pr);}
if (pr>0) { (void) fprintf(stdout,"#### Stats for maximum_flow ####\n"); (void) fprintf(stdout,"%d variables %d of which x[i]\n", Cudd_ReadSize(bdd), n); (void) fprintf(stdout,"time = %s\n", util_print_time(util_cpu_time() - stats.start_time)); (void) fprintf(stdout,"phases = %d\n", stats.phases); (void) fprintf(stdout,"layers = %d\n", stats.layers); (void) fprintf(stdout,"FP iter. = %d\n", stats.fpit); }
Cudd_RecursiveDeref(bdd,fit); Cudd_RecursiveDeref(bdd,pryz); Cudd_RecursiveDeref(bdd,prxz); Cudd_RecursiveDeref(bdd,xcube); Cudd_RecursiveDeref(bdd,ycube); Cudd_RecursiveDeref(bdd,zcube); #ifdef PRUNE
Cudd_RecursiveDeref(bdd,E); #endif
FREE(U); FREE(neW);
return(Ms);
} /* end of Ntr_maximum01Flow */
/*---------------------------------------------------------------------------*/ /* Definition of internal functions */ /*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/ /* Definition of static functions */ /*---------------------------------------------------------------------------*/
/**
@brief Selects set of edge-disjoint paths from layered network.
@details maximal_pull is called when the BFS constructing the layered graph reaches a sink. At this point the new sets of the BFS have been formed, and we know every vertex in these sets is reachable from the source vertex (or vertices) s. The new sets are used to compute the set of useful edges exiting each layer to the right. In each layer, propagate_maximal_flow is called to select a maximal subset of these useful edges. This subset is then used to prune new and U.
@sideeffect None
@see maximal_push
*/ static void maximal_pull( DdManager * bdd /**< manager */, int l /**< depth of layered network for current phase */, DdNode * ty /**< sink node */, DdNode ** neW /**< array of BFS layers */, DdNode ** U /**< array of useful edges */, DdNode * E /**< edge relation */, DdNode ** F /**< flow relation */, DdNode ** x /**< array of variables for rows and columns */, DdNode ** y /**< array of variables for rows and columns */, DdNode ** z /**< array of variables for rows and columns */, int n /**< number of x variables */, DdNode * pryz /**< priority function */, DdNode * prxz /**< priority function */, flowStats * stats /**< statistics */) { DdNode *p, *q, *r, *UF, *UB; int m, pr; /* Print control */
pr = stats->pr;
/* The useful edges of the last layer are all the empty edges into
** the sink(s) from new[l]. ** U^{l}(x,y) = t(y)\cdot \overline{F(x,y)}\cdot E(x,y)\cdot new^{l}(x) */ Cudd_Ref(p = Cudd_bddAnd(bdd, E, Cudd_Not(*F))); Cudd_Ref(q = Cudd_bddAnd(bdd, neW[l], p)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(U[l] = Cudd_bddAnd(bdd, ty, q)); Cudd_RecursiveDeref(bdd,q); if(pr>1){(void) fprintf(stdout,"U[%d]",l);Cudd_PrintDebug(bdd,U[l],n<<1,pr);} /* Eliminate from new[l] the states with no paths to the sink(s).
** new^{l}(x)=\exists_y U^{l}(x,y) */ Cudd_RecursiveDeref(bdd,neW[l]); Cudd_Ref(neW[l] = Cudd_bddExistAbstract(bdd, U[l], ycube));
for (m = l; m >= 1; m--) { /* Find usable backward edges from level m-1 to level m.
** UB(x,y) = new^{m}(x) \cdot F(x,y) \cdot new^{m-1}(y) */ Cudd_Ref(r = Cudd_bddSwapVariables(bdd, neW[m-1], x, y, n)); Cudd_Ref(q = Cudd_bddAnd(bdd, r, *F)); Cudd_RecursiveDeref(bdd,r); Cudd_Ref(UB = Cudd_bddAnd(bdd, neW[m], q)); Cudd_RecursiveDeref(bdd,q); if(pr>2){(void) fprintf(stdout,"UB");Cudd_PrintDebug(bdd,UB,n<<1,pr);} /* Find usable forward edges.
** UF(x,y) = new^{m}(y) \cdot \overline{F(x,y)} \cdot E(x,y) ** \cdot new^{m-1}(x) */ Cudd_Ref(p = Cudd_bddAnd(bdd, E, Cudd_Not(*F))); Cudd_Ref(q = Cudd_bddAnd(bdd, neW[m-1], p)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(r = Cudd_bddSwapVariables(bdd, neW[m], x, y, n)); Cudd_Ref(UF = Cudd_bddAnd(bdd, r, q)); Cudd_RecursiveDeref(bdd,q); Cudd_RecursiveDeref(bdd,r); if(pr>2){(void) fprintf(stdout,"UF");Cudd_PrintDebug(bdd,UF,n<<1,pr);} /* U^{m-1}(x,y) = UB(y,x) + UF(x,y) */ Cudd_Ref(r = Cudd_bddSwapVariables(bdd, UB, x, y, n)); Cudd_RecursiveDeref(bdd,UB); Cudd_Ref(U[m-1] = Cudd_bddOr(bdd, UF, r)); Cudd_RecursiveDeref(bdd,UF); Cudd_RecursiveDeref(bdd,r); if(pr>2){(void)fprintf(stdout,"U[%d]",m-1); Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);} /* new[m-1](x) = \exists_{y}U^{m-1}(x,y) */ Cudd_RecursiveDeref(bdd,neW[m-1]); Cudd_Ref(neW[m-1] = Cudd_bddExistAbstract(bdd, U[m-1], ycube)); /* Compute maximal disjoint interlayer edge set. */ propagate_maximal_flow(bdd, m, neW, U, x, y, z, n, pryz, prxz, stats); if(pr>0) { (void)fprintf(stdout,"U[%d]",m-1); Cudd_PrintDebug(bdd,U[m-1],n<<1,pr); } } /* prune next layer */
return;
} /* end of maximal_pull */
/**
@brief Pulls flow though a layer.
@details propagate_maximal_flow only affects U[m-1 and new[m-1]. At the end of this function, the edges in U[m] are guaranteed to drain all the flow supplied by the edges in U[m-1]. This effect is obtained by pruning U[m-1]. After the pruned U[m-1] is computed, new[m-1] is updated to keep track of what nodes are still useful.
The pruning is performed without actually measuring the in-potential and the out-potential of each node. Instead, pairs of nodes from U[m-1] and U[m] are matched. To avoid counting, the procedure computes sets of paths that connect layer m-1 to layer m+1 and are edge-disjoint.
Two paths from layer m-1 to layer m+1 are disjoint if they have distinct end-point or if they have distinct middle points. What condition to enforce depends on the "shape" of the layers.]
@sideeffect Changes U[m-1 and new[m-1]]
@see trellis rhombus hourglass
*/ static void propagate_maximal_flow( DdManager * bdd /**< %DD manager */, int m /**< center of current bilayer */, DdNode ** neW /**< array of reachable or useful nodes */, DdNode ** U /**< array of usable or useful edges */, DdNode ** x /**< array of variables for rows and columns */, DdNode ** y /**< array of variables for rows and columns */, DdNode ** z /**< array of variables for rows and columns */, int n /**< number of x variables */, DdNode * pryz /**< priority function */, DdNode * prxz /**< priority function */, flowStats * stats /**< statistics */) { DdNode *rN; double mtl, mtc, mtr; /* minterms for left, center, right levels */ int pr; /* print control */
pr = stats->pr;
mtl = Cudd_CountMinterm(bdd, neW[m-1], n); mtc = Cudd_CountMinterm(bdd, neW[m], n);
/* rN(y) = \exists_x U^{m}(x,y) */ Cudd_Ref(rN = Cudd_bddExistAbstract(bdd, U[m], xcube)); mtr = Cudd_CountMinterm(bdd, rN, n); Cudd_RecursiveDeref(bdd,rN);
if (pr > 0) { (void) fprintf(stdout, "layer = %d mtl = %g mtc = %g mtr = %g", m, mtl, mtc, mtr); }
if ((mtc > MANY_TIMES * mtl) || (mtc > MANY_TIMES * mtr)) { if (pr>0) (void) fprintf(stdout, " R\n"); rhombus(bdd, m, neW, U, x, y, z, n, pryz, prxz, stats); } else if (mtr > MANY_TIMES * mtc) { if (pr>0) (void) fprintf(stdout, " H\n"); hourglass(bdd, m, neW, U, x, y, z, n, pryz, prxz, stats); } else { if (pr>0) (void) fprintf(stdout, " T\n"); trellis(bdd, m, neW, U, x, y, z, n, pryz, prxz, stats); } return;
} /* end of propagate_maximal_flow */
/**
@brief Selects edges from a trellis-type bilayer.
@details Used to pull flow. First a matching is found in the left layer. Then the paths are extended (if possible) through the right layer. This process is repeated until a maximal flow is found.
@sideeffect None
@see rhombus hourglass trellisPush
*/ static void trellis( DdManager * bdd /**< %DD manager */, int m /**< center level of current bilayer */, DdNode ** neW /**< array of node levels */, DdNode ** U /**< array of edge layers */, DdNode ** x /**< array of variables for rows and columns */, DdNode ** y /**< array of variables for rows and columns */, DdNode ** z /**< array of variables for rows and columns */, int n /**< number of x variables */, DdNode * pryz /**< priority function */, DdNode * prxz /**< priority function */, flowStats * stats /**< statistics */) { DdNode *one, *zero, *p, *q, *r, *Uin, /* edges to be matched from U[m-1] */ *Uout, /* edges to be matched from U[m] */ *P, *LU, *RU, /* left-unique and right-unique sets of edges */ *D, *Ml, *Mr; /* nodes matched from left and right */ int k, pr; /* print control */
pr = stats->pr;
one = Cudd_ReadOne(bdd); zero = Cudd_Not(one);
/*Uout(x,y)=U^m(x,y)*/ Cudd_Ref(Uout = U[m]); if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} /*Uin(x,y)=U^{m-1}(x,y)*/ Cudd_Ref(Uin = U[m-1]); if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
for(k = 0; k < MAXFPIT; k++) { stats->fpit++; /*LU(x,y)=Uin(x,y)\cdot\overline{\exists_{z}(Uin(z,y)\cdot\Pi(x,z))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uin, x, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, prxz, zcube)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(LU = Cudd_bddAnd(bdd, Uin, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);} /*D(x,y)= LU(x,y)\cdot \overline{\exists_{z}(LU(x,z)\cdot \Pi(y,z))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, LU, y, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(D = Cudd_bddAnd(bdd, LU, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); Cudd_RecursiveDeref(bdd,LU); if(pr>3){(void)fprintf(stdout,"D");Cudd_PrintDebug(bdd,D,n<<1,pr);} /*Ml(y)=\exists_{x}D(x,y)*/ Cudd_Ref(Ml = Cudd_bddExistAbstract(bdd, D, xcube)); if(pr>3){(void)fprintf(stdout,"Ml");Cudd_PrintDebug(bdd,Ml,n,pr);} /*P(x,y)=Ml(x)\cdot Uout(x,y)*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Ml, x, y, n)); Cudd_Ref(P = Cudd_bddAnd(bdd, p, Uout)); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,Ml); if(pr>3){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n<<1,pr);} /*RU(x,y)= P(x,y)\cdot \overline{\exists_{z}(P(x,z)\cdot \Pi(y,z))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, y, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(RU = Cudd_bddAnd(bdd, P, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); Cudd_RecursiveDeref(bdd,P); if(pr>3){(void)fprintf(stdout,"RU");Cudd_PrintDebug(bdd,RU,n<<1,pr);} /*Mr(x)=\exists_{y}RU(x,y)*/ Cudd_Ref(Mr = Cudd_bddExistAbstract(bdd, RU, ycube)); if(pr>3){(void)fprintf(stdout,"Mr");Cudd_PrintDebug(bdd,Mr,n,pr);} /*D(x,y)=D(x,y)\cdot Mr(y)*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Mr, x, y, n)); Cudd_RecursiveDeref(bdd,Mr); Cudd_Ref(q = Cudd_bddAnd(bdd, D, p)); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,D); D = q; if(pr>3){(void)fprintf(stdout,"D");Cudd_PrintDebug(bdd,D,n<<1,pr);} /*Uin(x,y)=Uin(x,y)-D(x,y)*/ Cudd_Ref(p = Cudd_bddAnd(bdd, Uin, Cudd_Not(D))); Cudd_RecursiveDeref(bdd,Uin); Uin = p; if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} /*Uout(x,y)=Uout(x,y)-RU(x,y)*/ Cudd_Ref(p = Cudd_bddAnd(bdd, Uout, Cudd_Not(RU))); Cudd_RecursiveDeref(bdd,Uout); Cudd_RecursiveDeref(bdd,RU); Uout = p; if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} /*\KW{if}(($D(x,y)=zero$)~~\KW{or}~~($Uin(x,y)=zero$)~~\KW{or}
($Uout(x,y)=zero$))~~KW{break}*/ if ((D == zero)||(Uin == zero)||(Uout == zero)) { Cudd_RecursiveDeref(bdd,D); break; } Cudd_RecursiveDeref(bdd,D);
} /* Next least fixed point iteration with smaller Uin and Uout */ if (k == MAXFPIT) (void) fprintf(stderr, "Trellis: WARNING! MAXFPIT (%d) exceeded processing Layer %d.\n", MAXFPIT, m);
if (Uin != zero) { /* $U^{m-1}(x,y) = U^{m-1}(x,y)-Uin(x,y)$*/ Cudd_Ref(p = Cudd_bddAnd(bdd, U[m-1], Cudd_Not(Uin))); Cudd_RecursiveDeref(bdd,U[m-1]); U[m-1] = p; /* $new^{m-1}(x,y) = \esists_yU^{m-1}(x,y)$*/ Cudd_RecursiveDeref(bdd,neW[m-1]); Cudd_Ref(neW[m-1] = Cudd_bddExistAbstract(bdd, U[m-1], ycube)); } if(pr>2){(void)fprintf(stdout,"U[%d]",m-1); Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);} if(pr>2){(void)fprintf(stdout,"new[%d]",m-1); Cudd_PrintDebug(bdd,neW[m-1],n,pr);}
Cudd_RecursiveDeref(bdd,Uin); Cudd_RecursiveDeref(bdd,Uout);
return;
} /* end of trellis */
/**
@brief Selects edges from a rhombus-type bilayer.
@details Used to pull flow. Makes the left layer left-unique and the right layer right-unique. Prunes and repeats until convergence to a maximal flow. It makes sure that all intermediate points of the two-arc paths are disjoint at each iteration.
@sideeffect None
@see trellis hourglass rhombusPush
*/ static void rhombus( DdManager * bdd /**< %DD manager */, int m /**< center of current bilayer */, DdNode ** neW /**< array for flow propagation */, DdNode ** U /**< array for flow propagation */, DdNode ** x /**< array of variables for rows and columns */, DdNode ** y /**< array of variables for rows and columns */, DdNode ** z /**< array of variables for rows and columns */, int n /**< number of x variables */, DdNode * pryz /**< priority function */, DdNode * prxz /**< priority function */, flowStats * stats /**< statistics */) { DdNode *one, *zero, *p, *q, *r, *Uin, /* edges to be matched from U[m-1] */ *Uout, /* edges to be matched from U[m] */ *P, *LU, *RU, /* left-unique and right-unique sets of edges */ *Ml, *Mr; /* nodes matched from left and right */ int k, pr; /* print control */
pr = stats->pr;
one = Cudd_ReadOne(bdd); zero = Cudd_Not(one);
/*Uout(x,y)=U^m(x,y)*/ Cudd_Ref(Uout = U[m]); if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
/*Uin(x,y)=U^{m-1}(x,y)*/ Cudd_Ref(Uin = U[m-1]); if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
for(k = 0; k < MAXFPIT; k++) { stats->fpit++; /*LU(x,y)=Uin(x,y)\cdot\overline{\exists_{z}(Uin(z,y)\cdot\Pi(x,z))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uin, x, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, prxz, zcube)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(LU = Cudd_bddAnd(bdd, Uin, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);} /*Ml(y)=\exists_{x}LU(x,y)*/ Cudd_Ref(Ml = Cudd_bddExistAbstract(bdd, LU, xcube)); if(pr>3){(void)fprintf(stdout,"Ml");Cudd_PrintDebug(bdd,Ml,n,pr);} /*P(x,y)=Ml(x)\cdot Uout(x,y)*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Ml, x, y, n)); Cudd_Ref(P = Cudd_bddAnd(bdd, p, Uout)); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,Ml); if(pr>3){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n<<1,pr);} /*RU(x,y)= P(x,y)\cdot \overline{\exists_{z}(P(x,z)\cdot \Pi(y,z))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, y, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(RU = Cudd_bddAnd(bdd, P, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); Cudd_RecursiveDeref(bdd,P); if(pr>3){(void)fprintf(stdout,"RU");Cudd_PrintDebug(bdd,RU,n<<1,pr);} /*Mr(x)=\exists_{y}RU(x,y)*/ Cudd_Ref(Mr = Cudd_bddExistAbstract(bdd, RU, ycube)); if(pr>3){(void)fprintf(stdout,"Mr");Cudd_PrintDebug(bdd,Mr,n,pr);} /*LU(x,y)=LU(x,y)\cdot Mr(y)*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Mr, x, y, n)); Cudd_RecursiveDeref(bdd,Mr); Cudd_Ref(q = Cudd_bddAnd(bdd, LU, p)); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,LU); LU = q; if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);} /*Uin(x,y)=Uin(x,y)-LU(x,y)*/ Cudd_Ref(p = Cudd_bddAnd(bdd, Uin, Cudd_Not(LU))); Cudd_RecursiveDeref(bdd,Uin); Uin = p; if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} /*Uout(x,y)=Uout(x,y)-RU(x,y)*/ Cudd_Ref(p = Cudd_bddAnd(bdd, Uout, Cudd_Not(RU))); Cudd_RecursiveDeref(bdd,Uout); Cudd_RecursiveDeref(bdd,RU); Uout = p; if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} /*\KW{if}(($LU(x,y)=zero$)~~\KW{or}~~($Uin(x,y)=zero$)~~\KW{or}
($Uout(x,y)=zero$))~~KW{break}*/ if((LU == zero)||(Uin == zero)||(Uout == zero)) { Cudd_RecursiveDeref(bdd,LU); break; } Cudd_RecursiveDeref(bdd,LU);
} /* Next least fixed point iteration with smaller Uin and Uout */ if (k == MAXFPIT) (void) fprintf(stderr, "Rhombus: WARNING! MAXFPIT (%d) exceeded processing Layer %d.\n", MAXFPIT, m);
if (Uin != zero) { /* $U^{m-1}(x,y) = U^{m-1}(x,y)-Uin(x,y)$*/ Cudd_Ref(p = Cudd_bddAnd(bdd, U[m-1], Cudd_Not(Uin))); Cudd_RecursiveDeref(bdd,U[m-1]); U[m-1] = p; /* $new^{m-1}(x,y) = \esists_yU^{m-1}(x,y)$*/ Cudd_RecursiveDeref(bdd,neW[m-1]); Cudd_Ref(neW[m-1] = Cudd_bddExistAbstract(bdd, U[m-1], ycube)); } if(pr>2){(void)fprintf(stdout,"U[%d]",m-1); Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);} if(pr>2){ (void)fprintf(stdout,"new[%d]",m-1); Cudd_PrintDebug(bdd,neW[m-1],n,pr); } Cudd_RecursiveDeref(bdd,Uin); Cudd_RecursiveDeref(bdd,Uout);
return;
} /* end of rhombus */
/**
@brief Selects edges from a hourglass-type bilayer.
@details Used to pull flow. Method described in paper. More general, but more expensive than the others.
@sideeffect None
@see trellis rhombus hourglassPush
*/ static void hourglass( DdManager * bdd /**< %DD manager */, int m /**< center level of current bilayer */, DdNode ** neW /**< array for flow propagation */, DdNode ** U /**< array for flow propagation */, DdNode ** x /**< array of variables for rows and columns */, DdNode ** y /**< array of variables for rows and columns */, DdNode ** z /**< array of variables for rows and columns */, int n /**< number of x variables */, DdNode * pryz /**< priority function */, DdNode * prxz /**< priority function */, flowStats * stats /**< statistics */) { DdNode *one, *zero, *przy, *p, *q, *r, *Uin, /* edges to be matched from U[m-1] */ *Uout, /* edges to be matched from U[m] */ *P, *Q, *PA, *D; int k, pr; /* print control */
pr = stats->pr;
one = Cudd_ReadOne(bdd); zero = Cudd_Not(one);
/* Build priority function. */ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, pryz, y, z, n)); Cudd_Ref(przy = Cudd_bddAdjPermuteX(bdd,p,x,n)); Cudd_RecursiveDeref(bdd,p); if(pr>2){(void)fprintf(stdout,"przy");Cudd_PrintDebug(bdd,przy,n*3,pr);}
/*Uout(x,y)=U^m(x,y)*/ Cudd_Ref(Uout = U[m]); if(pr>1){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
/*Uin(x,y)=U^{m-1}(x,y)*/ Cudd_Ref(Uin = U[m-1]); if(pr>1){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
for(k = 0; k < MAXFPIT; k++) { stats->fpit++; /*P(x,y,z)=Uin(x,y)\cdot Uout(y,z)*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uout, y, z, n)); if(pr>2){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);} Cudd_Ref(q = Cudd_bddSwapVariables(bdd, p, x, y, n)); Cudd_RecursiveDeref(bdd,p); if(pr>2){(void)fprintf(stdout,"q");Cudd_PrintDebug(bdd,q,n<<1,pr);} Cudd_Ref(P = Cudd_bddAnd(bdd, Uin, q)); Cudd_RecursiveDeref(bdd,q); if(pr>1){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n*3,pr);} /*PA(x,z)=\exists_yP(x,y,z)*/ Cudd_Ref(PA = Cudd_bddExistAbstract(bdd, P, ycube)); if(pr>2){(void)fprintf(stdout,"PA");Cudd_PrintDebug(bdd,PA,n<<1,pr);} if(pr>3) { Cudd_Ref(p = Cudd_bddExistAbstract(bdd, PA, xcube)); (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(p = Cudd_bddExistAbstract(bdd, PA, zcube)); (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr); Cudd_RecursiveDeref(bdd,p); } /*Q(x,z)= PA(x,z)\cdot \overline{\exists_{y}(PA(x,y)\cdot \Pi(z,y))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, PA, y, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, przy, ycube)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(Q = Cudd_bddAnd(bdd, PA, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); Cudd_RecursiveDeref(bdd,PA); if(pr>2){(void)fprintf(stdout,"Q");Cudd_PrintDebug(bdd,Q,n<<1,pr);} if(pr>3) { Cudd_Ref(p = Cudd_bddExistAbstract(bdd, Q, xcube)); (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr); Cudd_RecursiveDeref(bdd,p); } /*D(x,z)= Q(x,z)\cdot \overline{\exists_{y}(Q(y,z)\cdot \Pi(x,y))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Q, x, y, n)); Cudd_Ref(q = Cudd_bddSwapVariables(bdd, prxz, y, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, q, ycube)); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,q); Cudd_Ref(D = Cudd_bddAnd(bdd, Q, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); Cudd_RecursiveDeref(bdd,Q); if(pr>1){(void)fprintf(stdout,"D");Cudd_PrintDebug(bdd,D,n<<1,pr);} /*P(x,y,z)=P(x,y,z)\cdot D(x,z)*/ Cudd_Ref(p = Cudd_bddAnd(bdd, P, D)); Cudd_RecursiveDeref(bdd,D); Cudd_RecursiveDeref(bdd,P); P = p; if(pr>2){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n*3,pr);} /*Uin(x,y)=Uin(x,y)-\exists_zP(x,y,z)*/ Cudd_Ref(p = Cudd_bddExistAbstract(bdd, P, zcube)); if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);} Cudd_Ref(q = Cudd_bddAnd(bdd, Uin, Cudd_Not(p))); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,Uin); Uin = q; if(pr>1){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);} /*Uout(x,y)=Uout(x,y)-\exists_zP(z,x,y)*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, x, y, n)); if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n*3,pr);} Cudd_Ref(r = Cudd_bddSwapVariables(bdd, p, y, z, n)); Cudd_RecursiveDeref(bdd,p); if(pr>3){(void)fprintf(stdout,"r");Cudd_PrintDebug(bdd,r,n*3,pr);} Cudd_Ref(p = Cudd_bddExistAbstract(bdd, r, zcube)); Cudd_RecursiveDeref(bdd,r); if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);} Cudd_Ref(q = Cudd_bddAnd(bdd, Uout, Cudd_Not(p))); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,Uout); Uout = q; if(pr>1){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);} /*\KW{if}(($P(x,y,z)=zero$)~~\KW{or}~~($Uin(x,y)=zero$)~~\KW{or}
($Uout(x,y)=zero$))~~KW{break}*/ if((P == zero)||(Uin == zero)||(Uout == zero)) { Cudd_RecursiveDeref(bdd,P); break; } Cudd_RecursiveDeref(bdd,P);
} /* Next least fixed point iteration with smaller P */ if (k == MAXFPIT) (void) fprintf(stderr, "Hourglass: WARNING! MAXFPIT (%d) exceeded processing Layer %d.\n", MAXFPIT, m);
if (Uin != zero) { /* $U^{m-1}(x,y) = U^{m-1}(x,y)-Uin(x,y)$*/ Cudd_Ref(p = Cudd_bddAnd(bdd, U[m-1], Cudd_Not(Uin))); Cudd_RecursiveDeref(bdd,U[m-1]); U[m-1] = p; /* $new^{m-1}(x,y) = \esists_yU^{m-1}(x,y)$*/ Cudd_RecursiveDeref(bdd,neW[m-1]); Cudd_Ref(neW[m-1] = Cudd_bddExistAbstract(bdd, U[m-1], ycube)); } if(pr>1){(void)fprintf(stdout,"U[%d]",m-1); Cudd_PrintDebug(bdd,U[m-1],n<<1,pr);} if(pr>1){(void)fprintf(stdout,"new[%d]",m-1); Cudd_PrintDebug(bdd,neW[m-1],n,pr);}
Cudd_RecursiveDeref(bdd,Uin); Cudd_RecursiveDeref(bdd,Uout); Cudd_RecursiveDeref(bdd,przy);
return;
} /* end of hourglass */
/**
@brief Pushes flow through useful edges.
@details Pushes flow from the source(s) to the sink(s) through useful edges.
@sideeffect None
*/ static void maximal_push( DdManager * bdd /**< %DD manager */, int l /**< Depth of layered network for current phase */, DdNode ** U /**< array of edge sets for flow propagation */, DdNode ** F /**< edge and flow relations */, DdNode ** x /**< array of variables for rows and columns */, DdNode ** y /**< array of variables for rows and columns */, DdNode ** z /**< array of variables for rows and columns */, int n /**< number of x variables */, DdNode * pryz /**< priority function */, DdNode * prxz /**< priority function */, flowStats * stats /**< statistics */) { DdNode *p, *q, *r, *UT, *lN, *cN, *rN; /* left, center, right nodes of bilayer */ double mtl, mtc, mtr; int m, pr; /* print control */
pr = stats->pr;
if (l == 0) { /* F(x,y) = F(x,y) + U^{0}(x,y) */ Cudd_Ref(q = Cudd_bddOr(bdd, *F, U[0])); Cudd_RecursiveDeref(bdd,*F); *F = q; if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);} return; }
for (m = 1; m < l; m++) { /* lN(x) = \exists_y U^{m-1}(x,y) */ Cudd_Ref(lN = Cudd_bddExistAbstract(bdd, U[m-1], ycube)); mtl = Cudd_CountMinterm(bdd, lN, n); Cudd_RecursiveDeref(bdd,lN);
/* cN(y) = \exists_x U^{m-1}(x,y) */ Cudd_Ref(cN = Cudd_bddExistAbstract(bdd, U[m-1], xcube)); mtc = Cudd_CountMinterm(bdd, cN, n); Cudd_RecursiveDeref(bdd,cN);
/* rN(y) = \exists_x U^{m}(x,y) */ Cudd_Ref(rN = Cudd_bddExistAbstract(bdd, U[m], xcube)); mtr = Cudd_CountMinterm(bdd, rN, n); Cudd_RecursiveDeref(bdd,rN);
if (pr > 0) { (void) fprintf(stdout, "layer = %d mtl = %g mtc = %g mtr = %g", m, mtl, mtc, mtr); } if ((mtc > MANY_TIMES * mtl) && !(mtr > MANY_TIMES * mtl)) { if (pr>0) (void) fprintf(stdout, " R\n"); rhombusPush(bdd, m, U, x, y, z, n, pryz, prxz, stats); } else if (mtl > MANY_TIMES * mtc) { if (pr>0) (void) fprintf(stdout, " H\n"); hourglassPush(bdd, m, U, x, y, z, n, pryz, prxz, stats); } else { if (pr>0) (void) fprintf(stdout, " T\n"); trellisPush(bdd, m, U, x, y, z, n, pryz, prxz, stats); }
/* F(x,y) = F(x,y) + U^{m-1}(x,y) \cdot \overline{F(y,x)} */ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, *F, x, y, n)); Cudd_Ref(q = Cudd_bddAnd(bdd, Cudd_Not(p), U[m-1])); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(r = Cudd_bddOr(bdd, *F, q)); Cudd_RecursiveDeref(bdd,q); Cudd_RecursiveDeref(bdd,*F); *F = r; if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
/* F(x,y) = F(x,y) - U^{m-1}(y,x) */ Cudd_Ref(r = Cudd_bddSwapVariables(bdd, U[m-1], x, y, n)); Cudd_Ref(q = Cudd_bddAnd(bdd, *F, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); Cudd_RecursiveDeref(bdd,*F); *F = q; if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
} /* Push maximal flow to next layer */
/*F(x,y)=F(x,y)+U^{l-1}(x,y)\cdot\overline{F(y,x)}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, *F, x, y, n)); Cudd_Ref(q = Cudd_bddAnd(bdd, Cudd_Not(p), U[l-1])); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(r = Cudd_bddOr(bdd, *F, q)); Cudd_RecursiveDeref(bdd,q); Cudd_RecursiveDeref(bdd,*F); *F = r; if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
/*F(y,x)=F(y,x)-U^{l-1}(x,y)*/ Cudd_Ref(r = Cudd_bddSwapVariables(bdd, U[l-1], x, y, n)); Cudd_Ref(q = Cudd_bddAnd(bdd, *F, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); Cudd_RecursiveDeref(bdd,*F); *F = q; if(pr>1){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
/*UT(x,y)=\exists_y(U^{l-1}(y,x))\cdot U^{l}(x,y)*/ Cudd_Ref(p = Cudd_bddExistAbstract(bdd, U[l-1], xcube)); if(pr>4){(void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr);} Cudd_Ref(q = Cudd_bddSwapVariables(bdd, p, x, y, n)); Cudd_RecursiveDeref(bdd,p); if(pr>4){(void) fprintf(stdout,"q");Cudd_PrintDebug(bdd,q,n,pr);} Cudd_Ref(UT = Cudd_bddAnd(bdd, U[l], q)); Cudd_RecursiveDeref(bdd,q); if(pr>2){(void) fprintf(stdout,"UT");Cudd_PrintDebug(bdd,UT,n<<1,pr);}
/*F(x,y)=F(x,y)+UT(x,y)\cdot\overline{F(y,x)}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, *F, x, y, n)); Cudd_Ref(q = Cudd_bddAnd(bdd, Cudd_Not(p), UT)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(r = Cudd_bddOr(bdd, *F, q)); Cudd_RecursiveDeref(bdd,q); Cudd_RecursiveDeref(bdd,*F); *F = r; if(pr>3){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
/*F(y,x)=F(y,x)-UT(x,y)*/ Cudd_Ref(r = Cudd_bddSwapVariables(bdd, UT, x, y, n)); Cudd_RecursiveDeref(bdd,UT); Cudd_Ref(q = Cudd_bddAnd(bdd, *F, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); Cudd_RecursiveDeref(bdd,*F); *F = q; if(pr>1){(void) fprintf(stdout,"F");Cudd_PrintDebug(bdd,*F,n<<1,pr);}
return;
} /* end of maximal_push */
/**
@brief Pushes flow through a trellis.
@sideeffect None
*/ static void trellisPush( DdManager * bdd /**< %DD manager */, int m /**< Current layer */, DdNode ** U /**< Array of edge sets for flow propagation */, DdNode ** x /**< Array of variables for rows and columns */, DdNode ** y /**< Array of variables for rows and columns */, DdNode ** z /**< Array of variables for rows and columns */, int n /**< Number of x variables */, DdNode * pryz /**< Priority function */, DdNode * prxz /**< Priority function */, flowStats * stats /**< statistics */) { DdNode *one, *zero, *p, *r, *Uin, /* Edges to be matched from U[m-1] */ *Uout, /* Edges to be matched from U[m] */ *RU, *LU, *P, *Ml;
int i, pr; /* Print control */
pr = stats->pr;
one = Cudd_ReadOne(bdd); zero = Cudd_Not(one);
/*Uout(x,y)=U^m(x,y)*/ Cudd_Ref(Uout = U[m]); if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
/*Uin(x,y)=U^{m-1}(x,y)*/ Cudd_Ref(Uin = U[m-1]); if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
for(i=0; i<MAXFPIT; i++) { stats->fpit++; /*LU(x,y)=Uin(x,y)\cdot\overline{\exists_{z}(Uin(z,y)\cdot\Pi(x,z))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uin, x, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, prxz, zcube)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(LU = Cudd_bddAnd(bdd, Uin, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);}
/*Ml(y)=\exists_{x}LU(x,y)*/ Cudd_Ref(Ml = Cudd_bddExistAbstract(bdd, LU, xcube)); if(pr>3){(void)fprintf(stdout,"Ml");Cudd_PrintDebug(bdd,Ml,n,pr);}
/*P(x,y)=Ml(x)\cdot Uout(x,y)*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Ml, x, y, n)); Cudd_Ref(P = Cudd_bddAnd(bdd, p, Uout)); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,Ml); if(pr>3){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n<<1,pr);}
/*RU(x,y)= P(x,y)\cdot \overline{\exists_{z}(P(x,z)\cdot \Pi(y,z))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, y, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(RU = Cudd_bddAnd(bdd, P, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); Cudd_RecursiveDeref(bdd,P); if(pr>3){(void)fprintf(stdout,"RU");Cudd_PrintDebug(bdd,RU,n<<1,pr);}
/*Uin(x,y)=Uin(x,y)-LU(x,y)*/ Cudd_Ref(p = Cudd_bddAnd(bdd, Uin, Cudd_Not(LU))); Cudd_RecursiveDeref(bdd,Uin); Uin = p; if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
/*Uout(x,y)=Uout(x,y)-RU(x,y)*/ Cudd_Ref(p = Cudd_bddAnd(bdd, Uout, Cudd_Not(RU))); Cudd_RecursiveDeref(bdd,Uout); Cudd_RecursiveDeref(bdd,RU); Uout = p; if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
/*\KW{if}(($LU(x,y)=zero$)~~\KW{or}~~($Uin(x,y)=zero$))~~KW{break}*/ if((LU == zero)||(Uin == zero)) { Cudd_RecursiveDeref(bdd,LU); break; }
Cudd_RecursiveDeref(bdd,LU);
} /* Next least fixed point iteration with smaller Uin and Uout */ if (i == MAXFPIT) (void) fprintf(stderr, "TrellisPush: ERROR! MAXFPIT (%d) exceeded at layer %d.\n", MAXFPIT, m);
/* $U^{m}(x,y) = U^{m}(x,y)-Uout(x,y)$*/ if (Uout != zero) { Cudd_Ref(p = Cudd_bddAnd(bdd, U[m], Cudd_Not(Uout))); Cudd_RecursiveDeref(bdd,U[m]); U[m] = p; if(pr>3){(void)fprintf(stdout,"U[%d]",m); Cudd_PrintDebug(bdd,U[m],n<<1,pr);} }
Cudd_RecursiveDeref(bdd,Uin); Cudd_RecursiveDeref(bdd,Uout);
} /* end of trellisPush */
/**
@brief Pushes flow through a rhombus.
@sideeffect None
*/ static void rhombusPush( DdManager * bdd /**< %DD manager */, int m /**< Current layer */, DdNode ** U /**< Array of edge sets for flow propagation */, DdNode ** x /**< Array of variables for rows and columns */, DdNode ** y /**< Array of variables for rows and columns */, DdNode ** z /**< Array of variables for rows and columns */, int n /**< Number of x variables */, DdNode * pryz /**< Priority function */, DdNode * prxz /**< Priority function */, flowStats * stats /**< statistics */) { DdNode *one, *zero, *p, *r, *Uin, /* Edges to be matched from U[m-1] */ *Uout, /* Edges to be matched from U[m] */ *RU, *LU, *P, *Ml;
int i, pr; /* Print control */
pr = stats->pr;
one = Cudd_ReadOne(bdd); zero = Cudd_Not(one);
/*Uout(x,y)=U^m(x,y)*/ Cudd_Ref(Uout = U[m]); if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
/*Uin(x,y)=U^{m-1}(x,y)*/ Cudd_Ref(Uin = U[m-1]); if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
for(i = 0; i < MAXFPIT; i++) { stats->fpit++; /*RU(x,y)=Uin(x,y)\cdot\overline{\exists_{z}(Uin(x,z)\cdot\Pi(y,z))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uin, y, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, pryz, zcube)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(RU = Cudd_bddAnd(bdd, Uin, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); if(pr>3){(void)fprintf(stdout,"RU");Cudd_PrintDebug(bdd,RU,n<<1,pr);}
/*Ml(y)=\exists_{x}RU(x,y)*/ Cudd_Ref(Ml = Cudd_bddExistAbstract(bdd, RU, xcube)); if(pr>3){(void)fprintf(stdout,"Ml");Cudd_PrintDebug(bdd,Ml,n,pr);}
/*P(x,y)=Ml(x)\cdot Uout(x,y)*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Ml, x, y, n)); Cudd_Ref(P = Cudd_bddAnd(bdd, p, Uout)); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,Ml); if(pr>3){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n<<1,pr);}
/*LU(x,y)= P(x,y)\cdot \overline{\exists_{z}(P(z,y)\cdot \Pi(x,z))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, x, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, prxz, zcube)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(LU = Cudd_bddAnd(bdd, P, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); Cudd_RecursiveDeref(bdd,P); if(pr>3){(void)fprintf(stdout,"LU");Cudd_PrintDebug(bdd,LU,n<<1,pr);}
/*Uin(x,y)=Uin(x,y)-RU(x,y)*/ Cudd_Ref(p = Cudd_bddAnd(bdd, Uin, Cudd_Not(RU))); Cudd_RecursiveDeref(bdd,Uin); Uin = p; if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
/*Uout(x,y)=Uout(x,y)-LU(x,y)*/ Cudd_Ref(p = Cudd_bddAnd(bdd, Uout, Cudd_Not(LU))); Cudd_RecursiveDeref(bdd,Uout); Cudd_RecursiveDeref(bdd,LU); Uout = p; if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
/*\KW{if}(($RU(x,y)=zero$)~~\KW{or}~~($Uin(x,y)=zero$))~~KW{break}*/ if((RU == zero)||(Uin == zero)) { Cudd_RecursiveDeref(bdd,RU); break; }
Cudd_RecursiveDeref(bdd,RU);
} /* Next least fixed point iteration with smaller Uin and Uout */ if (i == MAXFPIT) (void) fprintf(stderr, "RhombusPush: ERROR! MAXFPIT (%d) exceeded at layer %d.\n", MAXFPIT, m);
/* $U^{m}(x,y) = U^{m}(x,y)-Uout(x,y)$*/ if (Uout != zero) { Cudd_Ref(p = Cudd_bddAnd(bdd, U[m], Cudd_Not(Uout))); Cudd_RecursiveDeref(bdd,U[m]); U[m] = p; if(pr>3){(void)fprintf(stdout,"U[%d]",m); Cudd_PrintDebug(bdd,U[m],n<<1,pr);} }
Cudd_RecursiveDeref(bdd,Uin); Cudd_RecursiveDeref(bdd,Uout);
return;
} /* end of rhombusPush */
/**
@brief Pushes flow through an hourglass.
@sideeffect None
*/ static void hourglassPush( DdManager * bdd /**< %DD manager */, int m /**< Current layer */, DdNode ** U /**< Array of edge sets for flow propagation */, DdNode ** x /**< Array of variables for rows and columns */, DdNode ** y /**< Array of variables for rows and columns */, DdNode ** z /**< Array of variables for rows and columns */, int n /**< Number of x variables */, DdNode * pryz /**< Priority function */, DdNode * prxz /**< Priority function */, flowStats * stats /**< statistics */) { DdNode *one, *zero, *przy, *p, *q, *r, *Uin, /* Edges to be matched from U[m-1] */ *Uout, /* Edges to be matched from U[m] */ *P, *Q, *PA, *D;
int i, pr; /* Print control */
pr = stats->pr;
one = Cudd_ReadOne(bdd); zero = Cudd_Not(one);
/* Build priority function. */ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, pryz, y, z, n)); Cudd_Ref(przy = Cudd_bddAdjPermuteX(bdd,p,x,n)); Cudd_RecursiveDeref(bdd,p); if(pr>2){(void)fprintf(stdout,"przy");Cudd_PrintDebug(bdd,przy,n*3,pr);}
/*Uout(x,y)=U^m(x,y)*/ Cudd_Ref(Uout = U[m]); if(pr>3){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
/*Uin(x,y)=U^{m-1}(x,y)*/ Cudd_Ref(Uin = U[m-1]); if(pr>3){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
for(i = 0; i < MAXFPIT; i++) { stats->fpit++; /*P(x,y,z)=Uin(x,y)\cdot Uout(y,z)*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Uout, y, z, n)); if(pr>2){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);} Cudd_Ref(q = Cudd_bddSwapVariables(bdd, p, x, y, n)); Cudd_RecursiveDeref(bdd,p); if(pr>2){(void)fprintf(stdout,"q");Cudd_PrintDebug(bdd,q,n<<1,pr);} Cudd_Ref(P = Cudd_bddAnd(bdd, Uin, q)); Cudd_RecursiveDeref(bdd,q); if(pr>1){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n*3,pr);}
/*PA(x,z)=\exists_yP(x,y,z)*/ Cudd_Ref(PA = Cudd_bddExistAbstract(bdd, P, ycube)); if(pr>2){(void)fprintf(stdout,"PA");Cudd_PrintDebug(bdd,PA,n<<1,pr);} if(pr>3) { Cudd_Ref(p = Cudd_bddExistAbstract(bdd, PA, xcube)); (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(p = Cudd_bddExistAbstract(bdd, PA, zcube)); (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr); Cudd_RecursiveDeref(bdd,p); }
/*Q(x,z)= PA(x,z)\cdot \overline{\exists_{y}(PA(x,y)\cdot \Pi(z,y))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, PA, y, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, przy, ycube)); Cudd_RecursiveDeref(bdd,p); Cudd_Ref(Q = Cudd_bddAnd(bdd, PA, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); Cudd_RecursiveDeref(bdd,PA); if(pr>2){(void)fprintf(stdout,"Q");Cudd_PrintDebug(bdd,Q,n<<1,pr);} if(pr>3) { Cudd_Ref(p = Cudd_bddExistAbstract(bdd, Q, xcube)); (void) fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n,pr); Cudd_RecursiveDeref(bdd,p); }
/*D(x,z)= Q(x,z)\cdot \overline{\exists_{y}(Q(y,z)\cdot \Pi(x,y))}*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, Q, x, y, n)); Cudd_Ref(q = Cudd_bddSwapVariables(bdd, prxz, y, z, n)); Cudd_Ref(r = Cudd_bddAndAbstract(bdd, p, q, ycube)); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,q); Cudd_Ref(D = Cudd_bddAnd(bdd, Q, Cudd_Not(r))); Cudd_RecursiveDeref(bdd,r); Cudd_RecursiveDeref(bdd,Q); if(pr>1){(void)fprintf(stdout,"D");Cudd_PrintDebug(bdd,D,n<<1,pr);}
/*P(x,y,z)=P(x,y,z)\cdot D(x,z)*/ Cudd_Ref(p = Cudd_bddAnd(bdd, P, D)); Cudd_RecursiveDeref(bdd,D); Cudd_RecursiveDeref(bdd,P); P = p; if(pr>2){(void)fprintf(stdout,"P");Cudd_PrintDebug(bdd,P,n*3,pr);}
/*Uin(x,y)=Uin(x,y)-\exists_zP(x,y,z)*/ Cudd_Ref(p = Cudd_bddExistAbstract(bdd, P, zcube)); if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);} Cudd_Ref(q = Cudd_bddAnd(bdd, Uin, Cudd_Not(p))); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,Uin); Uin = q; if(pr>1){(void)fprintf(stdout,"Uin");Cudd_PrintDebug(bdd,Uin,n<<1,pr);}
/*Uout(x,y)=Uout(x,y)-\exists_zP(z,x,y)*/ Cudd_Ref(p = Cudd_bddSwapVariables(bdd, P, x, y, n)); if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n*3,pr);} Cudd_Ref(r = Cudd_bddSwapVariables(bdd, p, y, z, n)); Cudd_RecursiveDeref(bdd,p); if(pr>3){(void)fprintf(stdout,"r");Cudd_PrintDebug(bdd,r,n*3,pr);} Cudd_Ref(p = Cudd_bddExistAbstract(bdd, r, zcube)); Cudd_RecursiveDeref(bdd,r); if(pr>3){(void)fprintf(stdout,"p");Cudd_PrintDebug(bdd,p,n<<1,pr);} Cudd_Ref(q = Cudd_bddAnd(bdd, Uout, Cudd_Not(p))); Cudd_RecursiveDeref(bdd,p); Cudd_RecursiveDeref(bdd,Uout); Uout = q; if(pr>1){(void)fprintf(stdout,"Uout");Cudd_PrintDebug(bdd,Uout,n<<1,pr);}
/*\KW{if}(($P(x,y,z)=zero$)~~\KW{or}~~($Uin(x,y)=zero$)~~\KW{or}
($Uout(x,y)=zero$))~~KW{break}*/ if((P == zero)||(Uin == zero)||(Uout == zero)) { Cudd_RecursiveDeref(bdd,P); break; }
Cudd_RecursiveDeref(bdd,P);
} /* Next least fixed point iteration with smaller P */ if (i == MAXFPIT) (void) fprintf(stderr, "HourglassPush: ERROR! MAXFPIT (%d) exceeded at layer %d.\n", MAXFPIT, m);
/* $U^{m}(x,y) = U^{m}(x,y)-Uout(x,y)$*/ if (Uout != zero) { Cudd_Ref(p = Cudd_bddAnd(bdd, U[m], Cudd_Not(Uout))); Cudd_RecursiveDeref(bdd,U[m]); U[m] = p; } if(pr>1){(void)fprintf(stdout,"U[%d]",m); Cudd_PrintDebug(bdd,U[m],n<<1,pr);}
Cudd_RecursiveDeref(bdd,Uin); Cudd_RecursiveDeref(bdd,Uout); Cudd_RecursiveDeref(bdd,przy);
return;
} /* end of hourglassPush */
|