VIS
|
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