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.
		
		
		
		
		
			
		
			
				
					
					
						
							912 lines
						
					
					
						
							25 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							912 lines
						
					
					
						
							25 KiB
						
					
					
				| /**CFile*********************************************************************** | |
|  | |
|   FileName    [cuddZddIsop.c] | |
|  | |
|   PackageName [cudd] | |
|  | |
|   Synopsis    [Functions to find irredundant SOP covers as ZDDs from BDDs.] | |
|  | |
|   Description [External procedures included in this module: | |
| 		    <ul> | |
| 		    <li> Cudd_bddIsop() | |
| 		    <li> Cudd_zddIsop() | |
| 		    <li> Cudd_MakeBddFromZddCover() | |
| 		    </ul> | |
| 	       Internal procedures included in this module: | |
| 		    <ul> | |
| 		    <li> cuddBddIsop() | |
| 		    <li> cuddZddIsop() | |
| 		    <li> cuddMakeBddFromZddCover() | |
| 		    </ul> | |
| 	       Static procedures included in this module: | |
| 		    <ul> | |
| 		    </ul> | |
| 	      ] | |
|  | |
|   SeeAlso     [] | |
|  | |
|   Author      [In-Ho Moon] | |
|  | |
|   Copyright   [Copyright (c) 1995-2012, 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.] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| #include "util.h" | |
| #include "cuddInt.h" | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Constant declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Stucture declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Type declarations                                                         */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Variable declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| #ifndef lint | |
| static char rcsid[] DD_UNUSED = "$Id: cuddZddIsop.c,v 1.22 2012/02/05 01:07:19 fabio Exp $"; | |
| #endif | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Macro declarations                                                        */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**AutomaticStart*************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Static function prototypes                                                */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**AutomaticEnd***************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of exported functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Computes an ISOP in ZDD form from BDDs.] | |
|  | |
|   Description [Computes an irredundant sum of products (ISOP) in ZDD | |
|   form from BDDs. The two BDDs L and U represent the lower bound and | |
|   the upper bound, respectively, of the function. The ISOP uses two | |
|   ZDD variables for each BDD variable: One for the positive literal, | |
|   and one for the negative literal. These two variables should be | |
|   adjacent in the ZDD order. The two ZDD variables corresponding to | |
|   BDD variable <code>i</code> should have indices <code>2i</code> and | |
|   <code>2i+1</code>.  The result of this procedure depends on the | |
|   variable order. If successful, Cudd_zddIsop returns the BDD for | |
|   the function chosen from the interval. The ZDD representing the | |
|   irredundant cover is returned as a side effect in zdd_I. In case of | |
|   failure, NULL is returned.] | |
|  | |
|   SideEffects [zdd_I holds the pointer to the ZDD for the ISOP on | |
|   successful return.] | |
|  | |
|   SeeAlso     [Cudd_bddIsop Cudd_zddVarsFromBddVars] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| Cudd_zddIsop( | |
|   DdManager * dd, | |
|   DdNode * L, | |
|   DdNode * U, | |
|   DdNode ** zdd_I) | |
| { | |
|     DdNode	*res; | |
|     int		autoDynZ; | |
| 
 | |
|     autoDynZ = dd->autoDynZ; | |
|     dd->autoDynZ = 0; | |
| 
 | |
|     do { | |
| 	dd->reordered = 0; | |
| 	res = cuddZddIsop(dd, L, U, zdd_I); | |
|     } while (dd->reordered == 1); | |
|     dd->autoDynZ = autoDynZ; | |
|     return(res); | |
| 
 | |
| } /* end of Cudd_zddIsop */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Computes a BDD in the interval between L and U with a | |
|   simple sum-of-product cover.] | |
|  | |
|   Description [Computes a BDD in the interval between L and U with a | |
|   simple sum-of-product cover. This procedure is similar to | |
|   Cudd_zddIsop, but it does not return the ZDD for the cover. Returns | |
|   a pointer to the BDD if successful; NULL otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddIsop] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| Cudd_bddIsop( | |
|   DdManager * dd, | |
|   DdNode * L, | |
|   DdNode * U) | |
| { | |
|     DdNode	*res; | |
| 
 | |
|     do { | |
| 	dd->reordered = 0; | |
| 	res = cuddBddIsop(dd, L, U); | |
|     } while (dd->reordered == 1); | |
|     return(res); | |
| 
 | |
| } /* end of Cudd_bddIsop */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Converts a ZDD cover to a BDD.] | |
|  | |
|   Description [Converts a ZDD cover to a BDD for the function represented | |
|   by the cover. If successful, it returns a BDD node, otherwise it returns | |
|   NULL.] | |
|  | |
|   SideEffects [] | |
|  | |
|   SeeAlso     [Cudd_zddIsop] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| Cudd_MakeBddFromZddCover( | |
|   DdManager * dd, | |
|   DdNode * node) | |
| { | |
|     DdNode	*res; | |
| 
 | |
|     do { | |
| 	dd->reordered = 0; | |
| 	res = cuddMakeBddFromZddCover(dd, node); | |
|     } while (dd->reordered == 1); | |
|     return(res); | |
| } /* end of Cudd_MakeBddFromZddCover */ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of internal functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Performs the recursive step of Cudd_zddIsop.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddIsop] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| cuddZddIsop( | |
|   DdManager * dd, | |
|   DdNode * L, | |
|   DdNode * U, | |
|   DdNode ** zdd_I) | |
| { | |
|     DdNode	*one = DD_ONE(dd); | |
|     DdNode	*zero = Cudd_Not(one); | |
|     DdNode	*zdd_one = DD_ONE(dd); | |
|     DdNode	*zdd_zero = DD_ZERO(dd); | |
|     int		v, top_l, top_u; | |
|     DdNode	*Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; | |
|     DdNode	*Lsuper0, *Usuper0, *Lsuper1, *Usuper1; | |
|     DdNode	*Isub0, *Isub1, *Id; | |
|     DdNode	*zdd_Isub0, *zdd_Isub1, *zdd_Id; | |
|     DdNode	*x; | |
|     DdNode	*term0, *term1, *sum; | |
|     DdNode	*Lv, *Uv, *Lnv, *Unv; | |
|     DdNode	*r, *y, *z; | |
|     int		index; | |
|     DD_CTFP	cacheOp; | |
| 
 | |
|     statLine(dd); | |
|     if (L == zero) { | |
| 	*zdd_I = zdd_zero; | |
| 	return(zero); | |
|     } | |
|     if (U == one) { | |
| 	*zdd_I = zdd_one; | |
| 	return(one); | |
|     } | |
| 
 | |
|     if (U == zero || L == one) { | |
| 	printf("*** ERROR : illegal condition for ISOP (U < L).\n"); | |
| 	exit(1); | |
|     } | |
| 
 | |
|     /* Check the cache. We store two results for each recursive call. | |
|     ** One is the BDD, and the other is the ZDD. Both are needed. | |
|     ** Hence we need a double hit in the cache to terminate the | |
|     ** recursion. Clearly, collisions may evict only one of the two | |
|     ** results. */ | |
|     cacheOp = (DD_CTFP) cuddZddIsop; | |
|     r = cuddCacheLookup2(dd, cuddBddIsop, L, U); | |
|     if (r) { | |
| 	*zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U); | |
| 	if (*zdd_I) | |
| 	    return(r); | |
| 	else { | |
| 	    /* The BDD result may have been dead. In that case | |
| 	    ** cuddCacheLookup2 would have called cuddReclaim, | |
| 	    ** whose effects we now have to undo. */ | |
| 	    cuddRef(r); | |
| 	    Cudd_RecursiveDeref(dd, r); | |
| 	} | |
|     } | |
| 
 | |
