00001
00033 #include "util_hack.h"
00034 #include "cuddInt.h"
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 typedef struct hashEntry {
00052 DdNode *f;
00053 DdNode *g;
00054 } HashEntry;
00055
00056
00057
00058
00059
00060
00061 #ifndef lint
00062 static char rcsid[] DD_UNUSED = "$Id: cuddBddCorr.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $";
00063 #endif
00064
00065 #ifdef CORREL_STATS
00066 static int num_calls;
00067 #endif
00068
00069
00070
00071
00072
00073
00076
00077
00078
00079
00080 static double bddCorrelationAux ARGS((DdManager *dd, DdNode *f, DdNode *g, st_table *table));
00081 static double bddCorrelationWeightsAux ARGS((DdManager *dd, DdNode *f, DdNode *g, double *prob, st_table *table));
00082 static int CorrelCompare ARGS((const char *key1, const char *key2));
00083 static int CorrelHash ARGS((char *key, int modulus));
00084 static enum st_retval CorrelCleanUp ARGS((char *key, char *value, char *arg));
00085
00089
00090
00091
00092
00093
00108 double
00109 Cudd_bddCorrelation(
00110 DdManager * manager,
00111 DdNode * f,
00112 DdNode * g)
00113 {
00114
00115 st_table *table;
00116 double correlation;
00117
00118 #ifdef CORREL_STATS
00119 num_calls = 0;
00120 #endif
00121
00122 table = st_init_table(CorrelCompare,CorrelHash);
00123 if (table == NULL) return((double)CUDD_OUT_OF_MEM);
00124 correlation = bddCorrelationAux(manager,f,g,table);
00125 st_foreach(table, CorrelCleanUp, NIL(char));
00126 st_free_table(table);
00127 return(correlation);
00128
00129 }
00130
00131
00150 double
00151 Cudd_bddCorrelationWeights(
00152 DdManager * manager,
00153 DdNode * f,
00154 DdNode * g,
00155 double * prob)
00156 {
00157
00158 st_table *table;
00159 double correlation;
00160
00161 #ifdef CORREL_STATS
00162 num_calls = 0;
00163 #endif
00164
00165 table = st_init_table(CorrelCompare,CorrelHash);
00166 if (table == NULL) return((double)CUDD_OUT_OF_MEM);
00167 correlation = bddCorrelationWeightsAux(manager,f,g,prob,table);
00168 st_foreach(table, CorrelCleanUp, NIL(char));
00169 st_free_table(table);
00170 return(correlation);
00171
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00198 static double
00199 bddCorrelationAux(
00200 DdManager * dd,
00201 DdNode * f,
00202 DdNode * g,
00203 st_table * table)
00204 {
00205 DdNode *Fv, *Fnv, *G, *Gv, *Gnv;
00206 double min, *pmin, min1, min2, *dummy;
00207 HashEntry *entry;
00208 unsigned int topF, topG;
00209
00210 statLine(dd);
00211 #ifdef CORREL_STATS
00212 num_calls++;
00213 #endif
00214
00215
00216 if (f == g) return(1.0);
00217 if (f == Cudd_Not(g)) return(0.0);
00218
00219
00220
00221
00222
00223 if (f > g) {
00224 DdNode *tmp = f;
00225 f = g; g = tmp;
00226 }
00227 if (Cudd_IsComplement(f)) {
00228 f = Cudd_Not(f);
00229 g = Cudd_Not(g);
00230 }
00231
00232
00233 entry = ALLOC(HashEntry,1);
00234 if (entry == NULL) {
00235 dd->errorCode = CUDD_MEMORY_OUT;
00236 return(CUDD_OUT_OF_MEM);
00237 }
00238 entry->f = f; entry->g = g;
00239
00240
00241
00242
00243
00244 if (st_lookup(table, (char *)entry, (char **)&dummy)) {
00245 min = *dummy;
00246 FREE(entry);
00247 return(min);
00248 }
00249
00250 G = Cudd_Regular(g);
00251 topF = cuddI(dd,f->index); topG = cuddI(dd,G->index);
00252 if (topF <= topG) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; }
00253 if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; }
00254
00255 if (g != G) {
00256 Gv = Cudd_Not(Gv);
00257 Gnv = Cudd_Not(Gnv);
00258 }
00259
00260 min1 = bddCorrelationAux(dd, Fv, Gv, table) / 2.0;
00261 if (min1 == (double)CUDD_OUT_OF_MEM) {
00262 FREE(entry);
00263 return(CUDD_OUT_OF_MEM);
00264 }
00265 min2 = bddCorrelationAux(dd, Fnv, Gnv, table) / 2.0;
00266 if (min2 == (double)CUDD_OUT_OF_MEM) {
00267 FREE(entry);
00268 return(CUDD_OUT_OF_MEM);
00269 }
00270 min = (min1+min2);
00271
00272 pmin = ALLOC(double,1);
00273 if (pmin == NULL) {
00274 dd->errorCode = CUDD_MEMORY_OUT;
00275 return((double)CUDD_OUT_OF_MEM);
00276 }
00277 *pmin = min;
00278
00279 if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) {
00280 FREE(entry);
00281 FREE(pmin);
00282 return((double)CUDD_OUT_OF_MEM);
00283 }
00284 return(min);
00285
00286 }
00287
00288
00300 static double
00301 bddCorrelationWeightsAux(
00302 DdManager * dd,
00303 DdNode * f,
00304 DdNode * g,
00305 double * prob,
00306 st_table * table)
00307 {
00308 DdNode *Fv, *Fnv, *G, *Gv, *Gnv;
00309 double min, *pmin, min1, min2, *dummy;
00310 HashEntry *entry;
00311 int topF, topG, index;
00312
00313 statLine(dd);
00314 #ifdef CORREL_STATS
00315 num_calls++;
00316 #endif
00317
00318
00319 if (f == g) return(1.0);
00320 if (f == Cudd_Not(g)) return(0.0);
00321
00322
00323
00324
00325
00326 if (f > g) {
00327 DdNode *tmp = f;
00328 f = g; g = tmp;
00329 }
00330 if (Cudd_IsComplement(f)) {
00331 f = Cudd_Not(f);
00332 g = Cudd_Not(g);
00333 }
00334
00335
00336 entry = ALLOC(HashEntry,1);
00337 if (entry == NULL) {
00338 dd->errorCode = CUDD_MEMORY_OUT;
00339 return((double)CUDD_OUT_OF_MEM);
00340 }
00341 entry->f = f; entry->g = g;
00342
00343
00344
00345
00346
00347 if (st_lookup(table, (char *)entry, (char **)&dummy)) {
00348 min = *dummy;
00349 FREE(entry);
00350 return(min);
00351 }
00352
00353 G = Cudd_Regular(g);
00354 topF = cuddI(dd,f->index); topG = cuddI(dd,G->index);
00355 if (topF <= topG) {
00356 Fv = cuddT(f); Fnv = cuddE(f);
00357 index = f->index;
00358 } else {
00359 Fv = Fnv = f;
00360 index = G->index;
00361 }
00362 if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; }
00363
00364 if (g != G) {
00365 Gv = Cudd_Not(Gv);
00366 Gnv = Cudd_Not(Gnv);
00367 }
00368
00369 min1 = bddCorrelationWeightsAux(dd, Fv, Gv, prob, table) * prob[index];
00370 if (min1 == (double)CUDD_OUT_OF_MEM) {
00371 FREE(entry);
00372 return((double)CUDD_OUT_OF_MEM);
00373 }
00374 min2 = bddCorrelationWeightsAux(dd, Fnv, Gnv, prob, table) * (1.0 - prob[index]);
00375 if (min2 == (double)CUDD_OUT_OF_MEM) {
00376 FREE(entry);
00377 return((double)CUDD_OUT_OF_MEM);
00378 }
00379 min = (min1+min2);
00380
00381 pmin = ALLOC(double,1);
00382 if (pmin == NULL) {
00383 dd->errorCode = CUDD_MEMORY_OUT;
00384 return((double)CUDD_OUT_OF_MEM);
00385 }
00386 *pmin = min;
00387
00388 if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) {
00389 FREE(entry);
00390 FREE(pmin);
00391 return((double)CUDD_OUT_OF_MEM);
00392 }
00393 return(min);
00394
00395 }
00396
00397
00408 static int
00409 CorrelCompare(
00410 const char * key1,
00411 const char * key2)
00412 {
00413 HashEntry *entry1;
00414 HashEntry *entry2;
00415
00416 entry1 = (HashEntry *) key1;
00417 entry2 = (HashEntry *) key2;
00418 if (entry1->f != entry2->f || entry1->g != entry2->g) return(1);
00419
00420 return(0);
00421
00422 }
00423
00424
00435 static int
00436 CorrelHash(
00437 char * key,
00438 int modulus)
00439 {
00440 HashEntry *entry;
00441 int val = 0;
00442
00443 entry = (HashEntry *) key;
00444 #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
00445 val = ((int) ((long)entry->f))*997 + ((int) ((long)entry->g));
00446 #else
00447 val = ((int) entry->f)*997 + ((int) entry->g);
00448 #endif
00449
00450 return ((val < 0) ? -val : val) % modulus;
00451
00452 }
00453
00454
00465 static enum st_retval
00466 CorrelCleanUp(
00467 char * key,
00468 char * value,
00469 char * arg)
00470 {
00471 double *d;
00472 HashEntry *entry;
00473
00474 entry = (HashEntry *) key;
00475 FREE(entry);
00476 d = (double *)value;
00477 FREE(d);
00478 return ST_CONTINUE;
00479
00480 }
00481