VIS

src/mc/mcMc.c

Go to the documentation of this file.
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 }