VIS
|
00001 00076 #include "fsmInt.h" 00077 #include "bdd.h" 00078 #include "ntm.h" 00079 #include "img.h" 00080 00081 static char rcsid[] UNUSED = "$Id: fsmHD.c,v 1.32 2005/05/16 06:23:29 fabio Exp $"; 00082 00083 /*---------------------------------------------------------------------------*/ 00084 /* Constant declarations */ 00085 /*---------------------------------------------------------------------------*/ 00086 /* thresholds for computation */ 00087 #define FSM_HD_DEADEND_RESIDUE_LIMIT 5000/*size beyond which residue is freed*/ 00088 #define FSM_HD_FRONTIER_APPROX_THRESHOLD 3500 /* default frontier approximation 00089 threshold */ 00090 #define FSM_HD_REACHED_THRESHOLD 2000 /* Threshold below which reached is 00091 not decomposed */ 00092 #define FSM_HD_DISJ_SIZE 5000 /* default Size of disjunct whose image 00093 may be computed in dead end computation. */ 00094 #define FSM_HD_DEADEND_MAX_SIZE_FACTOR 5 /* Factor such that when multiplied with 00095 the approx threshold will allow partitioning of the reached disjunct. */ 00096 #define FSM_HD_FROM 0 /* Constant to indicate to subsetting method whether to use 00097 * specified method or remap_ua */ 00098 #define FSM_HD_DEADEND 1 /* Constant to indicate to subsetting method whether to use 00099 * specified method or remap_ua */ 00100 #define FSM_HD_MIN_SIZE_FROM 700 /* threshold to indicate not to subset if under this size */ 00101 #define FSM_HD_DONT_FREE 0 /* flag to indicate that mdds should not be freed */ 00102 #define FSM_HD_FREE 1 /* flag to indicate that mdds should be freed */ 00103 #define FSM_HD_SP_THRESHOLD 2000 /* Threshold for short_paths method */ 00104 00105 /*---------------------------------------------------------------------------*/ 00106 /* Type declarations */ 00107 /*---------------------------------------------------------------------------*/ 00108 typedef struct FsmHdSizeStruct FsmHdSizeStruct_t; 00109 00110 /*---------------------------------------------------------------------------*/ 00111 /* Structure declarations */ 00112 /*---------------------------------------------------------------------------*/ 00113 00114 00119 struct FsmHdSizeStruct { 00120 mdd_t *bdd; 00121 int size; 00122 long rnd; 00123 }; 00124 00125 00128 /*---------------------------------------------------------------------------*/ 00129 /* Static function prototypes */ 00130 /*---------------------------------------------------------------------------*/ 00131 00132 static mdd_t * ComputeNewSeedsAtDeadEnd(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, mdd_t *reachableStates, FsmHdStruct_t *hdInfo, int greedy, int verbosity); 00133 static mdd_t * ComputeImageOfDecomposedParts(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, mdd_t *reachedSet, mdd_t *reachableStates, FsmHdStruct_t *hdInfo, int frontierApproxThreshold, int nvars, int *failedPartition, int greedy, int verbosity); 00134 static mdd_t * ProcessDisjunctsRecursive(mdd_manager *mddManager, Img_ImageInfo_t *imageInfo, mdd_t **reachedSet, mdd_t *reachableStates, FsmHdStruct_t *hdInfo, int frontierApproxThreshold, int nvars, int *failedPartition, int reachedSize, int greedy, int verbosity); 00135 static mdd_t * ComputeSubsetBasedOnMethod(mdd_t *fromBetween, mdd_t *fromLowerBound, FsmHdTravOptions_t *options, int fromOrDeadEnd); 00136 static mdd_t * AddStates(mdd_t *a, mdd_t *b, int freeA, int freeB); 00137 static mdd_t * SubtractStates(mdd_t *a, mdd_t *b, int freeA, int freeB); 00138 static int RandomCompare(const void *ptrX, const void *ptrY); 00139 00143 /*---------------------------------------------------------------------------*/ 00144 /* Definition of exported functions */ 00145 /*---------------------------------------------------------------------------*/ 00146 00164 FsmHdTravOptions_t * 00165 Fsm_FsmHdGetTravOptions(int nvars) 00166 { 00167 char *frontierApproxMethodString, *frontierApproxThresholdString; 00168 char *scrapStatesString; 00169 char *deadEndString, *qualityString; 00170 char *newOnlyString, *partialImageString, *deadEndSubsetMethodString; 00171 FsmHdTravOptions_t *options; 00172 00173 if (nvars < 0) return NIL(FsmHdTravOptions_t); 00174 options = ALLOC(FsmHdTravOptions_t, 1); 00175 if (options == NIL(FsmHdTravOptions_t)) { 00176 return NIL(FsmHdTravOptions_t); 00177 } 00178 00179 options->nvars = nvars; 00180 /* set defaults */ 00181 options->frontierApproxMethod = BDD_APPROX_RUA; 00182 options->frontierApproxThreshold = FSM_HD_FRONTIER_APPROX_THRESHOLD; 00183 options->quality = 1.0; 00184 options->deadEnd = Fsm_Hd_DE_Con_c; 00185 options->deadEndSubsetMethod = BDD_APPROX_RUA; 00186 options->scrapStates = TRUE; 00187 options->newOnly = FALSE; 00188 options->onlyPartialImage = FALSE; 00189 options->qualityBias = 0.5; 00190 00191 /* method for subsetting reached, from */ 00192 frontierApproxMethodString = Cmd_FlagReadByName("hd_frontier_approx_method"); 00193 if (frontierApproxMethodString != NIL(char)) { 00194 if (strcmp(frontierApproxMethodString, "heavy_branch") == 0) { 00195 options->frontierApproxMethod = BDD_APPROX_HB; 00196 } else if (strcmp(frontierApproxMethodString, "short_paths") == 0) { 00197 options->frontierApproxMethod = BDD_APPROX_SP; 00198 } else if (strcmp(frontierApproxMethodString, "under_approx") == 0) { 00199 options->frontierApproxMethod = BDD_APPROX_UA; 00200 } else if (strcmp(frontierApproxMethodString, "remap_ua") == 0) { 00201 options->frontierApproxMethod = BDD_APPROX_RUA; 00202 } else if (strcmp(frontierApproxMethodString, "compress") == 0) { 00203 options->frontierApproxMethod = BDD_APPROX_COMP; 00204 } else if (strcmp(frontierApproxMethodString, "biased_rua") == 0) { 00205 options->frontierApproxMethod = BDD_APPROX_BIASED_RUA; 00206 } 00207 } 00208 00209 /* threshold value */ 00210 frontierApproxThresholdString = Cmd_FlagReadByName("hd_frontier_approx_threshold"); 00211 if (frontierApproxThresholdString != NIL(char)) { 00212 options->frontierApproxThreshold = strtol(frontierApproxThresholdString, 00213 NULL, 10); 00214 } 00215 /* adjust threshold if too small */ 00216 if ((options->frontierApproxMethod == BDD_APPROX_HB) || 00217 (options->frontierApproxMethod == BDD_APPROX_SP) || 00218 (options->frontierApproxMethod == BDD_APPROX_COMP)) { 00219 if (options->frontierApproxThreshold < FSM_HD_SP_THRESHOLD) { 00220 fprintf(vis_stdout, "** hd warning: Threshold too low, Correcting Frontier Approx Threshold to %d\n", FSM_HD_SP_THRESHOLD); 00221 options->frontierApproxThreshold = FSM_HD_SP_THRESHOLD; 00222 } 00223 } else if (options->frontierApproxThreshold < 0) { 00224 fprintf(vis_stdout, "** hd warning: Threshold negative, Correcting Frontier Approx Threshold to 0\n"); 00225 options->frontierApproxThreshold = FSM_HD_FRONTIER_APPROX_THRESHOLD; 00226 } 00227 00228 00229 /* quality option for remap_ua */ 00230 qualityString = Cmd_FlagReadByName("hd_approx_quality"); 00231 if (qualityString != NIL(char)) { 00232 options->quality = strtod(qualityString, NULL); 00233 if (options->quality < 0.0) { 00234 options->quality = 1.0; 00235 } 00236 } 00237 00238 /* quality option for biased_rua */ 00239 qualityString = Cmd_FlagReadByName("hd_approx_bias_quality"); 00240 if (qualityString != NIL(char)) { 00241 options->qualityBias = strtod(qualityString, NULL); 00242 if (options->qualityBias < 0.0) { 00243 options->qualityBias = 0.5; 00244 } 00245 } 00246 00247 /* method for dead end computations */ 00248 deadEndString = Cmd_FlagReadByName("hd_dead_end"); 00249 if (deadEndString != NIL(char)) { 00250 if (strcmp(deadEndString, "brute_force") == 0) { 00251 options->deadEnd = Fsm_Hd_DE_BF_c; 00252 } else if (strcmp(deadEndString, "conjuncts") == 0) { 00253 options->deadEnd = Fsm_Hd_DE_Con_c; 00254 } else if (strcmp(deadEndString, "hybrid") == 0) { 00255 options->deadEnd = Fsm_Hd_DE_Hyb_c; 00256 } 00257 } 00258 /* method for subsetting reached, from during deadEnds*/ 00259 deadEndSubsetMethodString = Cmd_FlagReadByName("hd_dead_end_approx_method"); 00260 if (deadEndSubsetMethodString != NIL(char)) { 00261 if (strcmp(deadEndSubsetMethodString, "heavy_branch") == 0) { 00262 options->deadEndSubsetMethod = BDD_APPROX_HB; 00263 } else if (strcmp(deadEndSubsetMethodString, "short_paths") == 0) { 00264 options->deadEndSubsetMethod = BDD_APPROX_SP; 00265 } else if (strcmp(deadEndSubsetMethodString, "under_approx") == 0) { 00266 options->deadEndSubsetMethod = BDD_APPROX_UA; 00267 } else if (strcmp(deadEndSubsetMethodString, "remap_ua") == 0) { 00268 options->deadEndSubsetMethod = BDD_APPROX_RUA; 00269 } else if (strcmp(deadEndSubsetMethodString, "compress") == 0) { 00270 options->deadEndSubsetMethod = BDD_APPROX_COMP; 00271 } 00272 } 00273 /* option to not add blocking states */ 00274 scrapStatesString = Cmd_FlagReadByName("hd_no_scrap_states"); 00275 if (scrapStatesString != NIL(char)) { 00276 options->scrapStates = FALSE; 00277 } 00278 00279 /* option to consider only new states instead of fromBetween */ 00280 newOnlyString = Cmd_FlagReadByName("hd_new_only"); 00281 if (newOnlyString != NIL(char)) { 00282 options->newOnly = TRUE; 00283 } 00284 00285 /* perform approximate traversal with only partial images */ 00286 partialImageString = Cmd_FlagReadByName("hd_only_partial_image"); 00287 if (partialImageString != NIL(char)) { 00288 options->onlyPartialImage = TRUE; 00289 } 00290 00291 return (options); 00292 } /* end of Fsm_FsmHdGetTraversalOptions */ 00293 00305 void 00306 Fsm_FsmHdFreeTravOptions(FsmHdTravOptions_t *options) 00307 { 00308 if (options) FREE(options); 00309 return; 00310 } /* end of Fsm_FsmHdFreeTravOptions */ 00311 00325 int 00326 Fsm_FsmHdOptionReadNumVars(FsmHdTravOptions_t *options) 00327 { 00328 if (options) return(options->nvars); 00329 else return 0; 00330 } 00331 00345 int 00346 Fsm_FsmHdOptionReadFrontierApproxThreshold(FsmHdTravOptions_t *options) 00347 { 00348 if (options) return (options->frontierApproxThreshold); 00349 else return 0; 00350 } 00351 00365 boolean 00366 Fsm_FsmHdOptionReadOnlyPartialImage(FsmHdTravOptions_t *options) 00367 { 00368 if (options) return (options->onlyPartialImage); 00369 else return FALSE; 00370 } 00371 00385 boolean 00386 Fsm_FsmHdOptionReadScrapStates(FsmHdTravOptions_t *options) 00387 { 00388 if (options) return (options->scrapStates); 00389 else return TRUE; 00390 } 00391 00405 double 00406 Fsm_FsmHdOptionReadQuality(FsmHdTravOptions_t *options) 00407 { 00408 if (options) return(options->quality); 00409 else return 1.0; 00410 } 00411 00425 bdd_approx_type_t 00426 Fsm_FsmHdOptionReadFrontierApproxMethod(FsmHdTravOptions_t *options) 00427 { 00428 if (options) return(options->frontierApproxMethod); 00429 else return BDD_APPROX_RUA; 00430 } 00431 00445 Fsm_HdDeadEndType_t 00446 Fsm_FsmHdOptionReadDeadEnd(FsmHdTravOptions_t *options) 00447 { 00448 if (options) return(options->deadEnd); 00449 else return Fsm_Hd_DE_Con_c; 00450 } 00451 00465 boolean 00466 Fsm_FsmHdOptionReadNewOnly(FsmHdTravOptions_t *options) 00467 { 00468 if (options) return(options->newOnly); 00469 else return FALSE; 00470 } 00471 00485 bdd_approx_type_t 00486 Fsm_FsmHdOptionReadDeadEndSubsetMethod(FsmHdTravOptions_t *options) 00487 { 00488 if (options) return(options->deadEndSubsetMethod); 00489 else return BDD_APPROX_RUA; 00490 } 00491 00507 int 00508 Fsm_FsmHdOptionSetFrontierApproxThreshold(FsmHdTravOptions_t *options, 00509 int threshold) 00510 { 00511 if ((options->frontierApproxMethod == BDD_APPROX_HB) || 00512 (options->frontierApproxMethod == BDD_APPROX_SP) || 00513 (options->frontierApproxMethod == BDD_APPROX_COMP)) { 00514 if (threshold < FSM_HD_SP_THRESHOLD) { 00515 fprintf(vis_stdout, "** hd warning: Threshold too low, Correcting Frontier Approx Threshold to %d\n", FSM_HD_SP_THRESHOLD); 00516 options->frontierApproxThreshold = FSM_HD_SP_THRESHOLD; 00517 return 0; 00518 } else { 00519 options->frontierApproxThreshold = threshold; 00520 return 1; 00521 } 00522 } else if (threshold < 0) { 00523 fprintf(vis_stdout, "** hd warning: Threshold negative, Correcting Frontier Approx Threshold to 0\n"); 00524 options->frontierApproxThreshold = FSM_HD_FRONTIER_APPROX_THRESHOLD; 00525 return 0; 00526 } else { 00527 options->frontierApproxThreshold = threshold; 00528 return 1; 00529 } 00530 } 00531 00545 void 00546 Fsm_FsmHdOptionSetOnlyPartialImage(FsmHdTravOptions_t *options, 00547 boolean onlyPartial) 00548 { 00549 if (options) options->onlyPartialImage = onlyPartial; 00550 return; 00551 } 00552 00566 void 00567 Fsm_FsmHdOptionSetScrapStates(FsmHdTravOptions_t *options, boolean scrapStates) 00568 { 00569 if (options) options->scrapStates = scrapStates; 00570 return; 00571 } 00572 00587 void 00588 Fsm_FsmHdOptionSetQuality(FsmHdTravOptions_t *options, double quality) 00589 { 00590 if (quality > 0.0) 00591 if (options) options->quality = quality; 00592 return; 00593 } 00594 00608 void 00609 Fsm_FsmHdOptionSetFrontierApproxMethod(FsmHdTravOptions_t *options, 00610 bdd_approx_type_t approxMethod) 00611 { 00612 if (options) options->frontierApproxMethod = approxMethod; 00613 if ((options->frontierApproxMethod == BDD_APPROX_HB) || 00614 (options->frontierApproxMethod == BDD_APPROX_SP) || 00615 (options->frontierApproxMethod == BDD_APPROX_COMP)) { 00616 if (options->frontierApproxThreshold < FSM_HD_SP_THRESHOLD) { 00617 fprintf(vis_stdout, "** hd warning: Threshold too low, Correcting Frontier Approx Threshold to %d\n", FSM_HD_SP_THRESHOLD); 00618 options->frontierApproxThreshold = FSM_HD_SP_THRESHOLD; 00619 return; 00620 } 00621 } else if (options->frontierApproxThreshold < 0) { 00622 fprintf(vis_stdout, "** hd warning: Threshold negative, Correcting Frontier Approx Threshold to 0\n"); 00623 options->frontierApproxThreshold = FSM_HD_FRONTIER_APPROX_THRESHOLD; 00624 return; 00625 } 00626 00627 return; 00628 } 00629 00643 void 00644 Fsm_FsmHdOptionSetDeadEnd(FsmHdTravOptions_t *options, 00645 Fsm_HdDeadEndType_t deadEnd) 00646 { 00647 if (options) options->deadEnd = deadEnd; 00648 return; 00649 } 00650 00664 void 00665 Fsm_FsmHdOptionSetNewOnly(FsmHdTravOptions_t *options, boolean newOnly) 00666 { 00667 if (options) options->newOnly = newOnly; 00668 return; 00669 } 00670 00684 void 00685 Fsm_FsmHdOptionSetDeadEndSubsetMethod(FsmHdTravOptions_t *options, 00686 bdd_approx_type_t approxMethod) 00687 { 00688 if (options) options->deadEndSubsetMethod = approxMethod; 00689 return; 00690 } 00691 00692 00693 /*---------------------------------------------------------------------------*/ 00694 /* Definition of internal functions */ 00695 /*---------------------------------------------------------------------------*/ 00696 00708 FsmHdMintSizeStats_t * 00709 FsmHdStatsStructAlloc(void) 00710 { 00711 FsmHdMintSizeStats_t *stats; 00712 00713 stats = ALLOC(FsmHdMintSizeStats_t, 1); 00714 if (stats == NULL) return NULL; 00715 00716 stats->sizeTo = 0; 00717 stats->mintermTo = 0.0; 00718 stats->sizeFrom = 0; 00719 stats->mintermFrom = 0.0; 00720 stats->sizeFromSubset = 0; 00721 stats->mintermFromSubset = 0.0; 00722 stats->sizeReached = 0; 00723 stats->mintermReached = 0.0; 00724 00725 return stats; 00726 } /* end of FsmHdStatsStructAlloc */ 00727 00728 00740 void 00741 FsmHdStatsStructFree(FsmHdMintSizeStats_t *stats) 00742 { 00743 FREE(stats); 00744 return; 00745 } /* end of FsmHdStatsStructFree */ 00746 00747 00748 00760 void 00761 FsmHdStatsComputeSizeAndMinterms(mdd_manager *mddManager, 00762 mdd_t *f, 00763 array_t *varArray, 00764 int nvars, 00765 Fsm_Hd_Quant_t field, 00766 FsmHdMintSizeStats_t *stats) 00767 { 00768 int size; 00769 double minterms = 0.0; 00770 00771 size = mdd_size(f); 00772 if (nvars <= 1023) 00773 minterms = mdd_count_onset(mddManager, f, varArray); 00774 00775 switch (field) { 00776 case Fsm_Hd_From: { 00777 stats->sizeFrom = size; 00778 stats->mintermFrom = minterms; 00779 break; 00780 } 00781 case Fsm_Hd_To: { 00782 stats->sizeTo = size; 00783 stats->mintermTo = minterms; 00784 break; 00785 } 00786 case Fsm_Hd_FromSubset: { 00787 stats->sizeFromSubset = size; 00788 stats->mintermFromSubset = minterms; 00789 break; 00790 } 00791 case Fsm_Hd_Reached: { 00792 stats->sizeReached = size; 00793 stats->mintermReached = minterms; 00794 break; 00795 } 00796 default: break; 00797 } 00798 return; 00799 } /* end of FsmHdStatsComputeSizeAndMinterms */ 00800 00811 void 00812 FsmHdStatsReset(FsmHdMintSizeStats_t *stats, 00813 Fsm_Hd_Quant_t field) 00814 { 00815 00816 switch (field) { 00817 case Fsm_Hd_To: 00818 stats->sizeTo = 0; 00819 stats->mintermTo = 0.0; 00820 break; 00821 case Fsm_Hd_From: 00822 stats->sizeFrom = 0; 00823 stats->mintermFrom = 0.0; 00824 break; 00825 case Fsm_Hd_FromSubset: 00826 stats->sizeFromSubset = 0; 00827 stats->mintermFromSubset = 0.0; 00828 break; 00829 case Fsm_Hd_Reached: 00830 stats->sizeReached = 0; 00831 stats->mintermReached = 0.0; 00832 break; 00833 } 00834 return; 00835 } /* end of FsmHdStatsReset */ 00836 00837 00849 void 00850 FsmHdPrintOptions(void) 00851 { 00852 FsmHdTravOptions_t *options; 00853 char *dummy; 00854 options = Fsm_FsmHdGetTravOptions( 0); 00855 if (options == NIL(FsmHdTravOptions_t)) { 00856 fprintf(vis_stderr, "HD: Unalble to get options\n"); 00857 return; 00858 } 00859 00860 dummy = ALLOC(char, 20); 00861 if (dummy == NULL) return; 00862 switch (options->frontierApproxMethod) { 00863 case BDD_APPROX_HB: sprintf(dummy, "%s", "heavy_branch"); break; 00864 case BDD_APPROX_SP: sprintf(dummy, "%s", "short_paths"); break; 00865 00866 case BDD_APPROX_UA: sprintf(dummy, "%s", "under_approx"); break; 00867 case BDD_APPROX_RUA: sprintf(dummy, "%s", "remap_ua"); break; 00868 case BDD_APPROX_BIASED_RUA: sprintf(dummy, "%s", "biased_rua"); break; 00869 00870 case BDD_APPROX_COMP: sprintf(dummy, "%s", "compress"); break; 00871 default: sprintf(dummy, "%s", "remap_ua"); break; 00872 } 00873 00874 fprintf(vis_stdout, "HD: Approx method for frontier subsets = %s\n", dummy); 00875 fprintf(vis_stdout, "HD: Threshold for frontier approximation = %d\n", options->frontierApproxThreshold); 00876 fprintf(vis_stdout, "HD: Quality option for approx methods = %g\n", options->quality); 00877 fprintf(vis_stdout, "HD: Bias quality option for the biased approx method = %g\n", options->qualityBias); 00878 00879 switch (options->deadEnd) { 00880 case Fsm_Hd_DE_BF_c: sprintf(dummy, "%s", "brute_force"); break; 00881 case Fsm_Hd_DE_Con_c: sprintf(dummy, "%s", "conjuncts"); break; 00882 case Fsm_Hd_DE_Hyb_c: sprintf(dummy, "%s", "hybrid"); break; 00883 } 00884 00885 fprintf(vis_stdout, "HD: Dead-End method = %s\n", dummy); 00886 00887 switch (options->deadEndSubsetMethod) { 00888 case BDD_APPROX_HB: sprintf(dummy, "%s", "heavy_branch"); break; 00889 case BDD_APPROX_SP: sprintf(dummy, "%s", "short_paths"); break; 00890 00891 case BDD_APPROX_UA: sprintf(dummy, "%s", "under_approx"); break; 00892 case BDD_APPROX_RUA: sprintf(dummy, "%s", "remap_ua"); break; 00893 00894 case BDD_APPROX_COMP: sprintf(dummy, "%s", "compress"); break; 00895 default: sprintf(dummy, "%s", "remap_ua"); break; 00896 } 00897 00898 fprintf(vis_stdout, "HD: Dead-end approx method = %s\n", dummy); 00899 FREE(dummy); 00900 00901 fprintf(vis_stdout, "HD: Add scrap states option = "); 00902 if (options->scrapStates == TRUE) fprintf(vis_stdout, "yes\n"); 00903 else fprintf(vis_stdout, "no\n"); 00904 00905 fprintf(vis_stdout, "HD: Only new states in frontier option = "); 00906 if (options->newOnly == TRUE) fprintf(vis_stdout, "yes\n"); 00907 else fprintf(vis_stdout, "no\n"); 00908 00909 fprintf(vis_stdout, "HD: Only partial image option = "); 00910 if (options->onlyPartialImage == TRUE) fprintf(vis_stdout, "yes\n"); 00911 else fprintf(vis_stdout, "no\n"); 00912 00913 Fsm_FsmHdFreeTravOptions(options); 00914 Img_ImagePrintPartialImageOptions(); 00915 00916 fprintf(vis_stdout, "See help page on print_hd_options for setting these options\n"); 00917 return; 00918 00919 } /* end of FsmHdPrintOptions */ 00920 00935 mdd_t * 00936 FsmHdDeadEnd(mdd_manager *mddManager, 00937 Img_ImageInfo_t *imageInfo, 00938 mdd_t *reachableStates, 00939 FsmHdStruct_t *hdInfo, 00940 array_t *varArray, 00941 int greedy, 00942 int verbosity) 00943 { 00944 mdd_t *fromLowerBound; 00945 00946 /* if residue is around to long, throw it away */ 00947 if (hdInfo->residueCount >= 4) { 00948 if (hdInfo->deadEndResidue != NULL) { 00949 mdd_free(hdInfo->deadEndResidue); 00950 hdInfo->deadEndResidue = NULL; 00951 } 00952 } 00953 00954 if ((hdInfo->deadEndResidue != NULL) && (greedy)) { 00955 /* dont compute new seeds out of dead end 00956 * if some states are left over from previous iterations. 00957 */ 00958 fromLowerBound = hdInfo->deadEndResidue; 00959 hdInfo->deadEndResidue = NULL; 00960 assert(!mdd_is_tautology(fromLowerBound, 0)); 00961 if (hdInfo->interiorStates != NIL(mdd_t)) 00962 assert(mdd_lequal(fromLowerBound, hdInfo->interiorStates, 1, 0)); 00963 if (verbosity >= 2) fprintf(vis_stdout, "Residue had new seeds\n"); 00964 (hdInfo->residueCount)++; 00965 } else { 00966 /* compute new seeds by decomposing reachable states */ 00967 if (hdInfo->deadEndResidue != NULL) { 00968 mdd_free(hdInfo->deadEndResidue); 00969 hdInfo->deadEndResidue = NULL; 00970 } 00971 hdInfo->residueCount = 0; 00972 fromLowerBound = ComputeNewSeedsAtDeadEnd(mddManager, 00973 imageInfo, 00974 reachableStates, 00975 hdInfo, 00976 greedy, 00977 verbosity); 00978 00979 } 00980 00981 /* mark that this is a dead end */ 00982 hdInfo->deadEndComputation = TRUE; 00983 00984 return (fromLowerBound); 00985 } /* end of FsmHdDeadEnd */ 00986 01021 void 01022 FsmHdFromComputeDenseSubset(mdd_manager *mddManager, 01023 mdd_t **fromLowerBound, 01024 mdd_t **fromUpperBound, 01025 mdd_t **reachableStates, 01026 mdd_t **image, 01027 mdd_t *initialStates, 01028 FsmHdStruct_t *hdInfo, 01029 int shellFlag, 01030 array_t *onionRings, 01031 int sizeOfOnionRings, 01032 array_t *varArray) 01033 { 01034 01035 int thisTimeSubset; 01036 mdd_t *fromSubset, *fromBetween; 01037 mdd_t *temp, *temp1, *nonInteriorStates; 01038 float densityFrom = 0.0, densityFromSubset = 0.0; /* initialize to pacify */ 01039 int numReorders; 01040 double mintResidue; 01041 int sizeResidue; 01042 int frontierApproxThreshold; 01043 int nvars; 01044 01045 numReorders = bdd_read_reorderings(mddManager); 01046 frontierApproxThreshold = Fsm_FsmHdOptionReadFrontierApproxThreshold(hdInfo->options); 01047 nvars = Fsm_FsmHdOptionReadNumVars(hdInfo->options); 01048 01049 /* if image is bigger and smaller in size, switch. Add initial states. 01050 * Reset dead states since they are no longer valid. 01051 */ 01052 01053 #if 0 /* taken out for counterexamples */ 01054 if ((FsmHdStatsReadMintermReached(hdInfo->stats) < 01055 FsmHdStatsReadMintermTo(hdInfo->stats)) && 01056 (FsmHdStatsReadSizeReached(hdInfo->stats) > FsmHdStatsReadSizeTo(hdInfo->stats))) { 01057 if (hdInfo->interiorStates != NIL(mdd_t)) mdd_free(hdInfo->interiorStates); 01058 hdInfo->interiorStates = bdd_zero(mddManager); 01059 bdd_free(*reachableStates); 01060 mdd_free(*fromUpperBound); 01061 *reachableStates = mdd_or(initialStates, *image, 1, 1); 01062 *reachableStates = AddStates(*fromLowerBound, *reachableStates, 01063 FSM_HD_DONT_FREE, FSM_HD_FREE); 01064 FsmHdStatsComputeSizeAndMinterms(mddManager, *reachableStates, 01065 varArray, nvars, Fsm_Hd_Reached, hdInfo->stats); 01066 *fromUpperBound = mdd_dup(*reachableStates); 01067 if (shellFlag && *onionRings) { 01068 int onionRingCount; 01069 mdd_t *onionRing; 01070 fprintf(vis_stdout, "Onion Rings no longer valid. \n"); 01071 arrayForEachItem(mdd_t *, *onionRings, onionRingCount, onionRing) { 01072 mdd_free(onionRing); 01073 } 01074 *onionRings = NIL(array_t); 01075 } 01076 } 01077 #endif 01078 01079 /* states which may produce new states as successors */ 01080 nonInteriorStates = SubtractStates(*reachableStates, hdInfo->interiorStates, 01081 FSM_HD_DONT_FREE, FSM_HD_DONT_FREE); 01082 01083 /* try and reinject the residue from a dead end into the frontier */ 01084 if (hdInfo->deadEndResidue != NULL) { 01085 temp = mdd_or(*fromLowerBound, hdInfo->deadEndResidue, 1, 1); 01086 } else { 01087 temp = mdd_dup(*fromLowerBound); 01088 } 01089 /* calculate the actual "from" going to be used */ 01090 if ( Fsm_FsmHdOptionReadNewOnly(hdInfo->options) == FALSE) { 01091 fromBetween = bdd_squeeze(temp, nonInteriorStates); 01092 mdd_free(temp); 01093 } else { 01094 fromBetween = temp; 01095 } 01096 mdd_free(nonInteriorStates); 01097 01098 if (nvars <= 1023) { 01099 FsmHdStatsComputeSizeAndMinterms(mddManager, fromBetween, 01100 varArray, nvars, 01101 Fsm_Hd_From, hdInfo->stats); 01102 } 01103 01104 /* if from is bigger in size than image, use image as from*/ 01105 if (( Fsm_FsmHdOptionReadNewOnly(hdInfo->options) == FALSE) && (*image != NULL) && 01106 (FsmHdStatsReadSizeTo(hdInfo->stats) < FsmHdStatsReadSizeFrom(hdInfo->stats))) { 01107 mdd_free(fromBetween); 01108 FsmHdStatsSetSizeFrom(hdInfo->stats, FsmHdStatsReadSizeTo(hdInfo->stats)); 01109 FsmHdStatsSetMintermFrom(hdInfo->stats, FsmHdStatsReadMintermTo(hdInfo->stats)); 01110 fromBetween = *image; 01111 *image = NULL; 01112 } 01113 01114 /* free image since no longer required */ 01115 if (*image != NULL) mdd_free(*image); 01116 01117 assert(FsmHdStatsReadMintermFromSubset(hdInfo->stats) == 0.0); 01118 assert(FsmHdStatsReadSizeFromSubset(hdInfo->stats) == 0); 01119 01120 /* flag to indicate whether a subset is computed this time */ 01121 thisTimeSubset = 0; 01122 01123 /* if size of from exceeds threshold, subset */ 01124 if ((FsmHdStatsReadSizeFrom(hdInfo->stats) > frontierApproxThreshold) && 01125 (FsmHdStatsReadSizeFrom(hdInfo->stats) > FSM_HD_MIN_SIZE_FROM)) { 01126 01127 /* get subset based on the different methods */ 01128 fromSubset = ComputeSubsetBasedOnMethod(fromBetween, 01129 *fromLowerBound, hdInfo->options, 01130 FSM_HD_FROM); 01131 if (nvars <= 1023) { 01132 /* record stats */ 01133 FsmHdStatsComputeSizeAndMinterms(mddManager, fromSubset, 01134 varArray, nvars, 01135 Fsm_Hd_FromSubset, hdInfo->stats); 01136 /* compute density */ 01137 densityFromSubset = FsmHdStatsReadDensityFromSubset(hdInfo->stats); 01138 densityFrom = FsmHdStatsReadDensityFrom(hdInfo->stats); 01139 } 01140 01141 /* check density of subset, discard the subset if not required*/ 01142 if (((nvars <= 1023) && 01143 (((densityFrom < densityFromSubset) || 01144 (FsmHdStatsReadSizeFrom(hdInfo->stats) > 2*frontierApproxThreshold)))) || 01145 ((nvars > 1023) && 01146 ((bdd_apa_compare_ratios(nvars, fromSubset, fromBetween, 01147 FsmHdStatsReadSizeFromSubset(hdInfo->stats), 01148 FsmHdStatsReadSizeFrom(hdInfo->stats)) || 01149 (FsmHdStatsReadSizeFrom(hdInfo->stats) > 2*frontierApproxThreshold))))) { 01150 01151 /* subset chosen this time */ 01152 thisTimeSubset = 1; 01153 01154 mdd_free(fromBetween); 01155 01156 /* discard the old bounds only if not required later */ 01157 if (hdInfo->deadEndComputation || hdInfo->firstSubset) { 01158 /* store the residue since subset has been taken. Use them in 01159 subsequent iterations*/ 01160 hdInfo->deadEndResidue = SubtractStates(*fromLowerBound, fromSubset, 01161 FSM_HD_DONT_FREE, FSM_HD_DONT_FREE); 01162 if(mdd_is_tautology(hdInfo->deadEndResidue, 0)) { 01163 mdd_free(hdInfo->deadEndResidue); 01164 hdInfo->deadEndResidue = NULL; 01165 } else if (mdd_size(hdInfo->deadEndResidue) > FSM_HD_DEADEND_RESIDUE_LIMIT) { 01166 mdd_free(hdInfo->deadEndResidue); 01167 hdInfo->deadEndResidue = NULL; 01168 } else { 01169 hdInfo->firstSubset = 0; 01170 } 01171 01172 } 01173 01174 /* set from lower bound for next image computation */ 01175 mdd_free(*fromLowerBound); 01176 *fromLowerBound = fromSubset; 01177 01178 } else { 01179 /* discard the old bounds; since no subset is discarded */ 01180 mdd_free(*fromLowerBound); 01181 /* Undo subset computation */ 01182 mdd_free(fromSubset); 01183 *fromLowerBound = fromBetween; 01184 } 01185 } else { 01186 /* No subsetting here */ 01187 mdd_free(*fromLowerBound); 01188 *fromLowerBound = fromBetween; 01189 } 01190 01191 /* remove frontier from dead-end residue */ 01192 if ((hdInfo->deadEndResidue != NULL) && (!hdInfo->deadEndComputation)) { 01193 hdInfo->deadEndResidue = SubtractStates(hdInfo->deadEndResidue, *fromLowerBound, 01194 FSM_HD_FREE, FSM_HD_DONT_FREE); 01195 if (mdd_is_tautology(hdInfo->deadEndResidue, 0)) { 01196 mdd_free(hdInfo->deadEndResidue); 01197 hdInfo->deadEndResidue = NULL; 01198 } else if (mdd_size(hdInfo->deadEndResidue) > FSM_HD_DISJ_SIZE) { 01199 mdd_free(hdInfo->deadEndResidue); 01200 hdInfo->deadEndResidue = NULL; 01201 } 01202 } 01203 01204 /* 01205 * check size of reached if there were any reorderings since 01206 * the last time the size was measured 01207 */ 01208 if (bdd_read_reorderings(mddManager)> numReorders) { 01209 FsmHdStatsSetSizeReached(hdInfo->stats, mdd_size(*reachableStates)); 01210 } 01211 /* Modify Reachable states if necessary. The conditions are if 01212 * blocking states are not to be included in Reached. The exceptions 01213 * are if no subset was computed or the size of Reached is less than 01214 * 30000 or if this were a DEAD-END computation (very important: 01215 * this rule isnt violated). That is ALL states computed out of a 01216 * DEAD_END must ALWAYS be added to reached. 01217 */ 01218 if (thisTimeSubset && (Fsm_FsmHdOptionReadScrapStates(hdInfo->options) == FALSE) && 01219 (!hdInfo->deadEndComputation) && 01220 (FsmHdStatsReadSizeReached(hdInfo->stats) > 30000)) { 01221 temp = AddStates(*fromUpperBound, *fromLowerBound, 01222 FSM_HD_FREE, FSM_HD_DONT_FREE); 01223 temp1 = bdd_squeeze(temp, *reachableStates); 01224 mdd_free(*reachableStates); 01225 mdd_free(temp); 01226 *reachableStates = temp1; 01227 FsmHdStatsComputeSizeAndMinterms(mddManager, *reachableStates, varArray, 01228 nvars, Fsm_Hd_Reached, hdInfo->stats); 01229 if (shellFlag && onionRings) { /* restrict the onion rings to the modified reachable set */ 01230 int onionRingCount; 01231 for (onionRingCount = sizeOfOnionRings; onionRingCount < array_n(onionRings); 01232 onionRingCount++) { 01233 mdd_t *onionRing; 01234 onionRing = array_fetch(mdd_t *, onionRings, onionRingCount); 01235 temp = mdd_and(onionRing, *reachableStates, 1, 1); 01236 mdd_free(onionRing); 01237 array_insert(mdd_t *, onionRings, onionRingCount, temp); 01238 } 01239 } 01240 01241 } else { 01242 mdd_free(*fromUpperBound); 01243 } 01244 01245 /* Throw away dead-end residue when it gets to be a pain. 01246 * i.e., when its density is larger than Reached or when the 01247 * fraction of minterms retained in it are too small. 01248 */ 01249 if (hdInfo->deadEndResidue != NULL) { 01250 mintResidue = mdd_count_onset(mddManager, hdInfo->deadEndResidue, varArray); 01251 sizeResidue = mdd_size(hdInfo->deadEndResidue); 01252 if ((mintResidue < 0.001*FsmHdStatsReadMintermReached(hdInfo->stats)) || 01253 (mintResidue/sizeResidue > FsmHdStatsReadDensityReached(hdInfo->stats))) { 01254 mdd_free(hdInfo->deadEndResidue); 01255 hdInfo->deadEndResidue = NULL; 01256 } 01257 } 01258 01259 /* set fromUpperBound for the next iteration */ 01260 *fromUpperBound = *fromLowerBound; 01261 return; 01262 } /* end of FsmHdFromComputeDenseSubset */ 01263 01264 01265 /*---------------------------------------------------------------------------*/ 01266 /* Definition of static functions */ 01267 /*---------------------------------------------------------------------------*/ 01268 01291 static mdd_t * 01292 ComputeNewSeedsAtDeadEnd(mdd_manager *mddManager, 01293 Img_ImageInfo_t *imageInfo, 01294 mdd_t *reachableStates, 01295 FsmHdStruct_t *hdInfo, 01296 int greedy, 01297 int verbosity) 01298 { 01299 mdd_t *toCareSet, *newSeeds = NULL, *possibleSeeds, *temp; 01300 mdd_t *reachedSubset, *reachedSet; 01301 int failedPartition = 0; 01302 int frontierApproxThreshold = Fsm_FsmHdOptionReadFrontierApproxThreshold(hdInfo->options); 01303 int deadEnd = Fsm_FsmHdOptionReadDeadEnd(hdInfo->options); 01304 int nvars = Fsm_FsmHdOptionReadNumVars(hdInfo->options); 01305 01306 /* in brute force method, compute the image of the entire reached */ 01307 if (deadEnd == Fsm_Hd_DE_BF_c) { 01308 toCareSet = mdd_not(reachableStates); 01309 possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, 01310 reachableStates, 01311 reachableStates, 01312 toCareSet); 01313 mdd_free(toCareSet); 01314 newSeeds = SubtractStates(possibleSeeds, reachableStates, 01315 FSM_HD_FREE, FSM_HD_DONT_FREE); 01316 return (newSeeds); 01317 } 01318 01319 /* in HYBRID method, first try with a subset of the reached set */ 01320 reachedSet = SubtractStates(reachableStates, hdInfo->interiorStates, 01321 FSM_HD_DONT_FREE, FSM_HD_DONT_FREE); 01322 if (deadEnd == Fsm_Hd_DE_Hyb_c) { 01323 /* compute image of a subset of reached */ 01324 reachedSubset = ComputeSubsetBasedOnMethod(reachedSet, 01325 NIL(mdd_t), 01326 hdInfo->options, 01327 FSM_HD_DEADEND); 01328 01329 if (bdd_size(reachedSubset) < 2*frontierApproxThreshold) { 01330 toCareSet = mdd_not(reachableStates); 01331 possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, 01332 reachedSubset, 01333 reachableStates, 01334 toCareSet); 01335 mdd_free(toCareSet); 01336 /* compute new states */ 01337 newSeeds = SubtractStates(possibleSeeds, reachableStates, 01338 FSM_HD_FREE, FSM_HD_DONT_FREE); 01339 /* add to interior states */ 01340 hdInfo->interiorStates = AddStates(hdInfo->interiorStates, reachedSubset, 01341 FSM_HD_FREE, FSM_HD_DONT_FREE); 01342 if (verbosity >= 2) { 01343 fprintf(vis_stdout, "Interior states added, Size = %d\n", 01344 mdd_size(hdInfo->interiorStates)); 01345 } 01346 01347 if ((!mdd_is_tautology(newSeeds, 0)) && (greedy)) { 01348 mdd_free(reachedSet); 01349 mdd_free(reachedSubset); 01350 return (newSeeds); 01351 } else { 01352 /* reset newSeeds value for further computations */ 01353 if (mdd_is_tautology(newSeeds, 0)) { 01354 mdd_free(newSeeds); 01355 newSeeds = NULL; 01356 } 01357 /* if new seeds not found or iter_decomp unsuccessful, set 01358 * reachedSet to the other part (which may be a part of the 01359 * reachable states (former) or the reachable states itself 01360 * (latter)). 01361 */ 01362 reachedSet = SubtractStates(reachedSet, reachedSubset, 01363 FSM_HD_FREE, FSM_HD_FREE); 01364 } 01365 } else { 01366 mdd_free(reachedSubset); 01367 } 01368 } 01369 01370 /* compute the decomposed image of reachedSet */ 01371 if ((deadEnd == Fsm_Hd_DE_Con_c) || 01372 (deadEnd == Fsm_Hd_DE_Hyb_c)) { 01373 /* this flag is set when the image of some decomposed part is 01374 * not computed due to its size. 01375 */ 01376 failedPartition = 0; 01377 /* save any previously computed new states */ 01378 temp = newSeeds; 01379 /* compute new seeds by recursively decomposing reachedSet */ 01380 newSeeds = ComputeImageOfDecomposedParts(mddManager, 01381 imageInfo, 01382 reachedSet, 01383 reachableStates, 01384 hdInfo, 01385 frontierApproxThreshold, 01386 nvars, 01387 &failedPartition, 01388 greedy, 01389 verbosity); 01390 /* combine new states */ 01391 newSeeds = AddStates(newSeeds, temp, FSM_HD_FREE, FSM_HD_FREE); 01392 01393 /* if no remains or partition didnt fail, return new Seeds */ 01394 /* if greedy and new states found, return */ 01395 if ((mdd_lequal(reachedSet, hdInfo->interiorStates, 1, 1)) || 01396 ((newSeeds != NULL) && (greedy))) { 01397 /* assert that the entire image was computed */ 01398 if (mdd_lequal(reachedSet, hdInfo->interiorStates, 1, 1)) assert(!failedPartition); 01399 mdd_free(reachedSet); 01400 if (newSeeds == NULL) 01401 newSeeds = bdd_zero(mddManager); 01402 else 01403 assert(!mdd_is_tautology(newSeeds, 0)); 01404 return(newSeeds); 01405 } 01406 01407 /* continue if either no new states have been found or the 01408 * computation is not greedy */ 01409 /* new set whose image is to be computed */ 01410 reachedSet = SubtractStates(reachedSet, hdInfo->interiorStates, 01411 FSM_HD_FREE, FSM_HD_DONT_FREE); 01412 01413 01414 /* one last shot with a subsetting the remains */ 01415 /* reachedSubset is the subset of reached remains */ 01416 reachedSubset = ComputeSubsetBasedOnMethod(reachedSet, 01417 NIL(mdd_t), 01418 hdInfo->options, 01419 FSM_HD_DEADEND); 01420 01421 /* compute image of the subset above */ 01422 toCareSet = mdd_not(reachableStates); 01423 possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, 01424 reachedSubset, 01425 reachableStates, 01426 toCareSet); 01427 mdd_free(toCareSet); 01428 /* add to interior states */ 01429 hdInfo->interiorStates = AddStates(hdInfo->interiorStates, reachedSubset, 01430 FSM_HD_FREE, FSM_HD_FREE); 01431 if (verbosity >= 2) { 01432 fprintf(vis_stdout, "Interior states added, Size = %d\n", 01433 mdd_size(hdInfo->interiorStates)); 01434 } 01435 /* combine all new states */ 01436 temp = newSeeds; 01437 newSeeds = SubtractStates(possibleSeeds, reachableStates, 01438 FSM_HD_FREE, FSM_HD_DONT_FREE); 01439 newSeeds = AddStates(newSeeds, temp, FSM_HD_FREE, FSM_HD_FREE); 01440 01441 /* if no new seeds, compute the image of (reachedSet - reachedSubset) */ 01442 if ((mdd_is_tautology(newSeeds, 0) != 1) && (greedy)) { 01443 mdd_free(reachedSet); 01444 mdd_free(reachedSubset); 01445 return newSeeds; 01446 } else { 01447 /* reset newSeeds for further computation */ 01448 if (mdd_is_tautology(newSeeds, 0)) { 01449 mdd_free(newSeeds); 01450 newSeeds = NULL; 01451 } 01452 /* set reached = reachedSet - reachedSubset */ 01453 reachedSet = SubtractStates(reachedSet, reachedSubset, 01454 FSM_HD_FREE, FSM_HD_FREE); 01455 } 01456 01457 /* save previously computed new states */ 01458 temp = newSeeds; 01459 failedPartition = 0; 01460 /* try decomposition again */ 01461 newSeeds = ComputeImageOfDecomposedParts(mddManager, 01462 imageInfo, 01463 reachedSet, 01464 reachableStates, hdInfo, 01465 frontierApproxThreshold, 01466 nvars, 01467 &failedPartition, 01468 greedy, 01469 verbosity); 01470 /* combine all new states */ 01471 newSeeds = AddStates(newSeeds, temp, FSM_HD_FREE, FSM_HD_FREE); 01472 /* if no remains or partition didnt fail, return new Seeds */ 01473 /* if greedy and new states found, return */ 01474 if ((mdd_lequal(reachedSet, hdInfo->interiorStates, 1, 1)) || 01475 ((newSeeds != NULL) && (greedy))) { 01476 /* assert that the entire image was computed */ 01477 if (mdd_lequal(reachedSet, hdInfo->interiorStates, 1, 1)) assert(!failedPartition); 01478 mdd_free(reachedSet); 01479 if (newSeeds == NULL) 01480 newSeeds = bdd_zero(mddManager); 01481 else 01482 assert(!mdd_is_tautology(newSeeds, 0)); 01483 return(newSeeds); 01484 } 01485 01486 /* continue if either no new states have been found or the 01487 * computation is not greedy */ 01488 /* new set whose image is to be computed */ 01489 reachedSet = SubtractStates(reachedSet, hdInfo->interiorStates, 01490 FSM_HD_FREE, FSM_HD_DONT_FREE); 01491 01492 /* now bite the bullet and compute the image of the whole 01493 * remainder. 01494 */ 01495 toCareSet = mdd_not(reachableStates); 01496 possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, 01497 reachedSet, 01498 reachableStates, 01499 toCareSet); 01500 mdd_free(toCareSet); 01501 /* add to interios states */ 01502 hdInfo->interiorStates = AddStates(hdInfo->interiorStates, reachedSet, 01503 FSM_HD_FREE, FSM_HD_FREE); 01504 if (verbosity >= 2) { 01505 fprintf(vis_stdout, "Interior states added, Size = %d\n", 01506 mdd_size(hdInfo->interiorStates)); 01507 } 01508 /* combine all new states */ 01509 temp = newSeeds; 01510 newSeeds = SubtractStates(possibleSeeds, reachableStates, 01511 FSM_HD_FREE, FSM_HD_DONT_FREE); 01512 newSeeds = AddStates(newSeeds, temp, FSM_HD_FREE, FSM_HD_FREE); 01513 01514 } 01515 return newSeeds; 01516 } 01517 01518 01534 static mdd_t * 01535 ComputeImageOfDecomposedParts(mdd_manager *mddManager, 01536 Img_ImageInfo_t *imageInfo, 01537 mdd_t *reachedSet, 01538 mdd_t *reachableStates, 01539 FsmHdStruct_t *hdInfo, 01540 int frontierApproxThreshold, 01541 int nvars, 01542 int *failedPartition, 01543 int greedy, 01544 int verbosity) 01545 { 01546 01547 mdd_t *temp, *newSeeds, *possibleSeeds; 01548 mdd_t *toCareSet; 01549 int reachedSize, threshold; 01550 01551 /* initialize some variables */ 01552 newSeeds = NULL; 01553 reachedSize = mdd_size(reachedSet); 01554 threshold = (FSM_HD_REACHED_THRESHOLD > frontierApproxThreshold) ? FSM_HD_REACHED_THRESHOLD : frontierApproxThreshold; 01555 01556 /* compute the image of reached if it is small */ 01557 if (reachedSize < threshold) { 01558 toCareSet = mdd_not(reachableStates); 01559 possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, 01560 reachedSet, 01561 reachableStates, 01562 toCareSet); 01563 mdd_free(toCareSet); 01564 newSeeds = SubtractStates(possibleSeeds, reachableStates, 01565 FSM_HD_FREE, FSM_HD_DONT_FREE); 01566 if (mdd_is_tautology(newSeeds, 0)) { 01567 mdd_free(newSeeds); 01568 newSeeds = NULL; 01569 } 01570 hdInfo->interiorStates = AddStates(hdInfo->interiorStates, reachedSet, 01571 FSM_HD_FREE, FSM_HD_DONT_FREE); 01572 return (newSeeds); 01573 } 01574 01575 /* create conjuncts of the complement, disjuncts of the 01576 * reachable set 01577 */ 01578 temp = mdd_dup(reachedSet); 01579 /* set threshold to some non-trivial value */ 01580 if (frontierApproxThreshold <= 0) 01581 frontierApproxThreshold = FSM_HD_REACHED_THRESHOLD/ 01582 FSM_HD_DEADEND_MAX_SIZE_FACTOR; 01583 /* compute the image of decomposed parts. Return when some new seeds are 01584 * found. 01585 */ 01586 newSeeds = ProcessDisjunctsRecursive(mddManager, 01587 imageInfo, 01588 &temp, 01589 reachableStates, 01590 hdInfo, 01591 frontierApproxThreshold, 01592 nvars, 01593 failedPartition, 01594 reachedSize, 01595 greedy, 01596 verbosity); 01597 01598 return (newSeeds); 01599 01600 } 01601 01623 static mdd_t * 01624 ProcessDisjunctsRecursive(mdd_manager *mddManager, 01625 Img_ImageInfo_t *imageInfo, 01626 mdd_t **reachedSet, 01627 mdd_t *reachableStates, 01628 FsmHdStruct_t *hdInfo, 01629 int frontierApproxThreshold, 01630 int nvars, 01631 int *failedPartition, 01632 int reachedSize, 01633 int greedy, 01634 int verbosity) 01635 { 01636 mdd_t *toCareSet, *newSeeds, *possibleSeeds; 01637 mdd_t *temp, *subset; 01638 int tempSize; 01639 int hitConstant; 01640 mdd_t **disjArray; 01641 char *decompString; 01642 int i; 01643 int numParts; 01644 FsmHdSizeStruct_t sizeStruct; 01645 array_t *sizeArray; 01646 01647 hitConstant = 0; 01648 01649 assert((!mdd_is_tautology(*reachedSet, 1)) && 01650 (!mdd_is_tautology(*reachedSet, 0))); 01651 if (verbosity >= 2) { 01652 fprintf(vis_stdout, "Orig Size = %d, ",mdd_size(*reachedSet)); 01653 } 01654 01655 /* decompose reached set into disjuntive parts */ 01656 decompString = Cmd_FlagReadByName("hd_decomp"); 01657 if (decompString == NIL(char)) { 01658 numParts = bdd_var_decomp(*reachedSet, 01659 (bdd_partition_type_t)BDD_DISJUNCTS, 01660 &disjArray); 01661 } else if (strcmp(decompString, "var") == 0) { 01662 numParts = bdd_var_decomp(*reachedSet, 01663 (bdd_partition_type_t)BDD_DISJUNCTS, 01664 &disjArray); 01665 } else if (strcmp(decompString, "gen") == 0) { 01666 numParts = bdd_gen_decomp(*reachedSet, 01667 (bdd_partition_type_t)BDD_DISJUNCTS, 01668 &disjArray); 01669 } else if (strcmp(decompString, "approx") == 0) { 01670 numParts = bdd_approx_decomp(*reachedSet, 01671 (bdd_partition_type_t)BDD_DISJUNCTS, 01672 &disjArray); 01673 } else if (strcmp(decompString, "iter") == 0) { 01674 numParts = bdd_iter_decomp(*reachedSet, 01675 (bdd_partition_type_t)BDD_DISJUNCTS, 01676 &disjArray); 01677 } else { 01678 numParts = bdd_var_decomp(*reachedSet, 01679 (bdd_partition_type_t)BDD_DISJUNCTS, 01680 &disjArray); 01681 } 01682 mdd_free(*reachedSet); 01683 01684 /* decomposition failed */ 01685 if (numParts == 0) return NULL; 01686 01687 /* decomposition failed, stop recurring */ 01688 if (numParts == 1) hitConstant = 1; 01689 01690 /* allocate array with bdds and sizes */ 01691 sizeArray = array_alloc(FsmHdSizeStruct_t, 0); 01692 if (sizeArray == NIL(array_t)) { 01693 for (i = 0; i < numParts; i++) { 01694 mdd_free(disjArray[i]); 01695 } 01696 FREE(disjArray); 01697 return NULL; 01698 } 01699 01700 /* free all constants and partitions that are larger than the 01701 * original reached size 01702 */ 01703 for (i = 0; i < numParts; i++) { 01704 assert(!mdd_is_tautology(disjArray[i], 1)); 01705 tempSize = bdd_size(disjArray[i]); 01706 if ((tempSize >= reachedSize) || 01707 (tempSize == 1)) { 01708 if (tempSize == 1) { 01709 hitConstant = 1; 01710 assert (mdd_is_tautology(disjArray[i], 0)); 01711 } else { 01712 *failedPartition = 1; 01713 } 01714 mdd_free(disjArray[i]); 01715 } else { 01716 sizeStruct.bdd = disjArray[i]; 01717 sizeStruct.size = tempSize; 01718 sizeStruct.rnd = util_random(); 01719 array_insert_last(FsmHdSizeStruct_t, sizeArray, sizeStruct); 01720 } 01721 } 01722 FREE(disjArray); 01723 01724 if (array_n(sizeArray) == 0) { 01725 array_free(sizeArray); 01726 return (NULL); 01727 } 01728 01729 /* shuffle parts randomly. */ 01730 if (array_n(sizeArray) > 1) { 01731 array_sort(sizeArray, RandomCompare); 01732 } 01733 01734 if (verbosity >= 2) { 01735 arrayForEachItem(FsmHdSizeStruct_t, sizeArray, i, sizeStruct) { 01736 fprintf(vis_stdout , "disjSize[%d] = %d ", i, sizeStruct.size); 01737 } 01738 fprintf(vis_stdout, "\n"); 01739 } 01740 01741 /* now compute image of parts or recur*/ 01742 newSeeds = NULL; 01743 arrayForEachItem(FsmHdSizeStruct_t, sizeArray, i, sizeStruct) { 01744 temp = NULL; 01745 if ((sizeStruct.size < 01746 frontierApproxThreshold*FSM_HD_DEADEND_MAX_SIZE_FACTOR) || 01747 (sizeStruct.size < FSM_HD_DISJ_SIZE)) { 01748 /* if this partition is small enough, compute its image */ 01749 /* compute image */ 01750 toCareSet = mdd_not(reachableStates); 01751 possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, 01752 sizeStruct.bdd, 01753 reachableStates, 01754 toCareSet); 01755 mdd_free(toCareSet); 01756 /* update interior states */ 01757 hdInfo->interiorStates = AddStates(hdInfo->interiorStates, sizeStruct.bdd, 01758 FSM_HD_FREE, FSM_HD_FREE); 01759 if (verbosity >= 2) { 01760 fprintf(vis_stdout, "Interior states added, Size = %d\n", 01761 mdd_size(hdInfo->interiorStates)); 01762 } 01763 /* store new states if any were already found */ 01764 temp = newSeeds; 01765 /* compute new states of this image */ 01766 newSeeds = SubtractStates(possibleSeeds, reachableStates, 01767 FSM_HD_FREE, FSM_HD_DONT_FREE); 01768 /* add up states or set newSeeds to NULL if no new states */ 01769 if (temp != NULL) { 01770 assert(!mdd_is_tautology(temp, 0)); 01771 newSeeds = AddStates(newSeeds, temp, FSM_HD_FREE, FSM_HD_FREE); 01772 } else if (mdd_is_tautology(newSeeds, 0) == 1) { 01773 mdd_free(newSeeds); 01774 newSeeds = NULL; 01775 } 01776 } else if ((!hitConstant) && ((newSeeds == NULL) || 01777 (!greedy) || 01778 (sizeStruct.size < 3* FSM_HD_DISJ_SIZE))) { 01779 /* recur if size is small enough, or non-greedy computation or 01780 * no new states have been found yet. But not if a constant is hit. */ 01781 /* store any new states already computed */ 01782 temp = newSeeds; 01783 newSeeds = ProcessDisjunctsRecursive(mddManager, 01784 imageInfo, 01785 &(sizeStruct.bdd), 01786 reachableStates, hdInfo, 01787 frontierApproxThreshold, 01788 nvars, 01789 failedPartition, 01790 reachedSize, 01791 greedy, 01792 verbosity); 01793 /* if new seeds not NULL, then not zero either */ 01794 if (newSeeds != NULL) { 01795 assert(!mdd_is_tautology(newSeeds, 0)); 01796 /* add states */ 01797 if (temp != NULL) { 01798 newSeeds = AddStates(temp, newSeeds, FSM_HD_FREE, FSM_HD_FREE); 01799 } 01800 } else { 01801 newSeeds = temp; 01802 } 01803 } else { 01804 /* if this partition is too large, compute the image of its 01805 * subset if the subset is small enough */ 01806 /* set failed partition as image is not being computed of this 01807 * whole part */ 01808 *failedPartition = 1; 01809 /* compute subset */ 01810 subset = bdd_approx_remap_ua(sizeStruct.bdd, 01811 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01812 nvars, 0, 1.0); 01813 mdd_free(sizeStruct.bdd); 01814 tempSize = bdd_size(subset); 01815 /* compute image of subset if small enough */ 01816 if ((tempSize < frontierApproxThreshold*FSM_HD_DEADEND_MAX_SIZE_FACTOR) || 01817 (tempSize < FSM_HD_DISJ_SIZE)) { 01818 /* compute image */ 01819 toCareSet = mdd_not(reachableStates); 01820 possibleSeeds = Img_ImageInfoComputeFwdWithDomainVars(imageInfo, 01821 subset, 01822 reachableStates, 01823 toCareSet); 01824 mdd_free(toCareSet); 01825 /* update dead states */ 01826 hdInfo->interiorStates = AddStates(hdInfo->interiorStates, subset, 01827 FSM_HD_FREE, FSM_HD_FREE); 01828 if (verbosity >= 2) { 01829 fprintf(vis_stdout, "Interior states added, Size = %d\n", 01830 mdd_size(hdInfo->interiorStates)); 01831 } 01832 /* store new states if any were already found */ 01833 temp = newSeeds; 01834 /* compute new states of this image */ 01835 newSeeds = SubtractStates(possibleSeeds, reachableStates, 01836 FSM_HD_FREE, FSM_HD_DONT_FREE); 01837 /* add up states or set newSeeds to NULL if no new states */ 01838 if (temp != NULL) { 01839 assert(!mdd_is_tautology(temp, 0)); 01840 newSeeds = AddStates(newSeeds, temp, FSM_HD_FREE, FSM_HD_FREE); 01841 } else if (mdd_is_tautology(newSeeds, 0) == 1) { 01842 mdd_free(newSeeds); 01843 newSeeds = NULL; 01844 } 01845 } else { 01846 mdd_free(subset); 01847 } 01848 } 01849 } /* end of array for each */ 01850 01851 array_free(sizeArray); 01852 01853 return (newSeeds); 01854 01855 } /* end of ProcessDisjunctsRecursive */ 01856 01857 01858 01871 static mdd_t * 01872 ComputeSubsetBasedOnMethod(mdd_t *fromBetween, 01873 mdd_t *fromLowerBound, 01874 FsmHdTravOptions_t *options, 01875 int fromOrDeadEnd) 01876 { 01877 mdd_t *fromSubset; 01878 int frontierApproxThreshold = Fsm_FsmHdOptionReadFrontierApproxThreshold(options); 01879 int frontierApproxMethod; 01880 double quality = Fsm_FsmHdOptionReadQuality(options); 01881 int nvars = Fsm_FsmHdOptionReadNumVars(options); 01882 01883 01884 frontierApproxMethod = (fromOrDeadEnd == FSM_HD_FROM) ? 01885 Fsm_FsmHdOptionReadFrontierApproxMethod(options) : 01886 ((fromOrDeadEnd == FSM_HD_DEADEND) ? 01887 Fsm_FsmHdOptionReadDeadEndSubsetMethod(options) : 01888 Fsm_FsmHdOptionReadFrontierApproxMethod(options)); 01889 01890 /* based on approximation method specified, compute subset */ 01891 switch (frontierApproxMethod) { 01892 case BDD_APPROX_HB: 01893 frontierApproxThreshold = (frontierApproxThreshold < FSM_HD_SP_THRESHOLD) ? FSM_HD_SP_THRESHOLD: frontierApproxThreshold; 01894 fromSubset = bdd_approx_hb(fromBetween, 01895 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01896 nvars, frontierApproxThreshold); 01897 if (fromLowerBound != NIL(mdd_t)) { 01898 if (!bdd_equal(fromBetween,fromLowerBound)) { 01899 if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) { 01900 mdd_free(fromSubset); 01901 fromSubset = bdd_approx_hb(fromLowerBound, 01902 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01903 nvars, frontierApproxThreshold); 01904 } 01905 } 01906 } 01907 01908 break; 01909 case BDD_APPROX_SP: 01910 frontierApproxThreshold = (frontierApproxThreshold < FSM_HD_SP_THRESHOLD) ? FSM_HD_SP_THRESHOLD: frontierApproxThreshold; 01911 fromSubset = bdd_approx_sp(fromBetween, 01912 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01913 nvars, frontierApproxThreshold, 01914 0); 01915 if (fromLowerBound != NIL(mdd_t)) { 01916 if (!bdd_equal(fromBetween,fromLowerBound)) { 01917 if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) { 01918 mdd_free(fromSubset); 01919 fromSubset = bdd_approx_sp(fromLowerBound, 01920 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01921 nvars, frontierApproxThreshold, 01922 0); 01923 } 01924 } 01925 } 01926 01927 break; 01928 case BDD_APPROX_UA: 01929 fromSubset = bdd_approx_ua(fromBetween, 01930 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01931 nvars, frontierApproxThreshold, 01932 0, quality); 01933 if (fromLowerBound != NIL(mdd_t)) { 01934 if (!bdd_equal(fromBetween,fromLowerBound)) { 01935 if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) { 01936 mdd_free(fromSubset); 01937 fromSubset = bdd_approx_ua(fromLowerBound, 01938 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01939 nvars, frontierApproxThreshold, 01940 0, quality); 01941 } 01942 } 01943 } 01944 break; 01945 case BDD_APPROX_RUA: 01946 fromSubset = bdd_approx_remap_ua(fromBetween, 01947 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01948 nvars, frontierApproxThreshold, 01949 quality ); 01950 if (fromLowerBound != NIL(mdd_t)) { 01951 if (!bdd_equal(fromBetween,fromLowerBound)) { 01952 if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) { 01953 mdd_free(fromSubset); 01954 fromSubset = bdd_approx_remap_ua(fromLowerBound, 01955 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01956 nvars, frontierApproxThreshold, 01957 quality); 01958 } 01959 } 01960 } 01961 01962 break; 01963 case BDD_APPROX_BIASED_RUA: 01964 if (fromLowerBound == NIL(mdd_t)) { 01965 fromLowerBound = fromBetween; 01966 } 01967 fromSubset = bdd_approx_biased_rua(fromBetween, 01968 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01969 fromLowerBound, 01970 nvars, frontierApproxThreshold, 01971 quality, options->qualityBias ); 01972 if (fromLowerBound != NIL(mdd_t)) { 01973 if (!bdd_equal(fromBetween,fromLowerBound)) { 01974 if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) { 01975 mdd_free(fromSubset); 01976 fromSubset = bdd_approx_remap_ua(fromLowerBound, 01977 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01978 nvars, frontierApproxThreshold, 01979 quality); 01980 } 01981 } 01982 } 01983 break; 01984 case BDD_APPROX_COMP: 01985 frontierApproxThreshold = (frontierApproxThreshold < FSM_HD_SP_THRESHOLD) ? FSM_HD_SP_THRESHOLD: frontierApproxThreshold; 01986 fromSubset = bdd_approx_compress(fromBetween, 01987 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01988 nvars, frontierApproxThreshold); 01989 01990 if (fromLowerBound != NIL(mdd_t)) { 01991 if (!bdd_equal(fromBetween,fromLowerBound)) { 01992 if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) { 01993 mdd_free(fromSubset); 01994 fromSubset = bdd_approx_compress(fromLowerBound, 01995 (bdd_approx_dir_t)BDD_UNDER_APPROX, 01996 nvars, frontierApproxThreshold); 01997 } 01998 } 01999 } 02000 02001 break; 02002 default: 02003 fromSubset = bdd_approx_remap_ua(fromBetween, 02004 (bdd_approx_dir_t)BDD_UNDER_APPROX, 02005 nvars, frontierApproxThreshold, 02006 quality ); 02007 if (fromLowerBound != NIL(mdd_t)) { 02008 if (!bdd_equal(fromBetween,fromLowerBound)) { 02009 if (mdd_lequal(fromSubset, fromLowerBound, 1, 0)) { 02010 mdd_free(fromSubset); 02011 fromSubset = bdd_approx_remap_ua(fromLowerBound, 02012 (bdd_approx_dir_t)BDD_UNDER_APPROX, 02013 nvars, frontierApproxThreshold, 02014 quality); 02015 } 02016 } 02017 } 02018 break; 02019 } 02020 02021 return (fromSubset); 02022 } /* end of ComputeSubsetBasedOnMethod */ 02023 02024 02034 static mdd_t * 02035 AddStates(mdd_t *a, mdd_t *b, int freeA, int freeB) 02036 { 02037 mdd_t *result; 02038 if ((a != NULL) && (b != NULL)) { 02039 result = mdd_or(a, b, 1, 1); 02040 } else if ((a == NULL) && (b == NULL)) { 02041 result = a; 02042 } else if (a == NULL) { 02043 result = mdd_dup(b); 02044 } else { 02045 result = mdd_dup(a); 02046 } 02047 if ((freeA == FSM_HD_FREE) && (a != NULL)) mdd_free(a); 02048 if ((freeB == FSM_HD_FREE) && (b != NULL)) mdd_free(b); 02049 return result; 02050 } /* end of AddStates */ 02051 02052 02053 02063 static mdd_t * 02064 SubtractStates(mdd_t *a, mdd_t *b, int freeA, int freeB) 02065 { 02066 mdd_t *result; 02067 if ((a != NULL) && (b != NULL)) { 02068 result = mdd_and(a, b, 1, 0); 02069 } else if ((a == NULL) && (b == NULL)) { 02070 result = a; 02071 } else if (b == NULL) { 02072 result = mdd_dup(a); 02073 } else { /* a = NULL , b != NULL */ 02074 result = NULL; 02075 } 02076 if ((freeA == FSM_HD_FREE) && (a != NULL)) mdd_free(a); 02077 if ((freeB == FSM_HD_FREE) && (b != NULL)) mdd_free(b); 02078 return result; 02079 } /* end of SubtractStates */ 02080 02081 02091 static int 02092 RandomCompare(const void *ptrX, 02093 const void *ptrY) 02094 { 02095 FsmHdSizeStruct_t *sizeStruct1 = (FsmHdSizeStruct_t *)ptrX; 02096 FsmHdSizeStruct_t *sizeStruct2 = (FsmHdSizeStruct_t *)ptrY; 02097 02098 if (sizeStruct1->rnd > sizeStruct2->rnd) return 1; 02099 else if (sizeStruct1->rnd < sizeStruct2->rnd) return -1; 02100 else return 0; 02101 } /* end of BddSizeCompare */