|     top_l = dd->perm[Cudd_Regular(L)->index]; | |
|     top_u = dd->perm[Cudd_Regular(U)->index]; | |
|     v = ddMin(top_l, top_u); | |
| 
 | |
|     /* Compute cofactors. */ | |
|     if (top_l == v) { | |
| 	index = Cudd_Regular(L)->index; | |
| 	Lv = Cudd_T(L); | |
| 	Lnv = Cudd_E(L); | |
| 	if (Cudd_IsComplement(L)) { | |
| 	    Lv = Cudd_Not(Lv); | |
| 	    Lnv = Cudd_Not(Lnv); | |
| 	} | |
|     } | |
|     else { | |
| 	index = Cudd_Regular(U)->index; | |
| 	Lv = Lnv = L; | |
|     } | |
| 
 | |
|     if (top_u == v) { | |
| 	Uv = Cudd_T(U); | |
| 	Unv = Cudd_E(U); | |
| 	if (Cudd_IsComplement(U)) { | |
| 	    Uv = Cudd_Not(Uv); | |
| 	    Unv = Cudd_Not(Unv); | |
| 	} | |
|     } | |
|     else { | |
| 	Uv = Unv = U; | |
|     } | |
| 
 | |
|     Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); | |
|     if (Lsub0 == NULL) | |
| 	return(NULL); | |
|     Cudd_Ref(Lsub0); | |
|     Usub0 = Unv; | |
|     Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); | |
|     if (Lsub1 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Lsub0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Lsub1); | |
|     Usub1 = Uv; | |
| 
 | |
