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.
		
		
		
		
		
			
		
			
				
					
					
						
							515 lines
						
					
					
						
							14 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							515 lines
						
					
					
						
							14 KiB
						
					
					
				| /**CFile*********************************************************************** | |
|  | |
|   FileName    [cuddBddCorr.c] | |
|  | |
|   PackageName [cudd] | |
|  | |
|   Synopsis    [Correlation between BDDs.] | |
|  | |
|   Description [External procedures included in this module: | |
| 		<ul> | |
| 		<li> Cudd_bddCorrelation() | |
| 		<li> Cudd_bddCorrelationWeights() | |
| 		</ul> | |
| 	    Static procedures included in this module: | |
| 		<ul> | |
| 		<li> bddCorrelationAux() | |
| 		<li> bddCorrelationWeightsAux() | |
| 		<li> CorrelCompare() | |
| 		<li> CorrelHash() | |
| 		<li> CorrelCleanUp() | |
| 		</ul> | |
| 		] | |
|  | |
|   Author      [Fabio Somenzi] | |
|  | |
|   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                                                         */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| typedef struct hashEntry { | |
|     DdNode *f; | |
|     DdNode *g; | |
| } HashEntry; | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Variable declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| #ifndef lint | |
| static char rcsid[] DD_UNUSED = "$Id: cuddBddCorr.c,v 1.15 2012/02/05 01:07:18 fabio Exp $"; | |
| #endif | |
|  | |
| #ifdef CORREL_STATS | |
| static	int	num_calls; | |
| #endif | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Macro declarations                                                        */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| #ifdef __cplusplus | |
| extern "C" { | |
| #endif | |
|  | |
| /**AutomaticStart*************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Static function prototypes                                                */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| static double bddCorrelationAux (DdManager *dd, DdNode *f, DdNode *g, st_table *table); | |
| static double bddCorrelationWeightsAux (DdManager *dd, DdNode *f, DdNode *g, double *prob, st_table *table); | |
| static int CorrelCompare (const char *key1, const char *key2); | |
| static int CorrelHash (char *key, int modulus); | |
| static enum st_retval CorrelCleanUp (char *key, char *value, char *arg); | |
| 
 | |
| /**AutomaticEnd***************************************************************/ | |
| 
 | |
| #ifdef __cplusplus | |
| } | |
| #endif | |
|  | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of exported functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Computes the correlation of f and g.] | |
|  | |
|   Description [Computes the correlation of f and g. If f == g, their | |
|   correlation is 1. If f == g', their correlation is 0.  Returns the | |
|   fraction of minterms in the ON-set of the EXNOR of f and g.  If it | |
|   runs out of memory, returns (double)CUDD_OUT_OF_MEM.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_bddCorrelationWeights] | |
|  | |
| ******************************************************************************/ | |
| double | |
| Cudd_bddCorrelation( | |
|   DdManager * manager, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
| 
 | |
|     st_table	*table; | |
|     double	correlation; | |
| 
 | |
| #ifdef CORREL_STATS | |
|     num_calls = 0; | |
| #endif | |
|  | |
|     table = st_init_table(CorrelCompare,CorrelHash); | |
|     if (table == NULL) return((double)CUDD_OUT_OF_MEM); | |
|     correlation = bddCorrelationAux(manager,f,g,table); | |
|     st_foreach(table, CorrelCleanUp, NIL(char)); | |
|     st_free_table(table); | |
|     return(correlation); | |
| 
 | |
| } /* end of Cudd_bddCorrelation */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Computes the correlation of f and g for given input | |
|   probabilities.] | |
|  | |
|   Description [Computes the correlation of f and g for given input | |
|   probabilities. On input, prob\[i\] is supposed to contain the | |
|   probability of the i-th input variable to be 1. | |
|   If f == g, their correlation is 1. If f == g', their | |
|   correlation is 0.  Returns the probability that f and g have the same | |
|   value. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM. The | |
|   correlation of f and the constant one gives the probability of f.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_bddCorrelation] | |
|  | |
| ******************************************************************************/ | |
| double | |
| Cudd_bddCorrelationWeights( | |
|   DdManager * manager, | |
|   DdNode * f, | |
|   DdNode * g, | |
|   double * prob) | |
| { | |
| 
 | |
|     st_table	*table; | |
|     double	correlation; | |
| 
 | |
| #ifdef CORREL_STATS | |
|     num_calls = 0; | |
| #endif | |
|  | |
|     table = st_init_table(CorrelCompare,CorrelHash); | |
|     if (table == NULL) return((double)CUDD_OUT_OF_MEM); | |
|     correlation = bddCorrelationWeightsAux(manager,f,g,prob,table); | |
|     st_foreach(table, CorrelCleanUp, NIL(char)); | |
|     st_free_table(table); | |
|     return(correlation); | |
| 
 | |
| } /* end of Cudd_bddCorrelationWeights */ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of internal functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of static functions                                            */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Performs the recursive step of Cudd_bddCorrelation.] | |
|  | |
|   Description [Performs the recursive step of Cudd_bddCorrelation. | |
|   Returns the fraction of minterms in the ON-set of the EXNOR of f and | |
|   g.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [bddCorrelationWeightsAux] | |
|  | |
| ******************************************************************************/ | |
| static double | |
| bddCorrelationAux( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g, | |
|   st_table * table) | |
| { | |
|     DdNode	*Fv, *Fnv, *G, *Gv, *Gnv; | |
|     double	min, *pmin, min1, min2, *dummy; | |
|     HashEntry	*entry; | |
|     unsigned int topF, topG; | |
| 
 | |
|     statLine(dd); | |
| #ifdef CORREL_STATS | |
|     num_calls++; | |
| #endif | |
|  | |
|     /* Terminal cases: only work for BDDs. */ | |
|     if (f == g) return(1.0); | |
|     if (f == Cudd_Not(g)) return(0.0); | |
| 
 | |
|     /* Standardize call using the following properties: | |
|     **     (f EXNOR g)   = (g EXNOR f) | |
|     **     (f' EXNOR g') = (f EXNOR g). | |
|     */ | |
|     if (f > g) { | |
| 	DdNode *tmp = f; | |
| 	f = g; g = tmp; | |
|     } | |
|     if (Cudd_IsComplement(f)) { | |
| 	f = Cudd_Not(f); | |
| 	g = Cudd_Not(g); | |
|     } | |
|     /* From now on, f is regular. */ | |
|      | |
|     entry = ALLOC(HashEntry,1); | |
|     if (entry == NULL) { | |
| 	dd->errorCode = CUDD_MEMORY_OUT; | |
| 	return(CUDD_OUT_OF_MEM); | |
|     } | |
|     entry->f = f; entry->g = g; | |
| 
 | |
|     /* We do not use the fact that | |
|     ** correlation(f,g') = 1 - correlation(f,g) | |
|     ** to minimize the risk of cancellation. | |
|     */ | |
|     if (st_lookup(table, entry, &dummy)) { | |
| 	min = *dummy; | |
| 	FREE(entry); | |
| 	return(min); | |
|     } | |
| 
 | |
|     G = Cudd_Regular(g); | |
|     topF = cuddI(dd,f->index); topG = cuddI(dd,G->index); | |
|     if (topF <= topG) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } | |
|     if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; } | |
| 
 | |
