You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							1555 lines
						
					
					
						
							55 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							1555 lines
						
					
					
						
							55 KiB
						
					
					
				
								/**
							 | 
						|
								  @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 */
							 |