|     Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0); | |
|     if (Isub0 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Lsub0); | |
| 	Cudd_RecursiveDeref(dd, Lsub1); | |
| 	return(NULL); | |
|     } | |
|     /* | |
|     if ((!cuddIsConstant(Cudd_Regular(Isub0))) && | |
| 	(Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 || | |
| 	dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) { | |
| 	printf("*** ERROR : illegal permutation in ZDD. ***\n"); | |
|     } | |
|     */ | |
|     Cudd_Ref(Isub0); | |
|     Cudd_Ref(zdd_Isub0); | |
|     Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1); | |
|     if (Isub1 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Lsub0); | |
| 	Cudd_RecursiveDeref(dd, Lsub1); | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	return(NULL); | |
|     } | |
|     /* | |
|     if ((!cuddIsConstant(Cudd_Regular(Isub1))) && | |
| 	(Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 || | |
| 	dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) { | |
| 	printf("*** ERROR : illegal permutation in ZDD. ***\n"); | |
|     } | |
|     */ | |
|     Cudd_Ref(Isub1); | |
|     Cudd_Ref(zdd_Isub1); | |
|     Cudd_RecursiveDeref(dd, Lsub0); | |
|     Cudd_RecursiveDeref(dd, Lsub1); | |
| 
 | |
|     Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); | |
|     if (Lsuper0 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Lsuper0); | |
|     Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); | |
|     if (Lsuper1 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
| 	Cudd_RecursiveDeref(dd, Lsuper0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Lsuper1); | |
|     Usuper0 = Unv; | |
|     Usuper1 = Uv; | |
| 
 | |
|     /* Ld = Lsuper0 + Lsuper1 */ | |
|     Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); | |
|     if (Ld == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
| 	Cudd_RecursiveDeref(dd, Lsuper0); | |
| 	Cudd_RecursiveDeref(dd, Lsuper1); | |
| 	return(NULL); | |
|     } | |
|     Ld = Cudd_Not(Ld); | |
|     Cudd_Ref(Ld); | |
|     /* Ud = Usuper0 * Usuper1 */ | |
|     Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); | |
|     if (Ud == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
| 	Cudd_RecursiveDeref(dd, Lsuper0); | |
| 	Cudd_RecursiveDeref(dd, Lsuper1); | |
| 	Cudd_RecursiveDeref(dd, Ld); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Ud); | |
|     Cudd_RecursiveDeref(dd, Lsuper0); | |
|     Cudd_RecursiveDeref(dd, Lsuper1); | |
| 
 | |
