12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556 |
- /**
- @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 */
|