VIS
|
00001 00037 #include "ctlpInt.h" 00038 #include "mcInt.h" 00039 #include "fsm.h" 00040 #include "bmc.h" 00041 00042 static char rcsid[] UNUSED = "$Id: mcMc.c,v 1.257 2007/04/17 00:01:22 sohail Exp $"; 00043 00044 #ifdef DEBUG_MC 00045 void _McPrintSatisfyingMinterms(mdd_t *aMdd, Fsm_Fsm_t *fsm); 00046 #endif 00047 00048 /*---------------------------------------------------------------------------*/ 00049 /* Macro declarations */ 00050 /*---------------------------------------------------------------------------*/ 00051 00054 /*---------------------------------------------------------------------------*/ 00055 /* Static function prototypes */ 00056 /*---------------------------------------------------------------------------*/ 00057 00058 static mdd_t * EvaluateFormulaRecur(Fsm_Fsm_t *modelFsm, Ctlp_Formula_t *ctlFormula, mdd_t *fairStates, Fsm_Fairness_t *fairCondition, array_t *modelCareStatesArray, Mc_EarlyTermination_t *earlyTermination, Fsm_HintsArray_t *hintsArray, Mc_GuidedSearch_t hintType, Ctlp_Approx_t TRMinimization, Ctlp_Approx_t *resultApproxType, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel, int buildOnionRings, Mc_GSHScheduleType GSHschedule); 00059 static mdd_t * McForwardReachable(Fsm_Fsm_t *modelFsm, mdd_t *targetMdd, mdd_t *invariantMdd, mdd_t *fairStates, array_t *careStatesArray, array_t *onionRings, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel); 00060 00064 /*---------------------------------------------------------------------------*/ 00065 /* Definition of exported functions */ 00066 /*---------------------------------------------------------------------------*/ 00067 00087 mdd_t * 00088 Mc_FsmCheckLanguageEmptiness( 00089 Fsm_Fsm_t *modelFsm, 00090 array_t *modelCareStatesArray, 00091 Mc_AutStrength_t automatonStrength, 00092 Mc_LeMethod_t leMethod, 00093 int dcLevel, 00094 int dbgLevel, 00095 int printInputs, 00096 int verbosity, 00097 Mc_GSHScheduleType GSHschedule, 00098 Mc_FwdBwdAnalysis GSHdirection, 00099 int lockstep, 00100 FILE *dbgFile, 00101 int UseMore, 00102 int SimValue, 00103 char *driverName) 00104 { 00105 mdd_t *result; 00106 mdd_t *mddOne; 00107 mdd_t *badStates; 00108 mdd_t *aBadState; 00109 mdd_t *initialStates; 00110 mdd_t *fairStates; 00111 mdd_manager *mddMgr; 00112 Ctlp_Formula_t *ctlFair, *ctlFormula; 00113 Mc_EarlyTermination_t *earlyTermination; 00114 array_t *arrayOfOnionRings; 00115 array_t *stemArray; 00116 array_t *cycleArray; 00117 McPath_t *fairPath; 00118 McPath_t *normalPath; 00119 FILE *tmpFile = vis_stdout; 00120 extern FILE *vis_stdpipe; 00121 int i; 00122 00123 if (leMethod == Mc_Le_Dnc_c && automatonStrength == 2) { 00124 return Mc_FsmCheckLanguageEmptinessByDnC(modelFsm, 00125 modelCareStatesArray, 00126 Mc_Aut_Strong_c, 00127 dcLevel, 00128 dbgLevel, 00129 printInputs, 00130 verbosity, 00131 GSHschedule, 00132 GSHdirection, 00133 lockstep, 00134 dbgFile, 00135 UseMore, 00136 SimValue, 00137 driverName); 00138 } 00139 00140 /************************************************************************** 00141 * CASE1 & CASE2: TERMINAL/WEAK AUTOMATON 00142 * problem is reduced to checking !EF (fair) for TERMINAL 00143 * or !EF EG (fair) for WEAK 00144 **************************************************************************/ 00145 if (automatonStrength == 0 || automatonStrength == 1) { 00146 Fsm_Fairness_t *modelFairness; 00147 modelFairness = Fsm_FsmReadFairnessConstraint(modelFsm); 00148 assert(Fsm_FairnessTestIsBuchi(modelFairness)); 00149 ctlFair = Ctlp_FormulaCreate(Ctlp_ID_c, 00150 (void *)util_strsav("fair1$AUT$NTK2"), 00151 (void *)util_strsav("1")); 00152 /* Dup(Fsm_FairnessReadFinallyInfFormula(modelFairness, 0, 0)); */ 00153 if (automatonStrength == 0) { 00154 Ctlp_Formula_t *ctlTRUE; 00155 ctlTRUE = Ctlp_FormulaCreate(Ctlp_TRUE_c, NIL(Ctlp_Formula_t), 00156 NIL(Ctlp_Formula_t)); 00157 ctlFormula = Ctlp_FormulaCreate(Ctlp_EU_c, ctlTRUE, ctlFair); 00158 if (dbgLevel || verbosity) 00159 fprintf(vis_stdout, "# %s: Terminal automaton -- check EF(states satisfy fairness)\n", 00160 driverName); 00161 }else { 00162 Ctlp_Formula_t *ctlTRUE, *ctlEGfair; 00163 ctlTRUE = Ctlp_FormulaCreate(Ctlp_TRUE_c, NIL(Ctlp_Formula_t), NIL(Ctlp_Formula_t)); 00164 ctlEGfair = Ctlp_FormulaCreate(Ctlp_EG_c, ctlFair, NIL(Ctlp_Formula_t)); 00165 ctlFormula = Ctlp_FormulaCreate(Ctlp_EU_c, ctlTRUE, ctlEGfair); 00166 if (dbgLevel || verbosity) 00167 fprintf(vis_stdout, "# %s: Weak automaton -- check EF EG (states satisfy fairness)\n", 00168 driverName); 00169 } 00170 00171 /* Evaluate ctlFormula */ 00172 mddMgr = Fsm_FsmReadMddManager(modelFsm); 00173 mddOne = mdd_one(mddMgr); 00174 initialStates = Fsm_FsmComputeInitialStates(modelFsm); 00175 earlyTermination = Mc_EarlyTerminationAlloc(McSome_c, initialStates); 00176 fairStates = 00177 Mc_FsmEvaluateFormula(modelFsm, ctlFormula, mddOne, modelFairness, 00178 modelCareStatesArray, 00179 earlyTermination, 00180 NIL(Fsm_HintsArray_t), Mc_None_c, 00181 (Mc_VerbosityLevel) verbosity, 00182 (Mc_DcLevel) dcLevel, 00183 (dbgLevel != McDbgLevelNone_c || verbosity), 00184 GSHschedule); 00185 Mc_EarlyTerminationFree(earlyTermination); 00186 mdd_free(mddOne); 00187 00188 /* If there is at least one fair initial state, language is not empty. */ 00189 if (!mdd_lequal(initialStates, fairStates, 1, 0)) { 00190 if (strcmp(driverName, "LE") == 0) 00191 fprintf(vis_stdout, "# LE: language is not empty\n"); 00192 else 00193 fprintf(vis_stdout, "# %s: formula failed\n", driverName); 00194 result = mdd_and(fairStates, initialStates, 1, 1); 00195 } else { 00196 if (strcmp(driverName, "LE") == 0) 00197 fprintf(vis_stdout, "# LE: language emptiness check passes\n"); 00198 else 00199 fprintf(vis_stdout, "# %s: formula passed\n", driverName); 00200 Ctlp_FormulaFree(ctlFormula); 00201 mdd_free(fairStates); 00202 mdd_free(initialStates); 00203 return NIL(mdd_t); 00204 } 00205 00206 /* If no wintness is requested, clean up and return. */ 00207 if (dbgLevel == McDbgLevelNone_c) { 00208 Ctlp_FormulaFree(ctlFormula); 00209 mdd_free(initialStates); 00210 mdd_free(fairStates); 00211 return result; 00212 }else { 00213 Ctlp_Formula_t *F; 00214 array_t *EGArrayOfOnionRings, *EGonionRings, *EFonionRings; 00215 array_t *newOnionRings; 00216 mdd_t *mdd1; 00217 int j; 00218 arrayOfOnionRings = array_alloc(array_t *, 0); 00219 EFonionRings = (array_t *) Ctlp_FormulaReadDebugData(ctlFormula); 00220 if (automatonStrength == 0) { 00221 array_insert_last(array_t *, arrayOfOnionRings, 00222 mdd_array_duplicate(EFonionRings)); 00223 }else if (automatonStrength == 1) { 00224 F = Ctlp_FormulaReadRightChild(ctlFormula); 00225 /* EG (states labelled fair) */ 00226 EGArrayOfOnionRings = (array_t *)Ctlp_FormulaReadDebugData(F); 00227 arrayForEachItem(array_t *, EGArrayOfOnionRings, i, EGonionRings) { 00228 newOnionRings = mdd_array_duplicate(EGonionRings); 00229 arrayForEachItem(mdd_t *, EFonionRings, j, mdd1) { 00230 if (j != 0) 00231 array_insert_last(mdd_t *, newOnionRings, mdd_dup(mdd1)); 00232 } 00233 array_insert_last(array_t *, arrayOfOnionRings, newOnionRings); 00234 } 00235 } 00236 Ctlp_FormulaFree(ctlFormula); 00237 fprintf(vis_stdout, "# %s: generating path to fair cycle\n", driverName); 00238 } 00239 00240 }else { 00241 /************************************************************************* 00242 * CASE3: STRONG AUTOMATON 00243 * need to solve the problem by computing EG_fair (true) 00244 *************************************************************************/ 00245 mddMgr = Fsm_FsmReadMddManager(modelFsm); 00246 initialStates = Fsm_FsmComputeInitialStates(modelFsm); 00247 00248 /* Compute fair states. */ 00249 if (lockstep == MC_LOCKSTEP_OFF) { 00250 fairStates = Fsm_FsmComputeFairStates(modelFsm, modelCareStatesArray, 00251 verbosity, dcLevel, GSHschedule, 00252 GSHdirection, FALSE); 00253 arrayOfOnionRings = Fsm_FsmReadDebugArray(modelFsm); 00254 } else { 00255 /* For lockstep, the computed set of states is a subset of the 00256 reachable fair states, with the property that the subset is 00257 empty only if there are no reachable fair states. Since the 00258 onion rings are built for the fairness constraint restricted to 00259 the subset of the fair states, they are not valid in general 00260 for the FSM. Hence, they are not saved. */ 00261 array_t *SCCs = array_alloc(mdd_t *, 0); 00262 arrayOfOnionRings = array_alloc(array_t *, 0); 00263 fairStates = McFsmComputeFairSCCsByLockStep(modelFsm, lockstep, SCCs, 00264 arrayOfOnionRings, 00265 (Mc_VerbosityLevel) 00266 verbosity, 00267 (Mc_DcLevel) dcLevel); 00268 mdd_array_free(SCCs); 00269 } 00270 00271 00272 /* Lockstep guarantees that all fair SCCs are reachable. However, 00273 it does not extend the fair states backward unless a 00274 counterexample is requested. For the SCC hull approach with backward 00275 operators, the language is not empty if there is at least one 00276 fair initial state. Finally, For SCC hull with forward operators, 00277 currently we do not extend the hull backward, but we enforce 00278 reachability of the hull. Hence, nonemptiness of the hull signals that 00279 the language is not empty. */ 00280 if ((lockstep == MC_LOCKSTEP_OFF && 00281 (!mdd_lequal(initialStates, fairStates, 1, 0) || 00282 (GSHdirection == McFwd_c && 00283 !mdd_lequal_array(fairStates, modelCareStatesArray, 1, 0)))) || 00284 (lockstep != MC_LOCKSTEP_OFF && 00285 !mdd_is_tautology(fairStates, 0))) { 00286 if (strcmp(driverName, "LE") == 0) 00287 fprintf(vis_stdout, "# LE: language is not empty\n"); 00288 else 00289 fprintf(vis_stdout, "# %s: formula failed\n", driverName); 00290 result = mdd_and(fairStates, initialStates, 1, 1); 00291 } else { 00292 if (strcmp(driverName, "LE") == 0) 00293 fprintf(vis_stdout, "# LE: language emptiness check passes\n"); 00294 else 00295 fprintf(vis_stdout, "# %s: formula passed\n", driverName); 00296 /* Dispose of onion rings if produced by lockstep. */ 00297 if (lockstep != MC_LOCKSTEP_OFF) { 00298 mdd_array_array_free(arrayOfOnionRings); 00299 } 00300 mdd_free(fairStates); 00301 mdd_free(initialStates); 00302 return NIL(mdd_t); 00303 } 00304 00305 /* If no witness is requested, clean up and return. */ 00306 if (dbgLevel == McDbgLevelNone_c) { 00307 /* Dispose of onion rings if produced by lockstep. */ 00308 if (lockstep != MC_LOCKSTEP_OFF) { 00309 mdd_array_array_free(arrayOfOnionRings); 00310 } 00311 mdd_free(fairStates); 00312 mdd_free(initialStates); 00313 return result; 00314 } else { 00315 (void) fprintf(vis_stdout, "# %s: generating path to fair cycle\n", 00316 driverName); 00317 } 00318 } 00319 00320 /* Generate witness. */ 00321 badStates = mdd_and(initialStates, fairStates, 1, 1); 00322 mdd_free(fairStates); 00323 mdd_free(initialStates); 00324 aBadState = Mc_ComputeAState(badStates, modelFsm); 00325 mdd_free(badStates); 00326 00327 mddOne = mdd_one(mddMgr); 00328 fairPath = McBuildFairPath(aBadState, mddOne, arrayOfOnionRings, modelFsm, 00329 modelCareStatesArray, 00330 (Mc_VerbosityLevel) verbosity, 00331 (Mc_DcLevel) dcLevel, 00332 McFwd_c); 00333 mdd_free(mddOne); 00334 mdd_free(aBadState); 00335 00336 /* Dispose of onion rings if produced by lockstep. */ 00337 if (lockstep != MC_LOCKSTEP_OFF || automatonStrength != 2) { 00338 mdd_array_array_free(arrayOfOnionRings); 00339 } 00340 00341 /* Print witness. */ 00342 normalPath = McPathNormalize(fairPath); 00343 McPathFree(fairPath); 00344 00345 stemArray = McPathReadStemArray(normalPath); 00346 cycleArray = McPathReadCycleArray(normalPath); 00347 00348 /* we should pass dbgFile/UseMore as parameters 00349 dbgFile = McOptionsReadDebugFile(options);*/ 00350 if (dbgFile != NIL(FILE)) { 00351 vis_stdpipe = dbgFile; 00352 } else if (UseMore == TRUE) { 00353 vis_stdpipe = popen("more","w"); 00354 } else { 00355 vis_stdpipe = vis_stdout; 00356 } 00357 vis_stdout = vis_stdpipe; 00358 00359 /* We should also pass SimValue as a parameter */ 00360 if (SimValue == FALSE) { 00361 (void) fprintf(vis_stdout, "# %s: path to fair cycle:\n\n", driverName); 00362 Mc_PrintPath(stemArray, modelFsm, printInputs); 00363 fprintf (vis_stdout, "\n"); 00364 00365 (void) fprintf(vis_stdout, "# %s: fair cycle:\n\n", driverName); 00366 Mc_PrintPath(cycleArray, modelFsm, printInputs); 00367 fprintf (vis_stdout, "\n"); 00368 }else { 00369 array_t *completePath = McCreateMergedPath(stemArray, cycleArray); 00370 (void) fprintf(vis_stdout, "# %s: counter-example\n", driverName); 00371 McPrintSimPath(vis_stdout, completePath, modelFsm); 00372 mdd_array_free(completePath); 00373 } 00374 00375 if (dbgFile == NIL(FILE) && UseMore == TRUE) { 00376 (void) pclose(vis_stdpipe); 00377 } 00378 vis_stdout = tmpFile; 00379 00380 McPathFree(normalPath); 00381 00382 return result; 00383 } 00384 00385 00449 mdd_t * 00450 Mc_FsmEvaluateFormula( 00451 Fsm_Fsm_t *fsm, 00452 Ctlp_Formula_t *ctlFormula, 00453 mdd_t *fairStates, 00454 Fsm_Fairness_t *fairCondition, 00455 array_t *careStatesArray, 00456 Mc_EarlyTermination_t *earlyTermination, 00457 Fsm_HintsArray_t *hintsArray, 00458 Mc_GuidedSearch_t hintType, 00459 Mc_VerbosityLevel verbosity, 00460 Mc_DcLevel dcLevel, 00461 int buildOnionRing, 00462 Mc_GSHScheduleType GSHschedule) 00463 { 00464 mdd_t *hint; /* to iterate over hintsArray */ 00465 int hintnr; /* idem */ 00466 Ctlp_Approx_t resultApproxType; 00467 00468 assert(hintType == Mc_None_c || hintsArray != NIL(Fsm_HintsArray_t)); 00469 00470 if(hintType != Mc_Global_c) 00471 return EvaluateFormulaRecur(fsm, ctlFormula, fairStates, 00472 fairCondition, careStatesArray, 00473 earlyTermination, hintsArray, hintType, 00474 Ctlp_Exact_c, &resultApproxType, 00475 verbosity, dcLevel, 00476 buildOnionRing, GSHschedule); 00477 else{ 00478 mdd_t *result = NIL(mdd_t); 00479 Ctlp_Approx_t approx; 00480 00481 if(verbosity >= McVerbosityMax_c) 00482 fprintf(vis_stdout, "--Using global hints\n"); 00483 00484 arrayForEachItem(mdd_t *, hintsArray, hintnr, hint){ 00485 if(result != NIL(mdd_t)) 00486 mdd_free(result); 00487 00488 if(verbosity >= McVerbosityMax_c) 00489 fprintf(vis_stdout, "--Instantiating global hint %d\n", hintnr); 00490 00491 Fsm_InstantiateHint(fsm, hint, FALSE, TRUE, Ctlp_Underapprox_c, 00492 (verbosity >= McVerbosityMax_c)); 00493 00494 approx = mdd_is_tautology(hint, 1) ? Ctlp_Exact_c : Ctlp_Underapprox_c; 00495 00496 result = EvaluateFormulaRecur(fsm, ctlFormula, fairStates, 00497 fairCondition, careStatesArray, 00498 earlyTermination, hintsArray, hintType, 00499 approx, &resultApproxType, verbosity, 00500 dcLevel, buildOnionRing, GSHschedule); 00501 /* TBD: take into account (early) termination here */ 00502 } 00503 Fsm_CleanUpHints(fsm, FALSE, TRUE, (verbosity >= McVerbosityMax_c)); 00504 00505 return result; 00506 } 00507 00508 } /* Mc_FsmEvaluateFormula */ 00509 00510 00525 mdd_t * 00526 Mc_FsmEvaluateEXFormula( 00527 Fsm_Fsm_t *modelFsm, 00528 mdd_t *targetMdd, 00529 mdd_t *fairStates, 00530 array_t *careStatesArray, 00531 Mc_VerbosityLevel verbosity, 00532 Mc_DcLevel dcLevel) 00533 { 00534 mdd_t *fromLowerBound; 00535 mdd_t *fromUpperBound; 00536 mdd_t *result; 00537 Img_ImageInfo_t * imageInfo; 00538 00539 if(Fsm_FsmReadUseUnquantifiedFlag(modelFsm)) 00540 imageInfo = Fsm_FsmReadOrCreateImageInfoFAFW(modelFsm, 1, 0); 00541 else 00542 imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 1, 0); 00543 00544 /* 00545 * The lower bound is the conjunction of the fair states, 00546 * and the target states. 00547 */ 00548 fromLowerBound = mdd_and(targetMdd, fairStates, 1, 1); 00549 /* 00550 * The upper bound is the same as the lower bound. 00551 */ 00552 fromUpperBound = mdd_dup(fromLowerBound); 00553 00554 result = Img_ImageInfoComputePreImageWithDomainVars(imageInfo, 00555 fromLowerBound, fromUpperBound, careStatesArray); 00556 mdd_free(fromLowerBound); 00557 mdd_free(fromUpperBound); 00558 00559 if (verbosity == McVerbosityMax_c) { 00560 static int refCount=0; 00561 mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm); 00562 array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm); 00563 mdd_t *tmpMdd = careStatesArray ? 00564 mdd_and_array(result, careStatesArray, 1, 1) : mdd_dup(result); 00565 fprintf(vis_stdout, "--EX called %d (bdd_size - %d)\n", ++refCount, 00566 mdd_size(result)); 00567 fprintf(vis_stdout, "--There are %.0f care states satisfying EX formula\n", 00568 mdd_count_onset(mddMgr, tmpMdd, psVars)); 00569 mdd_free(tmpMdd); 00570 } 00571 00572 return result; 00573 00574 } /* Mc_FsmEvaluateEXFormula */ 00575 00576 00593 mdd_t * 00594 Mc_FsmEvaluateMXFormula( 00595 Fsm_Fsm_t *modelFsm, 00596 mdd_t *targetMdd, 00597 mdd_t *fairStates, 00598 array_t *careStatesArray, 00599 Mc_VerbosityLevel verbosity, 00600 Mc_DcLevel dcLevel) 00601 { 00602 mdd_t *resultBar, *result; 00603 00604 result = Mc_FsmEvaluateEXFormula(modelFsm, targetMdd, fairStates, 00605 careStatesArray, verbosity, dcLevel); 00606 00607 if(Fsm_FsmReadUniQuantifyInputCube(modelFsm)) { 00608 resultBar = Mc_QuantifyInputFAFW(modelFsm, result); 00609 mdd_free(result); 00610 result = resultBar; 00611 } 00612 00613 return(result); 00614 } 00615 00633 bdd_t * 00634 Mc_QuantifyInputFAFW(Fsm_Fsm_t *fsm, bdd_t *result) 00635 { 00636 bdd_t *uniCube, *extCube, *newResult; 00637 bdd_t *oneMdd, *notResult; 00638 mdd_manager *mgr = Fsm_FsmReadMddManager(fsm); 00639 00640 oneMdd = mdd_one(mgr); 00641 uniCube = Fsm_FsmReadUniQuantifyInputCube(fsm); 00642 extCube = Fsm_FsmReadExtQuantifyInputCube(fsm); 00643 if(!mdd_equal(uniCube, oneMdd)) { 00647 notResult = bdd_not(result); 00648 newResult = bdd_smooth_with_cube(notResult, uniCube); 00649 bdd_free(notResult); 00650 result = bdd_not(newResult); 00651 bdd_free(newResult); 00652 } 00653 else { 00654 result = mdd_dup(result); 00655 } 00656 mdd_free(oneMdd); 00657 return(result); 00658 } 00659 00660 00670 mdd_t * 00671 Mc_FsmEvaluateEYFormula( 00672 Fsm_Fsm_t *modelFsm, 00673 mdd_t *targetMdd, 00674 mdd_t *fairStates, 00675 array_t *careStatesArray, 00676 Mc_VerbosityLevel verbosity, 00677 Mc_DcLevel dcLevel) 00678 { 00679 mdd_t *fromLowerBound; 00680 mdd_t *fromUpperBound; 00681 mdd_t *result; 00682 00683 Img_ImageInfo_t * imageInfo = Fsm_FsmReadOrCreateImageInfo(modelFsm, 0, 1); 00684 00685 /* 00686 * The lower bound is the conjunction of the fair states, 00687 * and the target states. 00688 */ 00689 fromLowerBound = mdd_and(targetMdd, fairStates, 1, 1); 00690 /* 00691 * The upper bound is the same as the lower bound. 00692 */ 00693 fromUpperBound = fromLowerBound; 00694 00695 result = Img_ImageInfoComputeImageWithDomainVars(imageInfo, 00696 fromLowerBound, fromUpperBound, careStatesArray); 00697 mdd_free(fromLowerBound); 00698 00699 if (verbosity == McVerbosityMax_c) { 00700 static int refCount=0; 00701 mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm); 00702 array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm); 00703 mdd_t *tmpMdd = careStatesArray ? 00704 mdd_and_array(result, careStatesArray, 1, 1) : mdd_dup(result); 00705 fprintf(vis_stdout, "--EY called %d (bdd_size - %d)\n", ++refCount, 00706 mdd_size(result)); 00707 fprintf(vis_stdout, "--There are %.0f care states satisfying EY formula\n", 00708 mdd_count_onset(mddMgr, tmpMdd, psVars)); 00709 mdd_free(tmpMdd); 00710 } 00711 00712 return result; 00713 00714 } /* Mc_FsmEvaluateEYFormula */ 00715 00716 00768 mdd_t * 00769 Mc_FsmEvaluateEUFormula( 00770 Fsm_Fsm_t *fsm, 00771 mdd_t *invariant, 00772 mdd_t *target, 00773 mdd_t *underapprox, 00774 mdd_t *fairStates, 00775 array_t *careStatesArray, 00776 Mc_EarlyTermination_t *earlyTermination, 00777 Fsm_HintsArray_t *hintsArray, 00778 Mc_GuidedSearch_t hintType, 00779 array_t *onionRings, 00780 Mc_VerbosityLevel verbosity, 00781 Mc_DcLevel dcLevel, 00782 boolean *fixpoint) 00783 { 00784 /* should be strengthened to check that rings supply a correct explanation. 00785 */ 00786 /*check out 00787 * assert(underapprox == NULL || onionRings == NULL || 00788 * array_n(onionRings) != 0); */ 00789 00790 if(hintType != Mc_Local_c) 00791 /* postcondition: rings should explain how to get from return value to 00792 * target. 00793 */ 00794 return McEvaluateEUFormulaWithGivenTR(fsm, invariant, target, 00795 underapprox, fairStates, 00796 careStatesArray, 00797 earlyTermination, onionRings, 00798 verbosity, dcLevel, fixpoint); 00799 else{ 00800 mdd_t *iterate, *newiterate; 00801 mdd_t *hint; 00802 int hintnr; 00803 00804 if(verbosity >= McVerbosityMax_c) 00805 fprintf(vis_stdout, "--Using local hints\n"); 00806 00807 if(underapprox != NIL(mdd_t)) 00808 iterate = mdd_dup(underapprox); 00809 else 00810 iterate = mdd_zero(Fsm_FsmReadMddManager(fsm)); 00811 00812 arrayForEachItem(mdd_t *, hintsArray, hintnr, hint){ 00813 if(verbosity >= McVerbosityMax_c) 00814 fprintf(vis_stdout, "--Instantiating local hint %d\n", hintnr); 00815 Fsm_InstantiateHint(fsm, hint, FALSE, TRUE, Ctlp_Underapprox_c, 00816 (verbosity >= McVerbosityMax_c)); 00817 00818 newiterate = 00819 McEvaluateEUFormulaWithGivenTR(fsm, invariant, target, iterate, 00820 fairStates, careStatesArray, 00821 earlyTermination, onionRings, 00822 verbosity, dcLevel, fixpoint); 00823 mdd_free(iterate); 00824 iterate = newiterate; 00825 00826 /* check if we can terminate without considering all hints */ 00827 if(mdd_is_tautology(iterate, 1)){ 00828 *fixpoint = 1; 00829 break; 00830 } 00831 if(McCheckEarlyTerminationForUnderapprox(earlyTermination, iterate, 00832 careStatesArray)){ 00833 *fixpoint = 0; 00834 break; 00835 } 00836 00837 }/* for all hints */ 00838 Fsm_CleanUpHints(fsm, FALSE, TRUE, (verbosity >= McVerbosityMax_c)); 00839 00840 /* postcondition: rings should explain how to get from return value to 00841 * target. 00842 */ 00843 return iterate; 00844 }/* if hinttype */ 00845 00846 } /* Mc_FsmEvaluateEUFormula */ 00847 00848 00893 mdd_t * 00894 Mc_FsmEvaluateESFormula( 00895 Fsm_Fsm_t *fsm, 00896 mdd_t *invariant, 00897 mdd_t *source, 00898 mdd_t *underapprox, 00899 mdd_t *fairStates, 00900 array_t *careStatesArray, 00901 Mc_EarlyTermination_t *earlyTermination, 00902 Fsm_HintsArray_t *hintsArray, 00903 Mc_GuidedSearch_t hintType, 00904 array_t *onionRings, 00905 Mc_VerbosityLevel verbosity, 00906 Mc_DcLevel dcLevel, 00907 boolean *fixpoint) 00908 { 00909 /* should be strengthened to check that rings supply a correct explanation. 00910 */ 00911 assert(underapprox == NULL || onionRings == NULL || 00912 array_n(onionRings) != 0); 00913 00914 if(hintType != Mc_Local_c) 00915 /* postcondition: rings should explain how to get from return value to 00916 * target. 00917 */ 00918 return McEvaluateESFormulaWithGivenTR(fsm, invariant, source, 00919 underapprox, fairStates, 00920 careStatesArray, 00921 earlyTermination, onionRings, 00922 verbosity, dcLevel, fixpoint); 00923 else{ 00924 mdd_t *iterate, *newiterate; 00925 mdd_t *hint; 00926 int hintnr; 00927 00928 if(verbosity >= McVerbosityMax_c) 00929 fprintf(vis_stdout, "--Using local hints\n"); 00930 00931 if(underapprox != NIL(mdd_t)) 00932 iterate = mdd_dup(underapprox); 00933 else 00934 iterate = mdd_zero(Fsm_FsmReadMddManager(fsm)); 00935 00936 arrayForEachItem(mdd_t *, hintsArray, hintnr, hint){ 00937 if(verbosity >= McVerbosityMax_c) 00938 fprintf(vis_stdout, "--Instantiating local hint %d\n", hintnr); 00939 Fsm_InstantiateHint(fsm, hint, FALSE, TRUE, Ctlp_Underapprox_c, 00940 (verbosity >= McVerbosityMax_c)); 00941 00942 newiterate = 00943 McEvaluateESFormulaWithGivenTR(fsm, invariant, source, iterate, 00944 fairStates, careStatesArray, 00945 earlyTermination, onionRings, 00946 verbosity, dcLevel, fixpoint); 00947 mdd_free(iterate); 00948 iterate = newiterate; 00949 00950 /* check if we can terminate without considering all hints */ 00951 if(mdd_is_tautology(iterate, 1)){ 00952 *fixpoint = 1; 00953 break; 00954 } 00955 if(McCheckEarlyTerminationForUnderapprox(earlyTermination, iterate, 00956 careStatesArray)){ 00957 *fixpoint = 0; 00958 break; 00959 } 00960 00961 }/* for all hints */ 00962 Fsm_CleanUpHints(fsm, FALSE, TRUE, (verbosity >= McVerbosityMax_c)); 00963 00964 /* postcondition: rings should explain how to get from return value to 00965 * target. 00966 */ 00967 00968 return iterate; 00969 }/* if hinttype */ 00970 00971 } /* Mc_FsmEvaluateESFormula */ 00972 00973 mdd_t * 00974 Mc_FsmEvaluateAUFormula( 00975 Fsm_Fsm_t *fsm, 00976 mdd_t *invariant, 00977 mdd_t *target, 00978 mdd_t *underapprox, 00979 mdd_t *fairStates, 00980 array_t *careStatesArray, 00981 Mc_EarlyTermination_t *earlyTermination, 00982 Fsm_HintsArray_t *hintsArray, 00983 Mc_GuidedSearch_t hintType, 00984 array_t *onionRings, 00985 Mc_VerbosityLevel verbosity, 00986 Mc_DcLevel dcLevel, 00987 boolean *fixpoint) 00988 { 00989 00990 return McEvaluateAUFormulaWithGivenTR(fsm, invariant, target, 00991 underapprox, fairStates, 00992 careStatesArray, 00993 earlyTermination, onionRings, 00994 verbosity, dcLevel, fixpoint); 00995 00996 } 00997 00998 00999 01040 mdd_t * 01041 Mc_FsmEvaluateEGFormula( 01042 Fsm_Fsm_t *fsm, 01043 mdd_t *invariant, 01044 mdd_t *overapprox, 01045 mdd_t *fairStates, 01046 Fsm_Fairness_t *modelFairness, 01047 array_t *careStatesArray, 01048 Mc_EarlyTermination_t *earlyTermination, 01049 Fsm_HintsArray_t *hintsArray, 01050 Mc_GuidedSearch_t hintType, 01051 array_t **pOnionRingsArrayForDbg, 01052 Mc_VerbosityLevel verbosity, 01053 Mc_DcLevel dcLevel, 01054 boolean *fixpoint, 01055 Mc_GSHScheduleType GSHschedule) 01056 { 01057 /* Illegal to pass in onion rings. */ 01058 #if 0 01059 assert(pOnionRingsArrayForDbg == NIL(array_t *) || 01060 *pOnionRingsArrayForDbg == NIL(array_t) || 01061 array_n(*pOnionRingsArrayForDbg) == 0); 01062 #endif 01063 if(hintType != Mc_Local_c) 01064 if (GSHschedule == McGSH_old_c) { 01065 return McEvaluateEGFormulaWithGivenTR(fsm, invariant, overapprox, 01066 fairStates, 01067 modelFairness, careStatesArray, 01068 earlyTermination, 01069 pOnionRingsArrayForDbg, 01070 verbosity, 01071 dcLevel, fixpoint); 01072 } else { 01073 return McFsmEvaluateEGFormulaUsingGSH(fsm, invariant, overapprox, 01074 fairStates, 01075 modelFairness, careStatesArray, 01076 earlyTermination, 01077 pOnionRingsArrayForDbg, verbosity, 01078 dcLevel, fixpoint, GSHschedule); 01079 } 01080 else { 01081 mdd_t *iterate, *newiterate; 01082 mdd_t *hint; 01083 int hintnr; 01084 boolean useRings; 01085 01086 useRings = (pOnionRingsArrayForDbg != NIL(array_t *) && 01087 *pOnionRingsArrayForDbg != NIL(array_t)); 01088 01089 if(verbosity >= McVerbosityMax_c) 01090 fprintf(vis_stdout, "** mc Info: Using local hints\n"); 01091 01092 if(overapprox != NIL(mdd_t)) 01093 iterate = mdd_dup(overapprox); 01094 else 01095 iterate = mdd_one(Fsm_FsmReadMddManager(fsm)); 01096 01097 arrayForEachItem(mdd_t *, hintsArray, hintnr, hint){ 01098 if(verbosity >= McVerbosityMax_c) 01099 fprintf(vis_stdout, "--Instantiating local hint %d\n", hintnr); 01100 Fsm_InstantiateHint(fsm, hint, FALSE, TRUE, Ctlp_Overapprox_c, 01101 (verbosity >= McVerbosityMax_c)); 01102 01103 /* old onionrings go stale. Fry 'em */ 01104 if(useRings){ 01105 mdd_array_array_free(*pOnionRingsArrayForDbg); 01106 *pOnionRingsArrayForDbg = array_alloc(array_t *, 0); 01107 } 01108 01109 if (GSHschedule == McGSH_old_c) { 01110 newiterate = 01111 McEvaluateEGFormulaWithGivenTR(fsm, invariant, iterate, fairStates, 01112 modelFairness, careStatesArray, 01113 earlyTermination, 01114 pOnionRingsArrayForDbg, 01115 verbosity, dcLevel, fixpoint); 01116 } else { 01117 newiterate = 01118 McFsmEvaluateEGFormulaUsingGSH(fsm, invariant, iterate, 01119 fairStates, 01120 modelFairness, careStatesArray, 01121 earlyTermination, 01122 pOnionRingsArrayForDbg, verbosity, 01123 dcLevel, fixpoint, GSHschedule); 01124 } 01125 mdd_free(iterate); 01126 iterate = newiterate; 01127 01128 /* check if we can terminate without considering all hints */ 01129 if(mdd_is_tautology(iterate, 0)){ 01130 *fixpoint = 1; 01131 break; 01132 } 01133 if(McCheckEarlyTerminationForOverapprox(earlyTermination, iterate, 01134 careStatesArray)){ 01135 *fixpoint = 0; 01136 break; 01137 } 01138 01139 } /* For all hints */ 01140 Fsm_CleanUpHints(fsm, FALSE, TRUE, (verbosity >= McVerbosityMax_c)); 01141 01142 return iterate; 01143 }/* if hinttype */ 01144 01145 } /* Mc_FsmEvaluateEGFormula */ 01146 01147 01188 mdd_t * 01189 Mc_FsmEvaluateEHFormula( 01190 Fsm_Fsm_t *fsm, 01191 mdd_t *invariant, 01192 mdd_t *overapprox, 01193 mdd_t *fairStates, 01194 Fsm_Fairness_t *modelFairness, 01195 array_t *careStatesArray, 01196 Mc_EarlyTermination_t *earlyTermination, 01197 Fsm_HintsArray_t *hintsArray, 01198 Mc_GuidedSearch_t hintType, 01199 array_t **pOnionRingsArrayForDbg, 01200 Mc_VerbosityLevel verbosity, 01201 Mc_DcLevel dcLevel, 01202 boolean *fixpoint, 01203 Mc_GSHScheduleType GSHschedule) 01204 { 01205 /* Illegal to pass in onion rings. */ 01206 assert(pOnionRingsArrayForDbg == NIL(array_t *) || 01207 *pOnionRingsArrayForDbg == NIL(array_t) || 01208 array_n(*pOnionRingsArrayForDbg) == 0); 01209 01210 if(hintType != Mc_Local_c) 01211 if (GSHschedule == McGSH_old_c) { 01212 return McEvaluateEHFormulaWithGivenTR(fsm, invariant, overapprox, 01213 fairStates, 01214 modelFairness, careStatesArray, 01215 earlyTermination, 01216 pOnionRingsArrayForDbg, 01217 verbosity, 01218 dcLevel, fixpoint); 01219 } else { 01220 return McFsmEvaluateEHFormulaUsingGSH(fsm, invariant, overapprox, 01221 fairStates, 01222 modelFairness, careStatesArray, 01223 earlyTermination, 01224 pOnionRingsArrayForDbg, verbosity, 01225 dcLevel, fixpoint, GSHschedule); 01226 } 01227 else { 01228 mdd_t *iterate, *newiterate; 01229 mdd_t *hint; 01230 int hintnr; 01231 boolean useRings; 01232 01233 useRings = (pOnionRingsArrayForDbg != NIL(array_t *) && 01234 *pOnionRingsArrayForDbg != NIL(array_t)); 01235 01236 if(verbosity >= McVerbosityMax_c) 01237 fprintf(vis_stdout, "** mc Info: Using local hints\n"); 01238 01239 if(overapprox != NIL(mdd_t)) 01240 iterate = mdd_dup(overapprox); 01241 else 01242 iterate = mdd_one(Fsm_FsmReadMddManager(fsm)); 01243 01244 arrayForEachItem(mdd_t *, hintsArray, hintnr, hint){ 01245 if(verbosity >= McVerbosityMax_c) 01246 fprintf(vis_stdout, "--Instantiating local hint %d\n", hintnr); 01247 Fsm_InstantiateHint(fsm, hint, FALSE, TRUE, Ctlp_Overapprox_c, 01248 (verbosity >= McVerbosityMax_c)); 01249 01250 /* old onionrings go stale. Fry 'em */ 01251 if(useRings){ 01252 mdd_array_array_free(*pOnionRingsArrayForDbg); 01253 *pOnionRingsArrayForDbg = array_alloc(array_t *, 0); 01254 } 01255 01256 if (GSHschedule == McGSH_old_c) { 01257 newiterate = 01258 McEvaluateEHFormulaWithGivenTR(fsm, invariant, iterate, fairStates, 01259 modelFairness, careStatesArray, 01260 earlyTermination, 01261 pOnionRingsArrayForDbg, 01262 verbosity, dcLevel, fixpoint); 01263 } else { 01264 newiterate = 01265 McFsmEvaluateEHFormulaUsingGSH(fsm, invariant, iterate, 01266 fairStates, 01267 modelFairness, careStatesArray, 01268 earlyTermination, 01269 pOnionRingsArrayForDbg, verbosity, 01270 dcLevel, fixpoint, GSHschedule); 01271 } 01272 mdd_free(iterate); 01273 iterate = newiterate; 01274 01275 /* check if we can terminate without considering all hints */ 01276 if(mdd_is_tautology(iterate, 0)){ 01277 *fixpoint = 1; 01278 break; 01279 } 01280 if(McCheckEarlyTerminationForOverapprox(earlyTermination, iterate, 01281 careStatesArray)){ 01282 *fixpoint = 0; 01283 break; 01284 } 01285 01286 } /* For all hints */ 01287 Fsm_CleanUpHints(fsm, FALSE, TRUE, (verbosity >= McVerbosityMax_c)); 01288 01289 return iterate; 01290 }/* if hinttype */ 01291 01292 } /* Mc_FsmEvaluateEHFormula */ 01293 01294 01306 mdd_t * 01307 Mc_FsmEvaluateFwdUFormula( 01308 Fsm_Fsm_t *modelFsm, 01309 mdd_t *targetMdd, 01310 mdd_t *invariantMdd, 01311 mdd_t *fairStates, 01312 array_t *careStatesArray, 01313 array_t *onionRings, 01314 Mc_VerbosityLevel verbosity, 01315 Mc_DcLevel dcLevel) 01316 { 01317 mdd_t *aMdd; 01318 mdd_t *bMdd; 01319 mdd_t *cMdd; 01320 mdd_t *resultMdd; 01321 mdd_t *ringMdd; 01322 int nImgComps; 01323 01324 /* t 01325 ** E[p U q] = lfp Z[q V (p ^ EX(Z))] : p p ... p q 01326 ** FwdUntil(p,q) = lfp Z[p V EY(Z ^ q)] : pq q q ... q 01327 */ 01328 01329 nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c); 01330 resultMdd = mdd_and(targetMdd, fairStates, 1, 1); 01331 ringMdd = mdd_dup(resultMdd); 01332 01333 /* if until is trivially satisfied, */ 01334 if (onionRings) { 01335 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 01336 } 01337 if (mdd_is_tautology(fairStates, 1)) { 01338 if (mdd_equal_mod_care_set_array(invariantMdd, resultMdd, careStatesArray)) 01339 { 01340 bdd_free(ringMdd); 01341 return(resultMdd); 01342 } 01343 } else { 01344 bdd_t *trivialCheck = mdd_and(invariantMdd, fairStates, 1, 1); 01345 if (mdd_equal_mod_care_set_array(trivialCheck, resultMdd, careStatesArray)) { 01346 bdd_free(trivialCheck); 01347 bdd_free(ringMdd); 01348 return(resultMdd); 01349 } 01350 bdd_free(trivialCheck); 01351 } 01352 01353 while (TRUE) { 01354 aMdd = mdd_and(ringMdd, invariantMdd, 1, 1); 01355 mdd_free(ringMdd); 01356 bMdd = Mc_FsmEvaluateEYFormula(modelFsm, aMdd, fairStates, careStatesArray, 01357 verbosity, dcLevel); 01358 mdd_free(aMdd); 01359 cMdd = mdd_or(resultMdd, bMdd, 1, 1); 01360 mdd_free(bMdd); 01361 01362 if (mdd_equal_mod_care_set_array(cMdd, resultMdd, careStatesArray)) { 01363 mdd_free(cMdd); 01364 break; 01365 } 01366 01367 if (dcLevel >= McDcLevelRchFrontier_c) { 01368 mdd_t *tmpMdd = mdd_and(resultMdd, cMdd, 0, 1); 01369 ringMdd = bdd_between(tmpMdd, cMdd); 01370 if (verbosity == McVerbosityMax_c) { 01371 fprintf(vis_stdout, 01372 "-- FwdU |A(n+1)-A(n)| = %d\t|A(n+1)| = %d\t|between-dc| = %d\n", 01373 mdd_size(tmpMdd), mdd_size(resultMdd), mdd_size(ringMdd)); 01374 } 01375 mdd_free(tmpMdd); 01376 } 01377 else { 01378 ringMdd = mdd_dup(cMdd); 01379 if (verbosity == McVerbosityMax_c) { 01380 fprintf(vis_stdout, "-- FwdU |ringMdd| = %d\n", mdd_size(ringMdd)); 01381 } 01382 } 01383 01384 mdd_free(resultMdd); 01385 resultMdd = cMdd; 01386 if (onionRings) { 01387 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 01388 } 01389 } /* while(!termination) for LFP */ 01390 01391 /* Print some debug info */ 01392 if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) { 01393 static int refCount=0; 01394 mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm); 01395 array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm); 01396 01397 if (verbosity == McVerbosityMax_c) { 01398 mdd_t *tmpMdd = careStatesArray ? 01399 mdd_and_array(resultMdd, careStatesArray, 1, 1) : 01400 mdd_dup(resultMdd); 01401 fprintf(vis_stdout, "--FwdU called %d (bdd_size - %d)\n", 01402 ++refCount, mdd_size(resultMdd)); 01403 fprintf(vis_stdout, 01404 "--There are %.0f care states satisfying FwdU formula\n", 01405 mdd_count_onset(mddMgr, tmpMdd, psVars)); 01406 #ifdef DEBUG_MC 01407 /* The following 2 lines are just for debug */ 01408 fprintf(vis_stdout, "FwdU satisfying minterms :\n"); 01409 (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm); 01410 #endif 01411 mdd_free(tmpMdd); 01412 } else { 01413 fprintf(vis_stdout, 01414 "--There are %.0f states satisfying FwdU formula\n", 01415 mdd_count_onset(mddMgr, resultMdd, psVars)); 01416 } 01417 fprintf(vis_stdout, "--FwdU: %d image computations\n", 01418 Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps); 01419 } 01420 01421 return resultMdd; 01422 } 01423 01424 01434 mdd_t * 01435 Mc_FsmEvaluateFwdGFormula( 01436 Fsm_Fsm_t *modelFsm, 01437 mdd_t *targetMdd, 01438 mdd_t *invariantMdd, 01439 mdd_t *fairStates, 01440 Fsm_Fairness_t *modelFairness, 01441 array_t *careStatesArray, 01442 array_t *onionRingsArrayForDbg, 01443 Mc_VerbosityLevel verbosity, 01444 Mc_DcLevel dcLevel) 01445 { 01446 mdd_t *resultMdd, *invariant; 01447 array_t *onionRings; 01448 int nImgComps; 01449 01450 nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c); 01451 onionRings = NIL(array_t); 01452 01453 invariant = McForwardReachable(modelFsm, targetMdd, invariantMdd, fairStates, 01454 careStatesArray, onionRings, verbosity, 01455 dcLevel); 01456 resultMdd = Mc_FsmEvaluateFwdEHFormula(modelFsm, invariant, fairStates, 01457 modelFairness, careStatesArray, 01458 onionRingsArrayForDbg, verbosity, 01459 dcLevel); 01460 mdd_free(invariant); 01461 01462 if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) { 01463 fprintf(vis_stdout, "--FwdG: %d image computations\n", 01464 Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps); 01465 } 01466 #ifdef DEBUG_MC 01467 /* The following 2 lines are just for debug */ 01468 if ((verbosity == McVerbosityMax_c)) { 01469 fprintf(vis_stdout, "FwdG satisfying minterms :\n"); 01470 (void)_McPrintSatisfyingMinterms(resultMdd, modelFsm); 01471 } 01472 #endif 01473 return resultMdd; 01474 } 01475 01476 01477 01487 mdd_t * 01488 Mc_FsmEvaluateFwdEHFormula( 01489 Fsm_Fsm_t *modelFsm, 01490 mdd_t *invariantMdd, 01491 mdd_t *fairStates, 01492 Fsm_Fairness_t *modelFairness, 01493 array_t *careStatesArray, 01494 array_t *onionRingsArrayForDbg, 01495 Mc_VerbosityLevel verbosity, 01496 Mc_DcLevel dcLevel) 01497 { 01498 int i; 01499 array_t *onionRings = NIL(array_t); 01500 array_t *tmpOnionRingsArrayForDbg = NIL(array_t); 01501 mdd_manager *mddManager = Fsm_FsmReadMddManager(modelFsm); 01502 mdd_t *mddOne = mdd_one(mddManager); 01503 mdd_t *Zmdd; 01504 int nIterations = 0; 01505 int nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c); 01506 01507 /* 01508 ** EG(f) = gfp Z[f ^ EX(Z)] 01509 ** EH(f) = gfp Z[f ^ EY(Z)] 01510 ** 01511 ** EcG(f) = gfp Z[f ^ EX( ^ E[Z U Z ^ c])] 01512 ** c<C 01513 ** EcH(f) = gfp Z[f ^ EY( ^ Reachable(c,Z))] 01514 ** c<C 01515 ** Reachable(p,q) = FwdUntil(p,q) ^ q 01516 */ 01517 01518 array_t *buchiFairness = array_alloc(mdd_t *, 0); 01519 if (modelFairness) { 01520 if (!Fsm_FairnessTestIsBuchi(modelFairness)) { 01521 (void) fprintf(vis_stdout, 01522 "** mc error: non-Buechi fairness constraints not supported\n"); 01523 return NIL(mdd_t); 01524 } 01525 else { 01526 int j; 01527 int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0); 01528 for (j = 0; j < numBuchi; j++) { 01529 mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j, 01530 careStatesArray, dcLevel); 01531 array_insert_last(mdd_t *, buchiFairness, tmpMdd); 01532 } 01533 } 01534 } 01535 else { 01536 array_insert_last(mdd_t *, buchiFairness, mdd_one(mddManager)); 01537 } 01538 01539 if (onionRingsArrayForDbg !=NIL(array_t)) { 01540 tmpOnionRingsArrayForDbg = array_alloc(array_t *, 0); 01541 } 01542 01543 Zmdd = mdd_dup(invariantMdd); 01544 while (TRUE) { 01545 mdd_t *ZprimeMdd = mdd_dup(Zmdd); 01546 mdd_t *conjunctsMdd = NIL(mdd_t); 01547 mdd_t *AAmdd = mdd_dup(Zmdd); 01548 01549 nIterations++; 01550 for (i = 0; i < array_n(buchiFairness); i++) { 01551 mdd_t *aMdd, *bMdd; 01552 mdd_t *FiMdd = array_fetch(mdd_t *, buchiFairness, i); 01553 01554 if (tmpOnionRingsArrayForDbg) { 01555 onionRings = array_alloc(mdd_t *, 0); 01556 array_insert_last(array_t *, tmpOnionRingsArrayForDbg, onionRings); 01557 } 01558 01559 aMdd = McForwardReachable(modelFsm, FiMdd, AAmdd, mddOne, careStatesArray, 01560 onionRings, verbosity, dcLevel); 01561 bMdd = Mc_FsmEvaluateEYFormula(modelFsm, aMdd, mddOne, careStatesArray, 01562 verbosity, dcLevel); 01563 mdd_free(aMdd); 01564 01565 if (conjunctsMdd == NIL(mdd_t)) { 01566 conjunctsMdd = mdd_dup(bMdd); 01567 } 01568 else { 01569 mdd_t *tmpMdd = mdd_and(bMdd, conjunctsMdd, 1, 1); 01570 mdd_free(conjunctsMdd); 01571 conjunctsMdd = tmpMdd; 01572 } 01573 mdd_free(AAmdd); AAmdd = mdd_and(conjunctsMdd, invariantMdd, 1, 1); 01574 mdd_free(bMdd); 01575 } 01576 mdd_free(AAmdd); 01577 01578 mdd_free(ZprimeMdd); 01579 ZprimeMdd = mdd_and(invariantMdd, conjunctsMdd, 1, 1); 01580 mdd_free(conjunctsMdd); 01581 01582 if (mdd_equal_mod_care_set_array(ZprimeMdd, Zmdd, careStatesArray)) { 01583 mdd_free(ZprimeMdd); 01584 break; 01585 } 01586 01587 mdd_free(Zmdd); 01588 Zmdd = ZprimeMdd; 01589 01590 if (tmpOnionRingsArrayForDbg) { 01591 arrayForEachItem(array_t *, tmpOnionRingsArrayForDbg, i, onionRings) { 01592 mdd_array_free(onionRings); 01593 } 01594 array_free(tmpOnionRingsArrayForDbg); 01595 tmpOnionRingsArrayForDbg = array_alloc(array_t *, 0); 01596 } 01597 } 01598 01599 if (onionRingsArrayForDbg != NIL(array_t)) { 01600 arrayForEachItem(array_t *, tmpOnionRingsArrayForDbg, i, onionRings) { 01601 array_insert_last(array_t *, onionRingsArrayForDbg, onionRings); 01602 } 01603 array_free(tmpOnionRingsArrayForDbg); 01604 } 01605 01606 if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) { 01607 if (onionRingsArrayForDbg) { 01608 for (i = 0; i < array_n(onionRingsArrayForDbg); i++) { 01609 int j; 01610 mdd_t *Fi = array_fetch(mdd_t *, buchiFairness, i); 01611 array_t *onionRings = array_fetch(array_t *, onionRingsArrayForDbg, i); 01612 for (j = 0; j < array_n(onionRings); j++) { 01613 mdd_t *ring = array_fetch(mdd_t *, onionRings, j); 01614 if (j == 0) { 01615 if (!mdd_lequal(ring, Fi, 1, 1)) { 01616 fprintf(vis_stderr, "** mc error: Problem w/ dbg in EH - "); 01617 fprintf(vis_stderr, 01618 "inner most ring not in Fi(fairness constraint).\n"); 01619 } 01620 } 01621 if (!mdd_lequal(ring, Zmdd, 1, 1)) { 01622 fprintf(vis_stderr, "** mc error: Problem w/ dbg in EH - "); 01623 fprintf(vis_stderr, "onion ring of last FwdU fails invariant\n"); 01624 } 01625 } 01626 } 01627 } 01628 01629 if (verbosity == McVerbosityMax_c) { 01630 mdd_t *tmpMdd = careStatesArray ? 01631 mdd_and_array(Zmdd, careStatesArray, 1, 1) : 01632 mdd_dup(Zmdd); 01633 fprintf(vis_stdout, 01634 "--There are %.0f care states satisfying EH formula\n", 01635 mdd_count_onset(Fsm_FsmReadMddManager(modelFsm), tmpMdd, 01636 Fsm_FsmReadPresentStateVars(modelFsm))); 01637 #ifdef DEBUG_MC 01638 /* The following 2 lines are just for debug */ 01639 fprintf(vis_stdout, "EH satisfying minterms :\n"); 01640 (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm); 01641 #endif 01642 mdd_free(tmpMdd); 01643 } else { 01644 fprintf(vis_stdout, "--There are %.0f states satisfying EH formula\n", 01645 mdd_count_onset(Fsm_FsmReadMddManager(modelFsm), Zmdd, 01646 Fsm_FsmReadPresentStateVars(modelFsm))); 01647 } 01648 01649 fprintf(vis_stdout, "--EH: %d iterations, %d image computations\n", 01650 nIterations, Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps); 01651 } 01652 01653 mdd_array_free(buchiFairness); 01654 mdd_free(mddOne); 01655 01656 return Zmdd; 01657 01658 } /* Mc_FsmEvaluateFwdEHFormula */ 01659 01660 01661 /*---------------------------------------------------------------------------*/ 01662 /* Definition of internal functions */ 01663 /*---------------------------------------------------------------------------*/ 01664 01677 mdd_t * 01678 McEvaluateEUFormulaWithGivenTR( 01679 Fsm_Fsm_t *modelFsm, 01680 mdd_t *invariantMdd, 01681 mdd_t *targetMdd, 01682 mdd_t *underapprox, 01683 mdd_t *fairStates, 01684 array_t *careStatesArray, 01685 Mc_EarlyTermination_t *earlyTermination, 01686 array_t *onionRings, 01687 Mc_VerbosityLevel verbosity, 01688 Mc_DcLevel dcLevel, 01689 boolean *fixpoint 01690 ) 01691 { 01692 mdd_t *aMdd; 01693 mdd_t *bMdd; 01694 mdd_t *cMdd; 01695 mdd_t *resultMdd; 01696 mdd_t *ringMdd; 01697 int nPreComps; 01698 boolean term_tautology = FALSE; /* different termination conditions */ 01699 boolean term_early = FALSE; 01700 boolean term_fixpoint = FALSE; 01701 01702 nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c); 01703 resultMdd = mdd_and(targetMdd, fairStates, 1, 1); 01704 01705 if(underapprox != NIL(mdd_t)){ 01706 mdd_t *tmp = mdd_or(resultMdd, underapprox, 1, 1); 01707 mdd_free(resultMdd); 01708 resultMdd = tmp; 01709 } 01710 01711 ringMdd = mdd_dup(resultMdd); 01712 01713 if (onionRings) { 01714 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 01715 } 01716 01717 /* if until is trivially satisfied, or 01718 the early termination condition holds*/ 01719 { 01720 bdd_t *fairInvariantStates = mdd_and(invariantMdd, fairStates, 1, 1); 01721 boolean trivial; 01722 01723 trivial = mdd_lequal_mod_care_set_array(fairInvariantStates, resultMdd, 01724 1, 1, careStatesArray); 01725 /* the lequal also takes care of the case where result = 1 */ 01726 if(trivial || 01727 McCheckEarlyTerminationForUnderapprox(earlyTermination, 01728 resultMdd, 01729 careStatesArray)){ 01730 bdd_free(fairInvariantStates); 01731 bdd_free(ringMdd); 01732 01733 /* trivially satisfied means that the fixpoint is complete. If this 01734 information is requested, give it. */ 01735 if(fixpoint != NIL(boolean)) 01736 *fixpoint = trivial; 01737 return(resultMdd); 01738 } 01739 bdd_free(fairInvariantStates); 01740 } 01741 01742 /* The LFP loop */ 01743 while (!term_fixpoint && !term_tautology && !term_early) { 01744 /* If dclevel is maximal, ringbdd is between the frontier and the 01745 reached set */ 01746 aMdd = Mc_FsmEvaluateEXFormula(modelFsm, ringMdd, fairStates, 01747 careStatesArray, verbosity, dcLevel); 01748 mdd_free(ringMdd); 01749 01750 bMdd = mdd_and(aMdd, invariantMdd, 1, 1); 01751 mdd_free(aMdd); 01752 01753 cMdd = mdd_or(resultMdd, bMdd, 1, 1); 01754 mdd_free(bMdd); 01755 01756 /* Can we stop? The tautology condition can be weakened to 01757 cMdd <= careStatesArray */ 01758 term_fixpoint = mdd_equal_mod_care_set_array(cMdd, resultMdd, 01759 careStatesArray); 01760 if(!term_fixpoint) 01761 term_tautology = mdd_is_tautology(cMdd, 1); 01762 if(!term_fixpoint && !term_tautology) 01763 term_early = McCheckEarlyTerminationForUnderapprox(earlyTermination, 01764 cMdd, 01765 careStatesArray); 01766 01767 /* Print some debug info, and set ringmdd */ 01768 if (dcLevel >= McDcLevelRchFrontier_c) { 01769 mdd_t *tmpMdd = mdd_and(resultMdd, cMdd, 0, 1); 01770 ringMdd = bdd_between(tmpMdd, cMdd); 01771 if (verbosity == McVerbosityMax_c) { 01772 fprintf(vis_stdout, 01773 "--EU |A(n+1)-A(n)|= %d\t|A(n+1)| = %d\t|between-dc| = %d\n", 01774 mdd_size(tmpMdd), mdd_size(resultMdd), mdd_size(ringMdd)); 01775 } 01776 mdd_free(tmpMdd); 01777 } 01778 else { 01779 ringMdd = mdd_dup(cMdd); 01780 if (verbosity == McVerbosityMax_c) { 01781 fprintf(vis_stdout, "-- EU |ringMdd| = %d\n", mdd_size(ringMdd)); 01782 } 01783 } 01784 01785 mdd_free(resultMdd); 01786 resultMdd = cMdd; 01787 /* add onion ring unless fixpoint reached */ 01788 if (!term_fixpoint && onionRings != NIL(array_t)) { 01789 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 01790 } 01791 } /* while(!termination) for LFP */ 01792 01793 mdd_free(ringMdd); 01794 01795 /* Print some debug info */ 01796 if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) { 01797 static int refCount=0; 01798 mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm); 01799 array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm); 01800 01801 if (verbosity == McVerbosityMax_c) { 01802 mdd_t *tmpMdd = careStatesArray ? 01803 mdd_and_array(resultMdd, careStatesArray, 1, 1) : 01804 mdd_dup(resultMdd); 01805 fprintf(vis_stdout, "--EU called %d (bdd_size - %d)\n", ++refCount, 01806 mdd_size(resultMdd)); 01807 fprintf(vis_stdout, 01808 "--There are %.0f care states satisfying EU formula\n", 01809 mdd_count_onset(mddMgr, tmpMdd, psVars)); 01810 #ifdef DEBUG_MC 01811 /* The following 2 lines are just for debug */ 01812 fprintf(vis_stdout, "EU satisfying minterms :\n"); 01813 (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm); 01814 #endif 01815 mdd_free(tmpMdd); 01816 } else { 01817 fprintf(vis_stdout, 01818 "--There are %.0f states satisfying EU formula\n", 01819 mdd_count_onset(mddMgr, resultMdd, psVars)); 01820 } 01821 01822 fprintf(vis_stdout, "--EU: %d preimage computations\n", 01823 Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps); 01824 } 01825 01826 if(fixpoint != NIL(boolean)) 01827 *fixpoint = term_fixpoint || term_tautology; 01828 return resultMdd; 01829 01830 } /* McEvaluateEUFormulaWithGivenTR */ 01831 01832 01845 mdd_t * 01846 McEvaluateESFormulaWithGivenTR( 01847 Fsm_Fsm_t *modelFsm, 01848 mdd_t *invariantMdd, 01849 mdd_t *sourceMdd, 01850 mdd_t *underapprox, 01851 mdd_t *fairStates, 01852 array_t *careStatesArray, 01853 Mc_EarlyTermination_t *earlyTermination, 01854 array_t *onionRings, 01855 Mc_VerbosityLevel verbosity, 01856 Mc_DcLevel dcLevel, 01857 boolean *fixpoint 01858 ) 01859 { 01860 mdd_t *aMdd; 01861 mdd_t *bMdd; 01862 mdd_t *cMdd; 01863 mdd_t *resultMdd; 01864 mdd_t *ringMdd; 01865 int nImgComps; 01866 boolean term_tautology = FALSE; /* different termination conditions */ 01867 boolean term_early = FALSE; 01868 boolean term_fixpoint = FALSE; 01869 01870 nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c); 01871 resultMdd = mdd_and(sourceMdd, fairStates, 1, 1); 01872 01873 if(underapprox != NIL(mdd_t)){ 01874 mdd_t *tmp = mdd_or(resultMdd, underapprox, 1, 1); 01875 mdd_free(resultMdd); 01876 resultMdd = tmp; 01877 } 01878 01879 ringMdd = mdd_dup(resultMdd); 01880 01881 if (onionRings) { 01882 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 01883 } 01884 01885 /* if Since is trivially satisfied, or 01886 the early termination condition holds*/ 01887 { 01888 bdd_t *fairInvariantStates = mdd_and(invariantMdd, fairStates, 1, 1); 01889 boolean trivial; 01890 01891 trivial = mdd_lequal_mod_care_set_array(fairInvariantStates, resultMdd, 01892 1, 1, careStatesArray); 01893 /* the lequal also takes care of the case where result = 1 */ 01894 if(trivial || 01895 McCheckEarlyTerminationForUnderapprox(earlyTermination, 01896 resultMdd, 01897 careStatesArray)){ 01898 bdd_free(fairInvariantStates); 01899 bdd_free(ringMdd); 01900 01901 /* trivially satisfied means that the fixpoint is complete. If this 01902 information is requested, give it. */ 01903 if(fixpoint != NIL(boolean)) 01904 *fixpoint = trivial; 01905 return(resultMdd); 01906 } 01907 bdd_free(fairInvariantStates); 01908 } 01909 01910 /* The LFP loop */ 01911 while (!term_fixpoint && !term_tautology && !term_early) { 01912 /* If dclevel is maximal, ringbdd is between the frontier and the 01913 reached set */ 01914 aMdd = Mc_FsmEvaluateEYFormula(modelFsm, ringMdd, fairStates, 01915 careStatesArray, verbosity, dcLevel); 01916 mdd_free(ringMdd); 01917 01918 bMdd = mdd_and(aMdd, invariantMdd, 1, 1); 01919 mdd_free(aMdd); 01920 01921 cMdd = mdd_or(resultMdd, bMdd, 1, 1); 01922 mdd_free(bMdd); 01923 01924 /* Can we stop? The tautology condition can be weakened to 01925 cMdd <= careStatesArray */ 01926 term_fixpoint = mdd_equal_mod_care_set_array(cMdd, resultMdd, 01927 careStatesArray); 01928 if(!term_fixpoint) 01929 term_tautology = mdd_is_tautology(cMdd, 1); 01930 if(!term_fixpoint && !term_tautology) 01931 term_early = McCheckEarlyTerminationForUnderapprox(earlyTermination, 01932 cMdd, 01933 careStatesArray); 01934 01935 /* Print some debug info, and set ringmdd */ 01936 if (dcLevel >= McDcLevelRchFrontier_c) { 01937 mdd_t *tmpMdd = mdd_and(resultMdd, cMdd, 0, 1); 01938 ringMdd = bdd_between(tmpMdd, cMdd); 01939 if (verbosity == McVerbosityMax_c) { 01940 fprintf(vis_stdout, 01941 "--ES |A(n+1)-A(n)|= %d\t|A(n+1)| = %d\t|between-dc| = %d\n", 01942 mdd_size(tmpMdd), mdd_size(resultMdd), mdd_size(ringMdd)); 01943 } 01944 mdd_free(tmpMdd); 01945 } 01946 else { 01947 ringMdd = mdd_dup(cMdd); 01948 if (verbosity == McVerbosityMax_c) { 01949 fprintf(vis_stdout, "-- ES |ringMdd| = %d\n", mdd_size(ringMdd)); 01950 } 01951 } 01952 01953 mdd_free(resultMdd); 01954 resultMdd = cMdd; 01955 /* add onion ring unless fixpoint reached */ 01956 if (!term_fixpoint && onionRings != NIL(array_t)) { 01957 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 01958 } 01959 } /* while(!termination) for LFP */ 01960 01961 mdd_free(ringMdd); 01962 01963 /* Print some debug info */ 01964 if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) { 01965 static int refCount=0; 01966 mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm); 01967 array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm); 01968 01969 if (verbosity == McVerbosityMax_c) { 01970 mdd_t *tmpMdd = careStatesArray ? 01971 mdd_and_array(resultMdd, careStatesArray, 1, 1) : 01972 mdd_dup(resultMdd); 01973 fprintf(vis_stdout, "--ES called %d (bdd_size - %d)\n", ++refCount, 01974 mdd_size(resultMdd)); 01975 fprintf(vis_stdout, 01976 "--There are %.0f care states satisfying ES formula\n", 01977 mdd_count_onset(mddMgr, tmpMdd, psVars)); 01978 #ifdef DEBUG_MC 01979 /* The following 2 lines are just for debug */ 01980 fprintf(vis_stdout, "ES satisfying minterms :\n"); 01981 (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm); 01982 #endif 01983 mdd_free(tmpMdd); 01984 } else { 01985 fprintf(vis_stdout, 01986 "--There are %.0f states satisfying ES formula\n", 01987 mdd_count_onset(mddMgr, resultMdd, psVars)); 01988 } 01989 01990 fprintf(vis_stdout, "--ES: %d image computations\n", 01991 Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps); 01992 } 01993 01994 if(fixpoint != NIL(boolean)) 01995 *fixpoint = term_fixpoint || term_tautology; 01996 return resultMdd; 01997 01998 } /* McEvaluateESFormulaWithGivenTR */ 01999 02000 02012 mdd_t * 02013 McEvaluateESFormulaWithGivenTRWithTarget( 02014 Fsm_Fsm_t *modelFsm, 02015 mdd_t *invariantMdd, 02016 mdd_t *sourceMdd, 02017 mdd_t *targetMdd, 02018 mdd_t *underapprox, 02019 mdd_t *fairStates, 02020 array_t *careStatesArray, 02021 Mc_EarlyTermination_t *earlyTermination, 02022 array_t *onionRings, 02023 Mc_VerbosityLevel verbosity, 02024 Mc_DcLevel dcLevel, 02025 boolean *fixpoint 02026 ) 02027 { 02028 mdd_t *aMdd; 02029 mdd_t *bMdd; 02030 mdd_t *cMdd; 02031 mdd_t *resultMdd; 02032 mdd_t *ringMdd; 02033 mdd_t *zeroMdd; 02034 int nImgComps; 02035 boolean term_tautology = FALSE; /* different termination conditions */ 02036 boolean term_early = FALSE; 02037 boolean term_fixpoint = FALSE; 02038 02039 mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm); 02040 02041 nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c); 02042 resultMdd = mdd_and(sourceMdd, fairStates, 1, 1); 02043 02044 if(underapprox != NIL(mdd_t)){ 02045 mdd_t *tmp = mdd_or(resultMdd, underapprox, 1, 1); 02046 mdd_free(resultMdd); 02047 resultMdd = tmp; 02048 } 02049 02050 ringMdd = mdd_dup(resultMdd); 02051 zeroMdd = mdd_zero(mddMgr); 02052 02053 if (onionRings) { 02054 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 02055 } 02056 02057 /* if Since is trivially satisfied, or 02058 the early termination condition holds*/ 02059 { 02060 bdd_t *fairInvariantStates = mdd_and(invariantMdd, fairStates, 1, 1); 02061 boolean trivial; 02062 02063 trivial = mdd_lequal_mod_care_set_array(fairInvariantStates, resultMdd, 02064 1, 1, careStatesArray); 02065 /* the lequal also takes care of the case where result = 1 */ 02066 if(trivial || 02067 McCheckEarlyTerminationForUnderapprox(earlyTermination, 02068 resultMdd, 02069 careStatesArray)){ 02070 bdd_free(fairInvariantStates); 02071 bdd_free(ringMdd); 02072 02073 /* trivially satisfied means that the fixpoint is complete. If this 02074 information is requested, give it. */ 02075 if(fixpoint != NIL(boolean)) 02076 *fixpoint = trivial; 02077 return(resultMdd); 02078 } 02079 bdd_free(fairInvariantStates); 02080 } 02081 02082 /* The LFP loop */ 02083 while (!term_fixpoint && !term_tautology && !term_early) { 02084 /* If dclevel is maximal, ringbdd is between the frontier and the 02085 reached set */ 02086 aMdd = Mc_FsmEvaluateEYFormula(modelFsm, ringMdd, fairStates, 02087 careStatesArray, verbosity, dcLevel); 02088 mdd_free(ringMdd); 02089 02090 bMdd = mdd_and(aMdd, invariantMdd, 1, 1); 02091 mdd_free(aMdd); 02092 02093 cMdd = mdd_or(resultMdd, bMdd, 1, 1); 02094 mdd_free(bMdd); 02095 02096 /* Can we stop? The tautology condition can be weakened to 02097 cMdd <= careStatesArray */ 02098 term_fixpoint = mdd_equal_mod_care_set_array(cMdd, resultMdd, 02099 careStatesArray); 02100 if(!term_fixpoint) 02101 term_tautology = mdd_is_tautology(cMdd, 1); 02102 if(!term_fixpoint && !term_tautology) 02103 term_early = McCheckEarlyTerminationForUnderapprox(earlyTermination, 02104 cMdd, 02105 careStatesArray); 02106 02107 /* Print some debug info, and set ringmdd */ 02108 if (dcLevel >= McDcLevelRchFrontier_c) { 02109 mdd_t *tmpMdd = mdd_and(resultMdd, cMdd, 0, 1); 02110 ringMdd = bdd_between(tmpMdd, cMdd); 02111 if (verbosity == McVerbosityMax_c) { 02112 fprintf(vis_stdout, 02113 "--ES |A(n+1)-A(n)|= %d\t|A(n+1)| = %d\t|between-dc| = %d\n", 02114 mdd_size(tmpMdd), mdd_size(resultMdd), mdd_size(ringMdd)); 02115 } 02116 mdd_free(tmpMdd); 02117 } 02118 else { 02119 ringMdd = mdd_dup(cMdd); 02120 if (verbosity == McVerbosityMax_c) { 02121 fprintf(vis_stdout, "-- ES |ringMdd| = %d\n", mdd_size(ringMdd)); 02122 } 02123 } 02124 02125 mdd_free(resultMdd); 02126 resultMdd = cMdd; 02127 02128 aMdd = mdd_and(resultMdd, targetMdd, 1, 1); 02129 if(!mdd_equal(aMdd, zeroMdd)) { 02130 array_insert_last(mdd_t *, onionRings, mdd_dup(targetMdd)); 02131 mdd_free(aMdd); 02132 break; 02133 } 02134 mdd_free(aMdd); 02135 02136 /* add onion ring unless fixpoint reached */ 02137 if (!term_fixpoint && onionRings != NIL(array_t)) { 02138 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 02139 } 02140 } /* while(!termination) for LFP */ 02141 02142 mdd_free(ringMdd); 02143 02144 /* Print some debug info */ 02145 if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) { 02146 static int refCount=0; 02147 array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm); 02148 02149 if (verbosity == McVerbosityMax_c) { 02150 mdd_t *tmpMdd = careStatesArray ? 02151 mdd_and_array(resultMdd, careStatesArray, 1, 1) : 02152 mdd_dup(resultMdd); 02153 fprintf(vis_stdout, "--ES called %d (bdd_size - %d)\n", ++refCount, 02154 mdd_size(resultMdd)); 02155 fprintf(vis_stdout, 02156 "--There are %.0f care states satisfying ES formula\n", 02157 mdd_count_onset(mddMgr, tmpMdd, psVars)); 02158 #ifdef DEBUG_MC 02159 /* The following 2 lines are just for debug */ 02160 fprintf(vis_stdout, "ES satisfying minterms :\n"); 02161 (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm); 02162 #endif 02163 mdd_free(tmpMdd); 02164 } else { 02165 fprintf(vis_stdout, 02166 "--There are %.0f states satisfying ES formula\n", 02167 mdd_count_onset(mddMgr, resultMdd, psVars)); 02168 } 02169 02170 fprintf(vis_stdout, "--ES: %d image computations\n", 02171 Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps); 02172 } 02173 mdd_free(zeroMdd); 02174 02175 if(fixpoint != NIL(boolean)) 02176 *fixpoint = term_fixpoint || term_tautology; 02177 return resultMdd; 02178 02179 } /* McEvaluateESFormulaWithGivenTR */ 02180 02181 02193 mdd_t * 02194 McEvaluateESFormulaWithGivenTRFAFW( 02195 Fsm_Fsm_t *modelFsm, 02196 mdd_t *invariantMdd, 02197 mdd_t *sourceMdd, 02198 mdd_t *underapprox, 02199 mdd_t *fairStates, 02200 array_t *careStatesArray, 02201 Mc_EarlyTermination_t *earlyTermination, 02202 array_t *onionRings, 02203 Mc_VerbosityLevel verbosity, 02204 Mc_DcLevel dcLevel, 02205 boolean *fixpoint, 02206 mdd_t *Swin 02207 ) 02208 { 02209 mdd_t *aMdd; 02210 mdd_t *bMdd; 02211 mdd_t *cMdd; 02212 mdd_t *resultMdd; 02213 mdd_t *ringMdd; 02214 Img_ImageInfo_t *imageInfo; 02215 int nImgComps; 02216 boolean term_tautology = FALSE; /* different termination conditions */ 02217 boolean term_early = FALSE; 02218 boolean term_fixpoint = FALSE; 02219 02220 nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c); 02221 resultMdd = mdd_and(sourceMdd, fairStates, 1, 1); 02222 02223 if(underapprox != NIL(mdd_t)){ 02224 mdd_t *tmp = mdd_or(resultMdd, underapprox, 1, 1); 02225 mdd_free(resultMdd); 02226 resultMdd = tmp; 02227 } 02228 02229 ringMdd = mdd_dup(resultMdd); 02230 02231 if (onionRings) { 02232 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 02233 } 02234 02235 /* if Since is trivially satisfied, or 02236 the early termination condition holds*/ 02237 { 02238 bdd_t *fairInvariantStates = mdd_and(invariantMdd, fairStates, 1, 1); 02239 boolean trivial; 02240 02241 trivial = mdd_lequal_mod_care_set_array(fairInvariantStates, resultMdd, 02242 1, 1, careStatesArray); 02243 /* the lequal also takes care of the case where result = 1 */ 02244 if(trivial || 02245 McCheckEarlyTerminationForUnderapprox(earlyTermination, 02246 resultMdd, 02247 careStatesArray)){ 02248 bdd_free(fairInvariantStates); 02249 bdd_free(ringMdd); 02250 02251 /* trivially satisfied means that the fixpoint is complete. If this 02252 information is requested, give it. */ 02253 if(fixpoint != NIL(boolean)) 02254 *fixpoint = trivial; 02255 return(resultMdd); 02256 } 02257 bdd_free(fairInvariantStates); 02258 } 02259 02260 imageInfo = Fsm_FsmReadOrCreateImageInfoPrunedFAFW(modelFsm, Swin, 0, 1); 02261 /* The LFP loop */ 02262 while (!term_fixpoint && !term_tautology && !term_early) { 02263 /* If dclevel is maximal, ringbdd is between the frontier and the 02264 reached set */ 02265 aMdd = Img_ImageInfoComputeImageWithDomainVars(imageInfo, 02266 ringMdd, ringMdd, careStatesArray); 02267 mdd_free(ringMdd); 02268 02269 bMdd = mdd_and(aMdd, invariantMdd, 1, 1); 02270 mdd_free(aMdd); 02271 02272 cMdd = mdd_or(resultMdd, bMdd, 1, 1); 02273 mdd_free(bMdd); 02274 02275 /* Can we stop? The tautology condition can be weakened to 02276 cMdd <= careStatesArray */ 02277 term_fixpoint = mdd_equal_mod_care_set_array(cMdd, resultMdd, 02278 careStatesArray); 02279 if(!term_fixpoint) 02280 term_tautology = mdd_is_tautology(cMdd, 1); 02281 if(!term_fixpoint && !term_tautology) 02282 term_early = McCheckEarlyTerminationForUnderapprox(earlyTermination, 02283 cMdd, 02284 careStatesArray); 02285 02286 /* Print some debug info, and set ringmdd */ 02287 if (dcLevel >= McDcLevelRchFrontier_c) { 02288 mdd_t *tmpMdd = mdd_and(resultMdd, cMdd, 0, 1); 02289 ringMdd = bdd_between(tmpMdd, cMdd); 02290 if (verbosity == McVerbosityMax_c) { 02291 fprintf(vis_stdout, 02292 "--ES |A(n+1)-A(n)|= %d\t|A(n+1)| = %d\t|between-dc| = %d\n", 02293 mdd_size(tmpMdd), mdd_size(resultMdd), mdd_size(ringMdd)); 02294 } 02295 mdd_free(tmpMdd); 02296 } 02297 else { 02298 ringMdd = mdd_dup(cMdd); 02299 if (verbosity == McVerbosityMax_c) { 02300 fprintf(vis_stdout, "-- ES |ringMdd| = %d\n", mdd_size(ringMdd)); 02301 } 02302 } 02303 02304 mdd_free(resultMdd); 02305 resultMdd = cMdd; 02306 /* add onion ring unless fixpoint reached */ 02307 if (!term_fixpoint && onionRings != NIL(array_t)) { 02308 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 02309 } 02310 } /* while(!termination) for LFP */ 02311 02312 /* Img_ImageInfoRecoverFromWinningStrategy(modelFsm, Img_Forward_c); */ 02313 Img_ImageInfoFreeFAFW(imageInfo); 02314 Img_ImageInfoFree(imageInfo); 02315 02316 mdd_free(ringMdd); 02317 02318 /* Print some debug info */ 02319 if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) { 02320 static int refCount=0; 02321 mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm); 02322 array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm); 02323 02324 if (verbosity == McVerbosityMax_c) { 02325 mdd_t *tmpMdd = careStatesArray ? 02326 mdd_and_array(resultMdd, careStatesArray, 1, 1) : 02327 mdd_dup(resultMdd); 02328 fprintf(vis_stdout, "--ES called %d (bdd_size - %d)\n", ++refCount, 02329 mdd_size(resultMdd)); 02330 fprintf(vis_stdout, 02331 "--There are %.0f care states satisfying ES formula\n", 02332 mdd_count_onset(mddMgr, tmpMdd, psVars)); 02333 #ifdef DEBUG_MC 02334 /* The following 2 lines are just for debug */ 02335 fprintf(vis_stdout, "ES satisfying minterms :\n"); 02336 (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm); 02337 #endif 02338 mdd_free(tmpMdd); 02339 } else { 02340 fprintf(vis_stdout, 02341 "--There are %.0f states satisfying ES formula\n", 02342 mdd_count_onset(mddMgr, resultMdd, psVars)); 02343 } 02344 02345 fprintf(vis_stdout, "--ES: %d image computations\n", 02346 Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps); 02347 } 02348 02349 if(fixpoint != NIL(boolean)) 02350 *fixpoint = term_fixpoint || term_tautology; 02351 return resultMdd; 02352 02353 } /* McEvaluateESFormulaWithGivenTR */ 02354 02355 02367 mdd_t * 02368 McEvaluateAUFormulaWithGivenTR( 02369 Fsm_Fsm_t *modelFsm, 02370 mdd_t *invariantMdd, 02371 mdd_t *targetMdd, 02372 mdd_t *underapprox, 02373 mdd_t *fairStates, 02374 array_t *careStatesArray, 02375 Mc_EarlyTermination_t *earlyTermination, 02376 array_t *onionRings, 02377 Mc_VerbosityLevel verbosity, 02378 Mc_DcLevel dcLevel, 02379 boolean *fixpoint 02380 ) 02381 { 02382 mdd_t *aMdd; 02383 mdd_t *bMdd; 02384 mdd_t *cMdd; 02385 mdd_t *resultMdd; 02386 mdd_t *ringMdd; 02387 boolean term_tautology = FALSE; /* different termination conditions */ 02388 boolean term_early = FALSE; 02389 boolean term_fixpoint = FALSE; 02390 02391 resultMdd = mdd_and(targetMdd, fairStates, 1, 1); 02392 02393 ringMdd = mdd_dup(resultMdd); 02394 if (onionRings) { 02395 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 02396 } 02397 /* The LFP loop */ 02398 while (!term_fixpoint && !term_tautology && !term_early) { 02399 /* If dclevel is maximal, ringbdd is between the frontier and the 02400 reached set */ 02401 aMdd = Mc_FsmEvaluateMXFormula(modelFsm, ringMdd, fairStates, 02402 careStatesArray, verbosity, dcLevel); 02403 02404 bMdd = mdd_and(aMdd, invariantMdd, 1, 1); 02405 mdd_free(aMdd); 02406 02407 cMdd = mdd_or(resultMdd, bMdd, 1, 1); 02408 mdd_free(bMdd); 02409 mdd_free(ringMdd); 02410 02411 /* Can we stop? The tautology condition can be weakened to 02412 cMdd <= careStatesArray */ 02413 term_fixpoint = mdd_equal_mod_care_set_array(cMdd, resultMdd, 02414 careStatesArray); 02415 if(!term_fixpoint) 02416 term_tautology = mdd_is_tautology(cMdd, 1); 02417 if(!term_fixpoint && !term_tautology) 02418 term_early = McCheckEarlyTerminationForUnderapprox(earlyTermination, 02419 cMdd, 02420 careStatesArray); 02421 02422 /* Print some debug info, and set ringmdd */ 02423 if (dcLevel >= McDcLevelRchFrontier_c) { 02424 mdd_t *tmpMdd = mdd_and(resultMdd, cMdd, 0, 1); 02425 ringMdd = bdd_between(tmpMdd, cMdd); 02426 if (verbosity == McVerbosityMax_c) { 02427 fprintf(vis_stdout, 02428 "--AU |A(n+1)-A(n)|= %d\t|A(n+1)| = %d\t|between-dc| = %d\n", 02429 mdd_size(tmpMdd), mdd_size(resultMdd), mdd_size(ringMdd)); 02430 } 02431 mdd_free(tmpMdd); 02432 } 02433 else { 02434 ringMdd = mdd_dup(cMdd); 02435 if (verbosity == McVerbosityMax_c) { 02436 fprintf(vis_stdout, "-- AU |ringMdd| = %d\n", mdd_size(ringMdd)); 02437 } 02438 } 02439 02440 mdd_free(resultMdd); 02441 resultMdd = cMdd; 02442 /* add onion ring unless fixpoint reached */ 02443 if (!term_fixpoint && onionRings) { 02444 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 02445 } 02446 } /* while(!termination) for LFP */ 02447 02448 mdd_free(ringMdd); 02449 02450 02451 if(fixpoint != NIL(boolean)) 02452 *fixpoint = term_fixpoint || term_tautology; 02453 return resultMdd; 02454 } 02455 02456 02469 mdd_t * 02470 McEvaluateEGFormulaWithGivenTR( 02471 Fsm_Fsm_t *modelFsm, 02472 mdd_t *invariantMdd, 02473 mdd_t *overapprox, 02474 mdd_t *fairStates, 02475 Fsm_Fairness_t *modelFairness, 02476 array_t *careStatesArray, 02477 Mc_EarlyTermination_t *earlyTermination, 02478 array_t **pOnionRingsArrayForDbg, 02479 Mc_VerbosityLevel verbosity, 02480 Mc_DcLevel dcLevel, 02481 boolean *fixpoint) 02482 { 02483 int i; 02484 array_t *onionRings; 02485 boolean useRings; 02486 mdd_manager *mddManager; 02487 mdd_t *mddOne; 02488 mdd_t *iterate; 02489 array_t *buchiFairness; 02490 int nPreComps; 02491 int nIterations; 02492 boolean term_fixpoint = FALSE; /* different termination conditions */ 02493 boolean term_tautology = FALSE; 02494 boolean term_early = FALSE; 02495 02496 /* Here's how the onionRingsArrayForDbg works. It is an array of 02497 arrays of mdds. It is filled in anew for every pass of the 02498 algorithm, that is for every /\_{c inC} EXE(Y U Y*c). There is 02499 one entry for every fairness constraint, and this entry contains 02500 the onionrings of the EU computation that corresponds to this 02501 constraint. */ 02502 assert(pOnionRingsArrayForDbg == NIL(array_t *) || 02503 *pOnionRingsArrayForDbg == NIL(array_t) || 02504 array_n(*pOnionRingsArrayForDbg) == 0); 02505 02506 useRings = (pOnionRingsArrayForDbg != NIL(array_t *) && 02507 *pOnionRingsArrayForDbg != NIL(array_t)); 02508 02509 nIterations = 0; 02510 nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c); 02511 onionRings = NIL(array_t); 02512 mddManager = Fsm_FsmReadMddManager(modelFsm); 02513 mddOne = mdd_one(mddManager); 02514 02515 /* If an overapproximation of the greatest fixpoint is given, use it. */ 02516 if(overapprox != NIL(mdd_t)){ 02517 iterate = mdd_and(invariantMdd, overapprox, 1, 1); 02518 } else { 02519 iterate = mdd_dup(invariantMdd); 02520 } 02521 02522 /* See if we need to enter the loop at all. If we wanted to test for 02523 * early termination here, we should fix the onion rings. In the current 02524 * case, we do not need to, since the EG does not hold, and hence a 02525 * counterexample does not exist. 02526 */ 02527 if( mdd_is_tautology(iterate, 0)){ 02528 mdd_free(mddOne); 02529 if(fixpoint != NIL(boolean)) *fixpoint = mdd_is_tautology(iterate, 0); 02530 return(iterate); 02531 } 02532 02533 /* read fairness constraints */ 02534 buchiFairness = array_alloc(mdd_t *, 0); 02535 if(modelFairness != NIL(Fsm_Fairness_t)) { 02536 if(!Fsm_FairnessTestIsBuchi(modelFairness)) { 02537 (void)fprintf(vis_stdout, 02538 "** mc error: non-Buechi fairness constraints not supported\n"); 02539 array_free(buchiFairness); 02540 mdd_free(iterate); 02541 mdd_free(mddOne); 02542 02543 if(fixpoint != NIL(boolean)) *fixpoint = FALSE; 02544 return NIL(mdd_t); 02545 } 02546 else { 02547 int j; 02548 int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0); 02549 for (j = 0 ; j < numBuchi; j++) { 02550 mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j, 02551 careStatesArray, dcLevel); 02552 array_insert_last(mdd_t *, buchiFairness, tmpMdd); 02553 } 02554 } 02555 } 02556 else { 02557 array_insert_last(mdd_t *, buchiFairness, mdd_one(mddManager)); 02558 } 02559 02560 02561 /* GFP. If we know that the result is a subset of a set S, we can conjoin 02562 the iterate with that set. We use this to converge faster. */ 02563 while (TRUE) { 02564 mdd_t *newIterate; /* the new iterate */ 02565 02566 nIterations++; 02567 newIterate = mdd_dup(iterate); 02568 02569 /* for all fairness constraints */ 02570 for (i = 0 ; i < array_n(buchiFairness) ; i++) { 02571 mdd_t *aMdd, *bMdd, *cMdd, *dMdd; 02572 mdd_t *FiMdd = array_fetch(mdd_t *, buchiFairness, i); 02573 02574 if(useRings) { 02575 onionRings = array_alloc(mdd_t *, 0); 02576 array_insert_last(array_t *, *pOnionRingsArrayForDbg, onionRings); 02577 } 02578 02579 aMdd = mdd_and(FiMdd, newIterate, 1, 1); 02580 02581 bMdd = Mc_FsmEvaluateEUFormula(modelFsm, newIterate, aMdd, NIL(mdd_t), 02582 mddOne, careStatesArray, 02583 MC_NO_EARLY_TERMINATION, NIL(array_t), 02584 Mc_None_c, onionRings, verbosity, dcLevel, 02585 NIL(boolean)); 02586 mdd_free(aMdd); 02587 cMdd = Mc_FsmEvaluateEXFormula(modelFsm, bMdd, mddOne, careStatesArray, 02588 verbosity, dcLevel); 02589 mdd_free(bMdd); 02590 02591 dMdd = mdd_and(newIterate, cMdd, 1, 1); 02592 02593 mdd_free(cMdd); 02594 mdd_free(newIterate); 02595 newIterate = dMdd; 02596 02597 /* invariants that hold here: newiterate <= iterate <= invariant. */ 02598 }/* for all fairness constraints */ 02599 02600 /* termination */ 02601 term_tautology = mdd_is_tautology(newIterate, 0); 02602 if(!term_tautology) 02603 term_fixpoint = mdd_equal_mod_care_set_array(newIterate, iterate, 02604 careStatesArray); 02605 if(!term_tautology && !term_fixpoint) 02606 term_early = McCheckEarlyTerminationForOverapprox(earlyTermination, 02607 newIterate, 02608 careStatesArray); 02609 if(term_tautology || term_fixpoint || term_early){ 02610 mdd_free(iterate); 02611 iterate = newIterate; 02612 break; /* from the GFP loop */ 02613 } 02614 02615 /* update iterate */ 02616 mdd_free(iterate); 02617 iterate = newIterate; 02618 02619 if(useRings){ 02620 mdd_array_array_free(*pOnionRingsArrayForDbg); 02621 *pOnionRingsArrayForDbg = array_alloc(array_t *, 0); 02622 } 02623 } /* while(true) for gfp */ 02624 02625 /* Check if onionrings are OK */ 02626 if(verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) { 02627 if(useRings){ 02628 for (i = 0 ; i < array_n(*pOnionRingsArrayForDbg); i++) { 02629 int j; 02630 mdd_t *Fi = array_fetch(mdd_t *, buchiFairness, i); 02631 array_t *onionRings = array_fetch(array_t *, *pOnionRingsArrayForDbg, 02632 i); 02633 for (j = 0 ; j < array_n(onionRings); j++) { 02634 mdd_t *ring = array_fetch(mdd_t *, onionRings, j); 02635 if(j == 0) { 02636 if(!mdd_lequal_mod_care_set_array(ring, Fi, 1, 1, 02637 careStatesArray)) { 02638 fprintf(vis_stderr, "** mc error: Problem w/ dbg in EG - "); 02639 fprintf(vis_stderr, 02640 "inner most ring not in Fi (fairness constraint).\n"); 02641 } 02642 } 02643 if(!mdd_lequal_mod_care_set_array(ring, invariantMdd, 1, 1, 02644 careStatesArray)) { 02645 fprintf(vis_stderr, "** mc error: Problem w/ dbg in EG - "); 02646 fprintf(vis_stderr, "An onion ring of last EU fails invariant\n"); 02647 } 02648 } /* for all onionrings in array i */ 02649 } /* for all onionringarrays in onionringsarray */ 02650 }/* if useRings */ 02651 02652 if(verbosity == McVerbosityMax_c) { 02653 mdd_t *tmpMdd = careStatesArray ? 02654 mdd_and_array(iterate, careStatesArray, 1, 1) : mdd_dup(iterate); 02655 fprintf(vis_stdout, 02656 "--There are %.0f care states satisfying EG formula\n", 02657 mdd_count_onset(Fsm_FsmReadMddManager(modelFsm), tmpMdd, 02658 Fsm_FsmReadPresentStateVars(modelFsm))); 02659 #ifdef DEBUG_MC 02660 /* The following 2 lines are just for debug */ 02661 fprintf(vis_stdout, "EG satisfying minterms :\n"); 02662 (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm); 02663 #endif 02664 mdd_free(tmpMdd); 02665 } else { 02666 fprintf(vis_stdout, "--There are %.0f states satisfying EG formula\n", 02667 mdd_count_onset(Fsm_FsmReadMddManager(modelFsm), iterate, 02668 Fsm_FsmReadPresentStateVars(modelFsm))); 02669 } 02670 02671 fprintf(vis_stdout, "--EG: %d iterations, %d preimage computations\n", 02672 nIterations, Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps); 02673 } 02674 02675 mdd_array_free(buchiFairness); 02676 mdd_free(mddOne); 02677 02678 if(fixpoint != NIL(boolean)) 02679 *fixpoint = term_fixpoint || term_tautology; 02680 return iterate; 02681 02682 } /* McEvaluateEGFormulaWithGivenTR */ 02683 02684 02697 mdd_t * 02698 McEvaluateEHFormulaWithGivenTR( 02699 Fsm_Fsm_t *modelFsm, 02700 mdd_t *invariantMdd, 02701 mdd_t *overapprox, 02702 mdd_t *fairStates, 02703 Fsm_Fairness_t *modelFairness, 02704 array_t *careStatesArray, 02705 Mc_EarlyTermination_t *earlyTermination, 02706 array_t **pOnionRingsArrayForDbg, 02707 Mc_VerbosityLevel verbosity, 02708 Mc_DcLevel dcLevel, 02709 boolean *fixpoint) 02710 { 02711 int i; 02712 array_t *onionRings; 02713 boolean useRings; 02714 mdd_manager *mddManager; 02715 mdd_t *mddOne; 02716 mdd_t *iterate; 02717 array_t *buchiFairness; 02718 int nImgComps; 02719 int nIterations; 02720 boolean term_fixpoint = FALSE; /* different termination conditions */ 02721 boolean term_tautology = FALSE; 02722 boolean term_early = FALSE; 02723 02724 /* Here's how the onionRingsArrayForDbg works. It is an array of 02725 arrays of mdds. It is filled in anew for every pass of the 02726 algorithm, that is for every /\_{c inC} EYE(Y S Y*c). There is 02727 one entry for every fairness constraint, and this entry contains 02728 the onionrings of the ES computation that corresponds to this 02729 constraint. */ 02730 assert(pOnionRingsArrayForDbg == NIL(array_t *) || 02731 *pOnionRingsArrayForDbg == NIL(array_t) || 02732 array_n(*pOnionRingsArrayForDbg) == 0); 02733 02734 useRings = (pOnionRingsArrayForDbg != NIL(array_t *) && 02735 *pOnionRingsArrayForDbg != NIL(array_t)); 02736 02737 nIterations = 0; 02738 nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c); 02739 onionRings = NIL(array_t); 02740 mddManager = Fsm_FsmReadMddManager(modelFsm); 02741 mddOne = mdd_one(mddManager); 02742 02743 /* If an overapproxiamtion of the greatest fixpoint is given, use it. */ 02744 if(overapprox != NIL(mdd_t)){ 02745 iterate = mdd_and(invariantMdd, overapprox, 1, 1); 02746 } else { 02747 iterate = mdd_dup(invariantMdd); 02748 } 02749 02750 /* See if we need to enter the loop at all */ 02751 if( mdd_is_tautology(iterate, 0) || 02752 McCheckEarlyTerminationForOverapprox(earlyTermination, 02753 iterate, 02754 careStatesArray)){ 02755 mdd_free(mddOne); 02756 02757 if(fixpoint != NIL(boolean)) *fixpoint = mdd_is_tautology(iterate, 0); 02758 return(iterate); 02759 } 02760 02761 /* read fairness constraints */ 02762 buchiFairness = array_alloc(mdd_t *, 0); 02763 if(modelFairness != NIL(Fsm_Fairness_t)) { 02764 if(!Fsm_FairnessTestIsBuchi(modelFairness)) { 02765 (void)fprintf(vis_stdout, 02766 "** mc error: non-Buechi fairness constraints not supported\n"); 02767 array_free(buchiFairness); 02768 mdd_free(iterate); 02769 mdd_free(mddOne); 02770 02771 if(fixpoint != NIL(boolean)) *fixpoint = FALSE; 02772 return NIL(mdd_t); 02773 } 02774 else { 02775 int j; 02776 int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0); 02777 for (j = 0 ; j < numBuchi; j++) { 02778 mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j, 02779 careStatesArray, dcLevel); 02780 array_insert_last(mdd_t *, buchiFairness, tmpMdd); 02781 } 02782 } 02783 } 02784 else { 02785 array_insert_last(mdd_t *, buchiFairness, mdd_one(mddManager)); 02786 } 02787 02788 02789 /* GFP. If we know that the result is a subset of a set S, we can conjoin 02790 the iterate with that set. We use this to converge faster. */ 02791 while (TRUE) { 02792 mdd_t *newIterate; /* the new iterate */ 02793 02794 nIterations++; 02795 newIterate = mdd_dup(iterate); 02796 02797 /* for all fairness constraints */ 02798 for (i = 0 ; i < array_n(buchiFairness) ; i++) { 02799 mdd_t *aMdd, *bMdd, *cMdd, *dMdd; 02800 mdd_t *FiMdd = array_fetch(mdd_t *, buchiFairness, i); 02801 02802 if(useRings) { 02803 onionRings = array_alloc(mdd_t *, 0); 02804 array_insert_last(array_t *, *pOnionRingsArrayForDbg, onionRings); 02805 } 02806 02807 aMdd = mdd_and(FiMdd, newIterate, 1, 1); 02808 02809 bMdd = Mc_FsmEvaluateESFormula(modelFsm, newIterate, aMdd, NIL(mdd_t), 02810 mddOne, careStatesArray, 02811 MC_NO_EARLY_TERMINATION, NIL(array_t), 02812 Mc_None_c, onionRings, verbosity, dcLevel, 02813 NIL(boolean)); 02814 mdd_free(aMdd); 02815 cMdd = Mc_FsmEvaluateEYFormula(modelFsm, bMdd, mddOne, careStatesArray, 02816 verbosity, dcLevel); 02817 mdd_free(bMdd); 02818 02819 dMdd = mdd_and(newIterate, cMdd, 1, 1); 02820 02821 mdd_free(cMdd); 02822 mdd_free(newIterate); 02823 newIterate = dMdd; 02824 02825 /* invariants that hold here: newiterate <= iterate <= invariant. */ 02826 }/* for all fairness constraints */ 02827 02828 /* termination */ 02829 term_tautology = mdd_is_tautology(newIterate, 0); 02830 if(!term_tautology) 02831 term_fixpoint = mdd_equal_mod_care_set_array(newIterate, iterate, 02832 careStatesArray); 02833 if(!term_tautology && !term_fixpoint) 02834 term_early = McCheckEarlyTerminationForOverapprox(earlyTermination, 02835 newIterate, 02836 careStatesArray); 02837 if(term_tautology || term_fixpoint || term_early){ 02838 mdd_free(iterate); 02839 iterate = newIterate; 02840 break; /* from the GFP loop */ 02841 } 02842 02843 /* update iterate */ 02844 mdd_free(iterate); 02845 iterate = newIterate; 02846 02847 if(useRings){ 02848 mdd_array_array_free(*pOnionRingsArrayForDbg); 02849 *pOnionRingsArrayForDbg = array_alloc(array_t *, 0); 02850 } 02851 } /* while(true) for gfp */ 02852 02853 /* Check if onionrings are OK */ 02854 if(verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) { 02855 if(useRings){ 02856 for (i = 0 ; i < array_n(*pOnionRingsArrayForDbg); i++) { 02857 int j; 02858 mdd_t *Fi = array_fetch(mdd_t *, buchiFairness, i); 02859 array_t *onionRings = array_fetch(array_t *, *pOnionRingsArrayForDbg, 02860 i); 02861 for (j = 0 ; j < array_n(onionRings); j++) { 02862 mdd_t *ring = array_fetch(mdd_t *, onionRings, j); 02863 if(j == 0) { 02864 if(!mdd_lequal_mod_care_set_array(ring, Fi, 1, 1, 02865 careStatesArray)) { 02866 fprintf(vis_stderr, "** mc error: Problem w/ dbg in EH - "); 02867 fprintf(vis_stderr, 02868 "inner most ring not in Fi (fairness constraint).\n"); 02869 } 02870 } 02871 if(!mdd_lequal_mod_care_set_array(ring, invariantMdd, 1, 1, 02872 careStatesArray)) { 02873 fprintf(vis_stderr, "** mc error: Problem w/ dbg in EH - "); 02874 fprintf(vis_stderr, "An onion ring of last ES fails invariant\n"); 02875 } 02876 } /* for all onionrings in array i */ 02877 } /* for all onionringarrays in onionringsarray */ 02878 }/* if useRings */ 02879 02880 if(verbosity == McVerbosityMax_c) { 02881 mdd_t *tmpMdd = careStatesArray ? 02882 mdd_and_array(iterate, careStatesArray, 1, 1) : mdd_dup(iterate); 02883 fprintf(vis_stdout, 02884 "--There are %.0f care states satisfying EH formula\n", 02885 mdd_count_onset(Fsm_FsmReadMddManager(modelFsm), tmpMdd, 02886 Fsm_FsmReadPresentStateVars(modelFsm))); 02887 #ifdef DEBUG_MC 02888 /* The following 2 lines are just for debug */ 02889 fprintf(vis_stdout, "EH satisfying minterms :\n"); 02890 (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm); 02891 #endif 02892 mdd_free(tmpMdd); 02893 } else { 02894 fprintf(vis_stdout, "--There are %.0f states satisfying EH formula\n", 02895 mdd_count_onset(Fsm_FsmReadMddManager(modelFsm), iterate, 02896 Fsm_FsmReadPresentStateVars(modelFsm))); 02897 } 02898 02899 fprintf(vis_stdout, "--EH: %d iterations, %d image computations\n", 02900 nIterations, Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps); 02901 } 02902 02903 mdd_array_free(buchiFairness); 02904 mdd_free(mddOne); 02905 02906 if(fixpoint != NIL(boolean)) 02907 *fixpoint = term_fixpoint || term_tautology; 02908 return iterate; 02909 02910 } /* McEvaluateEHFormulaWithGivenTR */ 02911 02912 02924 void 02925 McFormulaFreeDebugData( 02926 Ctlp_Formula_t *formula) 02927 { 02928 Ctlp_FormulaType type = Ctlp_FormulaReadType(formula); 02929 array_t *dbgArray = (array_t *) Ctlp_FormulaReadDebugData(formula); 02930 02931 if (type == Ctlp_EU_c || type == Ctlp_FwdU_c) { 02932 mdd_array_free(dbgArray); 02933 } 02934 else if (type == Ctlp_EG_c || type == Ctlp_FwdG_c || type == Ctlp_EH_c) 02935 mdd_array_array_free(dbgArray); 02936 else { 02937 fail("Error - called on non EG/EU formula.\n"); 02938 } 02939 } 02940 02941 02951 void 02952 _McPrintSatisfyingMinterms(mdd_t *aMdd, Fsm_Fsm_t *fsm) 02953 { 02954 array_t *support = Fsm_FsmReadPresentStateVars(fsm); 02955 mdd_manager *mddMgr = Fsm_FsmReadMddManager(fsm); 02956 Ntk_Network_t *network = Fsm_FsmReadNetwork(fsm); 02957 int i, n; 02958 array_t *mintermArray; 02959 mdd_t *aMinterm; 02960 02961 n = (int) mdd_count_onset(mddMgr, aMdd, support); 02962 mintermArray = mdd_pick_arbitrary_minterms(mddMgr, aMdd, support, n); 02963 02964 for (i = 0; i < n; i++) { 02965 aMinterm = array_fetch(mdd_t *, mintermArray, i); 02966 Mc_MintermPrint(aMinterm, support, network); 02967 mdd_free(aMinterm); 02968 } 02969 02970 array_free(mintermArray); 02971 02972 } 02973 02984 boolean 02985 McPrintPassFail( 02986 mdd_manager *mddMgr, 02987 Fsm_Fsm_t *modelFsm, 02988 Mc_FwdBwdAnalysis traversalDirection, 02989 Ctlp_Formula_t *ctlFormula, 02990 mdd_t *ctlFormulaStates, 02991 mdd_t *modelInitialStates, 02992 array_t *modelCareStatesArray, 02993 McOptions_t *options, 02994 Mc_VerbosityLevel verbosity) 02995 { 02996 if (mdd_lequal(modelInitialStates, ctlFormulaStates, 1, 1)) { 02997 fprintf(vis_stdout, "# MC: formula passed --- "); 02998 Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(ctlFormula)); 02999 fprintf(vis_stdout, "\n"); 03000 return TRUE; 03001 } 03002 else { 03003 fprintf(vis_stdout, "# MC: formula failed --- "); 03004 Ctlp_FormulaPrint(vis_stdout, Ctlp_FormulaReadOriginalFormula(ctlFormula)); 03005 fprintf(vis_stdout, "\n"); 03006 if (McOptionsReadDbgLevel(options) != McDbgLevelNone_c) { 03007 McFsmDebugFormula(options, ctlFormula,modelFsm, modelCareStatesArray); 03008 } 03009 return FALSE; 03010 } 03011 } 03012 03013 03026 mdd_t * 03027 McModelCheckAtomicFormula( 03028 Fsm_Fsm_t *modelFsm, 03029 Ctlp_Formula_t *ctlFormula) 03030 { 03031 mdd_t * resultMdd; 03032 mdd_t *tmpMdd; 03033 Ntk_Network_t *network = Fsm_FsmReadNetwork(modelFsm); 03034 char *nodeNameString = Ctlp_FormulaReadVariableName(ctlFormula); 03035 char *nodeValueString = Ctlp_FormulaReadValueName(ctlFormula); 03036 Ntk_Node_t *node = Ntk_NetworkFindNodeByName(network, nodeNameString); 03037 03038 Var_Variable_t *nodeVar; 03039 int nodeValue; 03040 03041 graph_t *modelPartition; 03042 vertex_t *partitionVertex; 03043 Mvf_Function_t *MVF; 03044 03045 nodeVar = Ntk_NodeReadVariable(node); 03046 if (Var_VariableTestIsSymbolic(nodeVar)) { 03047 nodeValue = Var_VariableReadIndexFromSymbolicValue(nodeVar, nodeValueString); 03048 } 03049 else { 03050 nodeValue = atoi(nodeValueString); 03051 } 03052 03053 #if 0 03054 modelPartition = Part_NetworkReadPartition(network); 03055 #endif 03056 modelPartition = Fsm_FsmReadPartition(modelFsm); 03057 if (!(partitionVertex = Part_PartitionFindVertexByName(modelPartition, 03058 nodeNameString))) { 03059 lsGen tmpGen; 03060 Ntk_Node_t *tmpNode; 03061 array_t *mvfArray; 03062 array_t *tmpRoots = array_alloc(Ntk_Node_t *, 0); 03063 st_table *tmpLeaves = st_init_table(st_ptrcmp, st_ptrhash); 03064 array_insert_last(Ntk_Node_t *, tmpRoots, node); 03065 03066 Ntk_NetworkForEachCombInput(network, tmpGen, tmpNode) { 03067 st_insert(tmpLeaves, (char *) tmpNode, (char *) NTM_UNUSED); 03068 } 03069 03070 mvfArray = Ntm_NetworkBuildMvfs(network, tmpRoots, tmpLeaves, 03071 NIL(mdd_t)); 03072 MVF = array_fetch(Mvf_Function_t *, mvfArray, 0); 03073 array_free(tmpRoots); 03074 st_free_table(tmpLeaves); 03075 array_free(mvfArray); 03076 03077 tmpMdd = Mvf_FunctionReadComponent(MVF, nodeValue); 03078 resultMdd = mdd_dup(tmpMdd); 03079 Mvf_FunctionFree(MVF); 03080 } 03081 else { 03082 MVF = Part_VertexReadFunction(partitionVertex); 03083 tmpMdd = Mvf_FunctionReadComponent(MVF, nodeValue); 03084 resultMdd = mdd_dup(tmpMdd); 03085 } 03086 if (Part_PartitionReadMethod(modelPartition) == Part_Frontier_c && 03087 Ntk_NodeTestIsCombOutput(node)) { 03088 array_t *psVars = Fsm_FsmReadPresentStateVars(modelFsm); 03089 mdd_manager *mgr = Ntk_NetworkReadMddManager(Fsm_FsmReadNetwork(modelFsm)); 03090 array_t *supportList; 03091 st_table *supportTable = st_init_table(st_numcmp, st_numhash); 03092 int i, j; 03093 int existIntermediateVars; 03094 int mddId; 03095 Mvf_Function_t *mvf; 03096 vertex_t *vertex; 03097 array_t *varBddRelationArray, *varArray; 03098 mdd_t *iv, *ivMdd, *relation; 03099 03100 for (i = 0; i < array_n(psVars); i++) { 03101 mddId = array_fetch(int, psVars, i); 03102 st_insert(supportTable, (char *)(long)mddId, NULL); 03103 } 03104 03105 existIntermediateVars = 1; 03106 while (existIntermediateVars) { 03107 existIntermediateVars = 0; 03108 supportList = mdd_get_support(mgr, resultMdd); 03109 for (i = 0; i < array_n(supportList); i++) { 03110 mddId = array_fetch(int, supportList, i); 03111 if (!st_lookup(supportTable, (char *)(long)mddId, NULL)) { 03112 vertex = Part_PartitionFindVertexByMddId(modelPartition, mddId); 03113 mvf = Part_VertexReadFunction(vertex); 03114 varBddRelationArray = mdd_fn_array_to_bdd_rel_array(mgr, mddId, mvf); 03115 varArray = mdd_id_to_bdd_array(mgr, mddId); 03116 assert(array_n(varBddRelationArray) == array_n(varArray)); 03117 for (j = 0; j < array_n(varBddRelationArray); j++) { 03118 iv = array_fetch(mdd_t *, varArray, j); 03119 relation = array_fetch(mdd_t *, varBddRelationArray, j); 03120 ivMdd = bdd_cofactor(relation, iv); 03121 mdd_free(relation); 03122 tmpMdd = resultMdd; 03123 resultMdd = bdd_compose(resultMdd, iv, ivMdd); 03124 mdd_free(tmpMdd); 03125 mdd_free(iv); 03126 mdd_free(ivMdd); 03127 } 03128 array_free(varBddRelationArray); 03129 array_free(varArray); 03130 existIntermediateVars = 1; 03131 } 03132 } 03133 array_free(supportList); 03134 } 03135 st_free_table(supportTable); 03136 } 03137 return resultMdd; 03138 } /* McModelCheckAtomicFormula */ 03139 03140 03155 void 03156 InvarPrintDebugInformation(Fsm_Fsm_t *modelFsm, 03157 array_t *invarFormulaArray, 03158 array_t *invarStatesArray, 03159 int *resultArray, 03160 McOptions_t *options, 03161 array_t *hintsStatesArray) 03162 { 03163 FILE *debugFile = McOptionsReadDebugFile(options); 03164 FILE *tmpFile = vis_stdout; 03165 extern FILE *vis_stdpipe; 03166 mdd_t *outerOnionRing=NIL(mdd_t); 03167 mdd_t *reachableBadStates; 03168 mdd_t *aBadReachableState, *reachableStates; 03169 array_t *aPath; 03170 boolean computeReach = TRUE; 03171 int ringsUpToDate; 03172 array_t *onionRings=NIL(array_t); 03173 int i, j; 03174 Fsm_RchType_t approxFlag; 03175 Ctlp_Formula_t *invarFormula; 03176 mdd_t *invarFormulaStates; 03177 approxFlag = McOptionsReadInvarApproxFlag(options); 03178 03179 if (debugFile) 03180 vis_stdpipe = debugFile; 03181 else if (McOptionsReadUseMore(options) == TRUE) 03182 vis_stdpipe = popen("more", "w"); 03183 else 03184 vis_stdpipe = vis_stdout; 03185 vis_stdout = vis_stdpipe; 03186 03187 arrayForEachItem(mdd_t *, invarStatesArray, i, invarFormulaStates) { 03188 if ((invarFormulaStates == NIL(mdd_t)) || (resultArray[i] == 1)) 03189 continue; 03190 onionRings = Fsm_FsmReadReachabilityOnionRings(modelFsm); 03191 ringsUpToDate = Fsm_FsmTestReachabilityOnionRingsUpToDate(modelFsm); 03192 /* search for onion ring intersecting invarStates' */ 03193 if (onionRings != NIL(array_t)) { 03194 for (j = 0; j < array_n(onionRings); j++) { 03195 outerOnionRing = array_fetch(mdd_t *, onionRings, j); 03196 if (!mdd_lequal(outerOnionRing, invarFormulaStates, 1, 1)) { 03197 computeReach = FALSE; 03198 break; 03199 } 03200 } 03201 } 03202 03203 /* no onion ring found, hence recompute with onion rings */ 03204 if (computeReach == TRUE) { 03205 Mc_VerbosityLevel verbosity; 03206 int debugFlag; 03207 int ardc; 03208 int dcLevel = McOptionsReadDcLevel(options); 03209 verbosity = McOptionsReadVerbosityLevel(options); 03210 debugFlag = (McOptionsReadDbgLevel(options) != McDbgLevelNone_c); 03211 if (dcLevel == McDcLevelArdc_c) 03212 ardc = 1; 03213 else 03214 ardc = 0; 03215 assert(!ringsUpToDate); 03216 reachableStates = Fsm_FsmComputeReachableStates( 03217 modelFsm, 0, (int)verbosity , 0, 0, debugFlag, 0, 0, approxFlag, ardc, 03218 0, invarStatesArray, (verbosity > 1), hintsStatesArray); 03219 mdd_free(reachableStates); 03220 /* find the onion ring with invariant failure */ 03221 onionRings = Fsm_FsmReadReachabilityOnionRings(modelFsm); 03222 if (onionRings == NIL(array_t)) { 03223 fprintf(vis_stdout, "Unable to generate onion rings for counterexample.\n"); 03224 fprintf(vis_stdout, "Try again with standard (without -A) options.\n"); 03225 if (vis_stdout != tmpFile && vis_stdout != debugFile) 03226 (void)pclose(vis_stdpipe); 03227 vis_stdout = tmpFile; 03228 return; 03229 } 03230 ringsUpToDate = Fsm_FsmTestReachabilityOnionRingsUpToDate(modelFsm); 03231 for (j = 0; j < array_n(onionRings); j++) { 03232 outerOnionRing = array_fetch(mdd_t *, onionRings, j); 03233 if (!mdd_lequal(outerOnionRing, invarFormulaStates, 1, 1)) { 03234 break; 03235 } 03236 } 03237 } 03238 invarFormula = array_fetch(Ctlp_Formula_t *, invarFormulaArray, i); 03239 /* this is the case of true negative */ 03240 if (outerOnionRing != NIL(mdd_t)) { 03241 /* compute the set of bad states */ 03242 if(Fsm_FsmReadFAFWFlag(modelFsm) > 1 && McOptionsReadInvarApproxFlag(options) == Fsm_Rch_Bfs_c) 03243 reachableBadStates = mdd_not(invarFormulaStates); 03244 else 03245 reachableBadStates = mdd_and(invarFormulaStates, outerOnionRing, 0, 1); 03246 /* pick one bad state */ 03247 aBadReachableState = Mc_ComputeAState(reachableBadStates, modelFsm); 03248 mdd_free(reachableBadStates); 03249 03250 /* build a path from the initial states to the bad state */ 03251 aPath = Mc_BuildPathFromCore(aBadReachableState, onionRings, 03252 modelFsm, McGreaterOrEqualZero_c); 03253 mdd_free(aBadReachableState); 03254 03255 03256 if(McOptionsReadDbgLevel(options)==2) 03257 { 03258 03259 (void) Mc_PrintPathAiger(aPath, modelFsm, McOptionsReadPrintInputs(options)); 03260 } 03261 else 03262 { 03263 (void) fprintf(vis_stdout, "# INV: formula %d failed --- ", i+1); 03264 Ctlp_FormulaPrint(vis_stdout, 03265 Ctlp_FormulaReadOriginalFormula(invarFormula)); 03266 fprintf(vis_stdout, "\n"); 03267 03268 (void) fprintf(vis_stdout, "# INV: calling debugger\n"); 03269 if (array_n(aPath) > 1) { 03270 (void) fprintf(vis_stdout, 03271 "# INV: a sequence of states starting at an initial "); 03272 (void) fprintf(vis_stdout, "state leading to a bad state\n"); 03273 } else { 03274 (void) fprintf(vis_stdout, 03275 "# INV: invariant fails at the following initial state\n"); 03276 } 03277 (void) Mc_PrintPath(aPath, modelFsm, McOptionsReadPrintInputs(options)); 03278 } 03279 (void) fprintf(vis_stdout, "\n"); 03280 03281 McNormalizeBddPointer(aPath); 03282 mdd_array_free(aPath); 03283 } else { 03284 /* Was a false negative */ 03285 assert (approxFlag == Fsm_Rch_Oa_c); 03286 (void) fprintf(vis_stdout, "# INV: formula passed --- "); 03287 Ctlp_FormulaPrint(vis_stdout, 03288 Ctlp_FormulaReadOriginalFormula(invarFormula)); 03289 fprintf(vis_stdout, "\n"); 03290 } 03291 } 03292 03293 if (vis_stdout != tmpFile && vis_stdout != debugFile) 03294 (void)pclose(vis_stdpipe); 03295 vis_stdout = tmpFile; 03296 } /* end of InvarPrintDebugInformation */ 03297 03298 03314 array_t * 03315 SortFormulasByFsm(Fsm_Fsm_t *totalFsm, 03316 array_t *invarFormulaArray, 03317 array_t *fsmArray, 03318 McOptions_t *options) 03319 { 03320 array_t *resultArray; 03321 array_t *formulaArray; 03322 array_t *tempArray; 03323 int i, j, found; 03324 Ctlp_Formula_t *formula; 03325 Ntk_Network_t *network = Fsm_FsmReadNetwork(totalFsm); 03326 Fsm_Fsm_t *reducedFsm, *fsm; 03327 int reducedFsmPos = -1; 03328 03329 if (invarFormulaArray == NIL(array_t)) return invarFormulaArray; 03330 if (array_n(invarFormulaArray) == 0) return NIL(array_t); 03331 03332 tempArray = array_alloc(array_t *, 0); 03333 /* do a semantic check and a quantifier check */ 03334 arrayForEachItem (Ctlp_Formula_t *, invarFormulaArray, i, formula) { 03335 if (!Mc_FormulaStaticSemanticCheckOnNetwork(formula, network, FALSE)){ 03336 (void) fprintf(vis_stderr, "** inv error: error in parsing Atomic Formula:\n%s\n", error_string()); 03337 error_init(); 03338 Ctlp_FormulaFree(formula); 03339 continue; 03340 } else { 03341 if (Ctlp_FormulaTestIsQuantifierFree(formula) == FALSE) { 03342 (void) fprintf(vis_stderr, "** inv error: invariant formula refers to path quantifiers\n"); 03343 Ctlp_FormulaFree(formula); 03344 continue; 03345 } 03346 } 03347 array_insert_last(Ctlp_Formula_t *, tempArray, formula); 03348 } 03349 if (array_n(tempArray) == 0) { 03350 array_free(tempArray); 03351 return NIL(array_t); 03352 } 03353 03354 /* if no -r option, return the original array */ 03355 resultArray = array_alloc(array_t *, 0); 03356 if (McOptionsReadReduceFsm(options) == FALSE) { 03357 array_insert_last(array_t *, resultArray, tempArray); 03358 reducedFsm = McConstructReducedFsm(network, tempArray); 03359 if (reducedFsm != NIL(Fsm_Fsm_t)) { 03360 array_insert_last(Fsm_Fsm_t *, fsmArray, reducedFsm); 03361 } else { 03362 array_insert_last(Fsm_Fsm_t *, fsmArray, totalFsm); 03363 } 03364 return resultArray; 03365 } 03366 03367 /* We want to minimize per formula only when "-r" option is not specified */ 03368 arrayForEachItem (Ctlp_Formula_t *, tempArray, i, formula) { 03369 /* Create reduced fsm */ 03370 formulaArray = array_alloc(Ctlp_Formula_t *, 0); 03371 array_insert_last(Ctlp_Formula_t *, formulaArray, formula); 03372 03373 reducedFsm = McConstructReducedFsm(network, formulaArray); 03374 if (reducedFsm == NIL(Fsm_Fsm_t)) { 03375 /* no reduction */ 03376 reducedFsm = totalFsm; 03377 } 03378 03379 /* Check if fsm already created */ 03380 found = 0; 03381 for (j = 0; j < array_n(fsmArray); j++) { 03382 fsm = array_fetch (Fsm_Fsm_t *, fsmArray, j); 03383 found = Fsm_FsmCheckSameSubFsmInTotalFsm(totalFsm, reducedFsm, fsm); 03384 if (found) break; 03385 } 03386 03387 /* If found, add to the existing list. Else add a new reduced fsm */ 03388 if (found) { 03389 if (reducedFsm != totalFsm) Fsm_FsmFree(reducedFsm); 03390 array_free(formulaArray); 03391 formulaArray = array_fetch(array_t *, resultArray, j); 03392 array_insert_last(Ctlp_Formula_t *, formulaArray, formula); 03393 } else { 03394 array_insert_last(Fsm_Fsm_t *, fsmArray, reducedFsm); 03395 array_insert_last(array_t *, resultArray, formulaArray); 03396 if (reducedFsm == totalFsm) reducedFsmPos = array_n(fsmArray)-1; 03397 } 03398 } 03399 03400 array_free(tempArray); 03401 /* swap the last reduced fsm with the total fsm. */ 03402 if ((reducedFsmPos != -1) && (reducedFsmPos != array_n(fsmArray)-1)) { 03403 array_t *totalFsmFormulaArray; 03404 assert(array_n(fsmArray) == array_n(resultArray)); 03405 fsm = array_fetch(Fsm_Fsm_t *, fsmArray, array_n(fsmArray)-1); 03406 array_insert(Fsm_Fsm_t *, fsmArray, reducedFsmPos, fsm); 03407 array_insert(Fsm_Fsm_t *, fsmArray, array_n(fsmArray)-1, totalFsm); 03408 formulaArray = array_fetch(array_t *, resultArray, array_n(resultArray)-1); 03409 totalFsmFormulaArray = array_fetch(array_t *, resultArray, reducedFsmPos); 03410 array_insert(array_t *, resultArray, reducedFsmPos, formulaArray); 03411 array_insert(array_t *, resultArray, array_n(resultArray)-1, totalFsmFormulaArray); 03412 } 03413 03414 return resultArray; 03415 } /* end of SortFormulasByFsm */ 03416 03417 03430 int 03431 TestInvariantsInTotalFsm(Fsm_Fsm_t *totalFsm, 03432 array_t *invarStatesArray, 03433 int shellFlag) 03434 { 03435 int i; 03436 mdd_t *invariant; 03437 mdd_t *reachableStates; 03438 boolean upToDate = FALSE; /* don't care initialization */ 03439 if (shellFlag) { 03440 upToDate = Fsm_FsmReachabilityOnionRingsStates(totalFsm, &reachableStates); 03441 } else { 03442 reachableStates = Fsm_FsmReadCurrentReachableStates(totalFsm); 03443 } 03444 if (reachableStates == NIL(mdd_t)) return TRUE; 03445 if (mdd_is_tautology(reachableStates, 0)) return TRUE; 03446 03447 arrayForEachItem(mdd_t *, invarStatesArray, i, invariant) { 03448 if (invariant == NIL(mdd_t)) continue; 03449 if (!mdd_lequal(reachableStates, invariant, 1, 1)) { 03450 if (shellFlag) mdd_free(reachableStates); 03451 return FALSE; 03452 } 03453 } 03454 if (shellFlag) mdd_free(reachableStates); 03455 if ((shellFlag && !upToDate) || 03456 (Fsm_FsmReadReachabilityApproxComputationStatus(totalFsm) == 03457 Fsm_Rch_Under_c)) 03458 return TRUE; 03459 else 03460 return FALSE; 03461 03462 } 03463 03464 03477 Ctlp_Approx_t 03478 ComputeResultingApproximation( 03479 Ctlp_FormulaType formulaType, 03480 Ctlp_Approx_t leftApproxType, 03481 Ctlp_Approx_t rightApproxType, 03482 Ctlp_Approx_t TRMinimization, 03483 Mc_EarlyTermination_t *earlyTermination, 03484 boolean fixpoint) 03485 { 03486 Ctlp_Approx_t thisApproxType; 03487 03488 switch (formulaType) { 03489 case Ctlp_ID_c: 03490 case Ctlp_TRUE_c: 03491 case Ctlp_FALSE_c: 03492 thisApproxType = Ctlp_Exact_c; 03493 break; 03494 case Ctlp_NOT_c: 03495 if (leftApproxType == Ctlp_Incomparable_c) { 03496 thisApproxType = Ctlp_Incomparable_c; 03497 } else if (leftApproxType == Ctlp_Overapprox_c) { 03498 thisApproxType = Ctlp_Underapprox_c; 03499 } else if (leftApproxType == Ctlp_Underapprox_c) { 03500 thisApproxType = Ctlp_Overapprox_c; 03501 } else { 03502 thisApproxType = Ctlp_Exact_c; 03503 } 03504 break; 03505 case Ctlp_AND_c: 03506 if (leftApproxType == Ctlp_Incomparable_c || 03507 rightApproxType == Ctlp_Incomparable_c || 03508 (leftApproxType == Ctlp_Overapprox_c && 03509 rightApproxType == Ctlp_Underapprox_c) || 03510 (leftApproxType == Ctlp_Underapprox_c && 03511 rightApproxType == Ctlp_Overapprox_c)) { 03512 thisApproxType = Ctlp_Incomparable_c; 03513 } else if (rightApproxType == Ctlp_Overapprox_c) { 03514 if (earlyTermination == MC_NO_EARLY_TERMINATION && 03515 leftApproxType == Ctlp_Exact_c) { 03516 thisApproxType = Ctlp_Exact_c; 03517 } else { 03518 thisApproxType = Ctlp_Overapprox_c; 03519 } 03520 } else if (leftApproxType == Ctlp_Overapprox_c) { 03521 thisApproxType = Ctlp_Overapprox_c; 03522 } else if (rightApproxType == Ctlp_Underapprox_c) { 03523 if (earlyTermination == MC_NO_EARLY_TERMINATION && 03524 leftApproxType == Ctlp_Exact_c) { 03525 thisApproxType = Ctlp_Exact_c; 03526 } else { 03527 thisApproxType = Ctlp_Underapprox_c; 03528 } 03529 } else if (leftApproxType == Ctlp_Underapprox_c) { 03530 thisApproxType = Ctlp_Underapprox_c; 03531 } else { 03532 thisApproxType = Ctlp_Exact_c; 03533 } 03534 break; 03535 case Ctlp_EQ_c: 03536 case Ctlp_XOR_c: 03537 if (leftApproxType != Ctlp_Exact_c || rightApproxType != Ctlp_Exact_c) { 03538 thisApproxType = Ctlp_Incomparable_c; 03539 } else { 03540 thisApproxType = Ctlp_Exact_c; 03541 } 03542 break; 03543 case Ctlp_THEN_c: 03544 if (leftApproxType == Ctlp_Incomparable_c || 03545 rightApproxType == Ctlp_Incomparable_c || 03546 (leftApproxType == Ctlp_Overapprox_c && 03547 rightApproxType == Ctlp_Overapprox_c) || 03548 (leftApproxType == Ctlp_Underapprox_c && 03549 rightApproxType == Ctlp_Underapprox_c)) { 03550 thisApproxType = Ctlp_Incomparable_c; 03551 } else if (rightApproxType == Ctlp_Overapprox_c) { 03552 if (earlyTermination == MC_NO_EARLY_TERMINATION && 03553 leftApproxType == Ctlp_Exact_c) { 03554 thisApproxType = Ctlp_Exact_c; 03555 } else { 03556 thisApproxType = Ctlp_Overapprox_c; 03557 } 03558 } else if (leftApproxType == Ctlp_Underapprox_c) { 03559 thisApproxType = Ctlp_Overapprox_c; 03560 } else if (rightApproxType == Ctlp_Underapprox_c) { 03561 if (earlyTermination == MC_NO_EARLY_TERMINATION && 03562 leftApproxType == Ctlp_Exact_c) { 03563 thisApproxType = Ctlp_Exact_c; 03564 } else { 03565 thisApproxType = Ctlp_Underapprox_c; 03566 } 03567 } else if (leftApproxType == Ctlp_Overapprox_c) { 03568 thisApproxType = Ctlp_Underapprox_c; 03569 } else { 03570 thisApproxType = Ctlp_Exact_c; 03571 } 03572 break; 03573 case Ctlp_OR_c: 03574 if (leftApproxType == Ctlp_Incomparable_c || 03575 rightApproxType == Ctlp_Incomparable_c || 03576 (leftApproxType == Ctlp_Overapprox_c && 03577 rightApproxType == Ctlp_Underapprox_c) || 03578 (leftApproxType == Ctlp_Underapprox_c && 03579 rightApproxType == Ctlp_Overapprox_c)) { 03580 thisApproxType = Ctlp_Incomparable_c; 03581 } else if (rightApproxType == Ctlp_Overapprox_c) { 03582 if (earlyTermination == MC_NO_EARLY_TERMINATION && 03583 leftApproxType == Ctlp_Exact_c) { 03584 thisApproxType = Ctlp_Exact_c; 03585 } else { 03586 thisApproxType = Ctlp_Overapprox_c; 03587 } 03588 } else if (leftApproxType == Ctlp_Overapprox_c) { 03589 thisApproxType = Ctlp_Overapprox_c; 03590 } else if (rightApproxType == Ctlp_Underapprox_c) { 03591 if (earlyTermination == MC_NO_EARLY_TERMINATION && 03592 leftApproxType == Ctlp_Exact_c) { 03593 thisApproxType = Ctlp_Exact_c; 03594 } else { 03595 thisApproxType = Ctlp_Underapprox_c; 03596 } 03597 } else if (leftApproxType == Ctlp_Underapprox_c) { 03598 thisApproxType = Ctlp_Underapprox_c; 03599 } else { 03600 thisApproxType = Ctlp_Exact_c; 03601 } 03602 break; 03603 case Ctlp_EX_c: 03604 if (leftApproxType == Ctlp_Underapprox_c) { 03605 if (TRMinimization == Ctlp_Overapprox_c) { 03606 thisApproxType = Ctlp_Incomparable_c; 03607 } else { 03608 thisApproxType = Ctlp_Underapprox_c; 03609 } 03610 } else if (leftApproxType == Ctlp_Overapprox_c) { 03611 if (TRMinimization == Ctlp_Underapprox_c) { 03612 thisApproxType = Ctlp_Incomparable_c; 03613 } else { 03614 thisApproxType = Ctlp_Overapprox_c; 03615 } 03616 } else if (leftApproxType == Ctlp_Exact_c) { 03617 thisApproxType = TRMinimization; 03618 } else { 03619 thisApproxType = Ctlp_Incomparable_c; 03620 } 03621 break; 03622 case Ctlp_EU_c: 03623 if (leftApproxType == Ctlp_Incomparable_c || 03624 rightApproxType == Ctlp_Incomparable_c || 03625 (leftApproxType == Ctlp_Overapprox_c && 03626 rightApproxType == Ctlp_Underapprox_c) || 03627 (leftApproxType == Ctlp_Underapprox_c && 03628 rightApproxType == Ctlp_Overapprox_c)) { 03629 thisApproxType = Ctlp_Incomparable_c; 03630 } else if (leftApproxType == Ctlp_Overapprox_c || 03631 rightApproxType == Ctlp_Overapprox_c) { 03632 thisApproxType = Ctlp_Overapprox_c; 03633 } else if (leftApproxType == Ctlp_Underapprox_c || 03634 rightApproxType == Ctlp_Underapprox_c) { 03635 thisApproxType = Ctlp_Underapprox_c; 03636 } else { 03637 thisApproxType = Ctlp_Exact_c; 03638 } 03639 if (!fixpoint) { 03640 if (TRMinimization == Ctlp_Overapprox_c || 03641 thisApproxType == Ctlp_Overapprox_c) { 03642 thisApproxType = Ctlp_Incomparable_c; 03643 } else if (thisApproxType == Ctlp_Exact_c) { 03644 thisApproxType = Ctlp_Underapprox_c; 03645 } 03646 } else { 03647 if ((TRMinimization == Ctlp_Overapprox_c && 03648 thisApproxType == Ctlp_Underapprox_c) || 03649 (TRMinimization == Ctlp_Underapprox_c && 03650 thisApproxType == Ctlp_Overapprox_c)) { 03651 thisApproxType = Ctlp_Incomparable_c; 03652 } else if (thisApproxType == Ctlp_Exact_c) { 03653 thisApproxType = TRMinimization; 03654 } 03655 } 03656 break; 03657 case Ctlp_EG_c: 03658 if (leftApproxType == Ctlp_Incomparable_c || 03659 rightApproxType == Ctlp_Incomparable_c || 03660 (leftApproxType == Ctlp_Overapprox_c && 03661 rightApproxType == Ctlp_Underapprox_c) || 03662 (leftApproxType == Ctlp_Underapprox_c && 03663 rightApproxType == Ctlp_Overapprox_c)) { 03664 thisApproxType = Ctlp_Incomparable_c; 03665 } else if (leftApproxType == Ctlp_Overapprox_c || 03666 rightApproxType == Ctlp_Overapprox_c) { 03667 thisApproxType = Ctlp_Overapprox_c; 03668 } else if (leftApproxType == Ctlp_Underapprox_c || 03669 rightApproxType == Ctlp_Underapprox_c) { 03670 thisApproxType = Ctlp_Underapprox_c; 03671 } else { 03672 thisApproxType = Ctlp_Exact_c; 03673 } 03674 if (!fixpoint) { 03675 if (TRMinimization == Ctlp_Underapprox_c || 03676 thisApproxType == Ctlp_Underapprox_c) { 03677 thisApproxType = Ctlp_Incomparable_c; 03678 } else if (thisApproxType == Ctlp_Exact_c) { 03679 thisApproxType = Ctlp_Overapprox_c; 03680 } 03681 } else { 03682 if ((TRMinimization == Ctlp_Overapprox_c && 03683 thisApproxType == Ctlp_Underapprox_c) || 03684 (TRMinimization == Ctlp_Underapprox_c && 03685 thisApproxType == Ctlp_Overapprox_c)) { 03686 thisApproxType = Ctlp_Incomparable_c; 03687 } else if (thisApproxType == Ctlp_Exact_c) { 03688 thisApproxType = TRMinimization; 03689 } 03690 } 03691 break; 03692 case Ctlp_Cmp_c: 03693 case Ctlp_Init_c: 03694 case Ctlp_FwdU_c: 03695 case Ctlp_FwdG_c: 03696 case Ctlp_EY_c: 03697 /* no early termination and no hints in forward model checking */ 03698 thisApproxType = Ctlp_Exact_c; 03699 break; 03700 default: fail("Encountered unknown type of CTL formula\n"); 03701 } 03702 03703 return thisApproxType; 03704 03705 } /* ComputeResultingApproximation */ 03706 03707 03708 /*---------------------------------------------------------------------------*/ 03709 /* Definition of static functions */ 03710 /*---------------------------------------------------------------------------*/ 03711 03712 03729 static mdd_t * 03730 EvaluateFormulaRecur( 03731 Fsm_Fsm_t *modelFsm, 03732 Ctlp_Formula_t *ctlFormula, 03733 mdd_t *fairStates, 03734 Fsm_Fairness_t *fairCondition, 03735 array_t *modelCareStatesArray, 03736 Mc_EarlyTermination_t *earlyTermination, 03737 Fsm_HintsArray_t *hintsArray, 03738 Mc_GuidedSearch_t hintType, 03739 Ctlp_Approx_t TRMinimization, 03740 Ctlp_Approx_t *resultApproxType, 03741 Mc_VerbosityLevel verbosity, 03742 Mc_DcLevel dcLevel, 03743 int buildOnionRings, 03744 Mc_GSHScheduleType GSHschedule) 03745 { 03746 mdd_t *leftMdd = NIL(mdd_t); 03747 mdd_t *rightMdd = NIL(mdd_t); 03748 mdd_t *result = NIL(mdd_t); 03749 03750 mdd_manager *mddMgr = Fsm_FsmReadMddManager(modelFsm); 03751 array_t *careStatesArray = NIL(array_t); 03752 mdd_t *tmpMdd; 03753 mdd_t *approx = NIL(mdd_t); /* prev computed approx of sat set */ 03754 mdd_t *ctlFormulaStates = Ctlp_FormulaObtainStates( ctlFormula ); 03755 Ctlp_Approx_t leftApproxType = Ctlp_Exact_c; 03756 Ctlp_Approx_t rightApproxType = Ctlp_Exact_c; 03757 Ctlp_Approx_t thisApproxType = Ctlp_Exact_c; 03758 boolean fixpoint = FALSE; 03759 boolean skipRight = FALSE; 03760 03761 if ( ctlFormulaStates ) { 03762 return ctlFormulaStates; 03763 } 03764 03765 { 03766 Ctlp_Formula_t *leftChild = Ctlp_FormulaReadLeftChild(ctlFormula); 03767 03768 if (leftChild) { 03769 Mc_EarlyTermination_t *nextEarlyTermination = 03770 McObtainUpdatedEarlyTerminationCondition( 03771 earlyTermination, NIL(mdd_t), Ctlp_FormulaReadType(ctlFormula)); 03772 03773 leftMdd = EvaluateFormulaRecur(modelFsm, leftChild, fairStates, 03774 fairCondition, modelCareStatesArray, 03775 nextEarlyTermination, 03776 hintsArray, hintType, TRMinimization, 03777 &leftApproxType, verbosity, dcLevel, 03778 buildOnionRings, GSHschedule); 03779 Mc_EarlyTerminationFree(nextEarlyTermination); 03780 if (!leftMdd) { 03781 return NIL(mdd_t); 03782 } 03783 } 03784 } 03785 03786 {/* read right */ 03787 Ctlp_Formula_t *rightChild = Ctlp_FormulaReadRightChild(ctlFormula); 03788 03789 if (rightChild) { 03790 Mc_EarlyTermination_t *nextEarlyTermination = 03791 McObtainUpdatedEarlyTerminationCondition( 03792 earlyTermination, leftMdd, Ctlp_FormulaReadType(ctlFormula)); 03793 03794 skipRight = Mc_EarlyTerminationIsSkip(nextEarlyTermination); 03795 if (!skipRight) { 03796 rightMdd = EvaluateFormulaRecur(modelFsm, rightChild, fairStates, 03797 fairCondition, modelCareStatesArray, 03798 nextEarlyTermination, 03799 hintsArray, hintType, TRMinimization, 03800 &rightApproxType, verbosity, dcLevel, 03801 buildOnionRings, GSHschedule); 03802 } 03803 Mc_EarlyTerminationFree(nextEarlyTermination); 03804 if (!(rightMdd || skipRight)) { 03805 if (leftMdd) 03806 mdd_free(leftMdd); 03807 return NIL(mdd_t); 03808 } 03809 } 03810 }/* read right */ 03811 03812 if (modelCareStatesArray != NIL(array_t)) { 03813 careStatesArray = modelCareStatesArray; 03814 } else { 03815 careStatesArray = array_alloc(mdd_t *, 0); 03816 array_insert_last(mdd_t *, careStatesArray, mdd_one(mddMgr)); 03817 } 03818 switch (Ctlp_FormulaReadType(ctlFormula)) { 03819 case Ctlp_ID_c: 03820 assert(!skipRight); 03821 result = McModelCheckAtomicFormula(modelFsm, ctlFormula); 03822 break; 03823 03824 case Ctlp_TRUE_c: 03825 assert(!skipRight); 03826 result = mdd_one(mddMgr); break; 03827 03828 case Ctlp_FALSE_c: 03829 assert(!skipRight); 03830 result = mdd_zero(mddMgr); break; 03831 03832 case Ctlp_NOT_c: 03833 assert(!skipRight); 03834 result = mdd_not(leftMdd); break; 03835 03836 case Ctlp_AND_c: 03837 if (skipRight) { 03838 result = mdd_dup(leftMdd); 03839 rightApproxType = Ctlp_Overapprox_c; 03840 } else { 03841 result = mdd_and(leftMdd, rightMdd, 1, 1); 03842 } 03843 break; 03844 03845 case Ctlp_EQ_c: 03846 assert(!skipRight); 03847 result = mdd_xnor(leftMdd, rightMdd); break; 03848 03849 case Ctlp_XOR_c: 03850 assert(!skipRight); 03851 result = mdd_xor(leftMdd, rightMdd); break; 03852 03853 case Ctlp_THEN_c: 03854 if (skipRight) { 03855 result = mdd_dup(leftMdd); 03856 rightApproxType = Ctlp_Underapprox_c; 03857 } else { 03858 result = mdd_or(leftMdd, rightMdd, 0, 1); 03859 } 03860 break; 03861 03862 case Ctlp_OR_c: 03863 if (skipRight) { 03864 result = mdd_dup(leftMdd); 03865 rightApproxType = Ctlp_Underapprox_c; 03866 } else { 03867 result = mdd_or(leftMdd, rightMdd, 1, 1); 03868 } 03869 break; 03870 03871 case Ctlp_EX_c: 03872 assert(!skipRight); 03873 result = Mc_FsmEvaluateEXFormula(modelFsm, leftMdd, fairStates, 03874 careStatesArray, verbosity, dcLevel); 03875 break; 03876 03877 case Ctlp_EU_c: { 03878 array_t *onionRings = NIL(array_t); /* array of mdd_t */ 03879 boolean newrings; 03880 03881 assert(!skipRight); 03882 /* An underapproximation, together with its explanation may be stored. */ 03883 approx = Ctlp_FormulaObtainApproxStates( ctlFormula, Ctlp_Underapprox_c ); 03884 onionRings = (array_t *) Ctlp_FormulaReadDebugData(ctlFormula); 03885 newrings = onionRings == NIL(array_t); 03886 03887 if (buildOnionRings){ 03888 assert((approx != NIL(mdd_t) && onionRings != NIL(array_t)) || 03889 (approx == NIL(mdd_t) && onionRings == NIL(array_t))); 03890 if(onionRings == NIL(array_t)) 03891 onionRings = array_alloc(mdd_t *, 0); 03892 } 03893 03894 result = Mc_FsmEvaluateEUFormula(modelFsm, leftMdd, rightMdd, 03895 approx, fairStates, 03896 careStatesArray, 03897 earlyTermination, hintsArray, 03898 hintType, onionRings, 03899 verbosity, dcLevel, &fixpoint); 03900 03901 if(buildOnionRings && newrings) 03902 Ctlp_FormulaSetDbgInfo(ctlFormula, (void *) onionRings, 03903 McFormulaFreeDebugData); 03904 if(approx != NIL(mdd_t)) 03905 mdd_free(approx); 03906 03907 break; 03908 } 03909 case Ctlp_EG_c: { 03910 array_t *arrayOfOnionRings = NIL(array_t); /* array of array of mdd_t* */ 03911 03912 assert(!skipRight); 03913 if(buildOnionRings) 03914 arrayOfOnionRings = array_alloc(array_t *, 0); 03915 03916 approx = Ctlp_FormulaObtainApproxStates( ctlFormula, Ctlp_Overapprox_c ); 03917 03918 result = Mc_FsmEvaluateEGFormula(modelFsm, leftMdd, approx, fairStates, 03919 fairCondition, careStatesArray, 03920 earlyTermination, hintsArray, hintType, 03921 &arrayOfOnionRings, verbosity, 03922 dcLevel, &fixpoint, GSHschedule); 03923 03924 if(buildOnionRings) 03925 Ctlp_FormulaSetDbgInfo(ctlFormula, (void *)arrayOfOnionRings, 03926 McFormulaFreeDebugData); 03927 03928 if(approx != NIL(mdd_t)) mdd_free(approx); 03929 03930 break; 03931 } 03932 case Ctlp_Cmp_c: { 03933 assert(!skipRight); 03934 if (Ctlp_FormulaReadCompareValue(ctlFormula) == 0) 03935 result = bdd_is_tautology(leftMdd, 0) ? 03936 mdd_one(mddMgr) : mdd_zero(mddMgr); 03937 else 03938 result = bdd_is_tautology(leftMdd, 0) ? 03939 mdd_zero(mddMgr) : mdd_one(mddMgr); 03940 break; 03941 } 03942 case Ctlp_Init_c: 03943 assert(!skipRight); 03944 result = Fsm_FsmComputeInitialStates(modelFsm); 03945 break; 03946 case Ctlp_FwdU_c: 03947 assert(!skipRight); 03948 if (buildOnionRings) { 03949 array_t *onionRings = array_alloc(mdd_t *, 0); 03950 result = Mc_FsmEvaluateFwdUFormula(modelFsm, leftMdd, rightMdd, 03951 fairStates, careStatesArray, 03952 onionRings, verbosity, dcLevel); 03953 Ctlp_FormulaSetDbgInfo(ctlFormula, (void *) onionRings, 03954 McFormulaFreeDebugData); 03955 } 03956 else { 03957 if (Ctlp_FormulaReadLeftChild(ctlFormula) && 03958 Ctlp_FormulaReadType(Ctlp_FormulaReadLeftChild(ctlFormula)) == 03959 Ctlp_Init_c && 03960 Ctlp_FormulaReadRightChild(ctlFormula) && 03961 Ctlp_FormulaReadType(Ctlp_FormulaReadRightChild(ctlFormula)) == 03962 Ctlp_TRUE_c && 03963 Fsm_FsmTestIsReachabilityDone(modelFsm)) { 03964 result = mdd_dup(Fsm_FsmReadReachableStates(modelFsm)); 03965 break; 03966 } 03967 result = Mc_FsmEvaluateFwdUFormula(modelFsm, leftMdd, rightMdd, 03968 fairStates, careStatesArray, 03969 NIL(array_t), verbosity, 03970 dcLevel); 03971 } 03972 break; 03973 case Ctlp_FwdG_c: 03974 assert(!skipRight); 03975 if (buildOnionRings) { 03976 array_t *arrayOfOnionRings = array_alloc(array_t *, 0); 03977 result = Mc_FsmEvaluateFwdGFormula(modelFsm, leftMdd, rightMdd, 03978 fairStates, fairCondition, 03979 careStatesArray, 03980 arrayOfOnionRings, verbosity, 03981 dcLevel); 03982 Ctlp_FormulaSetDbgInfo(ctlFormula, (void *)arrayOfOnionRings, 03983 McFormulaFreeDebugData); 03984 } else { 03985 result = Mc_FsmEvaluateFwdGFormula(modelFsm, leftMdd, rightMdd, 03986 fairStates, fairCondition, 03987 careStatesArray, 03988 NIL(array_t), verbosity, 03989 dcLevel); 03990 } 03991 break; 03992 case Ctlp_EY_c: 03993 assert(!skipRight); 03994 result = Mc_FsmEvaluateEYFormula(modelFsm, leftMdd, fairStates, 03995 careStatesArray, verbosity, dcLevel); 03996 break; 03997 03998 default: fail("Encountered unknown type of CTL formula\n"); 03999 } 04000 04001 tmpMdd = mdd_dup(result); 04002 thisApproxType = ComputeResultingApproximation( 04003 Ctlp_FormulaReadType(ctlFormula), leftApproxType, 04004 rightApproxType, TRMinimization, earlyTermination, fixpoint); 04005 Ctlp_FormulaSetApproxStates(ctlFormula, tmpMdd, thisApproxType); 04006 04007 #ifdef DEBUG_MC 04008 /* The following code is just for debugging */ 04009 if ((verbosity == McVerbosityMax_c)) { 04010 char *type = Ctlp_FormulaGetTypeString(ctlFormula); 04011 if (Ctlp_FormulaReadType(ctlFormula) == Ctlp_Cmp_c) { 04012 fprintf(vis_stdout, "Info : result for [Cmp]\n"); 04013 if (bdd_is_tautology(result, 1)) 04014 fprintf(vis_stdout, "TRUE\n"); 04015 else 04016 fprintf(vis_stdout, "FALSE\n"); 04017 } 04018 else if (Ctlp_FormulaReadType(ctlFormula) == Ctlp_ID_c) { 04019 char *atomic = Ctlp_FormulaConvertToString(ctlFormula); 04020 fprintf(vis_stdout, "Info : satisfying minterms for [%s(%s)]:\n", 04021 type, atomic); 04022 free(atomic); 04023 if (bdd_is_tautology(result, 1)) 04024 fprintf(vis_stdout, "-- TAUTOLOGY --\n"); 04025 else if (bdd_is_tautology(result, 0)) 04026 fprintf(vis_stdout, "-- null --\n"); 04027 else 04028 (void)_McPrintSatisfyingMinterms(result, modelFsm); 04029 } 04030 else { 04031 fprintf(vis_stdout, "Info : satisfying minterms for [%s]:\n", type); 04032 if (bdd_is_tautology(result, 1)) 04033 fprintf(vis_stdout, "-- TAUTOLOGY --\n"); 04034 else if (bdd_is_tautology(result, 0)) 04035 fprintf(vis_stdout, "-- null --\n"); 04036 else 04037 (void)_McPrintSatisfyingMinterms(result, modelFsm); 04038 } 04039 free(type); 04040 } 04041 #endif 04042 04043 if (modelCareStatesArray == NIL(array_t)) 04044 mdd_array_free(careStatesArray); 04045 if (leftMdd) 04046 mdd_free(leftMdd); 04047 if (rightMdd) 04048 mdd_free(rightMdd); 04049 *resultApproxType = thisApproxType; 04050 return result; 04051 } 04052 04053 04065 static mdd_t * 04066 McForwardReachable( 04067 Fsm_Fsm_t *modelFsm, 04068 mdd_t *targetMdd, 04069 mdd_t *invariantMdd, 04070 mdd_t *fairStates, 04071 array_t *careStatesArray, 04072 array_t *onionRings, 04073 Mc_VerbosityLevel verbosity, 04074 Mc_DcLevel dcLevel) 04075 { 04076 mdd_t *resultMdd, *fuMdd; 04077 04078 /* When McForwardReachable is called by Mc_FsmEvaluateFwdEHFormula 04079 * with no fairness constraints, this test saves one image 04080 * computation. */ 04081 if (mdd_is_tautology(fairStates, 1) && 04082 mdd_lequal_mod_care_set_array(invariantMdd, targetMdd, 04083 1, 1, careStatesArray)) { 04084 resultMdd = mdd_dup(invariantMdd); 04085 if (onionRings) { 04086 array_insert_last(mdd_t *, onionRings, mdd_dup(resultMdd)); 04087 } 04088 } else { 04089 fuMdd = Mc_FsmEvaluateFwdUFormula(modelFsm, targetMdd, invariantMdd, 04090 fairStates, careStatesArray, onionRings, 04091 verbosity, dcLevel); 04092 resultMdd = mdd_and(fuMdd, invariantMdd, 1, 1); 04093 mdd_free(fuMdd); 04094 } 04095 04096 /* Updates onionRings not to have warning message in 04097 * Mc_FsmEvaluateFwdEHFormula since Reachable(p,q) = FwdUntil(p,q) ^ q. 04098 */ 04099 if (onionRings) { 04100 int i; 04101 mdd_t *ring, *tmp; 04102 04103 for (i = 0 ; i < array_n(onionRings); i++) { 04104 tmp = array_fetch(mdd_t *, onionRings, i); 04105 ring = mdd_and(tmp, invariantMdd, 1, 1); 04106 mdd_free(tmp); 04107 array_insert(mdd_t *, onionRings, i, ring); 04108 } 04109 } 04110 04111 return(resultMdd); 04112 }