|     Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id); | |
|     if (Id == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
| 	Cudd_RecursiveDeref(dd, Ld); | |
| 	Cudd_RecursiveDeref(dd, Ud); | |
| 	return(NULL); | |
|     } | |
|     /* | |
|     if ((!cuddIsConstant(Cudd_Regular(Id))) && | |
| 	(Cudd_Regular(Id)->index != zdd_Id->index / 2 || | |
| 	dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) { | |
| 	printf("*** ERROR : illegal permutation in ZDD. ***\n"); | |
|     } | |
|     */ | |
|     Cudd_Ref(Id); | |
|     Cudd_Ref(zdd_Id); | |
|     Cudd_RecursiveDeref(dd, Ld); | |
|     Cudd_RecursiveDeref(dd, Ud); | |
| 
 | |
|     x = cuddUniqueInter(dd, index, one, zero); | |
|     if (x == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
| 	Cudd_RecursiveDeref(dd, Id); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Id); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(x); | |
|     /* term0 = x * Isub0 */ | |
|     term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); | |
|     if (term0 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
| 	Cudd_RecursiveDeref(dd, Id); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Id); | |
| 	Cudd_RecursiveDeref(dd, x); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term0); | |
|     Cudd_RecursiveDeref(dd, Isub0); | |
|     /* term1 = x * Isub1 */ | |
|     term1 = cuddBddAndRecur(dd, x, Isub1); | |
|     if (term1 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
| 	Cudd_RecursiveDeref(dd, Id); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Id); | |
| 	Cudd_RecursiveDeref(dd, x); | |
| 	Cudd_RecursiveDeref(dd, term0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term1); | |
|     Cudd_RecursiveDeref(dd, x); | |
|     Cudd_RecursiveDeref(dd, Isub1); | |
|     /* sum = term0 + term1 */ | |
|     sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); | |
|     if (sum == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
| 	Cudd_RecursiveDeref(dd, Id); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Id); | |
| 	Cudd_RecursiveDeref(dd, term0); | |
| 	Cudd_RecursiveDeref(dd, term1); | |
| 	return(NULL); | |
|     } | |
|     sum = Cudd_Not(sum); | |
|     Cudd_Ref(sum); | |
|     Cudd_RecursiveDeref(dd, term0); | |
|     Cudd_RecursiveDeref(dd, term1); | |
|     /* r = sum + Id */ | |
|     r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); | |
|     r = Cudd_NotCond(r, r != NULL); | |
|     if (r == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
| 	Cudd_RecursiveDeref(dd, Id); | |
| 	Cudd_RecursiveDerefZdd(dd, zdd_Id); | |
| 	Cudd_RecursiveDeref(dd, sum); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(r); | |
|     Cudd_RecursiveDeref(dd, sum); | |
|     Cudd_RecursiveDeref(dd, Id); | |
| 
 | |
|     if (zdd_Isub0 != zdd_zero) { | |
| 	z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id); | |
| 	if (z == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	    Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
| 	    Cudd_RecursiveDerefZdd(dd, zdd_Id); | |
| 	    Cudd_RecursiveDeref(dd, r); | |
| 	    return(NULL); | |
| 	} | |
|     } | |
|     else { | |
| 	z = zdd_Id; | |
|     } | |
|     Cudd_Ref(z); | |
|     if (zdd_Isub1 != zdd_zero) { | |
| 	y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z); | |
| 	if (y == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
| 	    Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
| 	    Cudd_RecursiveDerefZdd(dd, zdd_Id); | |
| 	    Cudd_RecursiveDeref(dd, r); | |
| 	    Cudd_RecursiveDerefZdd(dd, z); | |
| 	    return(NULL); | |
| 	} | |
|     } | |
|     else | |
| 	y = z; | |
|     Cudd_Ref(y); | |
| 
 | |
|     Cudd_RecursiveDerefZdd(dd, zdd_Isub0); | |
|     Cudd_RecursiveDerefZdd(dd, zdd_Isub1); | |
|     Cudd_RecursiveDerefZdd(dd, zdd_Id); | |
|     Cudd_RecursiveDerefZdd(dd, z); | |
| 
 | |
