00001
00060 #include "util.h"
00061 #include "cuddInt.h"
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 typedef struct hashEntry {
00079 DdNode *f;
00080 DdNode *g;
00081 } HashEntry;
00082
00083
00084
00085
00086
00087
00088 #ifndef lint
00089 static char rcsid[] DD_UNUSED = "$Id: cuddBddCorr.c,v 1.14 2004/08/13 18:04:46 fabio Exp $";
00090 #endif
00091
00092 #ifdef CORREL_STATS
00093 static int num_calls;
00094 #endif
00095
00096
00097
00098
00099
00100 #ifdef __cplusplus
00101 extern "C" {
00102 #endif
00103
00106
00107
00108
00109
00110 static double bddCorrelationAux (DdManager *dd, DdNode *f, DdNode *g, st_table *table);
00111 static double bddCorrelationWeightsAux (DdManager *dd, DdNode *f, DdNode *g, double *prob, st_table *table);
00112 static int CorrelCompare (const char *key1, const char *key2);
00113 static int CorrelHash (char *key, int modulus);
00114 static enum st_retval CorrelCleanUp (char *key, char *value, char *arg);
00115
00118 #ifdef __cplusplus
00119 }
00120 #endif
00121
00122
00123
00124
00125
00126
00127
00142 double
00143 Cudd_bddCorrelation(
00144 DdManager * manager,
00145 DdNode * f,
00146 DdNode * g)
00147 {
00148
00149 st_table *table;
00150 double correlation;
00151
00152 #ifdef CORREL_STATS
00153 num_calls = 0;
00154 #endif
00155
00156 table = st_init_table(CorrelCompare,CorrelHash);
00157 if (table == NULL) return((double)CUDD_OUT_OF_MEM);
00158 correlation = bddCorrelationAux(manager,f,g,table);
00159 st_foreach(table, CorrelCleanUp, NIL(char));
00160 st_free_table(table);
00161 return(correlation);
00162
00163 }
00164
00165
00184 double
00185 Cudd_bddCorrelationWeights(
00186 DdManager * manager,
00187 DdNode * f,
00188 DdNode * g,
00189 double * prob)
00190 {
00191
00192 st_table *table;
00193 double correlation;
00194
00195 #ifdef CORREL_STATS
00196 num_calls = 0;
00197 #endif
00198
00199 table = st_init_table(CorrelCompare,CorrelHash);
00200 if (table == NULL) return((double)CUDD_OUT_OF_MEM);
00201 correlation = bddCorrelationWeightsAux(manager,f,g,prob,table);
00202 st_foreach(table, CorrelCleanUp, NIL(char));
00203 st_free_table(table);
00204 return(correlation);
00205
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00232 static double
00233 bddCorrelationAux(
00234 DdManager * dd,
00235 DdNode * f,
00236 DdNode * g,
00237 st_table * table)
00238 {
00239 DdNode *Fv, *Fnv, *G, *Gv, *Gnv;
00240 double min, *pmin, min1, min2, *dummy;
00241 HashEntry *entry;
00242 unsigned int topF, topG;
00243
00244 statLine(dd);
00245 #ifdef CORREL_STATS
00246 num_calls++;
00247 #endif
00248
00249
00250 if (f == g) return(1.0);
00251 if (f == Cudd_Not(g)) return(0.0);
00252
00253
00254
00255
00256
00257 if (f > g) {
00258 DdNode *tmp = f;
00259 f = g; g = tmp;
00260 }
00261 if (Cudd_IsComplement(f)) {
00262 f = Cudd_Not(f);
00263 g = Cudd_Not(g);
00264 }
00265
00266
00267 entry = ALLOC(HashEntry,1);
00268 if (entry == NULL) {
00269 dd->errorCode = CUDD_MEMORY_OUT;
00270 return(CUDD_OUT_OF_MEM);
00271 }
00272 entry->f = f; entry->g = g;
00273
00274
00275
00276
00277
00278 if (st_lookup(table, entry, &dummy)) {
00279 min = *dummy;
00280 FREE(entry);
00281 return(min);
00282 }
00283
00284 G = Cudd_Regular(g);
00285 topF = cuddI(dd,f->index); topG = cuddI(dd,G->index);
00286 if (topF <= topG) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; }
00287 if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; }
00288
00289 if (g != G) {
00290 Gv = Cudd_Not(Gv);
00291 Gnv = Cudd_Not(Gnv);
00292 }
00293
00294 min1 = bddCorrelationAux(dd, Fv, Gv, table) / 2.0;
00295 if (min1 == (double)CUDD_OUT_OF_MEM) {
00296 FREE(entry);
00297 return(CUDD_OUT_OF_MEM);
00298 }
00299 min2 = bddCorrelationAux(dd, Fnv, Gnv, table) / 2.0;
00300 if (min2 == (double)CUDD_OUT_OF_MEM) {
00301 FREE(entry);
00302 return(CUDD_OUT_OF_MEM);
00303 }
00304 min = (min1+min2);
00305
00306 pmin = ALLOC(double,1);
00307 if (pmin == NULL) {
00308 dd->errorCode = CUDD_MEMORY_OUT;
00309 return((double)CUDD_OUT_OF_MEM);
00310 }
00311 *pmin = min;
00312
00313 if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) {
00314 FREE(entry);
00315 FREE(pmin);
00316 return((double)CUDD_OUT_OF_MEM);
00317 }
00318 return(min);
00319
00320 }
00321
00322
00334 static double
00335 bddCorrelationWeightsAux(
00336 DdManager * dd,
00337 DdNode * f,
00338 DdNode * g,
00339 double * prob,
00340 st_table * table)
00341 {
00342 DdNode *Fv, *Fnv, *G, *Gv, *Gnv;
00343 double min, *pmin, min1, min2, *dummy;
00344 HashEntry *entry;
00345 int topF, topG, index;
00346
00347 statLine(dd);
00348 #ifdef CORREL_STATS
00349 num_calls++;
00350 #endif
00351
00352
00353 if (f == g) return(1.0);
00354 if (f == Cudd_Not(g)) return(0.0);
00355
00356
00357
00358
00359
00360 if (f > g) {
00361 DdNode *tmp = f;
00362 f = g; g = tmp;
00363 }
00364 if (Cudd_IsComplement(f)) {
00365 f = Cudd_Not(f);
00366 g = Cudd_Not(g);
00367 }
00368
00369
00370 entry = ALLOC(HashEntry,1);
00371 if (entry == NULL) {
00372 dd->errorCode = CUDD_MEMORY_OUT;
00373 return((double)CUDD_OUT_OF_MEM);
00374 }
00375 entry->f = f; entry->g = g;
00376
00377
00378
00379
00380
00381 if (st_lookup(table, entry, &dummy)) {
00382 min = *dummy;
00383 FREE(entry);
00384 return(min);
00385 }
00386
00387 G = Cudd_Regular(g);
00388 topF = cuddI(dd,f->index); topG = cuddI(dd,G->index);
00389 if (topF <= topG) {
00390 Fv = cuddT(f); Fnv = cuddE(f);
00391 index = f->index;
00392 } else {
00393 Fv = Fnv = f;
00394 index = G->index;
00395 }
00396 if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; }
00397
00398 if (g != G) {
00399 Gv = Cudd_Not(Gv);
00400 Gnv = Cudd_Not(Gnv);
00401 }
00402
00403 min1 = bddCorrelationWeightsAux(dd, Fv, Gv, prob, table) * prob[index];
00404 if (min1 == (double)CUDD_OUT_OF_MEM) {
00405 FREE(entry);
00406 return((double)CUDD_OUT_OF_MEM);
00407 }
00408 min2 = bddCorrelationWeightsAux(dd, Fnv, Gnv, prob, table) * (1.0 - prob[index]);
00409 if (min2 == (double)CUDD_OUT_OF_MEM) {
00410 FREE(entry);
00411 return((double)CUDD_OUT_OF_MEM);
00412 }
00413 min = (min1+min2);
00414
00415 pmin = ALLOC(double,1);
00416 if (pmin == NULL) {
00417 dd->errorCode = CUDD_MEMORY_OUT;
00418 return((double)CUDD_OUT_OF_MEM);
00419 }
00420 *pmin = min;
00421
00422 if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) {
00423 FREE(entry);
00424 FREE(pmin);
00425 return((double)CUDD_OUT_OF_MEM);
00426 }
00427 return(min);
00428
00429 }
00430
00431
00442 static int
00443 CorrelCompare(
00444 const char * key1,
00445 const char * key2)
00446 {
00447 HashEntry *entry1;
00448 HashEntry *entry2;
00449
00450 entry1 = (HashEntry *) key1;
00451 entry2 = (HashEntry *) key2;
00452 if (entry1->f != entry2->f || entry1->g != entry2->g) return(1);
00453
00454 return(0);
00455
00456 }
00457
00458
00469 static int
00470 CorrelHash(
00471 char * key,
00472 int modulus)
00473 {
00474 HashEntry *entry;
00475 int val = 0;
00476
00477 entry = (HashEntry *) key;
00478 #if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4
00479 val = ((int) ((long)entry->f))*997 + ((int) ((long)entry->g));
00480 #else
00481 val = ((int) entry->f)*997 + ((int) entry->g);
00482 #endif
00483
00484 return ((val < 0) ? -val : val) % modulus;
00485
00486 }
00487
00488
00499 static enum st_retval
00500 CorrelCleanUp(
00501 char * key,
00502 char * value,
00503 char * arg)
00504 {
00505 double *d;
00506 HashEntry *entry;
00507
00508 entry = (HashEntry *) key;
00509 FREE(entry);
00510 d = (double *)value;
00511 FREE(d);
00512 return ST_CONTINUE;
00513
00514 }
00515