VIS

src/synth/synthDiv.c

Go to the documentation of this file.
00001 
00017 #include "synthInt.h"
00018 
00019 static char rcsid[] UNUSED = "$Id: synthDiv.c,v 1.25 2002/09/10 05:50:52 fabio Exp $";
00020 
00021 /*---------------------------------------------------------------------------*/
00022 /* Constant declarations                                                     */
00023 /*---------------------------------------------------------------------------*/
00024 
00025 #define MAX_COUNT       100000000 /* just chosen for a very large number */
00026 
00027 /*---------------------------------------------------------------------------*/
00028 /* Type declarations                                                         */
00029 /*---------------------------------------------------------------------------*/
00030 
00031 
00032 /*---------------------------------------------------------------------------*/
00033 /* Structure declarations                                                    */
00034 /*---------------------------------------------------------------------------*/
00035 
00045 typedef struct  bfs_item {
00046   int                   reach; /* number of path from top node */
00047   int                   count; /* number of path to constant 1 */
00048   bdd_node              *node; /* ZDD node */
00049   struct bfs_item       *next;
00050 } BfsItem;
00051 
00061 typedef struct  bfs_list {
00062   struct bfs_item       *item;
00063   int                   child; /* 1 : T, 0 : E */
00064   struct bfs_list       *next;
00065 } BfsList;
00066 
00067 
00068 /*---------------------------------------------------------------------------*/
00069 /* Variable declarations                                                     */
00070 /*---------------------------------------------------------------------------*/
00071 
00072 
00075 /*---------------------------------------------------------------------------*/
00076 /* Static function prototypes                                                */
00077 /*---------------------------------------------------------------------------*/
00078 
00079 static int FindQuickDivisor(bdd_node *f, bdd_node *one, int *v);
00080 
00084 /*---------------------------------------------------------------------------*/
00085 /* Definition of exported functions                                          */
00086 /*---------------------------------------------------------------------------*/
00087 
00088 
00103 bdd_node *
00104 Synth_ZddQuickDivisor(bdd_manager *dd,
00105                       bdd_node *f)
00106 {
00107   bdd_node      *res;
00108 
00109   if (bdd_get_package_name() != CUDD) {
00110     (void)fprintf(vis_stderr,
00111       "** synth error: Synthesis package can be used only with CUDD package\n");
00112     (void)fprintf(vis_stderr,"** synth error: Please link with CUDD package\n");
00113     return NIL(bdd_node);
00114   }
00115 
00116   do {
00117     bdd_set_reordered_field(dd, 0);
00118     res = SynthZddQuickDivisor(dd, f);
00119   } while (bdd_read_reordered_field(dd) == 1);
00120   return(res);
00121 }
00122 
00123 
00138 bdd_node *
00139 Synth_ZddLeastDivisor(bdd_manager *dd,
00140                       bdd_node *f)
00141 {
00142   bdd_node      *res;
00143 
00144   if (bdd_get_package_name() != CUDD) {
00145     (void)fprintf(vis_stderr,
00146       "** synth error: Synthesis package can be used only with CUDD package\n");
00147     (void)fprintf(vis_stderr,"** synth error: Please link with CUDD package\n");
00148     return NIL(bdd_node);
00149   }
00150 
00151   do {
00152     bdd_set_reordered_field(dd, 0);
00153     res = SynthZddLeastDivisor(dd, f);
00154   } while (bdd_read_reordered_field(dd) == 1);
00155   return(res);
00156 }
00157 
00158 
00173 bdd_node *
00174 Synth_ZddMostDivisor(bdd_manager *dd,
00175                      bdd_node *f)
00176 {
00177   bdd_node      *res;
00178 
00179   if (bdd_get_package_name() != CUDD) {
00180     (void)fprintf(vis_stderr,
00181       "** synth error: Synthesis package can be used only with CUDD package\n");
00182     (void)fprintf(vis_stderr,"** synth error: Please link with CUDD package\n");
00183     return NIL(bdd_node);
00184   }
00185 
00186   do {
00187     bdd_set_reordered_field(dd, 0);
00188     res = SynthZddMostDivisor(dd, f);
00189   } while (bdd_read_reordered_field(dd) == 1);
00190   return(res);
00191 }
00192 
00193 
00207 bdd_node *
00208 Synth_ZddLevelZeroDivisor(bdd_manager *dd,
00209                           bdd_node *f)
00210 {
00211   bdd_node      *res;
00212 
00213   if (bdd_get_package_name() != CUDD) {
00214     (void)fprintf(vis_stderr,
00215       "** synth error: Synthesis package can be used only with CUDD package\n");
00216     (void)fprintf(vis_stderr,"** synth error: Please link with CUDD package\n");
00217     return NIL(bdd_node);
00218   }
00219 
00220   do {
00221     bdd_set_reordered_field(dd, 0);
00222     res = SynthZddLevelZeroDivisor(dd, f);
00223   } while (bdd_read_reordered_field(dd) == 1);
00224   return(res);
00225 }
00226 
00227 
00241 bdd_node *
00242 Synth_ZddCommonDivisor(bdd_manager *dd,
00243                        bdd_node *f)
00244 {
00245   bdd_node      *res;
00246 
00247   if (bdd_get_package_name() != CUDD) {
00248     (void)fprintf(vis_stderr,
00249       "** synth error: Synthesis package can be used only with CUDD package\n");
00250     (void)fprintf(vis_stderr,"** synth error: Please link with CUDD package\n");
00251     return NIL(bdd_node);
00252   }
00253 
00254   do {
00255     bdd_set_reordered_field(dd, 0);
00256     res = SynthZddCommonDivisor(dd, f);
00257   } while (bdd_read_reordered_field(dd) == 1);
00258   return(res);
00259 }
00260 
00261 
00274 bdd_node *
00275 Synth_ZddLpDivisor(bdd_manager *dd,
00276                    bdd_node *f)
00277 {
00278   bdd_node      *res;
00279 
00280   if (bdd_get_package_name() != CUDD) {
00281     (void)fprintf(vis_stderr,
00282       "** synth error: Synthesis package can be used only with CUDD package\n");
00283     (void)fprintf(vis_stderr,"** synth error: Please link with CUDD package\n");
00284     return NIL(bdd_node);
00285   }
00286 
00287   do {
00288     bdd_set_reordered_field(dd, 0);
00289     res = SynthZddLpDivisor(dd, f);
00290   } while (bdd_read_reordered_field(dd) == 1);
00291   return(res);
00292 }
00293 
00294 
00295 /*---------------------------------------------------------------------------*/
00296 /* Definition of internal functions                                          */
00297 /*---------------------------------------------------------------------------*/
00298 
00299 
00317 bdd_node *
00318 SynthZddQuickDivisor(bdd_manager *dd,
00319                      bdd_node *f)
00320 {
00321   int           i, v;
00322   int           nvars;
00323   int           *count;
00324   bdd_node      *one = bdd_read_one(dd);
00325   bdd_node      *zero = bdd_read_zero(dd);
00326   bdd_node      *divisor, *node;
00327   bdd_node      *tmp;
00328   int           min_count;
00329 
00330   if (f == one || f == zero)
00331     return(f);
00332 
00333   /* Search for a literal appearing in at least two cubes. */
00334   v = -1;
00335   FindQuickDivisor(f, one, &v);
00336   SynthZddClearFlag(f);
00337 
00338   if (v == -1) {
00339     /* Quick divisor not found by looking at the ZDD graph.
00340      * Find the literal that occurs the least among those occuring
00341      * at least twice.
00342      */
00343     min_count = MAX_COUNT;
00344     nvars = bdd_num_zdd_vars(dd);
00345     count = ALLOC(int, nvars);
00346     (void)memset((void *)count, 0, sizeof(int) * nvars);
00347     SynthCountLiteralOccurrence(dd, f, count);
00348     for (i = 0; i < nvars; i++) {
00349       if (count[i] > 1 && count[i] < min_count) {
00350         v = i;
00351         min_count = count[i];
00352       }
00353     }
00354     FREE(count);
00355     if (v == -1) {
00356       /* All literal appear exactly once. We are done. */
00357       return(f);
00358     }
00359   }
00360 
00361   /* Obtain the literal divisor from its index and divide f. */
00362   node = bdd_zdd_get_node(dd, v, one, zero);
00363   if (!node)
00364     return(NULL);
00365   bdd_ref(node);
00366 
00367   tmp = (* SynthGetZddDivideRecurFunc())(dd, f, node);
00368   if (!tmp) {
00369     bdd_recursive_deref_zdd(dd,node);
00370     return(NULL);
00371   }
00372   bdd_ref(tmp);
00373   bdd_recursive_deref_zdd(dd, node);
00374 
00375   /* Recur on the quotient to make sure that all literals appear once. */
00376   divisor = SynthZddQuickDivisor(dd, tmp);
00377   if (!divisor) {
00378     bdd_recursive_deref_zdd(dd,tmp);
00379     return(NULL);
00380   }
00381   bdd_ref(divisor);
00382   bdd_recursive_deref_zdd(dd, tmp);
00383 
00384   bdd_deref(divisor);
00385   return(divisor);
00386 }
00387 
00388 
00401 bdd_node *
00402 SynthZddLeastDivisor(bdd_manager *dd,
00403                      bdd_node *f)
00404 {
00405   int           i, v;
00406   int           nvars, min_count;
00407   int           *count;
00408   bdd_node      *one = bdd_read_one(dd);
00409   bdd_node      *zero = bdd_read_zero(dd);
00410   bdd_node      *divisor, *node;
00411   bdd_node      *tmp1;
00412 
00413   if (f == one || f == zero)
00414     return(f);
00415 
00416   /* Find the literal that occurs the least among those occuring at
00417    * least twice.
00418    */
00419   v = -1;
00420   min_count = MAX_COUNT;
00421   nvars = bdd_num_zdd_vars(dd);
00422   count = ALLOC(int, nvars);
00423   (void)memset((void *)count, 0, sizeof(int) * nvars);
00424   SynthCountLiteralOccurrence(dd, f, count);
00425   for (i = 0; i < nvars; i++) {
00426     if (count[i] > 1 && count[i] < min_count) {
00427       v = i;
00428       min_count = count[i];
00429     }
00430   }
00431   FREE(count);
00432 
00433   if (v == -1) {
00434     /* All literal appear exactly once. We are done. */
00435     return(f);
00436   }
00437 
00438   /* Obtain the literal divisor from its index and divide f. */
00439   node = bdd_zdd_get_node(dd, v, one, zero);
00440   if (!node) {
00441     return(NULL);
00442   }
00443   bdd_ref(node);
00444 
00445   tmp1 = (* SynthGetZddDivideRecurFunc())(dd, f, node);
00446   if (!tmp1) {
00447     bdd_recursive_deref_zdd(dd, node);
00448     return(NULL);
00449   }
00450   bdd_ref(tmp1);
00451   bdd_recursive_deref_zdd(dd, node);
00452 
00453   /* Recur on the quotient to make sure that all literals appear once. */
00454   divisor = SynthZddLeastDivisor(dd, tmp1);
00455   if (!divisor) {
00456     bdd_recursive_deref_zdd(dd, tmp1);
00457     return(NULL);
00458   }
00459   bdd_ref(divisor);
00460   bdd_recursive_deref_zdd(dd, tmp1);
00461 
00462   bdd_deref(divisor);
00463   return(divisor);
00464 }
00465 
00466 
00479 bdd_node *
00480 SynthZddMostDivisor(bdd_manager *dd,
00481                     bdd_node *f)
00482 {
00483   int           i, v;
00484   int           nvars, max_count;
00485   int           *count;
00486   bdd_node      *one = bdd_read_one(dd);
00487   bdd_node      *zero = bdd_read_zero(dd);
00488   bdd_node      *divisor, *node;
00489   bdd_node      *tmp1;
00490 
00491   if (f == one || f == zero)
00492     return(f);
00493 
00494   /* Find the literal that occurs the most. */
00495   v = -1;
00496   max_count = 1;
00497   nvars = bdd_num_zdd_vars(dd);
00498   count = ALLOC(int, nvars);
00499   (void)memset((void *)count, 0, sizeof(int) * nvars);
00500   SynthCountLiteralOccurrence(dd, f, count);
00501   for (i = 0; i < nvars; i++) {
00502     if (count[i] > max_count) {
00503       v = i;
00504       max_count = count[i];
00505     }
00506   }
00507 
00508   FREE(count);
00509 
00510   if (v == -1) {
00511     /* All literal appear exactly once. We are done. */
00512     return(f);
00513   }
00514 
00515   /* Obtain the literal divisor from its index and divide f. */
00516   node = bdd_zdd_get_node(dd, v, one, zero);
00517   if (!node)
00518     return(NULL);
00519   bdd_ref(node);
00520 
00521   tmp1 = (* SynthGetZddDivideRecurFunc())(dd, f, node);
00522   if (!tmp1) {
00523     bdd_recursive_deref_zdd(dd, node);
00524     return(NULL);
00525   }
00526   bdd_ref(tmp1);
00527   bdd_recursive_deref_zdd(dd, node);
00528 
00529   /* Recur on the quotient to make sure that all literals appear once. */
00530   divisor = SynthZddMostDivisor(dd, tmp1);
00531   if (!divisor) {
00532     bdd_recursive_deref_zdd(dd, tmp1);
00533     return(NULL);
00534   }
00535   bdd_ref(divisor);
00536   bdd_recursive_deref_zdd(dd, tmp1);
00537 
00538   bdd_deref(divisor);
00539   return(divisor);
00540 }
00541 
00542 
00555 bdd_node *
00556 SynthZddLevelZeroDivisor(bdd_manager *dd,
00557                          bdd_node *f)
00558 {
00559   int           i, v;
00560   int           nvars, max_count;
00561   int           *count;
00562   bdd_node      *one = bdd_read_one(dd);
00563   bdd_node      *zero = bdd_read_zero(dd);
00564   bdd_node      *divisor, *node;
00565   bdd_node      *tmp1, *tmp2;
00566 
00567   if (f == one || f == zero)
00568     return(f);
00569 
00570   /* Find the literal that occurs the most. */
00571   v = -1;
00572   max_count = 1;
00573   nvars = bdd_num_zdd_vars(dd);
00574   count = ALLOC(int, nvars);
00575   (void)memset((void *)count, 0, sizeof(int) * nvars);
00576   SynthCountLiteralOccurrence(dd, f, count);
00577   for (i = 0; i < nvars; i++) {
00578     if (count[i] > max_count) {
00579       v = i;
00580       max_count = count[i];
00581     }
00582   }
00583 
00584   FREE(count);
00585 
00586   if (v == -1) {
00587     /* All literal appear exactly once. We are done. */
00588     return(f);
00589   }
00590 
00591   /* Obtain the literal divisor from its index and divide f. */
00592   node = bdd_zdd_get_node(dd, v, one, zero);
00593   if (!node)
00594     return(NULL);
00595   bdd_ref(node);
00596 
00597   tmp1 = (* SynthGetZddDivideRecurFunc())(dd, f, node);
00598   if (!tmp1) {
00599     bdd_recursive_deref_zdd(dd, node);
00600     return(NULL);
00601   }
00602   bdd_ref(tmp1);
00603   bdd_recursive_deref_zdd(dd, node);
00604 
00605   /* Factor out all literals appearing in all cubes. */
00606   tmp2 = SynthMakeCubeFree(dd, tmp1);
00607   if (!tmp2) {
00608     bdd_recursive_deref_zdd(dd, tmp1);
00609     return(NULL);
00610   }
00611   bdd_ref(tmp2);
00612   bdd_recursive_deref_zdd(dd, tmp1);
00613 
00614   /* Recur on the quotient to make sure that all literals appear once. */
00615   divisor = SynthZddLevelZeroDivisor(dd, tmp2);
00616   if (!divisor) {
00617     bdd_recursive_deref_zdd(dd, tmp2);
00618     return(NULL);
00619   }
00620   bdd_ref(divisor);
00621   bdd_recursive_deref_zdd(dd, tmp2);
00622 
00623   bdd_deref(divisor);
00624   return(divisor);
00625 }
00626 
00639 bdd_node *
00640 SynthZddCommonDivisor(bdd_manager *dd,
00641                       bdd_node *f)
00642 {
00643   int           i;
00644   int           nvars;
00645   int           *count;
00646   bdd_node      *one = bdd_read_one(dd);
00647   bdd_node      *zero = bdd_read_zero(dd);
00648   bdd_node      *divisor, *node, *tmp;
00649   int           nCubes;
00650 
00651   divisor = (bdd_node *)NULL;   /* NULL means no such divisor exists */
00652   if (f == one || f == zero)
00653     return(divisor);
00654 
00655   nCubes = bdd_zdd_count(dd, f);
00656   if (nCubes == 1)
00657     return(divisor);
00658 
00659   /* Find the literals that appear exactly as many times as there
00660    * are cubes. These literals appear in all cubes, hence in the
00661    * common divisor. Their product is accumulated in divisor. */
00662   nvars = bdd_num_zdd_vars(dd);
00663   count = ALLOC(int, nvars);
00664   (void)memset((void *)count, 0, sizeof(int) * nvars);
00665   SynthCountLiteralOccurrence(dd, f, count);
00666   for (i = 0; i < nvars; i++) {
00667     if (count[i] == nCubes) {
00668       node = bdd_zdd_get_node(dd, i, one, zero);
00669       if (!node) {
00670         FREE(count);
00671         return(NULL);
00672       }
00673       bdd_ref(node);
00674       if (!divisor) {
00675         divisor = node;
00676         continue;
00677       }
00678       tmp = divisor;
00679       divisor = (* SynthGetZddProductRecurFunc())(dd, divisor, node);
00680       if (!divisor) {
00681         bdd_recursive_deref_zdd(dd, tmp);
00682         bdd_recursive_deref_zdd(dd, node);
00683         FREE(count);
00684         return(NULL);
00685       }
00686       bdd_ref(divisor);
00687       bdd_recursive_deref_zdd(dd, tmp);
00688       bdd_recursive_deref_zdd(dd, node);
00689     }
00690   }
00691   FREE(count);
00692 
00693   if (divisor)
00694     bdd_deref(divisor);
00695   return(divisor);
00696 }
00697 
00698 
00711 bdd_node *
00712 SynthZddLpDivisor(bdd_manager *dd,
00713                   bdd_node *f)
00714 {
00715   int           i, v;
00716   int           nvars, min_count, min_pos = 0;
00717   int           *count;
00718   bdd_node      *one = bdd_read_one(dd);
00719   bdd_node      *zero = bdd_read_zero(dd);
00720   bdd_node      *divisor, *node;
00721   bdd_node      *tmp1;
00722 
00723   if (f == one || f == zero)
00724     return(f);
00725 
00726   /* Find the literal that occurs the least among those occuring at
00727    * least twice.
00728    */
00729   v = -1;
00730   min_count = MAX_COUNT;
00731   nvars = bdd_num_zdd_vars(dd);
00732   count = ALLOC(int, nvars);
00733   (void)memset((void *)count, 0, sizeof(int) * nvars);
00734 
00735   SynthCountLiteralOccurrence(dd, f, count);
00736   for (i = 0; i < nvars; i++) {
00737     if (count[i] > 1 && count[i] < min_count) {
00738       v = i;
00739       min_count = count[i];
00740       min_pos = i;
00741     }
00742   }
00743   if (v == -1) {
00744     /* All literal appear exactly once. We are done. */
00745     FREE(count);
00746     return(f);
00747   }
00748 
00749   /* Among the literals with minimum count, find a good one. */
00750   v = SynthFindDivisorForLowPower(count, nvars, min_count, min_pos);
00751 
00752   FREE(count);
00753 
00754   if (v == -1) {
00755     return(f);
00756   }
00757 
00758   /* Obtain the literal divisor from its index and divide f. */
00759   node = bdd_zdd_get_node(dd, v, one, zero);
00760   if (!node)
00761     return(NULL);
00762   bdd_ref(node);
00763 
00764   tmp1 = (* SynthGetZddDivideRecurFunc())(dd, f, node);
00765   if (!tmp1) {
00766     bdd_recursive_deref_zdd(dd, node);
00767     return(NULL);
00768   }
00769   bdd_ref(tmp1);
00770   bdd_recursive_deref_zdd(dd, node);
00771 
00772   /* Recur on the quotient to make sure that all literals appear once. */
00773   divisor = SynthZddLpDivisor(dd, tmp1);
00774   if (!divisor) {
00775     bdd_recursive_deref_zdd(dd, tmp1);
00776     return(NULL);
00777   }
00778   bdd_ref(divisor);
00779   bdd_recursive_deref_zdd(dd, tmp1);
00780 
00781   bdd_deref(divisor);
00782   return(divisor);
00783 }
00784 
00785 
00811 void
00812 SynthCountLiteralOccurrence(bdd_manager *dd,
00813                             bdd_node *f,
00814                             int *count)
00815 {
00816   BfsItem       **level, *item, *cur_item, *next_item, *last_item;
00817   BfsList       *list, *pre_list, *cur_list, *next_list, *last_list;
00818   BfsList       *new_list, *save_last_list;
00819   int           cur_level, next_level, start_level, last_level;
00820   int           exist;
00821   bdd_node      *zero = bdd_read_zero(dd);
00822   bdd_node      *one = bdd_read_one(dd);
00823   int           i, ct, ce;
00824   bdd_node      *node;
00825   int           lv, *index, id;
00826   int           sizeZ = bdd_num_zdd_vars(dd);
00827 
00828   if (bdd_is_constant(f))
00829     return;
00830 
00831   level = ALLOC(BfsItem *, sizeZ);
00832   (void)memset((void *)level, 0, sizeof(BfsItem *) * sizeZ);
00833   index = ALLOC(int, sizeZ);
00834   (void)memset((void *)index, 0, sizeof(int) * sizeZ);
00835 
00836   /* Initialize BFS by entering f in the queue. */
00837   item = ALLOC(BfsItem, 1);
00838   (void)memset((void *)item, 0, sizeof(BfsItem));
00839   item->node = f;
00840   item->reach = 1;
00841   lv = bdd_read_zdd_level(dd,bdd_node_read_index(f));
00842   level[lv] = item;
00843   index[lv] = bdd_node_read_index(f);
00844   start_level = last_level = lv;
00845 
00846   if (!bdd_is_constant(bdd_bdd_T(f))) {
00847     list = ALLOC(BfsList, 1);
00848     (void)memset((void *)list, 0, sizeof(BfsList));
00849     list->item = item;
00850     list->child = 1;
00851     last_list = list;
00852   } else
00853     list = last_list = (BfsList *)NULL;
00854   if (!bdd_is_constant(bdd_bdd_E(f))) {
00855     last_list = ALLOC(BfsList, 1);
00856     (void)memset((void *)last_list, 0, sizeof(BfsList));
00857     last_list->item = item;
00858     last_list->child = 0;
00859     if (list)
00860       list->next = last_list;
00861     else
00862       list = last_list;
00863   }
00864 
00865   /* Perform the BFS. */
00866   while (list) {
00867     cur_level = sizeZ;
00868     cur_list = list;
00869     while (cur_list) {
00870       if (cur_list->child)
00871         id = bdd_node_read_index(bdd_bdd_T(cur_list->item->node));
00872       else
00873         id = bdd_node_read_index(bdd_bdd_E(cur_list->item->node));
00874       next_level = bdd_read_zdd_level(dd,id);
00875       cur_level = (cur_level < next_level) ? cur_level : next_level;
00876       cur_list = cur_list->next;
00877     }
00878     last_level = cur_level;
00879     save_last_list = last_list;
00880 
00881     pre_list = (BfsList *)NULL;
00882     cur_list = list;
00883     while (cur_list) {
00884       if (cur_list->child)
00885         id = bdd_node_read_index(bdd_bdd_T(cur_list->item->node));
00886       else
00887         id = bdd_node_read_index(bdd_bdd_E(cur_list->item->node));
00888       next_level = bdd_read_zdd_level(dd,id);
00889 
00890       if (next_level != cur_level) {
00891         pre_list = cur_list;
00892         cur_list = cur_list->next;
00893         continue;
00894       }
00895 
00896       if (cur_list->child)
00897         node = bdd_bdd_T(cur_list->item->node);
00898       else
00899         node = bdd_bdd_E(cur_list->item->node);
00900 
00901       exist = 0;
00902       last_item = level[cur_level];
00903       while (last_item) {
00904         if (node == last_item->node) {
00905           last_item->reach += cur_list->item->reach;
00906           exist = 1;
00907           break;
00908         }
00909         if (last_item->next)
00910           last_item = last_item->next;
00911         else
00912           break;
00913       }
00914 
00915       if (exist == 0) {
00916         item = ALLOC(BfsItem, 1);
00917         (void)memset((void *)item, 0, sizeof(BfsItem));
00918         item->node = node;
00919         item->reach = cur_list->item->reach;
00920         if (last_item)
00921           last_item->next = item;
00922         else {
00923           level[cur_level] = item;
00924           index[cur_level] = id;
00925         }
00926 
00927         if (!bdd_is_constant(bdd_bdd_T(node))) {
00928           new_list = ALLOC(BfsList, 1);
00929           (void)memset((void *)new_list, 0, sizeof(BfsList));
00930           new_list->item = item;
00931           new_list->child = 1;
00932           last_list->next = new_list;
00933           last_list = new_list;
00934         }
00935         if (!bdd_is_constant(bdd_bdd_E(node))) {
00936           new_list = ALLOC(BfsList, 1);
00937           (void)memset((void *)new_list, 0, sizeof(BfsList));
00938           new_list->item = item;
00939           new_list->child = 0;
00940           last_list->next = new_list;
00941           last_list = new_list;
00942         }
00943       }
00944 
00945       next_list = cur_list->next;
00946       if (cur_list == list && cur_list == last_list) {
00947         FREE(cur_list);
00948         list = next_list;
00949       } else if (cur_list == list) {
00950         FREE(cur_list);
00951         pre_list = (BfsList *)NULL;
00952         if (list == save_last_list) {
00953           list = next_list;
00954           next_list = (BfsList *)NULL;
00955         } else
00956           list = next_list;
00957       } else if (cur_list == last_list) {
00958         if (pre_list)
00959           pre_list->next = cur_list->next;
00960         FREE(cur_list);
00961         last_list = pre_list;
00962       } else {
00963         if (pre_list)
00964           pre_list->next = cur_list->next;
00965         if (cur_list == save_last_list) {
00966           FREE(cur_list);
00967           next_list = (BfsList *)NULL;
00968         } else
00969           FREE(cur_list);
00970       }
00971 
00972       cur_list = next_list;
00973     }
00974   }
00975 
00976   /* Compute the number of paths to the constant 1 for each node in
00977    * bottom up fashion. Update the occurrence count of the variables.
00978    */
00979   for (i = last_level; i >= start_level; i--) {
00980     item = level[i];
00981     while (item) {
00982       ct = ce = 0;
00983       if (bdd_bdd_T(item->node) == one)
00984         ct = 1;
00985       else {
00986         node = bdd_bdd_T(item->node);
00987         next_level = bdd_read_zdd_level(dd, bdd_node_read_index(node));
00988         cur_item = level[next_level];
00989         while (cur_item) {
00990           if (cur_item->node == node) {
00991             ct = cur_item->count;
00992             break;
00993           }
00994           cur_item = cur_item->next;
00995         }
00996       }
00997       if (bdd_bdd_E(item->node) != zero) {
00998         node = bdd_bdd_E(item->node);
00999         next_level = bdd_read_zdd_level(dd,
01000                                         bdd_node_read_index(node));
01001         cur_item = level[next_level];
01002         while (cur_item) {
01003           if (cur_item->node == node) {
01004             ce = cur_item->count;
01005             break;
01006           }
01007           cur_item = cur_item->next;
01008         }
01009       }
01010       item->count = ct + ce;
01011       count[index[i]] += ct * item->reach;
01012       item = item->next;
01013     }
01014   }
01015 
01016   /* Clean up. */
01017   for (i = last_level; i >= start_level; i--) {
01018     item = level[i];
01019     while (item) {
01020       next_item = item->next;
01021       FREE(item);
01022       item = next_item;
01023     }
01024   }
01025 
01026   FREE(level);
01027   FREE(index);
01028 }
01029 
01030 
01031 /*---------------------------------------------------------------------------*/
01032 /* Definition of static functions                                            */
01033 /*---------------------------------------------------------------------------*/
01034 
01035 
01054 static int
01055 FindQuickDivisor(bdd_node *f,
01056                  bdd_node *one,
01057                  int *v)
01058 {
01059   int           c, ct, ce;
01060   bdd_node      *temp = bdd_read_next(f);
01061 
01062   if (bdd_is_constant(f)) {
01063     if (f == one)
01064       return(1);
01065     else
01066       return(0);
01067   }
01068 
01069   if (bdd_is_complement(temp)) { /* already visited */
01070     *v = bdd_node_read_index(f);
01071     return(-1);
01072   }
01073   /* mark as visited */
01074   bdd_set_next(f, bdd_not_bdd_node(temp));
01075 
01076   ct = FindQuickDivisor(bdd_bdd_T(f), one, v);
01077   if (ct == -1) /* already found */
01078     return(-1);
01079   else if (ct > 1) {
01080     *v = bdd_node_read_index(f);
01081     return(-1);
01082   }
01083 
01084   ce = FindQuickDivisor(bdd_bdd_E(f), one, v);
01085   if (ce == -1) /* already found */
01086     return(-1);
01087 
01088   /* Add the number of path to constant 1 from two children nodes. */
01089   c = ct + ce;
01090   return(c);
01091 }