VIS

src/abs/absEvaluate.c

Go to the documentation of this file.
00001 
00018 #include "absInt.h"
00019 
00020 static char rcsid[] UNUSED = "$Id: absEvaluate.c,v 1.19 2002/09/19 05:25:00 fabio Exp $";
00021 
00022 
00023 /*---------------------------------------------------------------------------*/
00024 /* Macro declarations                                                        */
00025 /*---------------------------------------------------------------------------*/
00026 
00027 /*---------------------------------------------------------------------------*/
00028 /* Variable declarations                                                     */
00029 /*---------------------------------------------------------------------------*/
00030 
00033 /*---------------------------------------------------------------------------*/
00034 /* Static function prototypes                                                */
00035 /*---------------------------------------------------------------------------*/
00036 
00037 static void EvaluateVariable(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
00038 static void EvaluateIdentifier(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
00039 static void EvaluateNot(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
00040 static void EvaluateAnd(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
00041 static void EvaluateFixedPoint(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
00042 static void EvaluatePreImage(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
00043 static mdd_t * OverApproximatePreImageWithSubFSM(Abs_VerificationInfo_t *absInfo, mdd_t *lowerBound, mdd_t *upperBound, mdd_t *careSet);
00044 static mdd_t * OverApproximatePreImageWithBddSubsetting(Abs_VerificationInfo_t *absInfo, mdd_t *lowerBound, mdd_t *upperBound, mdd_t *careSet);
00045 static mdd_t * UnderApproximatePreImageWithBddSubsetting(Abs_VerificationInfo_t *absInfo, mdd_t *lowerBound, mdd_t *upperBound, mdd_t *careSet);
00046 
00050 /*---------------------------------------------------------------------------*/
00051 /* Definition of exported functions                                          */
00052 /*---------------------------------------------------------------------------*/
00053 
00054 
00055 /*---------------------------------------------------------------------------*/
00056 /* Definition of internal functions                                          */
00057 /*---------------------------------------------------------------------------*/
00058 
00070 void
00071 AbsSubFormulaVerify(
00072   Abs_VerificationInfo_t *absInfo,
00073   AbsVertexInfo_t *vertexPtr)
00074 {
00075   AbsStats_t *stats;
00076   mdd_manager *mddManager;
00077   mdd_t *oldTmpCareSet = NIL(mdd_t);
00078   
00079   long verbosity;
00080 
00081   stats = AbsVerificationInfoReadStats(absInfo);
00082   mddManager = AbsVerificationInfoReadMddManager(absInfo);
00083 
00084   /* If the current vertex has more than one parent, the temporary care set
00085    * must be reset (because it depends on the path that led to this vertex */
00086   if (lsLength(vertexPtr->parent) > 1) {
00087     oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
00088     AbsVerificationInfoSetTmpCareSet(absInfo, mdd_one(mddManager));
00089   }
00090 
00091   switch (AbsVertexReadType(vertexPtr)) {
00092     case fixedPoint_c:
00093       EvaluateFixedPoint(absInfo, vertexPtr);
00094       AbsStatsReadEvalFixedPoint(stats)++;
00095       break;
00096     case and_c: 
00097       EvaluateAnd(absInfo, vertexPtr);
00098       AbsStatsReadEvalAnd(stats)++;
00099       break;
00100     case not_c:
00101       EvaluateNot(absInfo, vertexPtr);
00102       AbsStatsReadEvalNot(stats)++;
00103       break;
00104     case preImage_c:
00105       EvaluatePreImage(absInfo, vertexPtr);
00106       AbsStatsReadEvalPreImage(stats)++;
00107       break;
00108     case identifier_c:
00109       EvaluateIdentifier(absInfo, vertexPtr);
00110       AbsStatsReadEvalIdentifier(stats)++;
00111       break;
00112     case variable_c:
00113       EvaluateVariable(absInfo, vertexPtr);
00114       AbsStatsReadEvalVariable(stats)++;
00115       break;
00116     default: fail("Encountered unknown type of vertex\n");
00117     }
00118 
00119   verbosity = AbsOptionsReadVerbosity(AbsVerificationInfoReadOptions(absInfo));
00120 
00121   /* Print the size of the care set */
00122   if (verbosity & ABS_VB_CARESZ) {
00123     (void) fprintf(vis_stdout, "ABS: Size of Care Set: ");
00124     (void) fprintf(vis_stdout, "%d Nodes.\n", 
00125                    mdd_size(AbsVerificationInfoReadCareSet(absInfo)));
00126   }
00127 
00128   /* Print the care set */
00129   if (verbosity & ABS_VB_CARE) {
00130     (void) fprintf(vis_stdout, "ABS: Care Set for Evaluation:\n");
00131     AbsBddPrintMinterms(AbsVerificationInfoReadCareSet(absInfo));
00132   }
00133 
00134   /* Print the contents of the vertex */
00135   if (verbosity & ABS_VB_VTXCNT) {
00136     AbsVertexPrint(vertexPtr, NIL(st_table), FALSE, verbosity);
00137   }
00138 
00139   if (lsLength(vertexPtr->parent) > 1) {
00140     /* Restore the old temporary careset */
00141     mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
00142     AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
00143   }
00144 
00145 } /* End of AbsSubFormulaVerify */
00146 
00160 void
00161 AbsFormulaScheduleEvaluation(
00162   AbsVertexInfo_t *current,
00163   AbsVertexInfo_t *limit)
00164 {
00165   /* We reached the final case */
00166   if (current == limit) {
00167     return;
00168   }
00169   else {
00170     AbsVertexInfo_t *parentPtr;
00171     lsList          parentList;
00172     lsGen           gen;
00173 
00174     /* Set the re-evaluation flag for the current vertex */
00175     AbsVertexSetServed(current, 0);
00176 
00177     /* Recur over the parents */
00178     parentList = AbsVertexReadParent(current);
00179     lsForEachItem(parentList, gen, parentPtr) {
00180       if (parentPtr != NIL(AbsVertexInfo_t)) {
00181         AbsFormulaScheduleEvaluation(parentPtr, limit);
00182       }
00183     }
00184   }
00185 
00186   return;
00187 } /* End of AbsFormulaScheduleEvaluation */
00188 
00206 mdd_t *
00207 AbsComputeOptimalIterate(
00208   Abs_VerificationInfo_t *absInfo,
00209   AbsVertexInfo_t *vertexPtr,
00210   mdd_t *lowerIterate,
00211   mdd_t *upperIterate)
00212 {
00213   mdd_t *tmp;
00214   mdd_t *result;
00215 
00216   if (AbsOptionsReadMinimizeIterate(AbsVerificationInfoReadOptions(absInfo))
00217       && AbsVertexReadUseExtraCareSet(vertexPtr)) {
00218 
00219     /* 
00220      * For this computation we have three ingredients and a handfull of
00221      * choices. The ingredients are the sets newIterate, iterate and
00222      * careSet. The goal is to compute an interval delimited by two boolean
00223      * functions and then call the function bdd_between to try to obtain
00224      * the best bdd in size inside that interval. To compute the extremes
00225      * of the interval there are several choices. For example, the care set
00226      * can be used in the lower bound of the interval or in both
00227      * bounds. The bigger the interval the more choice the function
00228      * bdd_between has to minimize, however, this does not turn into a
00229      * better result. 
00230      *
00231      * Current Choice: [newIterate * iterate', newIterate]
00232      */
00233     tmp = mdd_and(lowerIterate, upperIterate, 0, 1);
00234     result = bdd_between(tmp, upperIterate);
00235     
00236     /* This line for debugging purposes, should be removed 
00237     (void) fprintf(vis_stdout, 
00238                    "newIterate : %d, Diff : %d, result %d\n",
00239                    mdd_size(upperIterate), mdd_size(tmp),
00240                    mdd_size(result)); */
00241     
00242     mdd_free(tmp);
00243   }
00244   else {
00245     result = mdd_dup(upperIterate);
00246   }
00247 
00248   return result;
00249 } /* End of AbsComputeOptimalIterate */
00250 
00260 boolean
00261 AbsFixedPointIterate(
00262   Abs_VerificationInfo_t *absInfo,
00263   AbsVertexInfo_t *vertexPtr,
00264   int iterateIndex)
00265 {
00266   AbsVertexInfo_t *subFormula;
00267   boolean         keepIterating;
00268   boolean         globalApprox;
00269   int             stepCount;
00270   long            verbosity;
00271   mdd_t           *iterate;
00272   mdd_t           *newIterate;
00273   mdd_t           *careSet;
00274     
00275   /* Do not allow to iterate from the middle of a fixed point computation */
00276   assert(iterateIndex == array_n(AbsVertexReadRings(vertexPtr)) - 1);
00277 
00278   careSet = AbsVerificationInfoReadCareSet(absInfo);
00279 
00280   /* Check if the set of iterates has already converged */
00281   if (array_n(AbsVertexReadRings(vertexPtr)) > 1) {
00282     mdd_t *ring1 = AbsVertexFetchRing(vertexPtr, iterateIndex);
00283     mdd_t *ring2 = AbsVertexFetchRing(vertexPtr, iterateIndex - 1);
00284     if (AbsMddLEqualModCareSet(ring1, ring2, careSet)) {
00285       return FALSE;
00286     }
00287     iterate = AbsVertexFetchRing(vertexPtr, iterateIndex - 1);
00288   }
00289   else {
00290     iterate = AbsVertexFetchRing(vertexPtr, iterateIndex);
00291   }
00292   newIterate = AbsVertexFetchRing(vertexPtr, iterateIndex);
00293 
00294   /* Variable initialization */
00295   keepIterating = TRUE;
00296   stepCount = iterateIndex;
00297   verbosity = AbsOptionsReadVerbosity(AbsVerificationInfoReadOptions(absInfo));
00298   subFormula = AbsVertexReadLeftKid(vertexPtr);
00299   globalApprox = AbsVertexFetchSubApprox(vertexPtr, iterateIndex);
00300   
00301   /* Main loop for the fixed point computation */
00302   while (keepIterating) {
00303     mdd_t *best;
00304     
00305     /* 
00306      * Given newIterate, iterate and CareSet, if the use of extra care set is
00307      * enabled, choose the best candidate as the value of the iterate. 
00308      */
00309     best = AbsComputeOptimalIterate(absInfo, vertexPtr, iterate, newIterate);
00310 
00311     /* Print the iterates */
00312     if ((verbosity & ABS_VB_PITER) || (verbosity & ABS_VB_ITSIZ)) {
00313       (void) fprintf(vis_stdout, "ABS: New Iterate: ");
00314       if (verbosity & ABS_VB_ITSIZ) {
00315         (void) fprintf(vis_stdout, "%d -> %d\n", mdd_size(newIterate),
00316                        mdd_size(best));
00317       }
00318       else {
00319         (void) fprintf(vis_stdout, "\n");
00320       }
00321       if (verbosity & ABS_VB_PITER) {
00322         AbsBddPrintMinterms(newIterate);
00323       }
00324     }
00325     
00326     /* Store the value of the variable */
00327     AbsVertexSetSat(AbsVertexReadFpVar(vertexPtr), best);
00328     
00329     /* Mark the proper sub-formulas for re-evaluation */
00330     AbsFormulaScheduleEvaluation(AbsVertexReadFpVar(vertexPtr), vertexPtr);
00331     
00332     /* Evaluate the sub-formula */
00333     AbsSubFormulaVerify(absInfo, subFormula);
00334     mdd_free(best);
00335     iterate = newIterate;
00336     
00337     /* 
00338      * Compute the new iterate. Due to the fact that don't cares are being
00339      * used, it might be possible that the new iterate does not contain the
00340      * previous one, in that case the or is taken 
00341      */
00342     newIterate = mdd_or(iterate, AbsVertexReadSat(subFormula), 1, 1);
00343     
00344     assert(AbsMddLEqualModCareSet(iterate, newIterate, careSet));
00345 
00346     /* Set the rings and the approximation flags */
00347     AbsVertexInsertRing(vertexPtr, newIterate);
00348     AbsVertexInsertRingApprox(vertexPtr, FALSE);
00349     globalApprox = globalApprox || AbsVertexReadGlobalApprox(subFormula);
00350     AbsVertexInsertSubApprox(vertexPtr, globalApprox);
00351 
00352     keepIterating = !AbsMddEqualModCareSet(newIterate, iterate, careSet);
00353     
00354     stepCount++;
00355   } /* End of main while loop */
00356 
00357   return TRUE;
00358 } /* End of AbsFixedPointIterate */
00359 
00360 /*---------------------------------------------------------------------------*/
00361 /* Definition of static functions                                            */
00362 /*---------------------------------------------------------------------------*/
00363 
00374 static void
00375 EvaluateVariable(
00376   Abs_VerificationInfo_t *absInfo,
00377   AbsVertexInfo_t *vertexPtr)
00378 {
00379   /* Increase the number of times the result has been used */
00380   AbsVertexReadServed(vertexPtr)++;
00381 
00382   return;
00383 } /* End of EvaluateVariable */
00384 
00399 static void
00400 EvaluateIdentifier(
00401   Abs_VerificationInfo_t *absInfo,
00402   AbsVertexInfo_t *vertexPtr)
00403 {
00404   if (AbsVertexReadServed(vertexPtr) == 0) {
00405     Ntk_Node_t     *node;
00406     Var_Variable_t *nodeVar;
00407     graph_t        *partition;
00408     vertex_t       *partitionVertex;
00409     Mvf_Function_t *nodeFunction;
00410     mdd_t          *result;
00411     char           *nodeNameString;
00412     char           *nodeValueString;
00413     int            nodeValue;
00414 
00415     /* Clean up of previous result */
00416     if (AbsVertexReadSat(vertexPtr) != NIL(mdd_t)) {
00417       mdd_free(AbsVertexReadSat(vertexPtr));
00418       AbsVertexSetSat(vertexPtr, NIL(mdd_t));
00419     }
00420 
00421     /* Read the partition */
00422     partition = AbsVerificationInfoReadPartition(absInfo);
00423     
00424     assert(partition != NIL(graph_t));
00425     
00426     /* Obtain the name and the value being used */
00427     nodeNameString = AbsVertexReadName(vertexPtr);
00428     nodeValueString = AbsVertexReadValue(vertexPtr);
00429     
00430     /* Obtain the the node in the network and the variable attached to it */
00431     node = Ntk_NetworkFindNodeByName(AbsVerificationInfoReadNetwork(absInfo),
00432                                      nodeNameString);
00433     nodeVar = Ntk_NodeReadVariable(node);
00434     
00435     /* Obtain the real value of the multi-valued vairable */
00436     if (Var_VariableTestIsSymbolic(nodeVar)) {
00437       nodeValue = Var_VariableReadIndexFromSymbolicValue(nodeVar,
00438                                                          nodeValueString);
00439     }
00440     else {
00441       nodeValue = atoi(nodeValueString);
00442     }
00443     
00444     /* Read the partition, find the vertex in the partition and its function */
00445     partitionVertex = Part_PartitionFindVertexByName(partition, 
00446                                                      nodeNameString);
00447     
00448     /* If the vertex is not represented in the partition must be built */
00449     if (partitionVertex == NIL(vertex_t)) { 
00450       Ntk_Node_t *tmpNode;
00451       lsGen      tmpGen;
00452       array_t    *mvfArray;
00453       array_t    *tmpRoots;
00454       st_table   *tmpLeaves;
00455       
00456       /* Initialize the variables */
00457       tmpRoots = array_alloc(Ntk_Node_t *, 0);
00458       tmpLeaves = st_init_table(st_ptrcmp, st_ptrhash);
00459       
00460       /* Insert the parameters in the array and table */
00461       array_insert_last(Ntk_Node_t *, tmpRoots, node);
00462       Ntk_NetworkForEachCombInput(AbsVerificationInfoReadNetwork(absInfo),
00463                                   tmpGen, tmpNode) {
00464         st_insert(tmpLeaves, (char *) tmpNode, (char *) NTM_UNUSED);
00465       }
00466       
00467       /* Effectively build the mdd for the given vertex */
00468       mvfArray =  Ntm_NetworkBuildMvfs(AbsVerificationInfoReadNetwork(absInfo),
00469                                        tmpRoots, tmpLeaves, NIL(mdd_t));
00470       nodeFunction = array_fetch(Mvf_Function_t *, mvfArray, 0);
00471       array_free(tmpRoots);
00472       st_free_table(tmpLeaves);
00473       array_free(mvfArray);
00474       
00475       /* Store the result in the vertex */
00476       result = Mvf_FunctionReadComponent(nodeFunction, nodeValue);
00477       AbsVertexSetSat(vertexPtr, mdd_dup(result));
00478       Mvf_FunctionFree(nodeFunction);
00479     }
00480     else {
00481       /* Store the result in the vertex */
00482       nodeFunction = Part_VertexReadFunction(partitionVertex);
00483       result = Mvf_FunctionReadComponent(nodeFunction, nodeValue);
00484       AbsVertexSetSat(vertexPtr, mdd_dup(result));
00485     }
00486     
00487     /* Set the approximation flags */
00488     AbsVertexSetLocalApprox(vertexPtr, FALSE);
00489     AbsVertexSetGlobalApprox(vertexPtr, FALSE);
00490   }
00491 
00492   /* Increase the number of times the result has been used */
00493   AbsVertexReadServed(vertexPtr)++;
00494   
00495   return;
00496 } /* End of EvaluateIdentifier */
00497 
00507 static void
00508 EvaluateNot(
00509   Abs_VerificationInfo_t *absInfo,
00510   AbsVertexInfo_t *vertexPtr)
00511 {
00512   if (AbsVertexReadServed(vertexPtr) == 0) {
00513     AbsVertexInfo_t *subFormula;
00514     
00515     /* Clean up of previous result */
00516     if (AbsVertexReadSat(vertexPtr) != NIL(mdd_t)) {
00517       mdd_free(AbsVertexReadSat(vertexPtr));
00518       AbsVertexSetSat(vertexPtr, NIL(mdd_t));
00519     }
00520 
00521     /* Recursively evaluate the sub-formula */
00522     subFormula = AbsVertexReadLeftKid(vertexPtr);
00523     AbsSubFormulaVerify(absInfo, subFormula);
00524 
00525     /* Negate the result of the sub-formula */
00526     AbsVertexSetSat(vertexPtr, mdd_not(AbsVertexReadSat(subFormula)));
00527 
00528     /* Set the approximation flags */
00529     AbsVertexSetLocalApprox(vertexPtr, FALSE);
00530     AbsVertexSetGlobalApprox(vertexPtr, AbsVertexReadGlobalApprox(subFormula));
00531   }
00532 
00533   /* Increase the number of times the result has been used */
00534   AbsVertexReadServed(vertexPtr)++;
00535 
00536   return;
00537 } /* End of EvaluateNot */
00538 
00548 static void
00549 EvaluateAnd(
00550   Abs_VerificationInfo_t *absInfo,
00551   AbsVertexInfo_t *vertexPtr)
00552 {
00553   if (AbsVertexReadServed(vertexPtr) == 0) {
00554     AbsVertexInfo_t *firstFormula;
00555     AbsVertexInfo_t *secondFormula;
00556     mdd_t *oldTmpCareSet;
00557 
00558     /* Clean up of previous result */
00559     if (AbsVertexReadSat(vertexPtr) != NIL(mdd_t)) {
00560       mdd_free(AbsVertexReadSat(vertexPtr));
00561       AbsVertexSetSat(vertexPtr, NIL(mdd_t));
00562     }
00563 
00564     /* Obtain the subformulas to evaluate */
00565     firstFormula = AbsVertexReadLeftKid(vertexPtr);
00566     secondFormula = AbsVertexReadRightKid(vertexPtr);
00567   
00568     /* Recursively evaluate the first sub-formula */
00569     AbsSubFormulaVerify(absInfo, firstFormula);
00570 
00571     /* Store the temporary careset and set the new one */
00572     oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
00573     AbsVerificationInfoSetTmpCareSet(absInfo, 
00574                                      mdd_and(oldTmpCareSet, 
00575                                              AbsVertexReadSat(firstFormula), 
00576                                              1,1));
00577 
00578     /* Recursively evaluate the second sub-formula */
00579     AbsSubFormulaVerify(absInfo, secondFormula);
00580 
00581     /* Restore the temporary careset */
00582     mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
00583     AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
00584     
00585     /* Compute result, so far no approximation is required */
00586     AbsVertexSetSat(vertexPtr, mdd_and(AbsVertexReadSat(firstFormula),
00587                                        AbsVertexReadSat(secondFormula), 
00588                                        1, 1));
00589 
00590     /* Set the approximation flags */
00591     AbsVertexSetLocalApprox(vertexPtr, FALSE);
00592     AbsVertexSetGlobalApprox(vertexPtr, 
00593                              AbsVertexReadGlobalApprox(firstFormula) || 
00594                              AbsVertexReadGlobalApprox(secondFormula));
00595   }
00596 
00597   /* Increase the number of times the result has been used */
00598   AbsVertexReadServed(vertexPtr)++;
00599 
00600   return;
00601 } /* End of EvaluateAnd */
00602 
00612 static void
00613 EvaluateFixedPoint(
00614   Abs_VerificationInfo_t *absInfo,
00615   AbsVertexInfo_t *vertexPtr)
00616 {
00617   if (AbsVertexReadServed(vertexPtr) == 0) {
00618     mdd_manager *mddManager;
00619     mdd_t       *oldTmpCareSet;
00620     mdd_t       *newTmpCareSet;
00621 
00622     if (AbsVertexReadRings(vertexPtr) != NIL(array_t)) {
00623       mdd_t *ringUnit;
00624       int i;
00625 
00626       arrayForEachItem(mdd_t *, AbsVertexReadRings(vertexPtr), i, ringUnit) {
00627         mdd_free(ringUnit);
00628       }
00629       array_free(AbsVertexReadRings(vertexPtr));
00630       array_free(AbsVertexReadRingApprox(vertexPtr));
00631       array_free(AbsVertexReadSubApprox(vertexPtr));
00632       mdd_free(AbsVertexReadSat(vertexPtr));
00633     }
00634 
00635     /* Re-allocation of the temporary structures */
00636     AbsVertexSetRings(vertexPtr, array_alloc(mdd_t *, 0));
00637     AbsVertexSetRingApprox(vertexPtr, array_alloc(boolean, 0));
00638     AbsVertexSetSubApprox(vertexPtr, array_alloc(boolean, 0));
00639     
00640     /* Initial values of the fixed point */
00641     mddManager = AbsVerificationInfoReadMddManager(absInfo);
00642     AbsVertexInsertRing(vertexPtr, mdd_zero(mddManager));
00643     AbsVertexInsertRingApprox(vertexPtr, FALSE);
00644     AbsVertexInsertSubApprox(vertexPtr, FALSE);
00645 
00646     /* Reset the temporary careset to the mdd one */
00647     oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
00648     newTmpCareSet = mdd_one(mddManager);
00649     AbsVerificationInfoSetTmpCareSet(absInfo, newTmpCareSet);
00650 
00651     /* Effectively iterate the body */
00652     AbsFixedPointIterate(absInfo, vertexPtr, 0);
00653 
00654     /* Restore the old temporary careset */
00655     mdd_free(newTmpCareSet);
00656     AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
00657     
00658     /* Set the last result as the set sat*/
00659     AbsVertexSetSat(vertexPtr, 
00660                     mdd_dup(AbsVertexFetchRing(vertexPtr,
00661                                         array_n(AbsVertexReadRings(vertexPtr))
00662                                                - 1)));
00663 
00664     /* Set the approximation flags */
00665     AbsVertexSetLocalApprox(vertexPtr, FALSE);
00666     AbsVertexSetGlobalApprox(vertexPtr, 
00667                              AbsVertexFetchSubApprox(vertexPtr,
00668                                array_n(AbsVertexReadSubApprox(vertexPtr)) - 1));
00669   }
00670 
00671   /* Increase the number of times the result has been used */
00672   AbsVertexReadServed(vertexPtr)++;
00673 
00674   return;
00675 }
00676 
00677  /* End of EvaluateFixedPoint */
00678 
00688 static void
00689 EvaluatePreImage(
00690   Abs_VerificationInfo_t *absInfo,
00691   AbsVertexInfo_t *vertexPtr)
00692 {
00693   AbsOptions_t *options;
00694   AbsStats_t   *stats;
00695   long         verbosity;
00696 
00697   /* Variable initialization */
00698   options = AbsVerificationInfoReadOptions(absInfo);
00699   verbosity = AbsOptionsReadVerbosity(options);
00700   stats = AbsVerificationInfoReadStats(absInfo);
00701 
00702   if (AbsVertexReadServed(vertexPtr) == 0) {
00703     AbsVertexInfo_t *subFormula;
00704     mdd_manager     *mddManager;
00705     mdd_t           *result;
00706     mdd_t           *careSet;
00707     mdd_t           *oldTmpCareSet;
00708     mdd_t           *minimizedSet;
00709 
00710     /* Variable initialization */
00711     mddManager = AbsVerificationInfoReadMddManager(absInfo);
00712     subFormula = AbsVertexReadLeftKid(vertexPtr);
00713 
00714     /* 
00715      * Compute the care set as the conjunction of the given one and the
00716      * temporary one 
00717      */
00718     careSet = mdd_and(AbsVerificationInfoReadCareSet(absInfo),
00719                       AbsVerificationInfoReadTmpCareSet(absInfo), 1, 1);
00720 
00721     /* Clean up */
00722     if (AbsVertexReadSat(vertexPtr) != NIL(mdd_t)) {
00723       mdd_free(AbsVertexReadSat(vertexPtr));
00724       AbsVertexSetSat(vertexPtr, NIL(mdd_t));
00725     }
00726     
00727     /* Reset the temporary careset to the mdd one */
00728     oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
00729     AbsVerificationInfoSetTmpCareSet(absInfo, mdd_one(mddManager));
00730 
00731     /* Evaluate the sub-formula */
00732     AbsSubFormulaVerify(absInfo, subFormula);
00733 
00734     /* Restore the old temporary careset */
00735     mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
00736     AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
00737     
00738     /* Check for trivial cases */
00739     if (mdd_is_tautology(AbsVertexReadSat(subFormula), 0) ||
00740         mdd_is_tautology(AbsVertexReadSat(subFormula), 1)) {
00741       AbsVertexSetSat(vertexPtr, mdd_dup(AbsVertexReadSat(subFormula)));
00742       AbsVertexSetLocalApprox(vertexPtr, FALSE);
00743       AbsVertexSetGlobalApprox(vertexPtr, 
00744                                AbsVertexReadGlobalApprox(subFormula));
00745       mdd_free(careSet);
00746       return;
00747     }
00748 
00749     /* if (AbsOptionsReadMinimizeIterate(options)){ */
00750     if (FALSE){
00751       minimizedSet = bdd_minimize(AbsVertexReadSat(subFormula),
00752                                   AbsVerificationInfoReadCareSet(absInfo));
00753     }
00754     else {
00755       minimizedSet = mdd_dup(AbsVertexReadSat(subFormula));
00756     }
00757       
00758     /* Look up in the cache if the result has been previously computed */
00759     if (AbsVertexReadSolutions(vertexPtr) != NIL(st_table)) {
00760       mdd_t   *unit;
00761       boolean localFlag;
00762       boolean exactness;
00763       
00764       exactness = AbsOptionsReadExact(options);
00765       if (AbsEvalCacheLookup(AbsVertexReadSolutions(vertexPtr),
00766                              minimizedSet, careSet, !exactness,
00767                              &unit, &localFlag)) {
00768 
00769         /* Set the sat */
00770         AbsVertexSetSat(vertexPtr, mdd_dup(unit));
00771 
00772         /* Set the approximation flags */
00773         AbsVertexSetLocalApprox(vertexPtr, localFlag & !exactness);
00774         AbsVertexSetGlobalApprox(vertexPtr, 
00775                                  AbsVertexReadGlobalApprox(subFormula) || 
00776                                  AbsVertexReadLocalApprox(vertexPtr));
00777         /* Increase the number of times the result has been used */
00778         AbsVertexReadServed(vertexPtr)++;
00779         
00780         mdd_free(careSet);
00781         mdd_free(minimizedSet);
00782         return;
00783       }
00784     }
00785     else {
00786       /* Initialize the cache */
00787       AbsVertexSetSolutions(vertexPtr, st_init_table(st_ptrcmp, st_ptrhash));
00788     }
00789 
00790     /* Effectively compute preImage */
00791     if (!AbsOptionsReadExact(options)) {
00792       if (AbsVertexReadPolarity(vertexPtr)) {
00793         if (AbsOptionsReadPartApprox(options)) {
00794           result = OverApproximatePreImageWithSubFSM(absInfo, minimizedSet, 
00795                                                      minimizedSet, careSet);
00796         }
00797         else {
00798           result = OverApproximatePreImageWithBddSubsetting(absInfo, 
00799                                                             minimizedSet, 
00800                                                             minimizedSet, 
00801                                                             careSet);
00802         }
00803         AbsVertexSetLocalApprox(vertexPtr, TRUE);
00804       }
00805       else {
00806         result = UnderApproximatePreImageWithBddSubsetting(absInfo, 
00807                                                            minimizedSet, 
00808                                                            minimizedSet,
00809                                                            careSet);
00810         AbsVertexSetLocalApprox(vertexPtr, TRUE);
00811       }
00812       AbsStatsReadApproxPreImage(AbsVerificationInfoReadStats(absInfo))++;
00813     }
00814     else {
00815       Fsm_Fsm_t       *system;
00816       Img_ImageInfo_t *imageInfo;
00817       long            cpuTime;
00818 
00819       system = AbsVerificationInfoReadFsm(absInfo);
00820       imageInfo = Fsm_FsmReadOrCreateImageInfo(system, 1, 0);
00821       cpuTime = util_cpu_time();
00822       result = Img_ImageInfoComputeBwdWithDomainVars(imageInfo, minimizedSet,
00823                                                      minimizedSet,careSet);
00824       AbsStatsReadPreImageCpuTime(stats)+= util_cpu_time() - cpuTime;
00825 
00826       AbsStatsReadExactPreImage(stats)++;
00827       AbsVertexSetLocalApprox(vertexPtr, FALSE);
00828     }
00829     AbsVertexSetSat(vertexPtr, result);
00830 
00831     /* Set the value in the cache */
00832     AbsEvalCacheInsert(AbsVertexReadSolutions(vertexPtr),
00833                        minimizedSet, AbsVertexReadSat(vertexPtr), careSet,
00834                        AbsVertexReadLocalApprox(vertexPtr), FALSE);
00835     AbsStatsReadPreImageCacheEntries(stats)++;
00836     mdd_free(minimizedSet);
00837 
00838     /* Set the approximation flags */
00839     AbsVertexSetGlobalApprox(vertexPtr, 
00840                              AbsVertexReadGlobalApprox(subFormula) || 
00841                              AbsVertexReadLocalApprox(vertexPtr));
00842 
00843     /* Print the number of states in the on set of Sat */
00844     if (verbosity & ABS_VB_TSAT) {
00845       Fsm_Fsm_t *globalSystem;
00846       array_t *domainVars;
00847       mdd_t *intersection;
00848       
00849       intersection = mdd_and(AbsVertexReadSat(vertexPtr), careSet, 1, 1);
00850       
00851       globalSystem = AbsVerificationInfoReadFsm(absInfo);
00852       domainVars = Fsm_FsmReadPresentStateVars(globalSystem);
00853       (void) fprintf(vis_stdout, "ABS: %.0f States satisfy the EX formula.\n",
00854                      mdd_count_onset(AbsVerificationInfoReadMddManager(absInfo),
00855                                      intersection, domainVars));
00856       mdd_free(intersection);
00857     }
00858     mdd_free(careSet);
00859   }
00860   
00861 
00862   /* Increase the number of times the result has been used */
00863   AbsVertexReadServed(vertexPtr)++;
00864 
00865   return;
00866 } /* End of EvaluatePreImage */
00867 
00878 static mdd_t *
00879 OverApproximatePreImageWithSubFSM(
00880   Abs_VerificationInfo_t *absInfo,
00881   mdd_t *lowerBound,
00882   mdd_t *upperBound,
00883   mdd_t *careSet)
00884 {
00885   Fsm_Fsm_t       *system;
00886   Img_ImageInfo_t *imageInfo;
00887   mdd_t           *result;
00888   long            cpuTime;
00889 
00890   /* Initialize some variables */
00891   system = AbsVerificationInfoReadApproxFsm(absInfo);
00892 
00893   if (system == NIL(Fsm_Fsm_t)) {
00894     system = AbsVerificationInfoReadFsm(absInfo);
00895   }
00896 
00897   /* Obtain the image info */
00898   imageInfo = Fsm_FsmReadOrCreateImageInfo(system, 1, 0);
00899 
00900   cpuTime = util_cpu_time();
00901   result = Img_ImageInfoComputeBwdWithDomainVars(imageInfo, lowerBound,
00902                                                  upperBound, careSet);
00903   AbsStatsReadAppPreCpuTime(AbsVerificationInfoReadStats(absInfo))+= 
00904     util_cpu_time() - cpuTime;
00905 
00906   return result;
00907 } /* End of OverApproximatePreImageWithSubFSM */
00908 
00909 
00920 static mdd_t *
00921 OverApproximatePreImageWithBddSubsetting(
00922   Abs_VerificationInfo_t *absInfo,
00923   mdd_t *lowerBound,
00924   mdd_t *upperBound,
00925   mdd_t *careSet)
00926 {
00927   Fsm_Fsm_t       *system;
00928   Img_ImageInfo_t *imageInfo;
00929   mdd_t           *superSet;
00930   mdd_t           *result;
00931   long            cpuTime;
00932 
00933   /* Initialize some variables */
00934   system = AbsVerificationInfoReadFsm(absInfo);
00935 
00936   /* Compute the subset of the restriction set */
00937   superSet = bdd_approx_remap_ua(lowerBound,BDD_OVER_APPROX,
00938                           AbsVerificationInfoReadNumStateVars(absInfo), 
00939                           0,1);
00940   
00941   /* Obtain the image info */
00942   imageInfo = Fsm_FsmReadOrCreateImageInfo(system, 1, 0);
00943 
00944   cpuTime = util_cpu_time();
00945   result = Img_ImageInfoComputeBwdWithDomainVars(imageInfo, superSet,
00946                                                  superSet, careSet);
00947   AbsStatsReadAppPreCpuTime(AbsVerificationInfoReadStats(absInfo))+= 
00948     util_cpu_time() - cpuTime;
00949 
00950   mdd_free(superSet);
00951 
00952   return result;
00953 } /* End of OverApproximatePreImageWithBddSubsetting */
00954 
00964 static mdd_t *
00965 UnderApproximatePreImageWithBddSubsetting(
00966   Abs_VerificationInfo_t *absInfo,
00967   mdd_t *lowerBound,
00968   mdd_t *upperBound,
00969   mdd_t *careSet)
00970 {
00971   Fsm_Fsm_t       *system;
00972   Img_ImageInfo_t *imageInfo;
00973   mdd_t           *subSet;
00974   mdd_t           *result;
00975   long            cpuTime;
00976 
00977   /* Initialize some variables */
00978   system = AbsVerificationInfoReadFsm(absInfo);
00979 
00980   /* Compute the subset of the restriction set */
00981   subSet = bdd_approx_remap_ua(lowerBound, BDD_UNDER_APPROX,
00982                       AbsVerificationInfoReadNumStateVars(absInfo),
00983                       0,1);
00984 
00985   /* Obtain the image info */
00986   imageInfo = Fsm_FsmReadOrCreateImageInfo(system, 1, 0);
00987 
00988   cpuTime = util_cpu_time();
00989   result = Img_ImageInfoComputeBwdWithDomainVars(imageInfo, subSet, subSet, 
00990                                                  careSet);
00991   AbsStatsReadAppPreCpuTime(AbsVerificationInfoReadStats(absInfo))+= 
00992     util_cpu_time() - cpuTime;
00993 
00994   mdd_free(subSet);
00995 
00996   return result;
00997 } /* End of UnderApproximatePreImageWithBddSubsetting */