|     if (g != G) { | |
| 	Gv = Cudd_Not(Gv); | |
| 	Gnv = Cudd_Not(Gnv); | |
|     } | |
| 
 | |
|     min1 = bddCorrelationAux(dd, Fv, Gv, table) / 2.0; | |
|     if (min1 == (double)CUDD_OUT_OF_MEM) { | |
| 	FREE(entry); | |
| 	return(CUDD_OUT_OF_MEM); | |
|     } | |
|     min2 = bddCorrelationAux(dd, Fnv, Gnv, table) / 2.0;  | |
|     if (min2 == (double)CUDD_OUT_OF_MEM) { | |
| 	FREE(entry); | |
| 	return(CUDD_OUT_OF_MEM); | |
|     } | |
|     min = (min1+min2); | |
|      | |
|     pmin = ALLOC(double,1); | |
|     if (pmin == NULL) { | |
| 	dd->errorCode = CUDD_MEMORY_OUT; | |
| 	return((double)CUDD_OUT_OF_MEM); | |
|     } | |
|     *pmin = min; | |
| 
 | |
|     if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) { | |
| 	FREE(entry); | |
| 	FREE(pmin); | |
| 	return((double)CUDD_OUT_OF_MEM); | |
|     } | |
|     return(min); | |
| 
 | |
