VIS

src/fsm/fsmFair.c

Go to the documentation of this file.
00001 
00037 #include "fsmInt.h"
00038 
00039 static char rcsid[] UNUSED = "$Id: fsmFair.c,v 1.28 2003/01/22 18:44:20 jinh Exp $";
00040 
00041 /*---------------------------------------------------------------------------*/
00042 /* Constant declarations                                                     */
00043 /*---------------------------------------------------------------------------*/
00044 
00045 
00046 /*---------------------------------------------------------------------------*/
00047 /* Type declarations                                                         */
00048 /*---------------------------------------------------------------------------*/
00049 
00050 
00051 /*---------------------------------------------------------------------------*/
00052 /* Structure declarations                                                    */
00053 /*---------------------------------------------------------------------------*/
00054 
00062 typedef struct FairnessConjunctStruct {
00063   Ctlp_Formula_t *finallyInf;  /* states to visit infinitely often */
00064   Ctlp_Formula_t *globallyInf; /* states to visit almost always */
00065 } FairnessConjunct_t;
00066 
00067 
00068 /*---------------------------------------------------------------------------*/
00069 /* Variable declarations                                                     */
00070 /*---------------------------------------------------------------------------*/
00071 
00072 
00073 /*---------------------------------------------------------------------------*/
00074 /* Macro declarations                                                        */
00075 /*---------------------------------------------------------------------------*/
00076 
00077 
00080 /*---------------------------------------------------------------------------*/
00081 /* Static function prototypes                                                */
00082 /*---------------------------------------------------------------------------*/
00083 
00084 static FairnessConjunct_t * FairnessReadConjunct(Fsm_Fairness_t *fairness, int i, int j);
00085 static mdd_t * FsmObtainStatesSatisfyingFormula(Fsm_Fsm_t *fsm, Ctlp_Formula_t *formula, array_t *careSetArray, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
00086 
00090 /*---------------------------------------------------------------------------*/
00091 /* Definition of exported functions                                          */
00092 /*---------------------------------------------------------------------------*/
00093 
00118 Fsm_Fairness_t *
00119 Fsm_FsmReadFairnessConstraint(
00120   Fsm_Fsm_t *fsm)
00121 {
00122   return (fsm->fairnessInfo.constraint);
00123 }
00124 
00125 mdd_t *
00126 Fsm_FsmReadFairnessStates(Fsm_Fsm_t *fsm)
00127 {
00128    return(fsm->fairnessInfo.states);
00129 }
00130 
00131 
00158 mdd_t *
00159 Fsm_FsmComputeFairStates(
00160   Fsm_Fsm_t *fsm,
00161   array_t *careSetArray,
00162   int verbosity,
00163   int dcLevel,
00164   Mc_GSHScheduleType schedule,
00165   Mc_FwdBwdAnalysis direction,
00166   boolean useEarlyTermination)
00167 {
00168   mdd_manager    *mddManager = Fsm_FsmReadMddManager(fsm);
00169   Fsm_Fairness_t *constraint = Fsm_FsmReadFairnessConstraint(fsm);
00170 
00171   assert(constraint != NIL(Fsm_Fairness_t));
00172 
00173   if (fsm->fairnessInfo.states != NIL(mdd_t)) {
00174     /* Already computed. */
00175     return mdd_dup(fsm->fairnessInfo.states);
00176   } else {
00177     /* Compute from scratch. */
00178     mdd_t   *fairStates;
00179     array_t *dbgArray = array_alloc(array_t *, 0);
00180 
00181     /* No or trivial fairness constraint */
00182     if (FsmFairnessConstraintIsDefault(constraint)) {
00183       array_t *onionRings;
00184       
00185       fairStates = mdd_one(mddManager);
00186       
00187       onionRings = array_alloc(mdd_t *, 1);
00188       array_insert_last(mdd_t *, onionRings, mdd_one(mddManager));
00189       array_insert_last(array_t *, dbgArray, onionRings);
00190 
00191       fsm->fairnessInfo.states = mdd_dup(fairStates);
00192       fsm->fairnessInfo.dbgArray = dbgArray;
00193     } else {
00194       mdd_t   *oneMdd = mdd_one(mddManager);
00195       array_t *tmpCareSetArray;
00196 
00197       if (careSetArray) {
00198         tmpCareSetArray = careSetArray;
00199       } else {
00200         /* oneMdd is default */
00201         tmpCareSetArray = array_alloc(mdd_t *, 0);
00202         array_insert_last(mdd_t *, tmpCareSetArray, oneMdd);
00203       }
00204 
00205       if (direction == McBwd_c) {
00206         mdd_t *initialStates;
00207         Mc_EarlyTermination_t *earlyTermination;
00208         int fixpoint = 1;
00209         
00210         if (useEarlyTermination == TRUE) {
00211           initialStates = Fsm_FsmComputeInitialStates(fsm);
00212           earlyTermination = Mc_EarlyTerminationAlloc(McSome_c, initialStates);
00213         } else {
00214           initialStates = NIL(mdd_t);
00215           earlyTermination = MC_NO_EARLY_TERMINATION;
00216         }
00217 
00218         fairStates =
00219           Mc_FsmEvaluateEGFormula(fsm,
00220                                   oneMdd, NIL(mdd_t), oneMdd,
00221                                   constraint, tmpCareSetArray,
00222                                   earlyTermination, NIL(array_t),
00223                                   Mc_None_c, &dbgArray,
00224                                   (Mc_VerbosityLevel) verbosity,
00225                                   (Mc_DcLevel) dcLevel,
00226                                   &fixpoint, schedule);
00227         if (useEarlyTermination == TRUE) {
00228           Mc_EarlyTerminationFree(earlyTermination);
00229           mdd_free(initialStates);
00230         }
00231         if (!fixpoint) {
00232           int i;
00233           array_t *mddArray;
00234           arrayForEachItem(array_t *, dbgArray, i, mddArray) {
00235             mdd_array_free(mddArray);
00236           }
00237           array_free(dbgArray);
00238         } else {
00239           fsm->fairnessInfo.states = mdd_dup(fairStates);
00240           fsm->fairnessInfo.dbgArray = dbgArray;
00241         }
00242       } else {
00243         fairStates =
00244           Mc_FsmEvaluateEHFormula(fsm,
00245                                   oneMdd, NIL(mdd_t), oneMdd,
00246                                   constraint, tmpCareSetArray,
00247                                   MC_NO_EARLY_TERMINATION, NIL(array_t),
00248                                   Mc_None_c, NIL(array_t *),
00249                                   (Mc_VerbosityLevel) verbosity,
00250                                   (Mc_DcLevel) dcLevel,
00251                                   NIL(boolean), schedule);
00252         array_free(dbgArray);
00253       }
00254       if (tmpCareSetArray != careSetArray)
00255         array_free(tmpCareSetArray);
00256       mdd_free(oneMdd);
00257     }
00258 
00259     return fairStates;
00260   }/* compute from scratch*/
00261 }
00262 
00263 
00282 Ctlp_Formula_t *
00283 Fsm_FairnessReadFinallyInfFormula(
00284   Fsm_Fairness_t *fairness,
00285   int i,
00286   int j)
00287 {
00288   FairnessConjunct_t *conjunct = FairnessReadConjunct(fairness, i, j);
00289   return (conjunct->finallyInf);
00290 }
00291 
00292 
00311 Ctlp_Formula_t *
00312 Fsm_FairnessReadGloballyInfFormula(
00313   Fsm_Fairness_t *fairness,
00314   int i,
00315   int j)
00316 {
00317   FairnessConjunct_t *conjunct = FairnessReadConjunct(fairness, i, j);
00318   return (conjunct->globallyInf);
00319 }
00320 
00344 mdd_t *
00345 Fsm_FairnessObtainFinallyInfMdd(
00346   Fsm_Fairness_t *fairness,
00347   int i,
00348   int j,
00349   array_t *careSetArray,
00350   Mc_DcLevel dcLevel)
00351 {
00352   Ctlp_Formula_t *formula = Fsm_FairnessReadFinallyInfFormula(fairness, i, j);
00353   /* hard code verbosity to Mc_VerbosityNone */
00354   return(FsmObtainStatesSatisfyingFormula(fairness->fsm, formula, careSetArray,
00355                                           McVerbosityNone_c, dcLevel));
00356 }
00357 
00358 
00382 mdd_t *
00383 Fsm_FairnessObtainGloballyInfMdd(
00384   Fsm_Fairness_t *fairness,
00385   int i,
00386   int j,
00387   array_t *careSetArray,
00388   Mc_DcLevel dcLevel)
00389 {
00390   Ctlp_Formula_t *formula = Fsm_FairnessReadGloballyInfFormula(fairness, i, j);
00391   /* hard code verbosity to Mc_VerbosityNone */
00392   return(FsmObtainStatesSatisfyingFormula(fairness->fsm, formula, careSetArray,
00393                                           McVerbosityNone_c, dcLevel));
00394 
00395 }
00396 
00397 
00411 boolean
00412 Fsm_FairnessTestIsStreett(
00413   Fsm_Fairness_t *fairness)
00414 {
00415   return (array_n(fairness->disjunctArray) == 1);
00416 }
00417 
00418 
00433 boolean
00434 Fsm_FairnessTestIsBuchi(
00435   Fsm_Fairness_t *fairness)
00436 {
00437   if (array_n(fairness->disjunctArray) != 1) {
00438     return (FALSE);
00439   }
00440   else {
00441     int      j;
00442     array_t *disjunct = array_fetch(array_t *, fairness->disjunctArray, 0);
00443 
00444     for (j = 0; j < array_n(disjunct); j++) {
00445       FairnessConjunct_t *conjunct = array_fetch(FairnessConjunct_t *,
00446                                                  disjunct, j);
00447       if (conjunct->globallyInf != NIL(Ctlp_Formula_t)) {
00448         return (FALSE);
00449       }
00450     }
00451     return (TRUE);
00452   }
00453 }
00454 
00455 
00467 int
00468 Fsm_FairnessReadNumDisjuncts(
00469   Fsm_Fairness_t *fairness)
00470 {
00471   return (array_n(fairness->disjunctArray));
00472 }
00473 
00474 
00485 int
00486 Fsm_FairnessReadNumConjunctsOfDisjunct(
00487   Fsm_Fairness_t *fairness,
00488   int i)
00489 {
00490   array_t *disjunct = array_fetch(array_t *, fairness->disjunctArray, i);
00491 
00492   return (array_n(disjunct));
00493 }
00494 
00495 
00514 array_t *
00515 Fsm_FsmReadDebugArray(Fsm_Fsm_t *fsm)
00516 {
00517   return (fsm->fairnessInfo.dbgArray);
00518 }
00519 
00520 
00533 void
00534 Fsm_FsmFairnessUpdate(
00535   Fsm_Fsm_t *fsm,
00536   array_t *formulaArray)
00537 {
00538     Fsm_Fairness_t *fairness = FsmFairnessAlloc(fsm);
00539     int j;
00540     /*
00541      * Interpret the array of CTL formulas as a set of Buchi conditions.
00542      * Hence, create a single disjunct, consisting of k conjuncts, where k is
00543      * the number of CTL formulas read in.  The jth conjunct has the jth
00544      * formula as its finallyInf component, and NULL as its globallyInf
00545      * component.
00546      */
00547     
00548     for (j = 0; j < array_n(formulaArray); j++) {
00549       Ctlp_Formula_t *formula = array_fetch(Ctlp_Formula_t *, formulaArray, j);
00550 
00551       FsmFairnessAddConjunct(fairness, formula, NIL(Ctlp_Formula_t), 0, j);
00552     }
00553 
00554     /*
00555      * Remove any existing fairnessInfo associated with the FSM, and update
00556      * the fairnessInfo.constraint with the new fairness just read.
00557      */
00558     FsmFsmFairnessInfoUpdate(fsm, NIL(mdd_t), fairness, NIL(array_t));
00559 }
00560 
00561 
00562 /*---------------------------------------------------------------------------*/
00563 /* Definition of internal functions                                          */
00564 /*---------------------------------------------------------------------------*/
00565 
00578 Fsm_Fairness_t *
00579 FsmFsmCreateDefaultFairnessConstraint(
00580   Fsm_Fsm_t *fsm)
00581 {
00582   Fsm_Fairness_t *fairness    = FsmFairnessAlloc(fsm);
00583   Ctlp_Formula_t *trueFormula = Ctlp_FormulaCreate(Ctlp_TRUE_c,
00584                                                    NIL(Ctlp_Formula_t),
00585                                                    NIL(Ctlp_Formula_t));
00586 
00587   FsmFairnessAddConjunct(fairness, trueFormula, NIL(Ctlp_Formula_t), 0, 0);
00588   return fairness;
00589 }
00590 
00591 
00604 boolean
00605 FsmFairnessConstraintIsDefault(
00606   Fsm_Fairness_t *fairness)
00607 {
00608   array_t            *disjuncts;
00609   array_t            *conjuncts;
00610   FairnessConjunct_t *leaf;
00611   Ctlp_Formula_t     *tautology;
00612   boolean            result;
00613   
00614   /* one disjunct */
00615   disjuncts = fairness->disjunctArray;
00616   if(array_n(disjuncts) !=  1)
00617     return FALSE;
00618 
00619   /* one conjunct */
00620   conjuncts = array_fetch(array_t *, disjuncts, 0);
00621   if(array_n(conjuncts) != 1)
00622     return FALSE;
00623 
00624   /* set to (GF TRUE * FG NULL) */
00625   leaf = array_fetch(FairnessConjunct_t *, conjuncts, 0);
00626   if(leaf->globallyInf != NIL(Ctlp_Formula_t))
00627     return FALSE;
00628 
00629   tautology = Ctlp_FormulaCreate(Ctlp_TRUE_c, NIL(Ctlp_Formula_t),
00630                                  NIL(Ctlp_Formula_t));
00631   result = Ctlp_FormulaIdentical(tautology, leaf->finallyInf);
00632   Ctlp_FormulaFree(tautology);
00633 
00634   return result;
00635 }
00636 
00637 
00650 void
00651 FsmFairnessFree(
00652   Fsm_Fairness_t *fairness)
00653 {
00654   int i;
00655 
00656   for (i = 0; i < array_n(fairness->disjunctArray); i++) {
00657     int j;
00658     array_t *disjunct = array_fetch(array_t *, fairness->disjunctArray, i);
00659 
00660     for (j = 0; j < array_n(disjunct); j++) {
00661       FairnessConjunct_t *conjunct = array_fetch(FairnessConjunct_t *,
00662                                                  disjunct, j);
00663       Ctlp_FormulaFree(conjunct->finallyInf);
00664       Ctlp_FormulaFree(conjunct->globallyInf);
00665       FREE(conjunct);
00666     }
00667     array_free(disjunct);
00668   }
00669   array_free(fairness->disjunctArray);
00670   FREE(fairness);
00671 }
00672 
00673 
00686 Fsm_Fairness_t *
00687 FsmFairnessAlloc(Fsm_Fsm_t *fsm)
00688 {
00689   Fsm_Fairness_t *fairness = ALLOC(Fsm_Fairness_t, 1);
00690 
00691   fairness->fsm           = fsm;
00692   fairness->disjunctArray = array_alloc(array_t *, 0);
00693 
00694   return fairness;
00695 }
00696 
00697 
00713 void
00714 FsmFairnessAddConjunct(
00715   Fsm_Fairness_t *fairness,
00716   Ctlp_Formula_t *finallyInf,
00717   Ctlp_Formula_t *globallyInf,
00718   int             i,
00719   int             j)
00720 {
00721   int k;
00722   array_t *disjunct;
00723   int numConjuncts;
00724   int                 numDisjuncts = array_n(fairness->disjunctArray);
00725   FairnessConjunct_t *conjunct     = ALLOC(FairnessConjunct_t, 1);
00726 
00727   assert((i >= 0) && (j >= 0));
00728 
00729   /* Get the array for row i. */
00730   if (i >= numDisjuncts) {
00731     /*
00732      * i is out of range.  Create a new disjunct, add it to the array, and
00733      * zero out the intervening entries.
00734      */
00735     disjunct = array_alloc(FairnessConjunct_t *, 0);
00736 
00737     /* Note that the array is dynamically extended. */
00738     array_insert(array_t *, fairness->disjunctArray, i, disjunct);
00739 
00740     /* Zero out the holes just created (if any). */
00741     for (k = numDisjuncts; k < i; k++) {
00742       array_insert(array_t *, fairness->disjunctArray, k, NIL(array_t));
00743     }
00744   }
00745   else {
00746     /*
00747      * i is in range.  However, there may not be a non-NIL array at entry i
00748      * yet.
00749      */
00750     disjunct = array_fetch(array_t *, fairness->disjunctArray, i);
00751     if (disjunct == NIL(array_t)) {
00752       disjunct = array_alloc(FairnessConjunct_t *, 0);
00753       array_insert(array_t *, fairness->disjunctArray, i, disjunct);
00754     }
00755   }
00756 
00757   /*
00758    * Fill in the conjunct, and add it to the jth position of the ith row.  If
00759    * holes are created, then zero them out.
00760    */
00761   conjunct->finallyInf  = finallyInf;
00762   conjunct->globallyInf = globallyInf;
00763 
00764   array_insert(FairnessConjunct_t *, disjunct, j, conjunct);
00765   numConjuncts = array_n(disjunct);
00766   for (k = numConjuncts; k < j; k++) {
00767     array_insert(FairnessConjunct_t *, disjunct, k, NIL(FairnessConjunct_t));
00768   }
00769 }
00770 
00771 
00783 void
00784 FsmFsmFairnessInfoUpdate(
00785   Fsm_Fsm_t *fsm,
00786   mdd_t *states,
00787   Fsm_Fairness_t *constraint,
00788   array_t *dbgArray)
00789 {
00790   array_t *oldDbgArray = fsm->fairnessInfo.dbgArray;
00791 
00792   if (fsm->fairnessInfo.states != NIL(mdd_t)){
00793     mdd_free(fsm->fairnessInfo.states);
00794   }
00795   fsm->fairnessInfo.states = states;
00796 
00797   if (fsm->fairnessInfo.constraint != NIL(Fsm_Fairness_t)) {
00798     FsmFairnessFree(fsm->fairnessInfo.constraint);
00799   }
00800   fsm->fairnessInfo.constraint = constraint;
00801 
00802   if (oldDbgArray != NIL(array_t)) {
00803     int i;
00804     for (i = 0; i < array_n(oldDbgArray); i++) {
00805       array_t *mddArray = array_fetch(array_t *, oldDbgArray, i);
00806       mdd_array_free(mddArray);
00807     }
00808     array_free(oldDbgArray);
00809   }
00810   fsm->fairnessInfo.dbgArray = dbgArray;
00811 }
00812 
00813 
00814 
00815 /*---------------------------------------------------------------------------*/
00816 /* Definition of static functions                                            */
00817 /*---------------------------------------------------------------------------*/
00818 
00832 static FairnessConjunct_t *
00833 FairnessReadConjunct(
00834   Fsm_Fairness_t *fairness,
00835   int i,
00836   int j)
00837 {
00838   array_t            *disjunct;
00839   FairnessConjunct_t *conjunct;
00840 
00841   assert((i >= 0) && (i < array_n(fairness->disjunctArray)));
00842   disjunct = array_fetch(array_t *, fairness->disjunctArray, i);
00843 
00844   assert((j >= 0) && (j < array_n(disjunct)));
00845   conjunct = array_fetch(FairnessConjunct_t *, disjunct, j);
00846 
00847   return conjunct;
00848 }
00849 
00850 
00867 static mdd_t *
00868 FsmObtainStatesSatisfyingFormula(
00869   Fsm_Fsm_t      *fsm,
00870   Ctlp_Formula_t *formula,
00871   array_t *careSetArray,
00872   Mc_VerbosityLevel verbosity,
00873   Mc_DcLevel dcLevel)
00874 {
00875   if (formula == NIL(Ctlp_Formula_t)) {
00876     return (NIL(mdd_t));
00877   }
00878   else {
00879     mdd_t *stateSet = Ctlp_FormulaObtainStates(formula);
00880 
00881     if (stateSet != NIL(mdd_t)) {
00882       return stateSet;
00883     }
00884     else {
00885       mdd_t          *result;
00886       mdd_manager    *mddManager  = Fsm_FsmReadMddManager(fsm);
00887       mdd_t          *oneMdd      = mdd_one(mddManager);
00888       Ctlp_Formula_t *convFormula =
00889                         Ctlp_FormulaConvertToExistentialForm(formula);
00890 
00891       /* Note that Mc_FsmEvaluateFormula returns a copy of the MDD. */
00892       result = Mc_FsmEvaluateFormula(fsm, convFormula, oneMdd,
00893                                      NIL(Fsm_Fairness_t),
00894                                      careSetArray,
00895                                      MC_NO_EARLY_TERMINATION,
00896                                      NIL(Fsm_HintsArray_t),
00897                                      Mc_None_c, verbosity, dcLevel, 0,
00898                                      McGSH_EL_c);
00899       mdd_free(oneMdd);
00900 
00901       /*
00902        * We must make a copy of the MDD for the return value.
00903        */
00904       Ctlp_FormulaSetStates(formula, result);
00905       stateSet = mdd_dup(result);
00906 
00907       Ctlp_FormulaFree(convFormula);
00908 
00909       return stateSet;
00910     }
00911   }
00912 }