VIS

src/mc/mcSCC.c

Go to the documentation of this file.
00001 
00025 #include "mcInt.h"
00026 
00027 /*#define  SCC_NO_TRIM */
00028 
00029 /*---------------------------------------------------------------------------*/
00030 /* Constant declarations                                                     */
00031 /*---------------------------------------------------------------------------*/
00032 
00033 /*---------------------------------------------------------------------------*/
00034 /* Stucture declarations                                                     */
00035 /*---------------------------------------------------------------------------*/
00036 struct GraphNodeSpineSet {
00037   mdd_t *states;  /* V    */
00038   mdd_t *spine;   /* S    */
00039   mdd_t *node;    /* Node */
00040 };
00041 
00042 /*---------------------------------------------------------------------------*/
00043 /* Type declarations                                                         */
00044 /*---------------------------------------------------------------------------*/
00045 typedef struct GraphNodeSpineSet gns_t;
00046 
00047 /*---------------------------------------------------------------------------*/
00048 /* Variable declarations                                                     */
00049 /*---------------------------------------------------------------------------*/
00050 
00051 #ifndef lint
00052 static char rcsid[] UNUSED = "$Id: mcSCC.c,v 1.11 2005/05/18 19:35:19 jinh Exp $";
00053 #endif
00054 
00055 /*---------------------------------------------------------------------------*/
00056 /* Macro declarations                                                        */
00057 /*---------------------------------------------------------------------------*/
00058 
00061 /*---------------------------------------------------------------------------*/
00062 /* Static function prototypes                                                */
00063 /*---------------------------------------------------------------------------*/
00064 
00065 static mdd_t * LockstepPickSeed(Fsm_Fsm_t *fsm, mdd_t *V, array_t *buechiFairness, array_t *onionRings, int ringIndex);
00066 static void LockstepQueueEnqueue(Fsm_Fsm_t *fsm, Heap_t *queue, mdd_t *states, array_t *onionRings, McLockstepMode mode, array_t *buechiFairness, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
00067 static void LinearstepQueueEnqueue(Fsm_Fsm_t *fsm, Heap_t *queue, mdd_t *states, mdd_t *spine, mdd_t *node, array_t *onionRings, McLockstepMode mode, array_t *buechiFairness, Mc_VerbosityLevel verbosity, Mc_DcLevel dcLevel);
00068 static int GetSccEnumerationMethod( void );
00069 
00073 /*---------------------------------------------------------------------------*/
00074 /* Definition of exported functions                                          */
00075 /*---------------------------------------------------------------------------*/
00076 
00077 
00093 Mc_SccGen_t *
00094 Mc_FsmFirstScc(
00095   Fsm_Fsm_t *fsm,
00096   mdd_t **scc,
00097   array_t *sccClosedSetArray,
00098   array_t *buechiFairness,
00099   array_t *onionRings,
00100   boolean earlyTermination,
00101   Mc_VerbosityLevel verbosity,
00102   Mc_DcLevel dcLevel)
00103 {
00104   Mc_SccGen_t *gen;
00105   Heap_t      *heap;
00106   int         i;
00107   mdd_t       *closedSet;
00108   int         linearStepMethod;
00109 
00110   if (fsm == NIL(Fsm_Fsm_t)) return NIL(Mc_SccGen_t);
00111 
00112   /* Allocate generator and initialize it. */
00113   gen = ALLOC(Mc_SccGen_t, 1);
00114   if (gen == NIL(Mc_SccGen_t))  return NIL(Mc_SccGen_t);
00115 
00116   gen->fsm = fsm;
00117   gen->heap = heap = Heap_HeapInit(1);
00118   gen->rings = onionRings;
00119   gen->buechiFairness = buechiFairness;
00120   gen->earlyTermination = earlyTermination;
00121   gen->verbosity = verbosity;
00122   gen->dcLevel = dcLevel;
00123   gen->totalExamined = 0;
00124   gen->nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
00125   gen->nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
00126 
00127   linearStepMethod = GetSccEnumerationMethod();
00128   /* Initialize the heap from the given sets of states. */
00129   arrayForEachItem(mdd_t *, sccClosedSetArray, i, closedSet) {
00130     if (linearStepMethod == 1) {
00131       mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
00132       LinearstepQueueEnqueue(fsm, heap, mdd_dup(closedSet), 
00133                              mdd_zero(mddManager),
00134                              mdd_zero(mddManager), onionRings,
00135                              McLS_none_c, buechiFairness, verbosity, dcLevel);
00136     }else {
00137       LockstepQueueEnqueue(fsm, heap, mdd_dup(closedSet), onionRings,
00138                            McLS_none_c, buechiFairness, verbosity, dcLevel);
00139     }
00140   }
00141   /* Find first SCC. */
00142   if (Heap_HeapCount(heap) == 0) {
00143     *scc = NIL(mdd_t);
00144   } else {
00145     if (linearStepMethod == 1)
00146       *scc = McFsmComputeOneFairSccByLinearStep(fsm, heap, buechiFairness,
00147                                                 onionRings, earlyTermination,
00148                                                 verbosity, dcLevel,
00149                                                 &(gen->totalExamined));
00150     else
00151       *scc = McFsmComputeOneFairSccByLockStep(fsm, heap, buechiFairness,
00152                                               onionRings, earlyTermination,
00153                                               verbosity, dcLevel,
00154                                               &(gen->totalExamined));
00155   }
00156   if (*scc == NIL(mdd_t)) {
00157     gen->status = McSccGenEmpty_c;
00158     gen->fairSccsFound = 0;
00159   } else {
00160     gen->status = McSccGenNonEmpty_c;
00161     gen->fairSccsFound = 1;
00162   }
00163   return gen;
00164 
00165 } /* Mc_FsmFirstScc */
00166 
00167 
00181 boolean
00182 Mc_FsmNextScc(
00183   Mc_SccGen_t *gen,
00184   mdd_t **scc)
00185 {
00186   int linearStepMethod;
00187 
00188   if (gen->earlyTermination == TRUE) {
00189     gen->status = McSccGenEmpty_c;
00190     return FALSE;
00191   }
00192   linearStepMethod = GetSccEnumerationMethod();
00193   if (linearStepMethod == 1) 
00194     *scc = McFsmComputeOneFairSccByLinearStep(gen->fsm, gen->heap,
00195                                               gen->buechiFairness, gen->rings,
00196                                               gen->earlyTermination,
00197                                               gen->verbosity, gen->dcLevel,
00198                                               &(gen->totalExamined));
00199   else
00200     *scc = McFsmComputeOneFairSccByLockStep(gen->fsm, gen->heap,
00201                                             gen->buechiFairness, gen->rings,
00202                                             gen->earlyTermination,
00203                                             gen->verbosity, gen->dcLevel,
00204                                             &(gen->totalExamined));
00205   if (*scc == NIL(mdd_t)) {
00206     gen->status = McSccGenEmpty_c;
00207     return FALSE;
00208   } else {
00209     gen->status = McSccGenNonEmpty_c;
00210     gen->fairSccsFound++;
00211     return TRUE;
00212   }
00213 
00214 } /* Mc_FsmNextScc */
00215 
00216 
00228 boolean
00229 Mc_FsmIsSccGenEmpty(
00230   Mc_SccGen_t *gen)
00231 {
00232   if (gen == NIL(Mc_SccGen_t)) return TRUE;
00233   return gen->status == McSccGenEmpty_c;
00234 
00235 } /* Mc_FsmIsSccGenEmpty */
00236 
00237 
00254 boolean
00255 Mc_FsmSccGenFree(
00256   Mc_SccGen_t *gen,
00257   array_t *leftover)    
00258 {
00259   int linearStepMethod;
00260 
00261   if (gen == NIL(Mc_SccGen_t)) return FALSE;
00262   /* Print some stats. */
00263   if (gen->verbosity == McVerbositySome_c || gen->verbosity == McVerbosityMax_c) {
00264     fprintf(vis_stdout,
00265             "--SCC: found %d fair SCC(s) out of %d examined\n",
00266             gen->fairSccsFound, gen->totalExamined);
00267     fprintf(vis_stdout,
00268             "--SCC: %d image computations, %d preimage computations\n",
00269             Img_GetNumberOfImageComputation(Img_Forward_c) - gen->nImgComps,
00270             Img_GetNumberOfImageComputation(Img_Backward_c) - gen->nPreComps);
00271   }
00272   /* Create array from elements still on queue if so requested. */
00273   linearStepMethod = GetSccEnumerationMethod();
00274   if (linearStepMethod == 1) {
00275     while (Heap_HeapCount(gen->heap)) {
00276       gns_t *set;
00277       long index;
00278       int retval UNUSED = Heap_HeapExtractMin(gen->heap, &set, &index);
00279       assert(retval);
00280       if (leftover == NIL(array_t) || gen->earlyTermination == TRUE) {
00281         mdd_free(set->states); 
00282       } else {
00283         array_insert_last(mdd_t *, leftover, set->states);
00284       }
00285       mdd_free(set->spine); mdd_free(set->node);
00286       FREE(set);
00287     }
00288   }else {
00289     while (Heap_HeapCount(gen->heap)) {
00290       mdd_t *set;
00291       long index;
00292       int retval UNUSED = Heap_HeapExtractMin(gen->heap, &set, &index);
00293       assert(retval);
00294       if (leftover == NIL(array_t) || gen->earlyTermination == TRUE) {
00295         mdd_free(set);
00296       } else {
00297         array_insert_last(mdd_t *, leftover, set);
00298       }
00299     }
00300   }
00301 
00302   Heap_HeapFree(gen->heap);
00303   FREE(gen);
00304   return FALSE;
00305 
00306 } /* Mc_FsmSccGenFree */
00307 
00308 
00327 mdd_t *
00328 McFsmComputeFairSCCsByLockStep(
00329   Fsm_Fsm_t *fsm,
00330   int maxNumberOfSCCs,
00331   array_t *SCCs,
00332   array_t *onionRingsArrayForDbg,
00333   Mc_VerbosityLevel verbosity,
00334   Mc_DcLevel dcLevel)
00335 {
00336   Mc_SccGen_t *sccGen;
00337   mdd_t *mddOne, *reached, *hull, *scc, *fairStates;
00338   array_t *onionRings, *sccClosedSetArray, *careStatesArray;
00339   mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
00340   int nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
00341   int nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
00342   Fsm_Fairness_t *modelFairness = Fsm_FsmReadFairnessConstraint(fsm);
00343   array_t *buechiFairness = array_alloc(mdd_t *, 0);
00344 
00345   /* Initialization. */
00346   mddOne = mdd_one(mddManager);
00347 
00348   sccClosedSetArray = array_alloc(mdd_t *, 0);
00349   reached = Fsm_FsmComputeReachableStates(fsm, 0, verbosity, 0, 0, 1, 0, 0,
00350                                           Fsm_Rch_Default_c, 0, 0,
00351                                           NIL(array_t), FALSE, NIL(array_t));
00352   array_insert_last(mdd_t *, sccClosedSetArray, reached);
00353   onionRings = Fsm_FsmReadReachabilityOnionRings(fsm);
00354 
00355   careStatesArray = array_alloc(mdd_t *, 0);
00356   array_insert_last(mdd_t *, careStatesArray, reached);
00357   Img_MinimizeTransitionRelation(Fsm_FsmReadOrCreateImageInfo(fsm, 1, 1),
00358                                  careStatesArray, Img_DefaultMinimizeMethod_c,
00359                                  Img_Both_c, FALSE);
00360 
00361   /* Read fairness constraints. */
00362   if (modelFairness != NIL(Fsm_Fairness_t)) {
00363     if (!Fsm_FairnessTestIsBuchi(modelFairness)) {
00364       (void) fprintf(vis_stdout,
00365                "** mc error: non-Buechi fairness constraints not supported\n");
00366       array_free(buechiFairness);
00367       return NIL(mdd_t);
00368     } else {
00369       int j;
00370       int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0);
00371       for (j = 0; j < numBuchi; j++) {
00372         mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j,
00373                                                         careStatesArray,
00374                                                         dcLevel);
00375         array_insert_last(mdd_t *, buechiFairness, tmpMdd);
00376       }
00377     }
00378   } else {
00379     array_insert_last(mdd_t *, buechiFairness, mdd_one(mddManager));
00380   }
00381 
00382   /* Enumerate the fair SCCs and accumulate their disjunction in hull. */
00383   hull = mdd_zero(mddManager);
00384   Mc_FsmForEachFairScc(fsm, sccGen, scc, sccClosedSetArray, NIL(array_t),
00385                        buechiFairness, onionRings,
00386                        maxNumberOfSCCs == MC_LOCKSTEP_EARLY_TERMINATION,
00387                        verbosity, dcLevel) {
00388     mdd_t *tmp = mdd_or(hull, scc, 1, 1);
00389     mdd_free(hull);
00390     hull = tmp;
00391     array_insert_last(mdd_t *, SCCs, scc);
00392     if (maxNumberOfSCCs > MC_LOCKSTEP_ALL_SCCS &&
00393         array_n(SCCs) == maxNumberOfSCCs) {
00394       Mc_FsmSccGenFree(sccGen, NIL(array_t));
00395       break;
00396     }
00397   }
00398 
00399   /* Compute (subset of) fair states and onion rings. */
00400   if (onionRingsArrayForDbg != NIL(array_t)) {
00401     mdd_t *fairSet;
00402     int i;
00403     fairStates = Mc_FsmEvaluateEUFormula(fsm, reached, hull,
00404                                          NIL(mdd_t), mddOne, careStatesArray,
00405                                          MC_NO_EARLY_TERMINATION,
00406                                          NIL(array_t), Mc_None_c, NIL(array_t),
00407                                          verbosity, dcLevel, NIL(boolean));
00408     arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
00409       mdd_t *restrictedFairSet = mdd_and(fairSet, hull, 1, 1);
00410       array_t *setOfRings = array_alloc(mdd_t *, 0);
00411       mdd_t *EU = Mc_FsmEvaluateEUFormula(fsm, fairStates, restrictedFairSet,
00412                                           NIL(mdd_t), mddOne, careStatesArray,
00413                                           MC_NO_EARLY_TERMINATION,
00414                                           NIL(array_t), Mc_None_c, setOfRings,
00415                                           verbosity, dcLevel, NIL(boolean));
00416       array_insert_last(array_t *, onionRingsArrayForDbg, setOfRings);
00417       mdd_free(restrictedFairSet);
00418       mdd_free(EU);
00419     }
00420   } else {
00421     fairStates = mdd_dup(hull);
00422   }
00423   if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
00424     fprintf(vis_stdout,
00425             "--Fair States: %d image computations, %d preimage computations\n",
00426             Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps,
00427             Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
00428   }
00429 
00430   /* Clean up. */
00431   array_free(sccClosedSetArray);
00432   mdd_free(reached);
00433   mdd_free(hull);
00434   mdd_free(mddOne);
00435   array_free(careStatesArray);
00436   mdd_array_free(buechiFairness);
00437   return fairStates;
00438 
00439 } /* McFsmComputeFairSCCsByLockStep */
00440 
00455 mdd_t *
00456 McFsmRefineFairSCCsByLockStep(
00457   Fsm_Fsm_t *fsm,
00458   int maxNumberOfSCCs,
00459   array_t *SCCs,
00460   array_t *sccClosedSets,
00461   array_t *careStates,
00462   array_t *onionRingsArrayForDbg,
00463   Mc_VerbosityLevel verbosity,
00464   Mc_DcLevel dcLevel)
00465 {
00466   Mc_SccGen_t *sccGen;
00467   mdd_t *mddOne, *reached, *hull, *scc, *fairStates;
00468   array_t *onionRings, *careStatesArray, *sccClosedSetArray;
00469   mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
00470   int nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
00471   int nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
00472   Fsm_Fairness_t *modelFairness = Fsm_FsmReadFairnessConstraint(fsm);
00473   array_t *buechiFairness = array_alloc(mdd_t *, 0);
00474 
00475   /* Initialization. */
00476   mddOne = mdd_one(mddManager);
00477 
00478   if (careStates == NIL(array_t)) {
00479     reached = Fsm_FsmComputeReachableStates(fsm, 0, verbosity, 0, 0, 1, 0, 0,
00480                                             Fsm_Rch_Default_c, 0, 0,
00481                                             NIL(array_t), FALSE, NIL(array_t));
00482     careStatesArray = array_alloc(mdd_t *, 0);
00483     array_insert_last(mdd_t *, careStatesArray, mdd_dup(reached));
00484   }else {
00485     reached = McMddArrayAnd(careStates);
00486     careStatesArray = mdd_array_duplicate(careStates);
00487   }
00488 
00489   onionRings = Fsm_FsmReadReachabilityOnionRings(fsm);
00490   if (onionRings == NIL(array_t)) {
00491     onionRings = array_alloc(mdd_t *, 0);
00492     array_insert_last(mdd_t *, onionRings, mdd_dup(mddOne));
00493   }else
00494     onionRings = mdd_array_duplicate(onionRings);
00495 
00496   if (sccClosedSets == NIL(array_t)) {
00497     sccClosedSetArray = array_alloc(mdd_t *, 0);
00498     array_insert_last(mdd_t *, sccClosedSetArray, mdd_dup(reached));
00499   }else {
00500     if (careStates != NIL(array_t))
00501       sccClosedSetArray = mdd_array_duplicate(sccClosedSets);
00502     else {
00503       mdd_t *mdd1, *mdd2;
00504       int i;
00505       sccClosedSetArray = array_alloc(mdd_t *, 0);
00506       arrayForEachItem(mdd_t *, sccClosedSets, i, mdd1) {
00507         mdd2 = mdd_and(mdd1, reached, 1, 1);
00508         if (mdd_is_tautology(mdd2, 0)) 
00509           mdd_free(mdd2);
00510         else
00511           array_insert_last(mdd_t *, sccClosedSetArray, mdd2);
00512       }
00513     }
00514   }
00515 
00516   Img_MinimizeTransitionRelation(Fsm_FsmReadOrCreateImageInfo(fsm, 1, 1),
00517                                  careStatesArray, Img_DefaultMinimizeMethod_c,
00518                                  Img_Both_c, FALSE);
00519 
00520   /* Read fairness constraints. */
00521   if (modelFairness != NIL(Fsm_Fairness_t)) {
00522     if (!Fsm_FairnessTestIsBuchi(modelFairness)) {
00523       (void) fprintf(vis_stdout,
00524                "** mc error: non-Buechi fairness constraints not supported\n");
00525       array_free(buechiFairness);
00526       mdd_array_free(sccClosedSetArray);
00527       mdd_array_free(onionRings);
00528       mdd_array_free(careStatesArray);
00529       mdd_free(reached);
00530       return NIL(mdd_t);
00531     } else {
00532       int j;
00533       int numBuchi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0);
00534       for (j = 0; j < numBuchi; j++) {
00535         mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j,
00536                                                         careStatesArray,
00537                                                         dcLevel);
00538         array_insert_last(mdd_t *, buechiFairness, tmpMdd);
00539       }
00540     }
00541   } else {
00542     array_insert_last(mdd_t *, buechiFairness, mdd_one(mddManager));
00543   }
00544 
00545   /* Enumerate the fair SCCs and accumulate their disjunction in hull. */
00546   hull = mdd_zero(mddManager);
00547   Mc_FsmForEachFairScc(fsm, sccGen, scc, sccClosedSetArray, NIL(array_t),
00548                        buechiFairness, onionRings,
00549                        maxNumberOfSCCs == MC_LOCKSTEP_EARLY_TERMINATION,
00550                        verbosity, dcLevel) {
00551     mdd_t *tmp = mdd_or(hull, scc, 1, 1);
00552     mdd_free(hull);
00553     hull = tmp;
00554     array_insert_last(mdd_t *, SCCs, scc);
00555     if (maxNumberOfSCCs > MC_LOCKSTEP_ALL_SCCS &&
00556         array_n(SCCs) == maxNumberOfSCCs) {
00557       Mc_FsmSccGenFree(sccGen, NIL(array_t));
00558       break;
00559     }
00560   }
00561 
00562   /* Compute (subset of) fair states and onion rings. */
00563   if (onionRingsArrayForDbg != NIL(array_t)) {
00564     mdd_t *fairSet;
00565     int i;
00566     fairStates = Mc_FsmEvaluateEUFormula(fsm, reached, hull,
00567                                          NIL(mdd_t), mddOne, careStatesArray,
00568                                          MC_NO_EARLY_TERMINATION,
00569                                          NIL(array_t), Mc_None_c, NIL(array_t),
00570                                          verbosity, dcLevel, NIL(boolean));
00571     arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
00572       mdd_t *restrictedFairSet = mdd_and(fairSet, hull, 1, 1);
00573       array_t *setOfRings = array_alloc(mdd_t *, 0);
00574       mdd_t *EU = Mc_FsmEvaluateEUFormula(fsm, fairStates, restrictedFairSet,
00575                                           NIL(mdd_t), mddOne, careStatesArray,
00576                                           MC_NO_EARLY_TERMINATION,
00577                                           NIL(array_t), Mc_None_c, setOfRings,
00578                                           verbosity, dcLevel, NIL(boolean));
00579       array_insert_last(array_t *, onionRingsArrayForDbg, setOfRings);
00580       mdd_free(restrictedFairSet);
00581       mdd_free(EU);
00582     }
00583   } else {
00584     fairStates = mdd_dup(hull);
00585   }
00586   if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
00587     fprintf(vis_stdout,
00588             "--Fair States: %d image computations, %d preimage computations\n",
00589             Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps,
00590             Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
00591   }
00592 
00593   /* Clean up. */
00594   mdd_array_free(sccClosedSetArray);
00595   mdd_free(reached);
00596   mdd_free(hull);
00597   mdd_free(mddOne);
00598   mdd_array_free(careStatesArray);
00599   mdd_array_free(buechiFairness);
00600   return fairStates;
00601 
00602 } /* McFsmRefineFairSCCsByLockStep */
00603 
00604 
00641 mdd_t *
00642 McFsmComputeOneFairSccByLinearStep( 
00643   Fsm_Fsm_t *fsm,
00644   Heap_t *priorityQueue,
00645   array_t *buechiFairness,
00646   array_t *onionRings,
00647   boolean earlyTermination,
00648   Mc_VerbosityLevel verbosity,
00649   Mc_DcLevel dcLevel,
00650   int *sccExamined)
00651 {
00652   mdd_t *mddOne, *SCC = NIL(mdd_t);
00653   mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
00654   int nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
00655   int nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
00656   array_t *careStatesArray = array_alloc(mdd_t *, 0);
00657   int totalSCCs = 0;
00658   boolean foundScc = FALSE;
00659   array_t *activeFairness = NIL(array_t);
00660   int firstActive = 0;
00661   gns_t *gns;
00662 
00663   /* Initialization. */
00664   mddOne = mdd_one(mddManager);
00665   array_insert(mdd_t *, careStatesArray, 0, mddOne); 
00666 
00667   while (Heap_HeapCount(priorityQueue)) {
00668     mdd_t *V, *F, *fFront, *bFront, *fairSet;
00669     mdd_t *S, *NODE, *newS, *newNODE, *preNODE;
00670     long ringIndex;
00671     int retval UNUSED = Heap_HeapExtractMin(priorityQueue, &gns, 
00672                                             &ringIndex);
00673     assert(retval && ringIndex < array_n(onionRings));
00674 
00675     /* Extract the SCC-closed set, together with its spine-set */
00676     V = gns->states;
00677     S = gns->spine;
00678     NODE = gns->node;
00679     FREE(gns);
00680 
00681     /* Determine the seed for which the SCC is computed */
00682     if (mdd_is_tautology(S, 0) ) {
00683       assert( mdd_is_tautology(NODE, 0) );
00684       mdd_free(NODE);
00685       NODE = LockstepPickSeed(fsm, V, buechiFairness, onionRings, ringIndex);
00686     } 
00687 
00688     if (earlyTermination == TRUE) {
00689       int i;
00690       activeFairness = array_alloc(mdd_t *, 0);
00691       for (i = 0; i < array_n(buechiFairness); i++) {
00692         mdd_t *fairSet = array_fetch(mdd_t *, buechiFairness, i);
00693         if (!mdd_lequal(NODE, fairSet, 1, 1)) {
00694           array_insert_last(mdd_t *, activeFairness, fairSet);
00695         }
00696       }
00697     }
00698     
00699     /* Compute the forward-set of seed, together with a new spine-set */
00700     {
00701       array_t *newCareStatesArray = array_alloc(mdd_t *, 0);
00702       array_t *stack = array_alloc(mdd_t *, 0);
00703       mdd_t   *tempMdd, *tempMdd2;
00704       int i;
00705       /* (1) Compute the forward-set, and push it onto STACK */
00706       F = mdd_zero(mddManager);
00707       fFront = mdd_dup(NODE);
00708       while (!mdd_is_tautology(fFront, 0)) {
00709         array_insert_last(mdd_t *, stack, mdd_dup(fFront));
00710 
00711         tempMdd = F;
00712         F = mdd_or(F, fFront, 1, 1);
00713         mdd_free(tempMdd);
00714 
00715         tempMdd = Mc_FsmEvaluateEYFormula(fsm, fFront, mddOne, careStatesArray,
00716                                           verbosity, dcLevel);
00717         mdd_free(fFront);
00718         tempMdd2 = mdd_and(tempMdd, V, 1, 1);
00719         mdd_free(tempMdd);
00720         fFront = mdd_and(tempMdd2, F, 1, 0);
00721         mdd_free(tempMdd2);
00722       }
00723       mdd_free(fFront);
00724       /* (2) Determine a spine-set of the forward-set */
00725       i = array_n(stack) - 1;
00726       fFront = array_fetch(mdd_t *, stack, i);
00727       newNODE = Mc_ComputeAState(fFront, fsm);
00728       mdd_free(fFront);
00729 
00730       newS = mdd_dup(newNODE);
00731       while (i > 0) {
00732         fFront = array_fetch(mdd_t *, stack, --i);
00733         /* Chao: The use of DCs here may slow down the computation,
00734          *       even though it reduces the peak BDD size
00735          */
00736         /* array_insert(mdd_t *, newCareStatesArray, 0, fFront); */
00737         array_insert(mdd_t *, newCareStatesArray, 0, mddOne);
00738         tempMdd = Mc_FsmEvaluateEXFormula(fsm, newS, mddOne, newCareStatesArray,
00739                                           verbosity, dcLevel);
00740         tempMdd2 = mdd_and(tempMdd, fFront, 1, 1);
00741         mdd_free(tempMdd);
00742         mdd_free(fFront);
00743         
00744         tempMdd = Mc_ComputeAState(tempMdd2, fsm);
00745         mdd_free(tempMdd2);
00746 
00747         tempMdd2 = newS;
00748         newS = mdd_or(newS, tempMdd, 1, 1);
00749         mdd_free(tempMdd2);
00750         mdd_free(tempMdd);
00751       }
00752       array_free(stack);
00753       array_free(newCareStatesArray);
00754     }
00755     /* now, we have {F, newS, newNODE} */
00756     
00757     /* Determine the SCC containing NODE */
00758     SCC    = mdd_dup(NODE);
00759     bFront = mdd_dup(NODE);
00760     while (1) {
00761       mdd_t   *tempMdd, *tempMdd2;
00762 
00763       if (earlyTermination == TRUE) {
00764         mdd_t * meet = mdd_and(SCC, NODE, 1, 0);
00765         if (!mdd_is_tautology(meet, 0)) {
00766           assert(mdd_lequal(meet, V, 1, 1));
00767           for ( ; firstActive < array_n(activeFairness); firstActive++) {
00768             mdd_t *fairSet = array_fetch(mdd_t *, activeFairness, firstActive);
00769             if (mdd_lequal(meet, fairSet, 1, 0)) break;
00770           }
00771           mdd_free(meet);
00772           if (firstActive == array_n(activeFairness)) {
00773             int i;
00774             (void) fprintf(vis_stdout, "EARLY TERMINATION!\n");
00775             totalSCCs++;
00776             /* Trim fair sets to guarantee counterexample will go through
00777              * this SCC. 
00778              */
00779             for (i = 0; i < array_n(buechiFairness); i++) {
00780               mdd_t *fairSet = array_fetch(mdd_t *, buechiFairness, i);
00781               mdd_t *trimmed = mdd_and(fairSet, SCC, 1, 1);
00782               mdd_free(fairSet);
00783               array_insert(mdd_t *, buechiFairness, i, trimmed);
00784             }
00785             mdd_free(bFront);
00786             mdd_free(F);
00787             mdd_free(V); 
00788             mdd_free(S); 
00789             mdd_free(NODE);
00790             mdd_free(newS);
00791             mdd_free(newNODE);
00792             array_free(activeFairness);
00793 
00794             foundScc = TRUE;
00795             goto cleanUp;
00796           }
00797         }
00798         mdd_free(meet);
00799       }
00800 
00801       tempMdd = Mc_FsmEvaluateEXFormula(fsm, bFront, mddOne, careStatesArray,
00802                                         verbosity, dcLevel);
00803       tempMdd2 = mdd_and(tempMdd, F, 1, 1);
00804       mdd_free(tempMdd);
00805       
00806       tempMdd = bFront;
00807       bFront = mdd_and(tempMdd2, SCC, 1, 0);
00808       mdd_free(tempMdd2);
00809       mdd_free(tempMdd);
00810       if (mdd_is_tautology(bFront, 0))  break;
00811 
00812       tempMdd = SCC;
00813       SCC = mdd_or(SCC, bFront, 1, 1);
00814       mdd_free(tempMdd);
00815     }
00816     mdd_free(bFront);
00817 
00818     totalSCCs++;
00819     preNODE = Mc_FsmEvaluateEYFormula(fsm, NODE, mddOne, careStatesArray,
00820                                     verbosity, dcLevel);
00821      
00822     /* Check for fairness. If SCC is a trival SCC, skip the check */
00823     if ( !mdd_equal(SCC, NODE) ||  mdd_lequal(NODE, preNODE, 1, 1) ) {
00824       /* Check fairness constraints. */
00825       int i;
00826       arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
00827         if (mdd_lequal(SCC, fairSet, 1, 0)) break;
00828       }
00829       if (i == array_n(buechiFairness)) {
00830         /* All fairness iconditions intersected.  We have a fair SCC. */
00831         if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
00832           array_t *PSvars = Fsm_FsmReadPresentStateVars(fsm);
00833           fprintf(vis_stdout, "--linearSCC: found a fair SCC with %.0f states\n",
00834                   mdd_count_onset(mddManager, SCC, PSvars));
00835           /* (void) bdd_print_minterm(SCC); */
00836         }
00837         foundScc = TRUE;
00838       }
00839     }
00840     mdd_free(preNODE);
00841     mdd_free(NODE);
00842 
00843     /* Divide the remaining states of V into V minus
00844      * the forward set F, and the rest (minus the fair SCC).  Add the two
00845      * sets thus obtained to the priority queue. */
00846     {
00847       mdd_t *V1, *S1, *NODE1;
00848       mdd_t *tempMdd, *tempMdd2;
00849 
00850       V1 = mdd_and(V, F, 1, 0);
00851       S1 = mdd_and(S, SCC, 1, 0);
00852       tempMdd = mdd_and(SCC, S, 1, 1);
00853       tempMdd2 = Mc_FsmEvaluateEXFormula(fsm, tempMdd, mddOne, 
00854                                          careStatesArray,
00855                                          verbosity, dcLevel);
00856       mdd_free(tempMdd);
00857       NODE1 = mdd_and(tempMdd2, S1, 1, 1);
00858       mdd_free(tempMdd2);
00859       LinearstepQueueEnqueue(fsm, priorityQueue, V1, S1, NODE1, 
00860                              onionRings, McLS_G_c,
00861                              buechiFairness, verbosity, dcLevel);
00862 
00863       V1 = mdd_and(F, SCC, 1, 0);
00864       S1 = mdd_and(newS, SCC, 1, 0);
00865       NODE1 = mdd_and(newNODE, SCC, 1, 0);
00866       LinearstepQueueEnqueue(fsm, priorityQueue, V1, S1, NODE1,
00867                              onionRings, McLS_H_c,
00868                              buechiFairness, verbosity, dcLevel);
00869     }
00870     mdd_free(F);
00871     mdd_free(V);
00872     mdd_free(S);
00873     mdd_free(newS);
00874     mdd_free(newNODE);
00875     
00876     if (foundScc == TRUE) break;
00877     mdd_free(SCC);
00878   }
00879 
00880 cleanUp:
00881   mdd_free(mddOne);
00882   array_free(careStatesArray);
00883   if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
00884     fprintf(vis_stdout,
00885             "--linearSCC: found %s fair SCC out of %d examined\n",
00886             foundScc ? "one" : "no", totalSCCs);
00887     fprintf(vis_stdout,
00888             "--linearSCC: %d image computations, %d preimage computations\n",
00889             Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps,
00890             Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
00891   }
00892   *sccExamined += totalSCCs;
00893   return foundScc ? SCC : NIL(mdd_t);
00894 
00895 } /* McFsmComputeOneFairSccByLinearStep */
00896 
00897 
00933 mdd_t *
00934 McFsmComputeOneFairSccByLockStep(
00935   Fsm_Fsm_t *fsm,
00936   Heap_t *priorityQueue,
00937   array_t *buechiFairness,
00938   array_t *onionRings,
00939   boolean earlyTermination,
00940   Mc_VerbosityLevel verbosity,
00941   Mc_DcLevel dcLevel,
00942   int *sccExamined)
00943 {
00944   mdd_t *mddOne, *SCC = NIL(mdd_t);
00945   mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
00946   int nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c);
00947   int nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c);
00948   array_t *careStatesArray = array_alloc(mdd_t *, 0);
00949   int totalSCCs = 0;
00950   boolean foundScc = FALSE;
00951   array_t *activeFairness = NIL(array_t);
00952   int firstActive = 0;
00953 
00954   /* Initialization. */
00955   mddOne = mdd_one(mddManager);
00956   array_insert(mdd_t *, careStatesArray, 0, mddOne); 
00957 
00958   while (Heap_HeapCount(priorityQueue)) {
00959     mdd_t *V, *seed, *B, *F, *fFront, *bFront, *fairSet;
00960     mdd_t *converged, *first, *second;
00961     long ringIndex;
00962     McLockstepMode firstMode, secondMode;
00963     int retval UNUSED = Heap_HeapExtractMin(priorityQueue, &V, &ringIndex);
00964     assert(retval && ringIndex < array_n(onionRings));
00965     /* Here, V contains at least one nontrivial SCC. We then choose the
00966      * seed for a new SCC, which may turn out to be trivial. */
00967     seed = LockstepPickSeed(fsm, V, buechiFairness, onionRings, ringIndex);
00968 
00969     if (earlyTermination == TRUE) {
00970       int i;
00971       activeFairness = array_alloc(mdd_t *, 0);
00972       for (i = 0; i < array_n(buechiFairness); i++) {
00973         mdd_t *fairSet = array_fetch(mdd_t *, buechiFairness, i);
00974         if (!mdd_lequal(seed, fairSet, 1, 1)) {
00975           array_insert_last(mdd_t *, activeFairness, fairSet);
00976         }
00977       }
00978     }
00979 
00980     /* Do lockstep search from seed.  Leave the seed initially out of
00981      * F and B to facilitate the detection of trivial SCCs.  Intersect
00982      * all results with V so that we can simplify the transition
00983      * relation. */
00984     fFront = Mc_FsmEvaluateEYFormula(fsm, seed, mddOne, careStatesArray,
00985                                      verbosity, dcLevel);
00986     F = mdd_and(fFront, V, 1, 1);
00987     mdd_free(fFront);
00988     fFront = mdd_dup(F);
00989     bFront = Mc_FsmEvaluateEXFormula(fsm, seed, mddOne, careStatesArray,
00990                                      verbosity, dcLevel);
00991     B = mdd_and(bFront, V , 1, 1);
00992     mdd_free(bFront);
00993     bFront = mdd_dup(B);
00994     /* Go until the fastest search converges. */
00995     while (!(mdd_is_tautology(fFront, 0) || mdd_is_tautology(bFront, 0))) {
00996       mdd_t *tmp;
00997 
00998       /* If the intersection of F and B intersects all fairness
00999        * constraints the union of F and B contains at least one fair
01000        * SCC.  Since the intersection of F and B is monotonically
01001        * non-decreasing, once a fair set has been intersected, there
01002        * is no need to check for it any more. */
01003       if (earlyTermination == TRUE) {
01004         mdd_t * meet = mdd_and(F, B, 1, 1);
01005         if (!mdd_is_tautology(meet, 0)) {
01006           assert(mdd_lequal(meet, V, 1, 1));
01007           for ( ; firstActive < array_n(activeFairness); firstActive++) {
01008             mdd_t *fairSet = array_fetch(mdd_t *, activeFairness, firstActive);
01009             if (mdd_lequal(meet, fairSet, 1, 0)) break;
01010           }
01011           if (firstActive == array_n(activeFairness)) {
01012             int i;
01013             (void) fprintf(vis_stdout, "EARLY TERMINATION!\n");
01014             totalSCCs++;
01015             /* A fair SCC is contained in the union of F, B, and seed. */
01016             tmp = mdd_or(F, B, 1, 1);
01017             SCC = mdd_or(tmp, seed, 1, 1);
01018             mdd_free(tmp);
01019             /* Trim fair sets to guarantee counterexample will go through
01020              * this SCC. */
01021             tmp = mdd_or(meet, seed, 1, 1);
01022             mdd_free(meet);
01023             meet = tmp;
01024             for (i = 0; i < array_n(buechiFairness); i++) {
01025               mdd_t *fairSet = array_fetch(mdd_t *, buechiFairness, i);
01026               mdd_t *trimmed = mdd_and(fairSet, meet, 1, 1);
01027               mdd_free(fairSet);
01028               array_insert(mdd_t *, buechiFairness, i, trimmed);
01029             }
01030             mdd_free(meet);
01031             mdd_free(F); mdd_free(B);
01032             mdd_free(fFront); mdd_free(bFront);
01033             mdd_free(seed); mdd_free(V);
01034             foundScc = TRUE;
01035             array_free(activeFairness);
01036             goto cleanUp;
01037           }
01038         }
01039         mdd_free(meet);
01040       }
01041 
01042       /* Forward step. */
01043       tmp = Mc_FsmEvaluateEYFormula(fsm, fFront, mddOne, careStatesArray,
01044                                     verbosity, dcLevel);
01045       mdd_free(fFront);
01046       fFront = mdd_and(tmp, F, 1, 0);
01047       mdd_free(tmp);
01048       tmp = mdd_and(fFront, V, 1, 1);
01049       mdd_free(fFront);
01050       fFront = tmp;
01051       if (mdd_is_tautology(fFront, 0)) break;
01052       tmp = mdd_or(F, fFront, 1, 1);
01053       mdd_free(F);
01054       F = tmp;
01055       /* Backward step. */
01056       tmp = Mc_FsmEvaluateEXFormula(fsm, bFront, mddOne, careStatesArray,
01057                                     verbosity, dcLevel);
01058       mdd_free(bFront);
01059       bFront = mdd_and(tmp, B, 1, 0);
01060       mdd_free(tmp);
01061       tmp = mdd_and(bFront, V, 1, 1);
01062       mdd_free(bFront);
01063       bFront = tmp;
01064       tmp = mdd_or(B, bFront, 1, 1);
01065       mdd_free(B);
01066       B = tmp;
01067     }
01068     /* Complete the slower search within the converged one. */
01069     if (mdd_is_tautology(fFront, 0)) {
01070       /* Forward search converged. */
01071       mdd_t *tmp = mdd_and(bFront, F, 1, 1);
01072       mdd_free(bFront);
01073       bFront = tmp;
01074       mdd_free(fFront);
01075       converged = mdd_dup(F);
01076       /* The two sets to be enqueued come from a set that has been
01077        * already trimmed.  Hence, we want to remove the trivial SCCs
01078        * left exposed at the rearguard of F, and the trivial SCCs left
01079        * exposed at the vanguard of B. */
01080       firstMode = McLS_H_c;
01081       secondMode = McLS_G_c;
01082       while (!mdd_is_tautology(bFront, 0)) {
01083         tmp =  Mc_FsmEvaluateEXFormula(fsm, bFront, mddOne,
01084                                        careStatesArray, verbosity, dcLevel);
01085         mdd_free(bFront);
01086         bFront = mdd_and(tmp, B, 1, 0);
01087         mdd_free(tmp);
01088         tmp = mdd_and(bFront, converged, 1, 1);
01089         mdd_free(bFront);
01090         bFront = tmp;
01091         tmp = mdd_or(B, bFront, 1, 1);
01092         mdd_free(B);
01093         B = tmp;
01094       }
01095       mdd_free(bFront);
01096     } else {
01097       /* Backward search converged. */
01098       mdd_t *tmp = mdd_and(fFront, B, 1, 1);
01099       mdd_free(fFront);
01100       fFront = tmp;
01101       mdd_free(bFront);
01102       converged = mdd_dup(B);
01103       firstMode = McLS_G_c;
01104       secondMode = McLS_H_c;
01105       while (!mdd_is_tautology(fFront, 0)) {
01106         tmp =  Mc_FsmEvaluateEYFormula(fsm, fFront, mddOne,
01107                                        careStatesArray, verbosity, dcLevel);
01108         mdd_free(fFront);
01109         fFront = mdd_and(tmp, F, 1 ,0);
01110         mdd_free(tmp);
01111         tmp = mdd_and(fFront, converged, 1, 1);
01112         mdd_free(fFront);
01113         fFront = tmp;
01114         tmp = mdd_or(F, fFront, 1, 1);
01115         mdd_free(F);
01116         F = tmp;
01117       }
01118       mdd_free(fFront);
01119     }
01120 
01121     totalSCCs++;
01122     SCC = mdd_and(F, B, 1, 1);
01123     mdd_free(F);
01124     mdd_free(B);
01125     /* Check for fairness.  If SCC is the empty set we know that seed
01126      * is a trivial strong component; hence, it is not fair. */
01127     if (mdd_is_tautology(SCC, 0)) {
01128       mdd_t *tmp = mdd_or(converged, seed, 1, 1);
01129       mdd_free(converged);
01130       converged = tmp;
01131       mdd_free(SCC);
01132       SCC = mdd_dup(seed);
01133     } else {
01134       /* Check fairness constraints. */
01135       int i;
01136       arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
01137         if (mdd_lequal(SCC, fairSet, 1, 0)) break;
01138       }
01139       if (i == array_n(buechiFairness)) {
01140         /* All fairness conditions intersected.  We have a fair SCC. */
01141         if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
01142           array_t *PSvars = Fsm_FsmReadPresentStateVars(fsm);
01143           fprintf(vis_stdout, "--SCC: found a fair SCC with %.0f states\n",
01144                   mdd_count_onset(mddManager, SCC, PSvars));
01145           /* (void) bdd_print_minterm(SCC); */
01146         }
01147         foundScc = TRUE;
01148       }
01149     }
01150     /* Divide the remaining states of V into the converged set minus
01151      * the fair SCC, and the rest (minus the fair SCC).  Add the two
01152      * sets thus obtained to the priority queue. */
01153     mdd_free(seed);
01154     first = mdd_and(converged, SCC, 1, 0);
01155     LockstepQueueEnqueue(fsm, priorityQueue, first, onionRings, firstMode,
01156                          buechiFairness, verbosity, dcLevel);
01157     second = mdd_and(V, converged, 1, 0);
01158     mdd_free(converged);
01159     mdd_free(V);
01160     LockstepQueueEnqueue(fsm, priorityQueue, second, onionRings, secondMode,
01161                          buechiFairness, verbosity, dcLevel);
01162     if (earlyTermination == TRUE) {
01163       array_free(activeFairness);
01164     }
01165     if (foundScc == TRUE) break;
01166     mdd_free(SCC);
01167   }
01168 
01169 cleanUp:
01170   mdd_free(mddOne);
01171   array_free(careStatesArray);
01172   if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) {
01173     fprintf(vis_stdout,
01174             "--SCC: found %s fair SCC out of %d examined\n",
01175             foundScc ? "one" : "no", totalSCCs);
01176     fprintf(vis_stdout,
01177             "--SCC: %d image computations, %d preimage computations\n",
01178             Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps,
01179             Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps);
01180   }
01181   *sccExamined += totalSCCs;
01182   return foundScc ? SCC : NIL(mdd_t);
01183 
01184 } /* McFsmComputeOneFairSccByLockStep */
01185 
01186 
01187 /*---------------------------------------------------------------------------*/
01188 /* Definition of internal functions                                          */
01189 /*---------------------------------------------------------------------------*/
01190 
01191 
01192 /*---------------------------------------------------------------------------*/
01193 /* Definition of static functions                                            */
01194 /*---------------------------------------------------------------------------*/
01195 
01196 
01213 static mdd_t *
01214 LockstepPickSeed(
01215   Fsm_Fsm_t *fsm,
01216   mdd_t *V,
01217   array_t *buechiFairness,
01218   array_t *onionRings,
01219   int ringIndex)
01220 {
01221   mdd_t *seed;
01222   int i, j;
01223 
01224   /* We know that there is at least one state in V from each fairness
01225    * constraint. */
01226   for (i = ringIndex; i < array_n(onionRings); i++) {
01227     mdd_t *ring = array_fetch(mdd_t *, onionRings, i);
01228     for (j = 0; j < array_n(buechiFairness); j++) {
01229       mdd_t *fairSet = array_fetch(mdd_t *, buechiFairness, j);
01230       if (!mdd_lequal_mod_care_set(ring, fairSet, 1, 0, V)) {
01231         mdd_t *tmp = mdd_and(V, ring, 1, 1);
01232         mdd_t *candidates = mdd_and(tmp, fairSet, 1, 1);
01233         mdd_free(tmp);
01234         for (j++; j < array_n(buechiFairness); j++) {
01235           fairSet = array_fetch(mdd_t *, buechiFairness, j);
01236           if (!mdd_lequal(candidates, fairSet, 1, 0)) {
01237             tmp = mdd_and(candidates, fairSet, 1, 1);
01238             mdd_free(candidates);
01239             candidates = tmp;
01240           }
01241         }
01242         seed = Mc_ComputeAState(candidates, fsm);
01243         mdd_free(candidates);
01244         return seed;
01245       }
01246     }
01247   }
01248 
01249   assert(FALSE);                /* we should never get here */
01250   return NIL(bdd_t);
01251 
01252 } /* LockstepPickSeed */
01253 
01254 
01270 static void
01271 LockstepQueueEnqueue(
01272   Fsm_Fsm_t *fsm,
01273   Heap_t *queue,
01274   mdd_t *states,
01275   array_t *onionRings,
01276   McLockstepMode mode,
01277   array_t *buechiFairness,
01278   Mc_VerbosityLevel verbosity,
01279   Mc_DcLevel dcLevel)
01280 {
01281   mdd_t *fairSet, *ring;
01282   int i;
01283   mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
01284   mdd_t *mddOne = mdd_one(mddManager);
01285   array_t *careStatesArray = array_alloc(mdd_t *, 0);
01286   array_insert_last(mdd_t *, careStatesArray, mddOne);
01287 
01288 #ifndef SCC_NO_TRIM
01289   if (mode == McLS_G_c || mode == McLS_GH_c) {
01290     mdd_t *trimmed = Mc_FsmEvaluateEGFormula(fsm, states, NIL(mdd_t), mddOne,
01291                                              NIL(Fsm_Fairness_t),
01292                                              careStatesArray,
01293                                              MC_NO_EARLY_TERMINATION,
01294                                              NIL(array_t),
01295                                              Mc_None_c, NIL(array_t *),
01296                                              verbosity, dcLevel, NIL(boolean),
01297                                              McGSH_EL_c);
01298     mdd_free(states);
01299     states = trimmed;
01300   }
01301   if (mode == McLS_H_c || mode == McLS_GH_c) {
01302     mdd_t *trimmed = Mc_FsmEvaluateEHFormula(fsm, states, NIL(mdd_t), mddOne,
01303                                              NIL(Fsm_Fairness_t),
01304                                              careStatesArray,
01305                                              MC_NO_EARLY_TERMINATION,
01306                                              NIL(array_t),
01307                                              Mc_None_c, NIL(array_t *),
01308                                              verbosity, dcLevel, NIL(boolean),
01309                                              McGSH_EL_c);
01310     mdd_free(states);
01311     states = trimmed;
01312   }
01313 #endif
01314 
01315   mdd_free(mddOne);
01316   array_free(careStatesArray);
01317   if (mode == McLS_none_c) {
01318     mdd_t *range = mdd_range_mdd(mddManager, Fsm_FsmReadPresentStateVars(fsm));
01319     mdd_t *valid = mdd_and(states, range, 1, 1);
01320     mdd_free(range);
01321     mdd_free(states);
01322     states = valid;
01323   }
01324   /* Discard set of states if it does not intersect all fairness conditions. */
01325   arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
01326     if (mdd_lequal(states, fairSet, 1, 0)) {
01327       mdd_free(states);
01328       return;
01329     }
01330   }
01331   /* Find the innermost onion ring intersecting the set of states.
01332    * Its index is the priority of the set. */
01333   arrayForEachItem(mdd_t *, onionRings, i, ring) {
01334     if (!mdd_lequal(states, ring, 1, 0)) break;
01335   }
01336   assert(i < array_n(onionRings));
01337   Heap_HeapInsert(queue,states,i);
01338   return;
01339 
01340 } /* LockstepQueueEnqueue */
01341 
01342 
01358 static void
01359 LinearstepQueueEnqueue(
01360   Fsm_Fsm_t *fsm,
01361   Heap_t *queue,
01362   mdd_t *states,
01363   mdd_t *spine,
01364   mdd_t *node,
01365   array_t *onionRings,
01366   McLockstepMode mode,
01367   array_t *buechiFairness,
01368   Mc_VerbosityLevel verbosity,
01369   Mc_DcLevel dcLevel)
01370 {
01371   mdd_t *fairSet, *ring;
01372   mdd_t *tmp, *tmp1;
01373   int   i;
01374   gns_t *gns;
01375   mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
01376   mdd_t *mddOne = mdd_one(mddManager);
01377   array_t *careStatesArray = array_alloc(mdd_t *, 0);
01378   array_insert_last(mdd_t *, careStatesArray, mddOne);
01379 
01380 #ifndef SCC_NO_TRIM
01381   if (mode == McLS_G_c || mode == McLS_GH_c) {
01382     mdd_t *trimmed = Mc_FsmEvaluateEGFormula(fsm, states, NIL(mdd_t), mddOne,
01383                                              NIL(Fsm_Fairness_t),
01384                                              careStatesArray,
01385                                              MC_NO_EARLY_TERMINATION,
01386                                              NIL(array_t),
01387                                              Mc_None_c, NIL(array_t *),
01388                                              verbosity, dcLevel, NIL(boolean),
01389                                              McGSH_EL_c);
01390     mdd_free(states);
01391     states = trimmed;
01392   }
01393   if (mode == McLS_H_c || mode == McLS_GH_c) {
01394     mdd_t *trimmed = Mc_FsmEvaluateEHFormula(fsm, states, NIL(mdd_t), mddOne,
01395                                              NIL(Fsm_Fairness_t),
01396                                              careStatesArray,
01397                                              MC_NO_EARLY_TERMINATION,
01398                                              NIL(array_t),
01399                                              Mc_None_c, NIL(array_t *),
01400                                              verbosity, dcLevel, NIL(boolean),
01401                                              McGSH_EL_c);
01402     mdd_free(states);
01403     states = trimmed;
01404   }
01405 #endif
01406 
01407   if (mode == McLS_none_c) {
01408     mdd_t *range = mdd_range_mdd(mddManager, Fsm_FsmReadPresentStateVars(fsm));
01409     mdd_t *valid = mdd_and(states, range, 1, 1);
01410     mdd_free(range);
01411     mdd_free(states);
01412     states = valid;
01413   }
01414   /* Discard set of states if it does not intersect all fairness conditions. */
01415   arrayForEachItem(mdd_t *, buechiFairness, i, fairSet) {
01416     if (mdd_lequal(states, fairSet, 1, 0)) {
01417       mdd_free(states);
01418       mdd_free(mddOne);
01419       array_free(careStatesArray);
01420       return;
01421     }
01422   }
01423   /* Find the innermost onion ring intersecting the set of states.
01424    * Its index is the priority of the set. */
01425   arrayForEachItem(mdd_t *, onionRings, i, ring) {
01426     if (!mdd_lequal(states, ring, 1, 0)) break;
01427   }
01428   assert(i < array_n(onionRings));
01429 
01430   /* Trim the spine-set. */
01431   while ( !mdd_lequal(node, states, 1, 1) ) {
01432     tmp = node;
01433     tmp1 =  Mc_FsmEvaluateEXFormula(fsm, node, mddOne,
01434                                     careStatesArray, verbosity, dcLevel);
01435     mdd_free(tmp);
01436     node = mdd_and(tmp1, spine, 1, 1); 
01437     mdd_free(tmp1);
01438   }
01439   
01440   tmp = spine;
01441   spine = mdd_and(spine, states, 1, 1);
01442   mdd_free(tmp);
01443 
01444 #if 0
01445   /* Invariants that should always hold */
01446   assert( mdd_is_tautology(node, 0) == mdd_is_tautology(spine, 0) );
01447   assert(mdd_lequal(node, states, 1, 1));
01448   assert(mdd_lequal(node, spine, 1, 1));
01449   assert(mdd_lequal(spine, states, 1, 1));
01450 #endif
01451 
01452   mdd_free(mddOne);
01453   array_free(careStatesArray);
01454   
01455   gns = ALLOC(gns_t, 1);
01456   gns->states = states;
01457   gns->node = node;
01458   gns->spine = spine;
01459 
01460 
01461   Heap_HeapInsert(queue,gns,i);
01462   return;
01463 
01464 } /* LinearstepQueueEnqueue */
01465 
01466 
01480 static int 
01481 GetSccEnumerationMethod( void )
01482 {
01483   char *flagValue;
01484   int  linearStepMethod = 0;
01485  
01486   flagValue = Cmd_FlagReadByName("scc_method");
01487   if (flagValue != NIL(char)) {
01488     if (strcmp(flagValue, "linearstep") == 0)
01489       linearStepMethod = 1;
01490     else if (strcmp(flagValue, "lockstep") == 0)
01491       linearStepMethod = 0;
01492     else {
01493       fprintf(vis_stderr, "** scc error: invalid scc method %s, method lockstep is used. \n", 
01494               flagValue);
01495     }
01496   }
01497 
01498   return linearStepMethod;
01499 }