|     cuddCacheInsert2(dd, cuddBddIsop, L, U, r); | |
|     cuddCacheInsert2(dd, cacheOp, L, U, y); | |
| 
 | |
|     Cudd_Deref(r); | |
|     Cudd_Deref(y); | |
|     *zdd_I = y; | |
|     /* | |
|     if (Cudd_Regular(r)->index != y->index / 2) { | |
| 	printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n"); | |
|     } | |
|     */ | |
|     return(r); | |
| 
 | |
| } /* end of cuddZddIsop */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Performs the recursive step of Cudd_bddIsop.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_bddIsop] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| cuddBddIsop( | |
|   DdManager * dd, | |
|   DdNode * L, | |
|   DdNode * U) | |
| { | |
|     DdNode	*one = DD_ONE(dd); | |
|     DdNode	*zero = Cudd_Not(one); | |
|     int		v, top_l, top_u; | |
|     DdNode	*Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; | |
|     DdNode	*Lsuper0, *Usuper0, *Lsuper1, *Usuper1; | |
|     DdNode	*Isub0, *Isub1, *Id; | |
|     DdNode	*x; | |
|     DdNode	*term0, *term1, *sum; | |
|     DdNode	*Lv, *Uv, *Lnv, *Unv; | |
|     DdNode	*r; | |
|     int		index; | |
| 
 | |
|     statLine(dd); | |
|     if (L == zero) | |
| 	return(zero); | |
|     if (U == one) | |
| 	return(one); | |
| 
 | |
|     /* Check cache */ | |
|     r = cuddCacheLookup2(dd, cuddBddIsop, L, U); | |
|     if (r) | |
| 	return(r); | |
| 
 | |
|     top_l = dd->perm[Cudd_Regular(L)->index]; | |
|     top_u = dd->perm[Cudd_Regular(U)->index]; | |
|     v = ddMin(top_l, top_u); | |
| 
 | |
|     /* Compute cofactors */ | |
|     if (top_l == v) { | |
| 	index = Cudd_Regular(L)->index; | |
| 	Lv = Cudd_T(L); | |
| 	Lnv = Cudd_E(L); | |
| 	if (Cudd_IsComplement(L)) { | |
| 	    Lv = Cudd_Not(Lv); | |
| 	    Lnv = Cudd_Not(Lnv); | |
| 	} | |
|     } | |
|     else { | |
| 	index = Cudd_Regular(U)->index; | |
| 	Lv = Lnv = L; | |
|     } | |
| 
 | |
|     if (top_u == v) { | |
| 	Uv = Cudd_T(U); | |
| 	Unv = Cudd_E(U); | |
| 	if (Cudd_IsComplement(U)) { | |
| 	    Uv = Cudd_Not(Uv); | |
| 	    Unv = Cudd_Not(Unv); | |
| 	} | |
|     } | |
|     else { | |
| 	Uv = Unv = U; | |
|     } | |
| 
 | |
|     Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); | |
|     if (Lsub0 == NULL) | |
| 	return(NULL); | |
|     Cudd_Ref(Lsub0); | |
|     Usub0 = Unv; | |
|     Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); | |
|     if (Lsub1 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Lsub0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Lsub1); | |
|     Usub1 = Uv; | |
| 
 | |
|     Isub0 = cuddBddIsop(dd, Lsub0, Usub0); | |
|     if (Isub0 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Lsub0); | |
| 	Cudd_RecursiveDeref(dd, Lsub1); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Isub0); | |
|     Isub1 = cuddBddIsop(dd, Lsub1, Usub1); | |
|     if (Isub1 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Lsub0); | |
| 	Cudd_RecursiveDeref(dd, Lsub1); | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Isub1); | |
|     Cudd_RecursiveDeref(dd, Lsub0); | |
|     Cudd_RecursiveDeref(dd, Lsub1); | |
| 
 | |