| } /* end of bddCorrelationAux */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Performs the recursive step of Cudd_bddCorrelationWeigths.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [bddCorrelationAux] | |
|  | |
| ******************************************************************************/ | |
| static double | |
| bddCorrelationWeightsAux( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g, | |
|   double * prob, | |
|   st_table * table) | |
| { | |
|     DdNode	*Fv, *Fnv, *G, *Gv, *Gnv; | |
|     double	min, *pmin, min1, min2, *dummy; | |
|     HashEntry	*entry; | |
|     int		topF, topG, index; | |
| 
 | |
|     statLine(dd); | |
| #ifdef CORREL_STATS | |
|     num_calls++; | |
| #endif | |
|  | |
|     /* Terminal cases: only work for BDDs. */ | |
|     if (f == g) return(1.0); | |
|     if (f == Cudd_Not(g)) return(0.0); | |
| 
 | |
|     /* Standardize call using the following properties: | |
|     **     (f EXNOR g)   = (g EXNOR f) | |
|     **     (f' EXNOR g') = (f EXNOR g). | |
|     */ | |
|     if (f > g) { | |
| 	DdNode *tmp = f; | |
| 	f = g; g = tmp; | |
|     } | |
|     if (Cudd_IsComplement(f)) { | |
| 	f = Cudd_Not(f); | |
| 	g = Cudd_Not(g); | |
|     } | |
|     /* From now on, f is regular. */ | |
|      | |
|     entry = ALLOC(HashEntry,1); | |
|     if (entry == NULL) { | |
| 	dd->errorCode = CUDD_MEMORY_OUT; | |
| 	return((double)CUDD_OUT_OF_MEM); | |
|     } | |
|     entry->f = f; entry->g = g; | |
| 
 | |
|     /* We do not use the fact that | |
|     ** correlation(f,g') = 1 - correlation(f,g) | |
|     ** to minimize the risk of cancellation. | |
|     */ | |
|     if (st_lookup(table, entry, &dummy)) { | |
| 	min = *dummy; | |
| 	FREE(entry); | |
| 	return(min); | |
|     } | |
| 
 | |
|     G = Cudd_Regular(g); | |
|     topF = cuddI(dd,f->index); topG = cuddI(dd,G->index); | |
|     if (topF <= topG) { | |
| 	Fv = cuddT(f); Fnv = cuddE(f); | |
| 	index = f->index; | |
|     } else { | |
| 	Fv = Fnv = f; | |
| 	index = G->index; | |
|     } | |
|     if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; } | |
| 
 | |
|     if (g != G) { | |
| 	Gv = Cudd_Not(Gv); | |
| 	Gnv = Cudd_Not(Gnv); | |
|     } | |
| 
 | |
|     min1 = bddCorrelationWeightsAux(dd, Fv, Gv, prob, table) * prob[index]; | |
|     if (min1 == (double)CUDD_OUT_OF_MEM) { | |
| 	FREE(entry); | |
| 	return((double)CUDD_OUT_OF_MEM); | |
|     } | |
|     min2 = bddCorrelationWeightsAux(dd, Fnv, Gnv, prob, table) * (1.0 - prob[index]);  | |
|     if (min2 == (double)CUDD_OUT_OF_MEM) { | |
| 	FREE(entry); | |
| 	return((double)CUDD_OUT_OF_MEM); | |
|     } | |
|     min = (min1+min2); | |
|      | |
|     pmin = ALLOC(double,1); | |
|     if (pmin == NULL) { | |
| 	dd->errorCode = CUDD_MEMORY_OUT; | |
| 	return((double)CUDD_OUT_OF_MEM); | |
|     } | |
|     *pmin = min; | |
| 
 | |
|     if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) { | |
| 	FREE(entry); | |
| 	FREE(pmin); | |
| 	return((double)CUDD_OUT_OF_MEM); | |
|     } | |
|     return(min); | |
| 
 | |
| } /* end of bddCorrelationWeightsAux */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Compares two hash table entries.] | |
|  | |
|   Description [Compares two hash table entries. Returns 0 if they are | |
|   identical; 1 otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
| ******************************************************************************/ | |
| static int | |
| CorrelCompare( | |
|   const char * key1, | |
|   const char * key2) | |
| { | |
|     HashEntry *entry1; | |
|     HashEntry *entry2; | |
| 
 | |
|     entry1 = (HashEntry *) key1; | |
|     entry2 = (HashEntry *) key2; | |
|     if (entry1->f != entry2->f || entry1->g != entry2->g) return(1); | |
| 
 | |
|     return(0); | |
| 
 | |
| } /* end of CorrelCompare */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Hashes a hash table entry.] | |
|  | |
|   Description [Hashes a hash table entry. It is patterned after | |
|   st_strhash. Returns a value between 0 and modulus.] | |
|  | |
|   SideEffects [None] | |
|  | |
| ******************************************************************************/ | |
| static int | |
| CorrelHash( | |
|   char * key, | |
|   int  modulus) | |
| { | |
|     HashEntry *entry; | |
|     int val = 0; | |
| 
 | |
|     entry = (HashEntry *) key; | |
| #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 | |
|     val = ((int) ((long)entry->f))*997 + ((int) ((long)entry->g)); | |
| #else | |
|     val = ((int) entry->f)*997 + ((int) entry->g); | |
| #endif | |
|  | |
|     return ((val < 0) ? -val : val) % modulus; | |
| 
 | |
| } /* end of CorrelHash */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Frees memory associated with hash table.] | |
|  | |
|   Description [Frees memory associated with hash table. Returns | |
|   ST_CONTINUE.] | |
|  | |
|   SideEffects [None] | |
|  | |
| ******************************************************************************/ | |
| static enum st_retval | |
| CorrelCleanUp( | |
|   char * key, | |
|   char * value, | |
|   char * arg) | |
| { | |
|     double	*d; | |
|     HashEntry *entry; | |
| 
 | |
|     entry = (HashEntry *) key; | |
|     FREE(entry); | |
|     d = (double *)value; | |
|     FREE(d); | |
|     return ST_CONTINUE; | |
| 
 | |
| } /* end of CorrelCleanUp */ | |
| 
 |