VIS

src/ltl/ltlSet.c

Go to the documentation of this file.
00001 
00017 #include "ltlInt.h"
00018 
00019 static char rcsid[] UNUSED = "$Id: ltlSet.c,v 1.25 2005/04/28 08:45:27 bli Exp $";
00020 
00021 /* Set manipulation functions.
00022  *  
00023  * Set is a term -- the conjunction of literals. In the Ltl->Aut process, a
00024  * literal can be an propositional formula, a X-formula and its negation.
00025  * In order to interpret a Set, we need to corresponding arrays: Table and
00026  * Negate. An '1' in the i-th position of the Set means "Table[i] is contained
00027  * in the Set", and the negation of "Table[i]" is "Negate[i]".
00028  * 
00029  * Cover is a lsList of terms -- the "union" of all the items (product terms).
00030  *
00031  * Pair is a data structure to hold a 'ordered pair of items': (First, Second).
00032  */
00033 
00034 /*---------------------------------------------------------------------------*/
00035 /* Constant declarations                                                     */
00036 /*---------------------------------------------------------------------------*/
00037 
00038 /*---------------------------------------------------------------------------*/
00039 /* Structure declarations                                                    */
00040 /*---------------------------------------------------------------------------*/
00041 
00042 /*---------------------------------------------------------------------------*/
00043 /* Type declarations                                                         */
00044 /*---------------------------------------------------------------------------*/
00045 
00046 /*---------------------------------------------------------------------------*/
00047 /* Variable declarations                                                     */
00048 /*---------------------------------------------------------------------------*/
00049 
00050 /*---------------------------------------------------------------------------*/
00051 /* Macro declarations                                                        */
00052 /*---------------------------------------------------------------------------*/
00053 
00056 /*---------------------------------------------------------------------------*/
00057 /* Static function prototypes                                                */
00058 /*---------------------------------------------------------------------------*/
00059 
00060 
00064 /*---------------------------------------------------------------------------*/
00065 /* Definition of exported functions                                          */
00066 /*---------------------------------------------------------------------------*/
00067 
00077 LtlSet_t *
00078 LtlSetNew(
00079   int size)
00080 {
00081   LtlSet_t *set = ALLOC(LtlSet_t, 1);
00082     
00083   set->e = var_set_new(size);
00084 
00085   return set;
00086 }
00087 
00097 void
00098 LtlSetFree(
00099   LtlSet_t *set)
00100 {
00101   var_set_free(set->e);
00102   FREE(set);
00103 }
00104 
00114 LtlSet_t *
00115 LtlSetCopy(
00116   LtlSet_t *from)
00117 {
00118   LtlSet_t *set = ALLOC(LtlSet_t, 1);
00119   
00120   set->e = var_set_copy(from->e);
00121   
00122   return set;
00123 }
00124 
00134 void
00135 LtlSetAssign(
00136   LtlSet_t *to,
00137   LtlSet_t *from)
00138 {
00139   var_set_assign(to->e, from->e);
00140 }
00141 
00151 int
00152 LtlSetEqual(
00153   LtlSet_t *s1,
00154   LtlSet_t *s2)
00155 {
00156   return var_set_equal(s1->e, s2->e);
00157 }
00158 
00159 
00169 int
00170 LtlSetCardinality(
00171   LtlSet_t *set)
00172 {
00173   return (var_set_n_elts(set->e));
00174 }
00175 
00186 int
00187 LtlSetCompareCardinality(
00188   const void *p1,
00189   const void *p2)
00190 {
00191   LtlSet_t **s1 = (LtlSet_t **) p1;
00192   LtlSet_t **s2 = (LtlSet_t **) p2;
00193   int c1;
00194   int c2;
00195   
00196   c1 = LtlSetCardinality(*s1);
00197   c2 = LtlSetCardinality(*s2);
00198   
00199   if (c1 < c2)
00200     return -1;
00201   else if (c1 == c2)
00202     return 0;
00203   else
00204     return +1;
00205 }
00206 
00216 int
00217 LtlSetIsContradictory(
00218   LtlSet_t *set,
00219   array_t *Negate)
00220 {
00221   int i, negi;
00222   int flag = 0;
00223 
00224   for (i=0; i<array_n(Negate); i++) {
00225     if (LtlSetGetElt(set, i)) {
00226       negi = array_fetch(int, Negate, i);
00227       if (LtlSetGetElt(set, negi)) {
00228         flag = 1;
00229         break;
00230       }
00231     }
00232   }
00233   
00234   return flag;
00235 }
00236 
00246 int
00247 LtlSetInclude(
00248   LtlSet_t *large,
00249   LtlSet_t *small)
00250 {
00251   var_set_t *neg_large = var_set_not(var_set_copy(large->e),large->e);
00252   int result = ! var_set_intersect(small->e, neg_large);
00253   var_set_free(neg_large);
00254   
00255   return result;
00256 }
00257 
00267 void
00268 LtlSetOR(
00269   LtlSet_t *to,
00270   LtlSet_t *from1,
00271   LtlSet_t *from2)
00272 {
00273   var_set_or(to->e, from1->e, from2->e);
00274 }
00275 
00285 void
00286 LtlSetClear(
00287   LtlSet_t *set)
00288 {
00289   var_set_clear(set->e);
00290 }
00291 
00301 void
00302 LtlSetSetElt(
00303   LtlSet_t *set,
00304   int index)
00305 {
00306   var_set_set_elt(set->e, index);
00307 }
00308 
00318 void
00319 LtlSetClearElt(
00320   LtlSet_t *set,
00321   int index)
00322 {
00323   var_set_clear_elt(set->e, index);
00324 }
00325 
00335 int
00336 LtlSetGetElt(
00337   LtlSet_t *set,
00338   int index)
00339 {
00340   return var_set_get_elt(set->e,index);
00341 }
00342 
00352 int
00353 LtlSetIsEmpty(
00354   LtlSet_t *set)
00355 {
00356   return var_set_is_empty(set->e);
00357 }
00358 
00368 LtlSet_t *
00369 LtlSetIsInList(
00370   LtlSet_t *set,
00371   lsList list)
00372 {
00373   lsGen gen;
00374   lsGeneric data;
00375   LtlSet_t *s = NIL(LtlSet_t);
00376   int flag = 0;
00377   
00378   lsForEachItem(list, gen, data) {
00379     s = (LtlSet_t *) data;
00380     if ( var_set_equal(s->e, set->e) ) {
00381       flag = 1;
00382       lsFinish(gen);
00383       break;
00384     }
00385   }
00386   
00387   return flag? s: NIL(LtlSet_t);
00388 }
00389     
00407 LtlSet_t *
00408 LtlSetToLabelSet(
00409   LtlTableau_t *tableau,
00410   LtlSet_t *set)
00411 {
00412   int i;
00413   LtlSet_t *vset = LtlSetNew(tableau->labelIndex);
00414   Ctlsp_Formula_t *F;
00415   
00416   for (i=0; i<tableau->abIndex; i++) {
00417     if (var_set_get_elt(set->e, i)) {
00418       F = tableau->abTable[i].F;
00419       if (Ctlsp_LtlFormulaIsPropositional(F)&&
00420           Ctlsp_FormulaReadType(F) != Ctlsp_TRUE_c &&
00421           Ctlsp_FormulaReadType(F) != Ctlsp_FALSE_c)
00422         var_set_set_elt(vset->e, 
00423                         Ctlsp_FormulaReadLabelIndex(tableau->abTable[i].F));
00424     }
00425   }
00426   
00427   return vset;
00428 }
00429 
00439 void
00440 LtlSetPrint(
00441   LtlTableau_t *tableau,
00442   LtlSet_t *set)
00443 {
00444   int i;
00445   
00446   fprintf(vis_stdout, "{ ");
00447   for (i=0; i<tableau->abIndex; i++) {
00448     if (LtlSetGetElt(set, i)) {
00449       Ctlsp_FormulaPrint(vis_stdout, tableau->abTable[i].F);
00450       fprintf(vis_stdout, "; ");
00451     }
00452   }
00453   fprintf(vis_stdout, " }");
00454 }
00455 
00465 void
00466 LtlSetPrintIndex(
00467   int length,
00468   LtlSet_t *set)
00469 {
00470   int i;
00471   
00472   fprintf(vis_stdout, "{ ");
00473   for (i=0; i<length; i++) {
00474     if (LtlSetGetElt(set, i)) {
00475       fprintf(vis_stdout, " %d ", i);
00476     }
00477   }
00478   fprintf(vis_stdout, " }\n");
00479 }
00480 
00481 
00491 LtlPair_t *
00492 LtlPairNew(
00493   char *First,
00494   char *Second)
00495 {
00496   LtlPair_t *pair = ALLOC(LtlPair_t, 1);
00497 
00498   pair->First = First;
00499   pair->Second= Second;
00500   return pair;
00501 }
00502 
00512 void
00513 LtlPairFree(
00514   LtlPair_t *pair)
00515 {
00516   FREE(pair);
00517 }
00518 
00529 int
00530 LtlPairHash(
00531   char *key,
00532   int modulus)
00533 {
00534   LtlPair_t *pair = (LtlPair_t *) key;
00535   
00536   return (int) ((((unsigned long) pair->First >>2) +
00537                  ((unsigned long) pair->Second>>4)) % modulus);
00538 }
00539 
00549 int 
00550 LtlPairCompare(
00551   const char *key1,
00552   const char *key2)
00553 {
00554   LtlPair_t *pair1 = (LtlPair_t *) key1;
00555   LtlPair_t *pair2 = (LtlPair_t *) key2;
00556   
00557   assert(key1 != NIL(char));
00558   assert(key2 != NIL(char));
00559 
00560   if ((pair1->First == pair2->First) && (pair1->Second == pair2->Second))
00561     return 0;
00562   else if (pair1->First >= pair2->First && pair1->Second >= pair2->Second)
00563     return 1;
00564   else
00565     return -1;
00566 }
00567 
00577 void
00578 LtlPairPrint(
00579   LtlPair_t *pair)
00580 {
00581   vertex_t *first = (vertex_t *) pair->First;
00582   vertex_t *second= (vertex_t *) pair->Second;
00583   Ltl_AutomatonNode_t *node1 = (Ltl_AutomatonNode_t *) first->user_data;
00584   Ltl_AutomatonNode_t *node2 = (Ltl_AutomatonNode_t *) second->user_data;
00585 
00586   fprintf(vis_stdout, " (n%d, n%d) ", node1->index, node2->index);
00587 }
00588 
00598 void
00599 LtlCoverPrintIndex(
00600   int length,
00601   lsList cover)
00602 {
00603   int first = 1;
00604   lsGen gen;
00605   LtlSet_t *set;
00606 
00607   fprintf(vis_stdout, "{ ");
00608   lsForEachItem(cover, gen, set) {
00609     if (first)    first = 0;
00610     else                  fprintf(vis_stdout, " + ");
00611     LtlSetPrintIndex(length, set);
00612   }
00613   fprintf(vis_stdout, " }");
00614 }
00615 
00616 
00627 lsList 
00628 LtlCoverCompleteSum(
00629   lsList Cover,
00630   array_t *Negate)
00631 {
00632   lsList cs = lsCreate();
00633   lsGen lsgen;
00634   array_t *products = array_alloc(LtlSet_t *, 0);
00635   LtlSet_t *term, *term1, *term2, *consensus;
00636   long i, j, k, flag;
00637   st_table *removed, *consList;  /* removed, and consensus generated */
00638   
00639   /* Check and remove contraditory terms -- containing both F and !F */
00640   lsForEachItem(Cover, lsgen, term) {
00641     if (!LtlSetIsContradictory(term, Negate))
00642       array_insert_last(LtlSet_t *, products, term);
00643   }
00644   
00645   /* Sort terms by increasing number of literals */
00646   array_sort(products, LtlSetCompareCardinality);
00647 
00648   /* Check tautologous term */
00649   term = array_fetch(LtlSet_t *, products, 0);
00650   if (LtlSetCardinality(term) == 0) {
00651     lsNewEnd(cs, (lsGeneric) LtlSetCopy(term), (lsHandle *)0);
00652     array_free(products);
00653     return cs;
00654   }
00655 
00656   /* In the following, we won't change 'products'. Instead, if a term need to
00657    * be removed, we will store it (its index number) in the hash table
00658    */
00659   removed = st_init_table(st_ptrcmp, st_ptrhash);
00660   /* In the following, we might generate some new consensus terms, and we will
00661    * store them (LtlSet_t) in the list 
00662    */
00663   consList = st_init_table(st_ptrcmp, st_ptrhash);
00664   
00665   /* Check terms for single-cube containment. Rely on ordering for efficiency.
00666    * A term can only be contained by another term with fewer literals 
00667    */
00668   for (i=array_n(products)-1; i>0; i--) {
00669     term = array_fetch(LtlSet_t *, products, i);
00670     for (j=0; j<i; j++) {
00671       term1 = array_fetch(LtlSet_t *, products, j);
00672       if (LtlSetCardinality(term1) == LtlSetCardinality(term)) break;
00673       if (LtlSetInclude(term, term1)) {
00674         /* remember the removed term */
00675         st_insert(removed, (char *)i, (char *)i);
00676         break;
00677       }
00678     }
00679   }
00680   
00681   /* Now do iterated consensus */
00682   for (i=1; i<array_n(products); i++) {
00683     if (st_is_member(removed, (char *)i)) continue;
00684     term = array_fetch(LtlSet_t *, products, i);
00685       
00686     for (j=0; j<i; j++) {
00687       if (st_is_member(removed, (char *)j)) continue;     
00688       term1 = array_fetch(LtlSet_t *, products, j);
00689       
00690       consensus = LtlSetConsensus(term, term1, Negate);
00691           
00692       if (consensus) {
00693         /* should store consensus ? */
00694         flag = 1;  
00695         for(k=0; k<array_n(products); k++) {
00696           if (st_is_member(removed, (char *)k)) continue;
00697           term2 = array_fetch(LtlSet_t *, products, k);
00698           
00699           if (LtlSetInclude(consensus, term2)) {
00700             /* redudant new term */
00701             flag = 0;  
00702             break;
00703           } 
00704           if (LtlSetInclude(term2, consensus)) {
00705             /* remember the removed term2 (k)  */
00706             st_insert(removed, (char *)k, (char *)k);
00707           }
00708         }
00709         if (flag) {
00710           array_insert_last(LtlSet_t *, products, consensus);
00711           st_insert(consList, consensus, (char *)0);
00712         }else
00713           LtlSetFree(consensus);
00714       }
00715     }
00716   }
00717 
00718 #if 0
00719   if (0) {
00720     fprintf(vis_stdout, "\nLtlCompleteSum: products = {  ");
00721     for(i=0; i<array_n(products); i++) {
00722       term = array_fetch(LtlSet_t *, products, i);
00723       LtlSetPrintIndex(array_n(Negate), term);
00724     }
00725     fprintf(vis_stdout, "}\nLtlCompleteSum: removed = {  ");
00726     st_foreach_item(removed, stgen, &i, NIL(char *)) {
00727       term = array_fetch(LtlSet_t *, products, i);
00728       LtlSetPrintIndex(array_n(Negate), term);
00729     }
00730     fprintf(vis_stdout, "}\nLtlCompleteSum: consList = {  ");
00731     st_foreach_item(consList, stgen, &term, NIL(char *)) {
00732       LtlSetPrintIndex(array_n(Negate), term);
00733     }
00734     fprintf(vis_stdout, "}\n");
00735     
00736     fflush(vis_stdout);
00737   }
00738 #endif      
00739   
00740   arrayForEachItem(LtlSet_t *, products, i, term) {
00741     if (!st_is_member(removed, (char *)i)) {
00742       /* put it into the complete sum list */
00743       if (!st_is_member(consList, term))
00744         term1 = LtlSetCopy(term);
00745       else
00746         term1 = term;
00747       lsNewEnd(cs, (lsGeneric) term1, NIL(lsHandle));
00748     }else {
00749       /* it has been removed. If it was allocated locally, free it */
00750       if (st_is_member(consList, term))
00751         LtlSetFree(term);
00752     }
00753   }
00754 
00755   array_free(products);
00756   st_free_table(removed);
00757   st_free_table(consList);
00758 
00759   return cs;
00760 }
00761 
00762 
00772 LtlSet_t *
00773 LtlSetConsensus(
00774   LtlSet_t *first,
00775   LtlSet_t *second,
00776   array_t *Negate)
00777 {
00778   LtlSet_t *consensus = LtlSetNew(array_n(Negate));
00779   int pivot = -1;
00780   int literal, complement;
00781   
00782   for (literal=0; literal<array_n(Negate); literal++) {
00783     if (LtlSetGetElt(first, literal)) {
00784       complement = array_fetch(int, Negate, literal);
00785       if (LtlSetGetElt(second, complement)) {
00786         if (pivot != -1) {
00787           LtlSetFree(consensus);
00788           return NIL(LtlSet_t);
00789         }else {
00790           pivot = complement;
00791         }
00792       }else {
00793         LtlSetSetElt(consensus, literal);
00794       }
00795     }
00796   }
00797   /* if pivot has never been defined, return NIL */
00798   if (pivot == -1) {
00799     LtlSetFree(consensus);
00800     return NIL(LtlSet_t);
00801   }
00802 
00803   for (literal=0; literal<array_n(Negate); literal++) {
00804     if (LtlSetGetElt(second, literal)) {
00805       if (literal != pivot)
00806         LtlSetSetElt(consensus, literal);
00807     }
00808   }
00809 
00810   return consensus;
00811 }
00812 
00823 lsList
00824 LtlCoverCofactor(
00825   lsList Cover,
00826   LtlSet_t *c,
00827   array_t *Negate)
00828 {
00829   lsList cofactor = lsCopy(Cover, (lsGeneric (*)(lsGeneric))LtlSetCopy);
00830   lsList list;
00831   lsGen  lsgen;
00832   st_table *removed = st_init_table(st_ptrcmp, st_ptrhash);
00833   int literal, complement;
00834   LtlSet_t *term;
00835   
00836   for (literal=0; literal<array_n(Negate); literal++) {
00837     if (!LtlSetGetElt(c, literal))  continue;
00838     complement = array_fetch(int, Negate, literal);
00839     lsForEachItem(cofactor, lsgen, term) {
00840       if (st_is_member(removed, term)) continue;
00841       if (LtlSetGetElt(term, complement)) 
00842         st_insert(removed, term, term);
00843       else if (LtlSetGetElt(term, literal))
00844         LtlSetClearElt(term, literal);
00845     }
00846   }
00847 
00848   list = cofactor;
00849   cofactor = lsCreate();
00850   lsForEachItem(list, lsgen, term) {
00851     if (st_is_member(removed, term)) 
00852       LtlSetFree(term);
00853     else
00854       lsNewEnd(cofactor, (lsGeneric) term, (lsHandle *) 0);
00855   }
00856   lsDestroy(list, (void (*)(lsGeneric))0);
00857 
00858   st_free_table(removed);
00859 
00860   return cofactor;
00861 }
00862       
00873 int
00874 LtlCoverIsTautology(
00875   lsList Cover,
00876   array_t *Negate)
00877 {
00878   lsList complete = LtlCoverCompleteSum(Cover, Negate);
00879   LtlSet_t *term;
00880   int result;
00881 
00882   if (lsLength(complete) !=1)
00883     result = 0;
00884   else {
00885     lsFirstItem(complete, &term, (lsHandle *)0);
00886     result = (LtlSetCardinality(term) == 0);
00887   }
00888 
00889   lsDestroy(complete, (void (*)(lsGeneric))LtlSetFree);
00890   return result;
00891 }
00892 
00902 int
00903 LtlCoverIsImpliedBy(
00904   lsList Cover,
00905   LtlSet_t *term,
00906   array_t *Negate)
00907 {
00908   lsList cofactor = LtlCoverCofactor(Cover, term, Negate);
00909   int result = LtlCoverIsTautology(Cover, Negate);
00910   lsDestroy(cofactor, (void (*)(lsGeneric))LtlSetFree);
00911   
00912   return result;
00913 }
00914     
00915 
00930 lsList
00931 LtlCoverPrimeAndIrredundant(
00932   LtlTableau_t *tableau,
00933   lsList Cover,
00934   array_t *Negate)
00935 {
00936   lsList pai = LtlCoverCompleteSum(Cover, Negate);
00937   int totalnum;   /* total num of terms in current lsList pai */
00938   int procnum;    /* how many are already processed so far ? */
00939   LtlSet_t *term;
00940   
00941   totalnum = lsLength(pai);
00942   procnum = 0;
00943   /* Try to drop each term in turn */
00944   while(lsDelBegin(pai, &term) != LS_NOMORE) {
00945     if ( (lsLength(pai) != 0) &&
00946          /* !LtlAutomatonSetIsFair(tableau, term) && */
00947          LtlCoverIsImpliedBy(pai, term, Negate) ) {
00948       LtlSetFree(term);
00949       totalnum--;
00950     }else 
00951       lsNewEnd(pai, (lsGeneric) term, (lsHandle *)0);
00952     
00953     procnum++;
00954     if (procnum >= totalnum)
00955       break;
00956   }
00957   
00958   return pai;
00959 }
00960 
00961 
00971 LtlSet_t *
00972 LtlCoverGetSuperCube(
00973   lsList Cover,
00974   array_t *Negate)
00975 {
00976   LtlSet_t *unate = LtlSetNew(array_n(Negate));
00977   LtlSet_t *binate = LtlSetNew(array_n(Negate));
00978   lsGen  lsgen;
00979   LtlSet_t *term;
00980   int literal, neg;
00981 
00982   lsForEachItem( Cover, lsgen, term ) {
00983     for (literal=0; literal<array_n(Negate); literal++) {
00984       if (!LtlSetGetElt(term, literal))  continue;
00985       if (LtlSetGetElt(binate, literal) || LtlSetGetElt(unate, literal))
00986         continue;
00987       neg = array_fetch(int, Negate, literal);
00988       if (LtlSetGetElt(unate, neg)) {
00989         LtlSetClearElt(unate, neg);
00990         LtlSetSetElt(binate, literal);
00991         LtlSetSetElt(binate, neg);
00992       }else
00993         LtlSetSetElt(unate, literal);
00994     }
00995   }
00996 
00997   LtlSetFree(binate);
00998   
00999   return unate;
01000 }
01001 
01002 
01003 
01013 mdd_t *
01014 LtlSetModelCheckFormulae(
01015   LtlSet_t *set,
01016   array_t *labelTable,
01017   Fsm_Fsm_t *fsm)
01018 {
01019   mdd_t *minterm, *mdd1, *mdd2;
01020   mdd_manager *mddManager = Fsm_FsmReadMddManager(fsm);
01021   mdd_t *mddOne = mdd_one(mddManager);
01022   array_t *careStatesArray = array_alloc(mdd_t *, 0);
01023   int i;
01024 
01025   array_insert(mdd_t *, careStatesArray, 0, mddOne);
01026 
01027   minterm = mdd_dup(mddOne);
01028   for (i=0; i<array_n(labelTable); i++) {
01029     if (LtlSetGetElt(set, i)) {
01030       Ctlsp_Formula_t *F = array_fetch(Ctlsp_Formula_t *, labelTable, i);
01031       Ctlp_Formula_t *ctlF = Ctlsp_PropositionalFormulaToCTL(F);
01032       mdd1 = Mc_FsmEvaluateFormula(fsm, ctlF, mddOne, 
01033                                    NIL(Fsm_Fairness_t),
01034                                    careStatesArray, 
01035                                    MC_NO_EARLY_TERMINATION,
01036                                    NIL(Fsm_HintsArray_t), Mc_None_c,
01037                                    McVerbosityNone_c, McDcLevelNone_c, 0,
01038                                    McGSH_EL_c);
01039       mdd2 = minterm;
01040       minterm = mdd_and(minterm, mdd1, 1, 1);
01041       mdd_free(mdd2);
01042       mdd_free(mdd1);
01043       Ctlp_FormulaFree(ctlF);
01044     }
01045   }
01046 
01047   mdd_array_free(careStatesArray);
01048 
01049   return minterm;
01050 }