|     Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); | |
|     if (Lsuper0 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Lsuper0); | |
|     Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); | |
|     if (Lsuper1 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDeref(dd, Lsuper0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Lsuper1); | |
|     Usuper0 = Unv; | |
|     Usuper1 = Uv; | |
| 
 | |
|     /* Ld = Lsuper0 + Lsuper1 */ | |
|     Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); | |
|     Ld = Cudd_NotCond(Ld, Ld != NULL); | |
|     if (Ld == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDeref(dd, Lsuper0); | |
| 	Cudd_RecursiveDeref(dd, Lsuper1); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Ld); | |
|     Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); | |
|     if (Ud == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDeref(dd, Lsuper0); | |
| 	Cudd_RecursiveDeref(dd, Lsuper1); | |
| 	Cudd_RecursiveDeref(dd, Ld); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Ud); | |
|     Cudd_RecursiveDeref(dd, Lsuper0); | |
|     Cudd_RecursiveDeref(dd, Lsuper1); | |
| 
 | |
|     Id = cuddBddIsop(dd, Ld, Ud); | |
|     if (Id == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDeref(dd, Ld); | |
| 	Cudd_RecursiveDeref(dd, Ud); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Id); | |
|     Cudd_RecursiveDeref(dd, Ld); | |
|     Cudd_RecursiveDeref(dd, Ud); | |
| 
 | |
|     x = cuddUniqueInter(dd, index, one, zero); | |
|     if (x == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDeref(dd, Id); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(x); | |
|     term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); | |
|     if (term0 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub0); | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDeref(dd, Id); | |
| 	Cudd_RecursiveDeref(dd, x); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term0); | |
|     Cudd_RecursiveDeref(dd, Isub0); | |
|     term1 = cuddBddAndRecur(dd, x, Isub1); | |
|     if (term1 == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Isub1); | |
| 	Cudd_RecursiveDeref(dd, Id); | |
| 	Cudd_RecursiveDeref(dd, x); | |
| 	Cudd_RecursiveDeref(dd, term0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term1); | |
|     Cudd_RecursiveDeref(dd, x); | |
|     Cudd_RecursiveDeref(dd, Isub1); | |
|     /* sum = term0 + term1 */ | |
|     sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); | |
|     sum = Cudd_NotCond(sum, sum != NULL); | |
|     if (sum == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Id); | |
| 	Cudd_RecursiveDeref(dd, term0); | |
| 	Cudd_RecursiveDeref(dd, term1); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(sum); | |
|     Cudd_RecursiveDeref(dd, term0); | |
|     Cudd_RecursiveDeref(dd, term1); | |
|     /* r = sum + Id */ | |
|     r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); | |
|     r = Cudd_NotCond(r, r != NULL); | |
|     if (r == NULL) { | |
| 	Cudd_RecursiveDeref(dd, Id); | |
| 	Cudd_RecursiveDeref(dd, sum); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(r); | |
|     Cudd_RecursiveDeref(dd, sum); | |
|     Cudd_RecursiveDeref(dd, Id); | |
| 
 | |
|     cuddCacheInsert2(dd, cuddBddIsop, L, U, r); | |
| 
 | |
|     Cudd_Deref(r); | |
|     return(r); | |
| 
 | |
| } /* end of cuddBddIsop */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Converts a ZDD cover to a BDD.] | |
|  | |
|   Description [Converts a ZDD cover to a BDD. If successful, it returns | |
|   a BDD node, otherwise it returns NULL. It is a recursive algorithm | |
|   that works as follows. First it computes 3 cofactors of a ZDD cover: | |
|   f1, f0 and fd. Second, it compute BDDs (b1, b0 and bd) of f1, f0 and fd. | |
|   Third, it computes T=b1+bd and E=b0+bd. Fourth, it computes ITE(v,T,E) where | |
|   v is the variable which has the index of the top node of the ZDD cover. | |
|   In this case, since the index of v can be larger than either the one of T | |
|   or the one of E, cuddUniqueInterIVO is called, where IVO stands for | |
|   independent from variable ordering.] | |
|  | |
|   SideEffects [] | |
|  | |
|   SeeAlso     [Cudd_MakeBddFromZddCover] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| cuddMakeBddFromZddCover( | |
|   DdManager * dd, | |
|   DdNode * node) | |
| { | |
|     DdNode	*neW; | |
|     int		v; | |
|     DdNode	*f1, *f0, *fd; | |
|     DdNode	*b1, *b0, *bd; | |
|     DdNode	*T, *E; | |
| 
 | |
|     statLine(dd); | |
|     if (node == dd->one) | |
| 	return(dd->one); | |
|     if (node == dd->zero) | |
| 	return(Cudd_Not(dd->one)); | |
| 
 | |
|     /* Check cache */ | |
|     neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node); | |
|     if (neW) | |
| 	return(neW); | |
| 
 | |
