VIS

src/ltl/ltlAutomaton.c

Go to the documentation of this file.
00001 
00017 #include "ltlInt.h"
00018 
00019 static char rcsid[] UNUSED = "$Id: ltlAutomaton.c,v 1.34 2005/04/28 08:47:15 bli Exp $";
00020 
00021 /*---------------------------------------------------------------------------*/
00022 /* Constant declarations                                                     */
00023 /*---------------------------------------------------------------------------*/
00024 
00025 /*---------------------------------------------------------------------------*/
00026 /* Structure declarations                                                    */
00027 /*---------------------------------------------------------------------------*/
00028 
00029 /*---------------------------------------------------------------------------*/
00030 /* Type declarations                                                         */
00031 /*---------------------------------------------------------------------------*/
00032 
00033 /*---------------------------------------------------------------------------*/
00034 /* Variable declarations                                                     */
00035 /*---------------------------------------------------------------------------*/
00036 
00037 /*---------------------------------------------------------------------------*/
00038 /* Macro declarations                                                        */
00039 /*---------------------------------------------------------------------------*/
00040 
00043 /*---------------------------------------------------------------------------*/
00044 /* Static function prototypes                                                */
00045 /*---------------------------------------------------------------------------*/
00046 
00047 static int HasToBeStored(LtlTableau_t *tableau, int index);
00048 static int Contradiction(LtlTableau_t *tableau, int index, LtlSet_t *ToCover, LtlSet_t *Current, LtlSet_t *Covered);
00049 static int Redundant(LtlTableau_t *tableau, int index, LtlSet_t *ToCover, LtlSet_t *Current, LtlSet_t *Covered);
00050 static int SI(LtlTableau_t *tableau, int index, LtlSet_t *A);
00051 static void AutomatonComputeFair(LtlTableau_t *tableau, LtlSet_t *r, vertex_t *vtx1);
00052 static int AutomatonCreateFairList(LtlTableau_t *tableau, Ltl_Automaton_t *aut);
00053 static void AutomatonAssignNext(LtlTableau_t *tableau, LtlSet_t * toCover, LtlSet_t * s);
00054 static LtlSet_t * AutomatonSetCreate(LtlTableau_t *tableau, Ctlsp_Formula_t *F);
00055 static lsList AutomatonBuildCover(LtlTableau_t *tableau, LtlSet_t *ToCover);
00056 static void AutomatonBuildCover_Aux(LtlTableau_t *tableau, LtlSet_t *pToCover, LtlSet_t *pCurrent, LtlSet_t *pCovered, lsList Cover);
00057 
00060 /*---------------------------------------------------------------------------*/
00061 /* Definition of exported functions                                          */
00062 /*---------------------------------------------------------------------------*/
00063 
00075 Ltl_Automaton_t *
00076 Ltl_AutomatonCreate(void)
00077 {
00078   Ltl_Automaton_t *aut = ALLOC(Ltl_Automaton_t, 1);  
00079   (void)memset((void *)aut, 0, sizeof(Ltl_Automaton_t));
00080   
00081   aut->name = 0;
00082   aut->SCC = (st_table *)0;
00083   aut->G = g_alloc();
00084   /* table of the initial states */
00085   aut->Init = st_init_table(st_ptrcmp, st_ptrhash);  
00086   /* these states can be either in or outside the "FairSet" */
00087   aut->dontcare = st_init_table(st_ptrcmp, st_ptrhash); 
00088   /* list of FairSets (each FairSet is a table of states) */
00089   aut->Fair = lsCreate();  
00090   aut->node_idx = 1;
00091   
00092   return aut;
00093 }
00094 
00106 void
00107 Ltl_AutomatonFree(gGeneric g)
00108 {
00109   st_table *tbl;
00110   st_generator *stgen;
00111   int i, n;
00112   Ltl_Automaton_t *aut = (Ltl_Automaton_t *) g;
00113 
00114   if (aut->name)  FREE(aut->name);
00115 
00116   g_free(aut->G, (void (*)(gGeneric))0, Ltl_AutomatonNodeFree,
00117          (void (*)(gGeneric))0);
00118 
00119   st_free_table(aut->Init);
00120   st_free_table(aut->dontcare);
00121   
00122   while (lsDelBegin(aut->Fair, &tbl) != LS_NOMORE) {
00123       st_free_table(tbl);
00124   }
00125   lsDestroy(aut->Fair, (void (*)(lsGeneric)) NULL);
00126 
00127   if (aut->labelTable) {
00128       n = array_n(aut->labelTable);
00129       for (i=0; i<n; i++) 
00130           Ctlsp_FormulaFree(array_fetch(Ctlsp_Formula_t *, 
00131                                         aut->labelTable, i));
00132       array_free(aut->labelTable);
00133       array_free(aut->labelTableNegate);
00134   }
00135 
00136   /* free the partition/quotient */
00137   if (aut->SCC) {
00138     /* for a Buechi automaton, this is a st_table of st_table of vertices;
00139      * otherwise, this is a st_table of vertices */
00140     if (aut->isQuotientGraph == 0) {
00141       st_foreach_item(aut->SCC, stgen, &tbl, NIL(char *)) {
00142         st_free_table(tbl);
00143       }
00144     }
00145     st_free_table(aut->SCC);
00146   }
00147 
00148   if (aut->Q)
00149       Ltl_AutomatonFree((gGeneric) aut->Q);
00150 
00151   FREE(aut);
00152 }
00153         
00165 Ltl_AutomatonNode_t *
00166 Ltl_AutomatonNodeCreate(Ltl_Automaton_t *aut)
00167 {
00168   Ltl_AutomatonNode_t *node = ALLOC(Ltl_AutomatonNode_t, 1);
00169   (void)memset((void *)node, 0, sizeof(Ltl_AutomatonNode_t));
00170 
00171   node->index = aut->node_idx++;
00172   node->Labels = NIL(LtlSet_t);
00173   node->CoverSet = NIL(LtlSet_t);
00174   node->Class = (st_table *)0;        /* used in Quotient graph */
00175       
00176   return node;
00177 }
00178 
00190 void
00191 Ltl_AutomatonNodeFree(gGeneric g)
00192 {
00193   Ltl_AutomatonNode_t *node = (Ltl_AutomatonNode_t *) g;
00194   if (node->Labels)
00195     LtlSetFree(node->Labels);
00196   if (node->CoverSet)
00197     LtlSetFree(node->CoverSet);
00198   /*  if (node->Class)
00199         st_free_table(node->Class);*/
00200   
00201   FREE(node);
00202 }
00203 
00215 void
00216 Ltl_AutomatonNodePrint(
00217   Ltl_Automaton_t *aut,
00218   Ltl_AutomatonNode_t *node)
00219 {
00220   st_generator *stgen;
00221   vertex_t *vtx;
00222   Ltl_AutomatonNode_t *state;
00223   Ctlsp_Formula_t *F;
00224   int first, i, n;
00225   
00226   /* index (required) */
00227   fprintf(vis_stdout, "n%d: ", node->index);
00228   
00229   /* 1. cover (set of formulae) ? */
00230   if (aut->tableau && node->CoverSet) 
00231     LtlSetPrint(aut->tableau, node->CoverSet);
00232   
00233   /* 2. label ? */
00234   if (node->Labels) {
00235     fprintf(vis_stdout, " label: {");
00236     first = 1; n = array_n(aut->labelTable);
00237     for (i=0; i<n; i++) {
00238       if (LtlSetGetElt(node->Labels, i)) {
00239         if (!first)       fprintf(vis_stdout, ",");
00240         else              first = 0;
00241         F = array_fetch(Ctlsp_Formula_t *, aut->labelTable, i);
00242         Ctlsp_FormulaPrint(vis_stdout, F);
00243       }
00244     }
00245     fprintf(vis_stdout, "}");
00246   }
00247 
00248   /* 3. Class ? (for quotient graph node) */
00249   if (node->Class) {
00250     fprintf(vis_stdout, "scc{");
00251     st_foreach_item(node->Class, stgen, &vtx, NIL(char *)) {
00252       state = (Ltl_AutomatonNode_t *)vtx->user_data;
00253       fprintf(vis_stdout, "n%d ", state->index);
00254     }
00255     fprintf(vis_stdout, "}");
00256   }
00257   
00258   fprintf(vis_stdout, "\n");
00259 }
00260 
00272 void
00273 Ltl_AutomatonPrint(
00274   Ltl_Automaton_t *aut,
00275   int verbosity)
00276 {
00277   edge_t   *edge;
00278   vertex_t *vtx1, *vtx2;           
00279   Ltl_AutomatonNode_t *node, *node2;
00280   lsGen     gen;
00281   lsGeneric data;
00282 
00283   st_table  *tbl;
00284   st_generator *stgen;
00285 
00286   int n_states = 0;
00287   int n_trans = 0;
00288   int n_fairsets = 0;
00289   int n_init = 0;
00290   int strength;
00291   
00292   /* name ? */
00293   if (verbosity)
00294     fprintf(vis_stdout, "Automaton:\n");
00295 
00296   if (verbosity > 1) {
00297     fprintf(vis_stdout, "-----------------------------------------------\n");
00298     if (aut->name)
00299       fprintf(vis_stdout, "Name: %s \n", aut->name);
00300     fprintf(vis_stdout, "-----------------------------------------------\n");
00301     
00302     /* negation normal form ?*/
00303     if(aut->tableau)
00304       Ctlsp_FormulaPrint(vis_stdout, aut->tableau->F);
00305     
00306     /* States & Labels */
00307     fprintf(vis_stdout, "\nStates: \n");
00308     foreach_vertex( aut->G, gen, vtx1) {
00309       node = (Ltl_AutomatonNode_t *) vtx1->user_data;
00310       Ltl_AutomatonNodePrint(aut, node);
00311     }
00312     
00313     /* Init States ? */
00314     fprintf(vis_stdout, "Arcs: \n");  
00315     st_foreach_item(aut->Init, stgen,  &vtx1, NIL(char *)) {
00316       node = (Ltl_AutomatonNode_t *) vtx1->user_data;
00317       fprintf(vis_stdout, "-> n%d\n", node->index);
00318     }
00319     
00320     /* Edges */
00321     foreach_edge(aut->G, gen, edge) {
00322       vtx1 = g_e_source(edge);
00323       vtx2 = g_e_dest(edge);
00324       node = (Ltl_AutomatonNode_t *) vtx1->user_data;
00325       node2 = (Ltl_AutomatonNode_t *) vtx2->user_data;
00326           
00327       if (node)
00328         fprintf(vis_stdout, "   n%d -> ", node->index);
00329       if (node2)
00330         fprintf(vis_stdout, "n%d\n", node2->index);
00331     }
00332 
00333     /* Sets of Fair Sets */
00334     fprintf(vis_stdout, "Fair Sets: \n");  
00335     lsForEachItem (aut->Fair, gen, data) {
00336       tbl = (st_table *) data;
00337       fprintf(vis_stdout, "{ ");
00338       st_foreach_item(tbl, stgen,  &vtx1, NIL(char *)) {
00339         node = (Ltl_AutomatonNode_t *) vtx1->user_data;
00340         fprintf(vis_stdout, "n%d ", node->index);
00341       }
00342       fprintf(vis_stdout, " }\n");
00343     }
00344     
00345 #ifdef DEBUG_LTLMC      
00346     /* Dontcare states */
00347     fprintf(vis_stdout, "Dontcare States: \n{");
00348     if (aut->dontcare) {
00349       st_foreach_item(aut->dontcare, stgen, &vtx1, NIL(char *)) {
00350         node = (Ltl_AutomatonNode_t *) vtx1->user_data;
00351         fprintf(vis_stdout, "n%d ", node->index);
00352       }
00353     }
00354     fprintf(vis_stdout, " }\n");
00355 #endif
00356   
00357     fprintf(vis_stdout, "End\n");
00358   }
00359   
00360   /* Get the strength (2, 1, 0) */
00361   n_states = lsLength(g_get_vertices(aut->G));
00362   n_init = st_count(aut->Init);
00363   n_trans = lsLength(g_get_edges(aut->G));
00364   n_fairsets = lsLength(aut->Fair);
00365   strength = Ltl_AutomatonGetStrength(aut);
00366 
00367   if (verbosity) 
00368     fprintf(vis_stdout, "Stats: %d states, %d trans, %d fair sets, %d init states, %s\n", n_states, n_trans, n_fairsets, n_init, (strength==2)? "strong":((strength==1)?"weak":"terminal") );
00369 
00370 }
00371 
00372 
00373 /*---------------------------------------------------------------------------*/
00374 /* Definition of internal functions                                          */
00375 /*---------------------------------------------------------------------------*/
00376 
00391 Ltl_Automaton_t *
00392 LtlAutomatonGeneration(
00393   LtlTableau_t *tableau)
00394 {
00395   LtlSet_t *toCover, *s, *r, *rprime; /* terms (set) */
00396   lsList Cover;                       /* current list of terms (cover) */
00397   lsList U = lsCreate();              /* a list of terms <to be processed>*/
00398   lsList Q = lsCreate();              /* unique table for terms <processed> */
00399   st_table  *Set2Vtx = st_init_table(st_ptrcmp, st_ptrhash);
00400   vertex_t *vtx1, *vtx2;              /* vertex in graph, related to node */
00401   Ltl_Automaton_t *A = Ltl_AutomatonCreate();
00402   Ltl_AutomatonNode_t *node;
00403   Ctlsp_Formula_t *F;
00404   int i;
00405 
00406   A->tableau = tableau;
00407   
00408   /* Compute Cover( {F} ), the init states, and U */
00409   toCover = AutomatonSetCreate(tableau, tableau->F); 
00410   Cover = AutomatonBuildCover(tableau, toCover);     
00411   while (lsDelBegin(Cover, &r) != LS_NOMORE) {
00412 #ifdef DEBUG_LTLMC
00413     if (tableau->verbosity >=2) {
00414       fprintf(vis_stdout, "**** term: ");
00415       LtlSetPrintIndex(tableau->abIndex, r);
00416       fprintf(vis_stdout, "**** n%d added! \n", A->node_idx);
00417     }
00418 #endif
00419     lsNewEnd(U, (lsGeneric) r, (lsHandle *) 0);
00420     lsNewEnd(Q, (lsGeneric) r, (lsHandle *) 0);
00421     /* Build the initial states of the Buechi automaton 
00422      * add a new node in G
00423      */
00424     node = Ltl_AutomatonNodeCreate(A);
00425     node->Labels = LtlSetToLabelSet(tableau, r);
00426     node->CoverSet = LtlSetCopy(r); 
00427     vtx1 = g_add_vertex(A->G);
00428     vtx1->user_data = (gGeneric) node;
00429     /* add into A->Init */
00430     st_insert(A->Init, vtx1,  vtx1);
00431     /* put this node to proper Fair sets */
00432     AutomatonComputeFair(tableau, r, vtx1);
00433     /* add into the (Set, Vtx) unique table */
00434     st_insert(Set2Vtx, r,  vtx1);
00435   }
00436   lsDestroy(Cover, (void (*)(lsGeneric))0);
00437 
00438   /* Each time, remove one set 's' from the to-be-processed list 'U' */
00439   while (lsDelBegin(U, &s) == LS_OK) {
00440     /* Put all the next (state) formulae into toCover */
00441     AutomatonAssignNext(tableau, toCover, s);
00442 #ifdef DEBUG_LTLMC
00443     if (tableau->verbosity >= 2) {
00444       fprintf(vis_stdout, "\n** AssignNext Of:");
00445       LtlSetPrintIndex(tableau->abIndex, s);
00446       fprintf(vis_stdout, "** ==>           ");
00447       LtlSetPrintIndex(tableau->abIndex, toCover);
00448     }
00449 #endif
00450     /* Build the cover for next state */
00451     Cover = AutomatonBuildCover(tableau, toCover);
00452     while (lsDelBegin(Cover, &r) == LS_OK) {
00453       /* Get the existing identical copy of r from Q (if exist) */
00454       rprime = LtlSetIsInList(r, Q);
00455 #ifdef DEBUG_LTLMC        
00456       if (tableau->verbosity >=2 ) {
00457         fprintf(vis_stdout, "** term: ");
00458         LtlSetPrintIndex(tableau->abIndex, r);
00459       }
00460 #endif
00461       /* If the next state exists, simply add the new edge; Otherwise,
00462          create the next state, and add the new edge */
00463       if (rprime) {
00464         /* both s and r' are already in G */
00465         st_lookup(Set2Vtx,  rprime,  &vtx1);
00466         assert(vtx1 != NIL(vertex_t));
00467         st_lookup(Set2Vtx, s,  &vtx2); 
00468         assert(vtx2 != NIL(vertex_t));
00469         /* add edge(s, r') */
00470         g_add_edge(vtx2, vtx1);       
00471         LtlSetFree(r);
00472       }else {
00473 #ifdef DEBUG_LTLMC            
00474         if (tableau->verbosity >=2 ) {
00475           fprintf(vis_stdout, "** n%d added!\n", A->node_idx);
00476         }
00477 #endif
00478         /* add a new state in G */
00479         node = Ltl_AutomatonNodeCreate(A);
00480         node->Labels = LtlSetToLabelSet(tableau, r);
00481         node->CoverSet = LtlSetCopy(r); 
00482         vtx1 = g_add_vertex(A->G);  
00483         vtx1->user_data = (gGeneric) node;
00484         /* add edge(s, r) */
00485         st_lookup(Set2Vtx,  s,  &vtx2);
00486         assert(vtx2 != NIL(vertex_t));     
00487         g_add_edge(vtx2, vtx1); 
00488         /* put the new state to the proper Fair Sets */
00489         AutomatonComputeFair(tableau, r, vtx1);
00490         /* add r in the (Set, Vtx) unique table */
00491         st_insert(Set2Vtx,  r,  vtx1);        
00492         lsNewEnd(Q, (lsGeneric) r, (lsHandle *) 0);
00493         lsNewEnd(U, (lsGeneric) r, (lsHandle *) 0);
00494       }
00495     }
00496       
00497     lsDestroy(Cover, (void (*)(lsGeneric))0);
00498   }
00499 
00500   /* Convert fair sets of the tableau into fair sets of the automaton:
00501    * if there is an empty fairset, create an empty automaton and return;
00502    * otherwise, keep going ...
00503    */
00504   if (AutomatonCreateFairList(tableau, A) == 0) {
00505     st_table *tbl;
00506     while (lsDelBegin(A->Fair, &tbl) != LS_NOMORE) {
00507       st_free_table(tbl);
00508     }
00509     g_free(A->G, (void (*)(gGeneric))0, Ltl_AutomatonNodeFree,
00510            (void (*)(gGeneric))0);
00511     A->G = g_alloc();
00512     st_free_table(A->Init);
00513     A->Init = st_init_table(st_ptrcmp, st_ptrhash);
00514   }
00515 
00516   /* Copy the lable table of the tableau into the automaton 
00517    * Note that the new one shares nothing with the one in the tableau 
00518    */
00519   A->labelTable = array_alloc(Ctlsp_Formula_t *, tableau->labelIndex);
00520   for (i=0; i<tableau->labelIndex; i++) {
00521     F = Ctlsp_LtlFormulaNegationNormalForm(tableau->labelTable[i]);
00522     array_insert(Ctlsp_Formula_t *, A->labelTable, i, F);
00523   }
00524   A->labelTableNegate = array_dup(tableau->labelTableNegate);
00525   
00526   /* Free all the sets in the list 
00527    * toCover/U  should be empty sets, while Q contains all the processed set 
00528    */
00529   LtlSetFree(toCover);         
00530   lsDestroy(U, (void (*)(lsGeneric)) 0);    
00531   lsDestroy(Q, (void (*)(lsGeneric))LtlSetFree);    
00532   st_free_table(Set2Vtx);
00533 
00534 #ifdef DEBUG_LTLMC  
00535   /* sanity check */
00536   g_check(A->G);
00537 #endif
00538   
00539   return A;
00540 }
00541 
00542 
00553 int 
00554 LtlAutomatonSetIsFair(
00555   LtlTableau_t *tableau,
00556   LtlSet_t *r)
00557 {
00558 #if 0
00559   st_table *uniqueTable = tableau->untilUniqueTable;
00560   char *key, *value;
00561   st_generator *gen;
00562   int flag = 0;
00563 #endif
00564 
00565   /* this is the same as "Wring" */
00566   return 0;  
00567 
00568 #if 0  
00569   st_foreach_item(uniqueTable, gen, &key, &value) {
00570     Ctlsp_Formula_t *F = (Ctlsp_Formula_t *) key;
00571     Ctlsp_Formula_t *right = Ctlsp_FormulaReadRightChild(F);
00572     int F_ab_idx = Ctlsp_FormulaReadABIndex(F);
00573     int right_ab_idx = Ctlsp_FormulaReadABIndex(right);
00574       
00575     if ( SI(tableau, right_ab_idx, r) ||
00576          !(SI(tableau, F_ab_idx, r)) ) {
00577       /* set 'r' belongs to one fair set */
00578       flag = 1;
00579       st_free_gen(gen);
00580       break;
00581     }
00582   }
00583   return flag;
00584 #endif
00585 }
00586 
00587 
00588 /*---------------------------------------------------------------------------*/
00589 /* Definition of exported functions                                          */
00590 /*---------------------------------------------------------------------------*/
00591 
00601 static int
00602 HasToBeStored(
00603   LtlTableau_t *tableau,
00604   int index)
00605 {
00606   int result = 1;
00607   Ctlsp_Formula_t *F;
00608   Ctlsp_FormulaType F_type;
00609   
00610   F = tableau->abTable[index].F;
00611   
00612   switch(tableau->algorithm) {
00613   case Ltl2Aut_GPVW_c:
00614     result = 1;
00615     break;
00616   case Ltl2Aut_GPVWplus_c:
00617     /* T iff 'u' is an until formula or 'u' is the right hand of an until */
00618     F_type = Ctlsp_FormulaReadType(F);
00619     result = (F_type == Ctlsp_U_c || Ctlsp_FormulaReadRhs(F) == 1);
00620     break;
00621   case Ltl2Aut_LTL2AUT_c:  
00622   case Ltl2Aut_WRING_c:   
00623     result = 0;
00624     break;
00625   }
00626 #ifdef DEBUG_LTLMC
00627   if (tableau->verbosity >2)
00628     fprintf(vis_stdout, "...HasToBeStored=%d\n", result);
00629 #endif
00630   
00631   return result;
00632 }
00633 
00643 static int
00644 Contradiction(
00645   LtlTableau_t *tableau,
00646   int index,
00647   LtlSet_t *ToCover,
00648   LtlSet_t *Current,
00649   LtlSet_t *Covered)
00650 {
00651   int result = 0;
00652   Ctlsp_Formula_t *F, *notF;
00653   LtlSet_t *UC;
00654   int notF_ab_idx;
00655   Ctlsp_FormulaType F_type;
00656   
00657   F = tableau->abTable[index].F;
00658   F_type = Ctlsp_FormulaReadType(F);
00659   notF = tableau->abTable[index].notF;
00660   notF_ab_idx = Ctlsp_FormulaReadABIndex(notF);
00661 
00662   
00663   switch(tableau->algorithm) {
00664   case Ltl2Aut_GPVW_c:
00665     /* if 'u' is False, or (!u) exists in Current */
00666     result = ( F_type == Ctlsp_FALSE_c ||
00667                LtlSetGetElt(Current, notF_ab_idx) );
00668     break;
00669   case Ltl2Aut_GPVWplus_c:
00670     /* if 'u' is False, or !(u) exists in Covered */
00671     result = ( F_type == Ctlsp_FALSE_c ||
00672                LtlSetGetElt(Covered, notF_ab_idx) );
00673     break;
00674   case Ltl2Aut_LTL2AUT_c:
00675   case Ltl2Aut_WRING_c:
00676     UC = LtlSetCopy(ToCover);
00677     LtlSetOR(UC, ToCover, Current);
00678     /* T iff (!u) \in SI(ToCover U Current) */
00679     result = SI(tableau, notF_ab_idx, UC);
00680     LtlSetFree(UC);
00681     break;
00682   }
00683 #ifdef DEBUG_LTLMC
00684   if (tableau->verbosity >2)
00685     fprintf(vis_stdout, "...Contradiction=%d\n", result);
00686 #endif
00687   
00688   return result;
00689 }
00690 
00700 static int
00701 Redundant(
00702   LtlTableau_t *tableau,
00703   int index,
00704   LtlSet_t *ToCover,
00705   LtlSet_t *Current,
00706   LtlSet_t *Covered)
00707 {
00708   int result = 0;
00709   Ctlsp_Formula_t *F;
00710   LtlSet_t *UC = LtlSetCopy(ToCover);
00711   int Fleft_ab_idx , Fright_ab_idx;
00712   Ctlsp_FormulaType F_type;
00713   
00714   LtlSetOR(UC, ToCover, Current);
00715   
00716   F = tableau->abTable[index].F;
00717   
00718   F_type = Ctlsp_FormulaReadType(F);
00719   if (F_type == Ctlsp_U_c || F_type == Ctlsp_R_c) {
00720     Fleft_ab_idx = Ctlsp_FormulaReadABIndex(Ctlsp_FormulaReadLeftChild(F));
00721     Fright_ab_idx = Ctlsp_FormulaReadABIndex(Ctlsp_FormulaReadRightChild(F));
00722   } else { /* to remove uninitialized variable warnings */
00723     Fleft_ab_idx = 0;
00724     Fright_ab_idx = 0;
00725   }
00726   switch(tableau->algorithm) {
00727   case Ltl2Aut_GPVW_c:
00728     result = 0;
00729     break;
00730   case Ltl2Aut_GPVWplus_c:
00731     /* T iff  'u' is (n U v) and {v} is in (ToCover U Current),
00732      *   or   'u' is (n R v) and {n,v} is in (ToCover U Current) 
00733      */
00734     if (F_type == Ctlsp_U_c) 
00735       result = LtlSetGetElt(UC, Fright_ab_idx);
00736     else if (F_type == Ctlsp_R_c) 
00737       result = ( LtlSetGetElt(UC, Fleft_ab_idx) &&
00738                  LtlSetGetElt(UC, Fright_ab_idx) );
00739     else
00740       result = 0;
00741     break;
00742   case Ltl2Aut_LTL2AUT_c:
00743   case Ltl2Aut_WRING_c:
00744     /* T iff the following two cases are both true:
00745      *  (1) 'u' is in SI(ToCover U Current)
00746      *  (2) if 'u' is (n U v), then 'v' is in (ToCover U Current) 
00747      */
00748     result = SI(tableau, index, UC);
00749     if (result && F_type == Ctlsp_U_c) {
00750       result = SI(tableau, Fright_ab_idx, UC);
00751     }
00752     break;
00753   }
00754   LtlSetFree(UC);
00755 #ifdef DEBUG_LTLMC  
00756   if (tableau->verbosity >2)
00757     fprintf(vis_stdout, "...Redundant=%d\n", result);
00758 #endif
00759   
00760   return result;
00761 }
00762 
00774 static int
00775 SI(
00776   LtlTableau_t *tableau,
00777   int index,
00778   LtlSet_t *A)
00779 {
00780   int result = 0;
00781   Ctlsp_Formula_t *XF;
00782   Ctlsp_Formula_t *F = tableau->abTable[index].F;
00783   Ctlsp_FormulaType F_type = Ctlsp_FormulaReadType(F);
00784   int Fleft_ab_idx, Fright_ab_idx;
00785   
00786   if (tableau->algorithm == Ltl2Aut_GPVW_c ||
00787       tableau->algorithm == Ltl2Aut_GPVWplus_c) {
00788     result = LtlSetGetElt(A, index);
00789   } else {
00790     if (F_type == Ctlsp_AND_c || F_type == Ctlsp_OR_c ||
00791         F_type == Ctlsp_U_c || F_type == Ctlsp_R_c) {
00792       Fleft_ab_idx =
00793         Ctlsp_FormulaReadABIndex(Ctlsp_FormulaReadLeftChild(F));
00794       Fright_ab_idx =
00795         Ctlsp_FormulaReadABIndex(Ctlsp_FormulaReadRightChild(F));
00796     } else { /* to remove uninitialized variable warnings */
00797       Fleft_ab_idx = 0;
00798       Fright_ab_idx = 0;
00799     }
00800     
00801     switch(Ctlsp_FormulaReadType(F)) {
00802     case Ctlsp_FALSE_c:
00803       result = 0;
00804       break;
00805     case Ctlsp_TRUE_c:
00806       result = 1;
00807       break;
00808     case Ctlsp_X_c:
00809     case Ctlsp_NOT_c:
00810     case Ctlsp_ID_c:
00811       result = LtlSetGetElt(A, index);
00812       break;
00813     case Ctlsp_AND_c:
00814       if (Ctlsp_LtlFormulaIsPropositional(F))
00815         result = LtlSetGetElt(A, index);
00816       else {
00817         result = (SI(tableau, Fleft_ab_idx, A) &&
00818                   SI(tableau, Fright_ab_idx, A));
00819       }
00820       break;
00821     case Ctlsp_OR_c:
00822       if (Ctlsp_LtlFormulaIsPropositional(F))
00823         result = LtlSetGetElt(A, index);
00824       else {
00825         result = (SI(tableau, Fleft_ab_idx, A) ||
00826                   SI(tableau, Fright_ab_idx, A));
00827       }
00828       break;
00829     case Ctlsp_U_c:
00830       XF = LtlTableauGetUniqueXFormula(tableau, F);       
00831       result = (SI(tableau, Fright_ab_idx, A) ||
00832                 (SI(tableau, Fleft_ab_idx, A) &&
00833                  LtlSetGetElt(A, Ctlsp_FormulaReadABIndex(XF))));
00834       break;
00835     case Ctlsp_R_c:
00836       XF = LtlTableauGetUniqueXFormula(tableau, F);       
00837       result = SI(tableau, Fright_ab_idx, A) &&
00838         (SI(tableau, Fleft_ab_idx, A) ||
00839          LtlSetGetElt(A, Ctlsp_FormulaReadABIndex(XF)));
00840       break;
00841     default:
00842       assert(0);
00843     }
00844   }
00845   
00846 #ifdef DEBUG_LTLMC
00847   if (tableau->verbosity > 3) {
00848     fprintf(vis_stdout, "...SI( %d, ", index);
00849     LtlSetPrintIndex(tableau->abIndex, A);
00850     fprintf(vis_stdout, "     )=%d\n", result);
00851   }
00852 #endif
00853   
00854   return result;
00855 }
00856 
00857 
00870 static void
00871 AutomatonComputeFair(
00872   LtlTableau_t *tableau,
00873   LtlSet_t *r,
00874   vertex_t *vtx1)
00875 {
00876   st_table *uniqueTable = tableau->untilUniqueTable;
00877   char *key, *value;
00878   st_generator *gen;
00879 
00880   /* Notice that each pair in 'uniqueTable' is a (Unitl formula, Fair set) */
00881   st_foreach_item(uniqueTable, gen, &key, &value) {
00882     Ctlsp_Formula_t *F = (Ctlsp_Formula_t *) key;
00883     Ctlsp_Formula_t *right = Ctlsp_FormulaReadRightChild(F);
00884     int F_ab_idx = Ctlsp_FormulaReadABIndex(F);
00885     int right_ab_idx = Ctlsp_FormulaReadABIndex(right);
00886     lsList Fair = (lsList) value;
00887       
00888     if ( SI(tableau, right_ab_idx, r) || !(SI(tableau, F_ab_idx, r)) ) {
00889       lsNewEnd(Fair, (lsGeneric) vtx1, (lsHandle *) 0); 
00890     }
00891   }
00892 }
00893 
00910 static int
00911 AutomatonCreateFairList(
00912   LtlTableau_t *tableau,
00913   Ltl_Automaton_t *aut)
00914 {
00915   lsList FairList = aut->Fair;
00916   char *key, *value;
00917   st_generator *gen;
00918   int noEmptyFairSet = 1;
00919 
00920   st_foreach_item(tableau->untilUniqueTable, gen, &key, &value) {
00921     lsList Fair = (lsList) value;
00922 
00923     /* translate a lsList into a st_table */
00924     if (lsLength(Fair) > 0) {
00925       lsGen lsgen;
00926       lsGeneric lsdata;
00927       st_table *tbl = st_init_table(st_ptrcmp, st_ptrhash);
00928       
00929       lsForEachItem (Fair, lsgen, lsdata) {
00930         st_insert(tbl, lsdata, lsdata);
00931       }
00932       lsNewEnd(FairList, (lsGeneric) tbl, (lsHandle *) 0); 
00933     }else 
00934       noEmptyFairSet = 0;
00935 
00936     lsDestroy(Fair, (void (*)(lsGeneric)) NULL);
00937   }
00938 
00939   return noEmptyFairSet;
00940 }
00941 
00952 static void
00953 AutomatonAssignNext(
00954   LtlTableau_t *tableau,
00955   LtlSet_t * toCover,
00956   LtlSet_t * s)
00957 {
00958   int i;
00959   Ctlsp_FormulaType type;
00960   Ctlsp_Formula_t *left;
00961   int left_ab_idx;
00962       
00963   LtlSetClear(toCover);
00964   
00965   for (i=0; i<tableau->abIndex; i++) {
00966     if (LtlSetGetElt(s, i)) {
00967       type = Ctlsp_FormulaReadType(tableau->abTable[i].F);
00968       if (type == Ctlsp_X_c) {
00969         left = Ctlsp_FormulaReadLeftChild(tableau->abTable[i].F);
00970         left_ab_idx = Ctlsp_FormulaReadABIndex(left);
00971         LtlSetSetElt(toCover, left_ab_idx);
00972         
00973       }
00974     }
00975   }
00976 }  
00977 
00978 
00989 static LtlSet_t *
00990 AutomatonSetCreate(
00991   LtlTableau_t *tableau,
00992   Ctlsp_Formula_t *F)  
00993 {
00994   LtlSet_t *cs = LtlSetNew(tableau->abIndex);
00995 
00996   if (!F)
00997     return cs;
00998 
00999   LtlSetSetElt(cs, Ctlsp_FormulaReadABIndex(F));
01000     
01001   return cs;
01002 }
01003 
01014 static lsList
01015 AutomatonBuildCover(
01016   LtlTableau_t *tableau,
01017   LtlSet_t *ToCover)
01018 {
01019   LtlSet_t *Current = LtlSetNew(tableau->abIndex);
01020   LtlSet_t *Covered = LtlSetNew(tableau->abIndex);
01021   lsList Cover = lsCreate();
01022 
01023   AutomatonBuildCover_Aux(tableau, ToCover, Current, Covered, Cover);
01024   LtlSetFree(Current);
01025   LtlSetFree(Covered);
01026   
01027   /* Boolean Minimization -- heuristics */
01028   if (tableau->booleanmin == 1) {
01029     if (lsLength(Cover)) {
01030       lsList list = Cover;
01031       Cover = LtlCoverPrimeAndIrredundant(tableau, Cover,
01032                                           tableau->abTableNegate);
01033       lsDestroy(list, (void (*)(lsGeneric))LtlSetFree);
01034     }
01035   }
01036   return Cover;
01037 }
01038 
01049 static void
01050 AutomatonBuildCover_Aux(
01051   LtlTableau_t *tableau,
01052   LtlSet_t *pToCover,
01053   LtlSet_t *pCurrent,
01054   LtlSet_t *pCovered,
01055   lsList Cover)
01056 {
01057   LtlSet_t *ToCover = LtlSetCopy(pToCover);
01058   LtlSet_t *Current = LtlSetCopy(pCurrent);
01059   LtlSet_t *Covered = LtlSetCopy(pCovered);
01060   int i;
01061 
01062 #ifdef DEBUG_LTLMC  
01063   if (tableau->verbosity >2 ) {
01064     fprintf(vis_stdout, "ToCover=");
01065     LtlSetPrintIndex(tableau->abIndex, ToCover);
01066     fprintf(vis_stdout, "Current=");
01067     LtlSetPrintIndex(tableau->abIndex, Current);
01068     fprintf(vis_stdout, "Covered=");
01069     LtlSetPrintIndex(tableau->abIndex, Covered);
01070     fflush(vis_stdout);
01071   }      
01072 #endif
01073   
01074   if (LtlSetIsEmpty(ToCover)) {
01075 #if 1
01076     /* chao: 7/22/2002 remove identical set in current Cover */
01077     if (!LtlSetIsInList(Current, Cover))
01078 #endif
01079       lsNewEnd(Cover, (lsGeneric) LtlSetCopy(Current), (lsHandle *) 0);
01080     /* return */
01081   }else {
01082     /* select 'u' from 'ToCover' */
01083     for (i=0; i<tableau->abIndex; i++) {
01084       if (LtlSetGetElt(ToCover,i))
01085         break;
01086     }
01087     /* remove 'u' from 'ToCover' and add it to 'Covered' */
01088     LtlSetClearElt(ToCover, i);
01089     LtlSetSetElt(Covered, i);
01090     
01091     /* if HAS_TO_BE_STORED(u), store into 'Current' */
01092     if (HasToBeStored(tableau,i)) 
01093       LtlSetSetElt(Current, i);
01094     
01095     /* if CONTRADICTION(u, ToCover, Current, Covered), return 'Cover' */
01096     if (Contradiction(tableau, i, ToCover, Current, Covered)) {
01097       ; /* return */
01098     }else if (Redundant(tableau, i, ToCover, Current, Covered)) {
01099       AutomatonBuildCover_Aux(tableau, ToCover, Current, Covered, Cover);
01100       /* return */
01101     }else {
01102       if (Ctlsp_LtlFormulaIsElementary(tableau->abTable[i].F)) {
01103         LtlSetSetElt(Current, i);
01104         AutomatonBuildCover_Aux(tableau, ToCover, Current, Covered,
01105                                 Cover);
01106         /* return */
01107       }else {
01108         int A0B0 = tableau->abTable[i].A[0].B[0];
01109         int A0B1 = tableau->abTable[i].A[0].B[1];
01110         int A0n = tableau->abTable[i].A[0].n;
01111         int A1B0 = tableau->abTable[i].A[1].B[0];
01112         int A1B1 = tableau->abTable[i].A[1].B[1];
01113         int A1n = tableau->abTable[i].A[1].n;
01114         
01115         /* cover( (ToCover+alph2(u)-Current), Current, Covered, Cover) */
01116         if (A1B0 != -1 || A1B1!= -1 || A1n!= -1) {
01117           LtlSet_t *saveToCover = LtlSetCopy(ToCover);        
01118           if (A1B0 != -1)
01119             if (!LtlSetGetElt(Current, A1B0))
01120               LtlSetSetElt(ToCover, A1B0);
01121           if (A1B1 != -1)
01122             if (!LtlSetGetElt(Current, A1B1))
01123               LtlSetSetElt(ToCover, A1B1);
01124           if (A1n != -1)
01125             if (!LtlSetGetElt(Current, A1n))
01126               LtlSetSetElt(ToCover, A1n);
01127           
01128           AutomatonBuildCover_Aux(tableau, ToCover, Current, Covered,
01129                                   Cover);
01130           
01131           LtlSetAssign(ToCover, saveToCover);
01132           LtlSetFree(saveToCover);
01133         }
01134         
01135         /* cover( (ToCover+alph1(u)-Current), Current, Covered, Cover) */
01136         if (A0B0 != -1 || A0B1!= -1 || A0n!= -1) {            
01137           if (A0B0 != -1)
01138             if (!LtlSetGetElt(Current, A0B0))
01139               LtlSetSetElt(ToCover, A0B0);
01140           if (A0B1 != -1)
01141             if (!LtlSetGetElt(Current, A0B1))
01142               LtlSetSetElt(ToCover, A0B1);
01143           if (A0n != -1)
01144             if (!LtlSetGetElt(Current, A0n))
01145               LtlSetSetElt(ToCover, A0n);
01146           
01147           AutomatonBuildCover_Aux(tableau, ToCover, Current, Covered,
01148                                   Cover);
01149         }
01150         /* return */
01151       }
01152     }
01153   }
01154   
01155   /* Clean-Ups */
01156   LtlSetFree(ToCover);
01157   LtlSetFree(Current);
01158   LtlSetFree(Covered);
01159 }
01160 
01161 
01162 
01163 
01164