|     v = Cudd_Regular(node)->index;	/* either yi or zi */ | |
|     if (cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd)) return(NULL); | |
|     Cudd_Ref(f1); | |
|     Cudd_Ref(f0); | |
|     Cudd_Ref(fd); | |
| 
 | |
|     b1 = cuddMakeBddFromZddCover(dd, f1); | |
|     if (!b1) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(b1); | |
|     b0 = cuddMakeBddFromZddCover(dd, f0); | |
|     if (!b0) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDeref(dd, b1); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(b0); | |
|     Cudd_RecursiveDerefZdd(dd, f1); | |
|     Cudd_RecursiveDerefZdd(dd, f0); | |
|     if (fd != dd->zero) { | |
| 	bd = cuddMakeBddFromZddCover(dd, fd); | |
| 	if (!bd) { | |
| 	    Cudd_RecursiveDerefZdd(dd, fd); | |
| 	    Cudd_RecursiveDeref(dd, b1); | |
| 	    Cudd_RecursiveDeref(dd, b0); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(bd); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 
 | |
| 	T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd)); | |
| 	if (!T) { | |
| 	    Cudd_RecursiveDeref(dd, b1); | |
| 	    Cudd_RecursiveDeref(dd, b0); | |
| 	    Cudd_RecursiveDeref(dd, bd); | |
| 	    return(NULL); | |
| 	} | |
| 	T = Cudd_NotCond(T, T != NULL); | |
| 	Cudd_Ref(T); | |
| 	Cudd_RecursiveDeref(dd, b1); | |
| 	E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd)); | |
| 	if (!E) { | |
| 	    Cudd_RecursiveDeref(dd, b0); | |
| 	    Cudd_RecursiveDeref(dd, bd); | |
| 	    Cudd_RecursiveDeref(dd, T); | |
| 	    return(NULL); | |
| 	} | |
| 	E = Cudd_NotCond(E, E != NULL); | |
| 	Cudd_Ref(E); | |
| 	Cudd_RecursiveDeref(dd, b0); | |
| 	Cudd_RecursiveDeref(dd, bd); | |
|     } | |
|     else { | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	T = b1; | |
| 	E = b0; | |
|     } | |
| 
 | |
|     if (Cudd_IsComplement(T)) { | |
| 	neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E)); | |
| 	if (!neW) { | |
| 	    Cudd_RecursiveDeref(dd, T); | |
| 	    Cudd_RecursiveDeref(dd, E); | |
| 	    return(NULL); | |
| 	} | |
| 	neW = Cudd_Not(neW); | |
|     } | |
|     else { | |
| 	neW = cuddUniqueInterIVO(dd, v / 2, T, E); | |
| 	if (!neW) { | |
| 	    Cudd_RecursiveDeref(dd, T); | |
| 	    Cudd_RecursiveDeref(dd, E); | |
| 	    return(NULL); | |
| 	} | |
|     } | |
|     Cudd_Ref(neW); | |
|     Cudd_RecursiveDeref(dd, T); | |
|     Cudd_RecursiveDeref(dd, E); | |
| 
 | |
|     cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW); | |
|     Cudd_Deref(neW); | |
|     return(neW); | |
| 
 | |
| } /* end of cuddMakeBddFromZddCover */ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of static functions                                            */ | |
| /*---------------------------------------------------------------------------*/
 |