VIS

src/abs/absRefine.c

Go to the documentation of this file.
00001 
00018 #include "absInt.h"
00019 
00020 static char rcsid[] UNUSED = "$Id: absRefine.c,v 1.24 2002/09/19 05:25:01 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 mdd_t * RefineVariable(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
00038 static mdd_t * RefineIdentifier(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
00039 static mdd_t * RefineNot(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
00040 static mdd_t * RefineAnd(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
00041 static mdd_t * RefineFixedPoint(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
00042 static mdd_t * RefineFixedPointIterate(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet, int iterateNumber);
00043 static mdd_t * RefinePreImage(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr, mdd_t *goalSet);
00044 static boolean RestoreContainment(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
00045 static int PruneIterateVector(Abs_VerificationInfo_t *absInfo, AbsVertexInfo_t *vertexPtr);
00046 static mdd_t * SuccessTest(mdd_t *sat, mdd_t *goalSet, boolean polarity);
00047 
00051 /*---------------------------------------------------------------------------*/
00052 /* Definition of exported functions                                          */
00053 /*---------------------------------------------------------------------------*/
00054 
00055 
00056 /*---------------------------------------------------------------------------*/
00057 /* Definition of internal functions                                          */
00058 /*---------------------------------------------------------------------------*/
00059 
00073 mdd_t *
00074 AbsSubFormulaRefine(
00075   Abs_VerificationInfo_t *absInfo,
00076   AbsVertexInfo_t *vertexPtr,
00077   mdd_t *goalSet)
00078 {
00079   AbsStats_t *stats;
00080   mdd_manager *mddManager;
00081   mdd_t *oldTmpCareSet = NIL(mdd_t);
00082   mdd_t      *realGoalSet;
00083   mdd_t      *result;
00084   long       verbosity;
00085 
00086   verbosity = AbsOptionsReadVerbosity(AbsVerificationInfoReadOptions(absInfo));
00087   stats = AbsVerificationInfoReadStats(absInfo);
00088   mddManager = AbsVerificationInfoReadMddManager(absInfo);
00089 
00090   if (verbosity & ABS_VB_REFINE) {
00091     (void) fprintf(vis_stdout, "ABS: Beginning Refinement of Vertex(%3d)\n",
00092                    AbsVertexReadId(vertexPtr));
00093   }
00094 
00095   /* If the goal set is empty, do not refine */
00096   if (mdd_is_tautology(goalSet, 0)) {
00097 
00098     if (verbosity & ABS_VB_GOALSZ) {
00099       (void) fprintf(vis_stdout, 
00100                      "ABS: Empty Goal in Refinement of Vertex(%3d)\n",
00101                      AbsVertexReadId(vertexPtr));
00102     }
00103 
00104     /* Set the refine flag */
00105     AbsVertexSetTrueRefine(vertexPtr, TRUE);
00106 
00107     return mdd_dup(goalSet);
00108   }
00109 
00110   realGoalSet = SuccessTest(AbsVertexReadSat(vertexPtr), goalSet, 
00111                             AbsVertexReadPolarity(vertexPtr));
00112 
00113   /* If the vertex is refined already do not try to refine it */
00114   if (mdd_is_tautology(realGoalSet, 0) || 
00115       !AbsVertexReadGlobalApprox(vertexPtr)) {
00116 
00117     if (verbosity & ABS_VB_GOALSZ) {
00118       (void) fprintf(vis_stdout, 
00119                      "ABS: Quick (%d,%d) Refinement of Vertex(%3d)\n",
00120                      mdd_is_tautology(realGoalSet, 0)? 1: 0,
00121                      AbsVertexReadGlobalApprox(vertexPtr)? 0: 1,
00122                      AbsVertexReadId(vertexPtr));
00123     }
00124 
00125     AbsVertexSetTrueRefine(vertexPtr, TRUE);
00126     return realGoalSet;
00127   }
00128 
00129   if (verbosity & ABS_VB_GOALSZ) {
00130     (void) fprintf(vis_stdout, "ABS: Received Goal Set-> ");
00131     (void) fprintf(vis_stdout, "%d Nodes\n",
00132                    mdd_size(realGoalSet));
00133     if (verbosity & ABS_VB_GLCUBE) {
00134       AbsBddPrintMinterms(realGoalSet);
00135     }
00136   }
00137 
00138   mdd_free(realGoalSet);
00139 
00140   /* If the current vertex has more than one parent, the temporary care set
00141    * must be reset (because it depends on the path that led to this vertex) */
00142   if (lsLength(vertexPtr->parent) > 1) {
00143     oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
00144     AbsVerificationInfoSetTmpCareSet(absInfo, mdd_one(mddManager));
00145   }
00146 
00147   switch (AbsVertexReadType(vertexPtr)) {
00148     case fixedPoint_c:
00149       result = RefineFixedPoint(absInfo, vertexPtr, goalSet);
00150       AbsStatsReadRefineFixedPoint(stats)++;
00151       break;
00152     case and_c: 
00153       result = RefineAnd(absInfo, vertexPtr, goalSet);
00154       AbsStatsReadRefineAnd(stats)++;
00155       break;
00156     case not_c:
00157       result = RefineNot(absInfo, vertexPtr, goalSet);
00158       AbsStatsReadRefineNot(stats)++;
00159       break;
00160     case preImage_c:
00161       result = RefinePreImage(absInfo, vertexPtr, goalSet);
00162       AbsStatsReadRefinePreImage(stats)++;
00163       break;
00164     case identifier_c:
00165       result = RefineIdentifier(absInfo, vertexPtr, goalSet);
00166       AbsStatsReadRefineIdentifier(stats)++;
00167       break;
00168     case variable_c:
00169       result = RefineVariable(absInfo, vertexPtr, goalSet);
00170       AbsStatsReadRefineVariable(stats)++;
00171       break;
00172     default: fail("Encountered unknown type of vertex\n");
00173     }
00174 
00175   if (verbosity & ABS_VB_REFINE) {
00176     (void) fprintf(vis_stdout, 
00177                    "ABS: Done Refining Vertex(%3d).\n",
00178                    AbsVertexReadId(vertexPtr));
00179   }
00180 
00181   if (verbosity & ABS_VB_GOALSZ) {
00182     (void) fprintf(vis_stdout, "ABS: Returned Goal Set-> ");
00183     (void) fprintf(vis_stdout, "%d Nodes\n",
00184                    mdd_size(result));
00185     if (verbosity & ABS_VB_GLCUBE) {
00186       AbsBddPrintMinterms(result);
00187     }
00188   }
00189 
00190   if (verbosity  & ABS_VB_REFVTX) {
00191     AbsVertexPrint(vertexPtr, NIL(st_table), FALSE, verbosity);
00192   }
00193 
00194   if (lsLength(vertexPtr->parent) > 1) {
00195     /* Restore the old temporary careset */
00196     mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
00197     AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
00198   }
00199 
00200   return result;
00201 } /* End of AbsSubFormulaRefine */
00202 
00203 /*---------------------------------------------------------------------------*/
00204 /* Definition of static functions                                            */
00205 /*---------------------------------------------------------------------------*/
00206 
00225 static mdd_t *
00226 RefineVariable(
00227   Abs_VerificationInfo_t *absInfo,
00228   AbsVertexInfo_t *vertexPtr,
00229   mdd_t *goalSet)
00230 {
00231   /* Set the current goalSet. If the pointer is non-empty, that means that the
00232      variable belongs to a different pointer from the one being considered,
00233      therefore, only the first goal set is of interest to us.*/
00234   if (AbsVertexReadGoalSet(vertexPtr) == NIL(mdd_t)) {
00235     AbsVertexSetGoalSet(vertexPtr, mdd_dup(goalSet));
00236   }
00237 
00238   /* Set the validity of the refinement */
00239   AbsVertexSetTrueRefine(vertexPtr, !AbsVertexReadGlobalApprox(vertexPtr));
00240 
00241   return mdd_dup(goalSet);
00242 } /* End of RefineVariable */
00243 
00253 static mdd_t *
00254 RefineIdentifier(
00255   Abs_VerificationInfo_t *absInfo,
00256   AbsVertexInfo_t *vertexPtr,
00257   mdd_t *goalSet)
00258 {
00259   /* Set the refinement flags */
00260   AbsVertexSetTrueRefine(vertexPtr, TRUE);
00261 
00262   /*
00263    * If the polarity of this vertex is negative, we need to add states to
00264    * the satisfying set.  Since we already have the exact set, the states not
00265    * in it are the returned goal.  If the polarity is positive, we need to
00266    * remove states.  The states of the incoming goal that are in the
00267    * satisfying set are the returned goal.
00268    */
00269   if (AbsVertexReadPolarity(vertexPtr)) {
00270     return mdd_and(goalSet, AbsVertexReadSat(vertexPtr), 1, 1);
00271   } else {
00272     return mdd_and(goalSet, AbsVertexReadSat(vertexPtr), 1, 0);
00273   }
00274 } /* End of RefineIdentifier */
00275 
00285 static mdd_t *
00286 RefineNot(
00287   Abs_VerificationInfo_t *absInfo,
00288   AbsVertexInfo_t *vertexPtr,
00289   mdd_t *goalSet)
00290 {
00291   AbsVertexInfo_t *subFormula;
00292   mdd_t *result;
00293 
00294   /* The not vertex has a trivial propagation equation */
00295   subFormula = AbsVertexReadLeftKid(vertexPtr);
00296 
00297   /* Go ahead and re-evaluate */
00298   mdd_free(AbsVertexReadSat(vertexPtr));
00299 
00300   /* Refine recursively */
00301   result = AbsSubFormulaRefine(absInfo, subFormula, goalSet);
00302 
00303   /* Set the set sat */
00304   AbsVertexSetSat(vertexPtr, mdd_not(AbsVertexReadSat(subFormula)));
00305   
00306   /* Set the approximation flags */
00307   AbsVertexSetLocalApprox(vertexPtr, FALSE);
00308   AbsVertexSetGlobalApprox(vertexPtr, AbsVertexReadGlobalApprox(subFormula));
00309 
00310   /* Set the trueRefine flag */
00311   AbsVertexSetTrueRefine(vertexPtr, AbsVertexReadTrueRefine(subFormula));
00312 
00313   assert(mdd_lequal(result, goalSet, 1, 1));
00314 
00315   return result;
00316 } /* End of RefineNot */
00317 
00327 static mdd_t *
00328 RefineAnd(
00329   Abs_VerificationInfo_t *absInfo,
00330   AbsVertexInfo_t *vertexPtr,
00331   mdd_t *goalSet)
00332 {
00333   AbsVertexInfo_t *firstFormula;
00334   AbsVertexInfo_t *secondFormula;
00335   mdd_t           *kidFirstResult;
00336   mdd_t           *conjunction;
00337   mdd_t           *result;
00338   mdd_t           *oldTmpCareSet;
00339 
00340   /* Delete the old sat */
00341   mdd_free(AbsVertexReadSat(vertexPtr));
00342 
00343   /* Obtain the Sub-formulas  */
00344   firstFormula = AbsVertexReadLeftKid(vertexPtr);
00345   secondFormula = AbsVertexReadRightKid(vertexPtr);
00346 
00347   kidFirstResult = AbsSubFormulaRefine(absInfo, firstFormula, goalSet);
00348   
00349   /* Store the temporary careset and set the new one */
00350   oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
00351   AbsVerificationInfoSetTmpCareSet(absInfo, 
00352                                    mdd_and(oldTmpCareSet, 
00353                                            AbsVertexReadSat(firstFormula), 
00354                                            1,1));
00355   
00356   if (AbsVertexReadPolarity(vertexPtr)) {
00357     /* 
00358      * Positive polarity: The goal set is given to one sub-formula first for
00359      * refinement, and the left-overs are given to the second sub-formula.
00360      */
00361     result = AbsSubFormulaRefine(absInfo, secondFormula, kidFirstResult);
00362     mdd_free(kidFirstResult);
00363   }
00364   else { /* Vertex with negative polarity */
00365     mdd_t *kidSecondResult;
00366     mdd_t *reducedGoalSet;
00367 
00368     reducedGoalSet = mdd_and(goalSet, AbsVertexReadSat(firstFormula), 1, 1);
00369     kidSecondResult = AbsSubFormulaRefine(absInfo, secondFormula,
00370                                           reducedGoalSet);
00371     result = mdd_or(kidFirstResult, kidSecondResult, 1, 1);
00372 
00373     mdd_free(reducedGoalSet);
00374     mdd_free(kidFirstResult);
00375     mdd_free(kidSecondResult);
00376   }
00377 
00378   /* Restore the temporary careset */
00379   mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
00380   AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
00381   
00382   /* Re-evaluate the vertex just in case there has been some refinement */
00383   conjunction = mdd_and(AbsVertexReadSat(firstFormula),
00384                         AbsVertexReadSat(secondFormula), 1, 1);
00385   
00386   /* Store the new Sat value */
00387   AbsVertexSetSat(vertexPtr, conjunction);
00388   
00389   /* Set the approximation flags */
00390   AbsVertexSetLocalApprox(vertexPtr, FALSE);
00391   AbsVertexSetGlobalApprox(vertexPtr,
00392                            AbsVertexReadGlobalApprox(firstFormula) || 
00393                            AbsVertexReadGlobalApprox(secondFormula));
00394 
00395   /* Set the refinement flags */
00396   AbsVertexSetTrueRefine(vertexPtr, AbsVertexReadTrueRefine(firstFormula) &&
00397                          AbsVertexReadTrueRefine(secondFormula));
00398 
00399   assert(mdd_lequal(result, goalSet, 1, 1));
00400 
00401   return result;
00402 } /* End of RefineAnd */
00403 
00417 static mdd_t *
00418 RefineFixedPoint(
00419   Abs_VerificationInfo_t *absInfo,
00420   AbsVertexInfo_t *vertexPtr,
00421   mdd_t *goalSet)
00422 {
00423   boolean newIterates;
00424   mdd_t   *currentGoalSet;
00425   mdd_t   *result;
00426   mdd_t   *oldTmpCareSet;
00427   mdd_t   *newTmpCareSet;
00428   mdd_t   *oneMdd;
00429   int     numIterates;
00430 
00431   /* Variable initialization */
00432   numIterates = array_n(AbsVertexReadRings(vertexPtr)) - 1;
00433   newIterates = TRUE;
00434 
00435   /* Delete the previous result */
00436   if (AbsVertexReadSat(vertexPtr) != NIL(mdd_t)) {
00437     mdd_free(AbsVertexReadSat(vertexPtr));
00438   }
00439 
00440   /* Set the new care set */
00441   oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
00442   newTmpCareSet = mdd_one(AbsVerificationInfoReadMddManager(absInfo));
00443   AbsVerificationInfoSetTmpCareSet(absInfo, newTmpCareSet);
00444 
00445   oneMdd = mdd_one(AbsVerificationInfoReadMddManager(absInfo));
00446   currentGoalSet = mdd_dup(oneMdd);
00447   /* While the fixed point has not been approximated exactly */
00448   while (newIterates && AbsVertexReadGlobalApprox(vertexPtr)
00449          && !mdd_is_tautology(currentGoalSet, 0)) {
00450     mdd_t *newGoalSet;
00451     boolean pruneIterates;
00452 
00453     newGoalSet = RefineFixedPointIterate(absInfo, vertexPtr, currentGoalSet,
00454                                          numIterates);
00455 
00456     /* Release unnecessary functions */
00457     mdd_free(newGoalSet);
00458     mdd_free(currentGoalSet);
00459 
00460     /* Restore the inclusion property in the fixed point iterates */
00461     pruneIterates = RestoreContainment(absInfo, vertexPtr);
00462 
00463     /* Remove redundant iterates */
00464     if (pruneIterates) {
00465       numIterates = PruneIterateVector(absInfo, vertexPtr);
00466     }
00467 
00468     /* Sanity check of the refinement process */
00469     assert(AbsIteratesSanityCheck(absInfo, vertexPtr));
00470 
00471     /* Check if further iteration is required */
00472     newIterates = AbsFixedPointIterate(absInfo, vertexPtr, numIterates);
00473     numIterates = array_n(AbsVertexReadRings(vertexPtr)) - 1;
00474 
00475     currentGoalSet = SuccessTest(AbsVertexFetchRing(vertexPtr, numIterates),
00476                                  oneMdd, AbsVertexReadPolarity(vertexPtr));
00477   } /* End of while loop */
00478 
00479   mdd_free(oneMdd);
00480 
00481   /* Restore the old temporary careset */
00482   mdd_free(newTmpCareSet);
00483   AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
00484 
00485   AbsVertexSetSat(vertexPtr, 
00486                   mdd_dup(AbsVertexFetchRing(vertexPtr, numIterates)));
00487 
00488   AbsVertexSetLocalApprox(vertexPtr, FALSE);
00489   AbsVertexSetGlobalApprox(vertexPtr, 
00490                            AbsVertexFetchSubApprox(vertexPtr, numIterates));
00491 
00492   result = mdd_and(currentGoalSet, goalSet, 1, 1);
00493   mdd_free(currentGoalSet);
00494   return result;
00495 } /* End of RefineFixedPoint */
00496 
00507 static mdd_t *
00508 RefineFixedPointIterate(
00509   Abs_VerificationInfo_t *absInfo,
00510   AbsVertexInfo_t *vertexPtr,
00511   mdd_t *goalSet,
00512   int iterateNumber)
00513 {
00514   AbsVertexInfo_t *varFormula;
00515   AbsVertexInfo_t *subFormula;
00516   boolean         trueRefine;
00517   mdd_t           *careSet;
00518   mdd_t           *variableValue;
00519   mdd_t           *result;
00520   mdd_t           *previousGoal;
00521   mdd_t           *refinedGoal;
00522   mdd_t           *newIterate;
00523   mdd_t           *oldIterate;
00524   mdd_t           *subFormulaSat;
00525   int             saveExact;
00526 
00527   assert(iterateNumber != 0);
00528 
00529   /* Variable initialization */
00530   varFormula = AbsVertexReadFpVar(vertexPtr);
00531   subFormula = AbsVertexReadLeftKid(vertexPtr);
00532   careSet = AbsVerificationInfoReadCareSet(absInfo);
00533   oldIterate = AbsVertexFetchRing(vertexPtr, iterateNumber);
00534 
00535   /* Propagate the goalSet for refinement */
00536   variableValue = AbsVertexFetchRing(vertexPtr, iterateNumber - 1);
00537 
00538   AbsVertexSetSat(varFormula, variableValue);
00539 
00540   AbsVertexSetGlobalApprox(varFormula,
00541                            AbsVertexFetchSubApprox(vertexPtr,
00542                                                    iterateNumber - 1));
00543 
00544   /* Schedule the formula for Re-evaluation */
00545   AbsFormulaScheduleEvaluation(varFormula, vertexPtr);
00546 
00547   /* Evaluate the sub-formula again */
00548   AbsSubFormulaVerify(absInfo, subFormula);
00549 
00550   /* Set the goal to empty to detect if the refinement reaches it */
00551   if (AbsVertexReadGoalSet(varFormula) != NIL(mdd_t)) {
00552     mdd_free(AbsVertexReadGoalSet(varFormula));
00553     AbsVertexSetGoalSet(varFormula, NIL(mdd_t));
00554   }
00555 
00556   /* Refine the sub-formula for this iterate */
00557   result = AbsSubFormulaRefine(absInfo, subFormula, goalSet);
00558 
00559   /* Read the trueRefine from the subFormula */
00560   trueRefine = AbsVertexReadTrueRefine(subFormula);
00561 
00562   /* If The refinement does not need a recursive step, return. The return may
00563    * be for three different reasons:
00564    *   a) The local refinement that was just done, succeeded completely.
00565    *   b) The goalset in varFormula is NIL, which means, the refinement
00566           process failed somewhere earlier in the process, and therefore, the
00567           false result was computed without the refinement of the variable.
00568        c) trueRefine is TRUE. Which means, that even though the approximate
00569           flag in the vertex is TRUE, meaning that there has been an
00570           approximation, the refinement is still solid
00571    */
00572   if (mdd_is_tautology(result, 0) || trueRefine || 
00573       AbsVertexReadGoalSet(varFormula) == NIL(mdd_t)) {
00574 
00575     subFormulaSat = AbsVertexReadSat(subFormula);
00576     if (AbsVertexReadPolarity(vertexPtr)) {
00577       if (AbsMddLEqualModCareSet(subFormulaSat, oldIterate, careSet)) {
00578         newIterate = mdd_dup(subFormulaSat);
00579       }
00580       else {
00581         newIterate = mdd_and(subFormulaSat, oldIterate, 1, 1);
00582       }
00583     }
00584     else {
00585       if (AbsMddLEqualModCareSet(oldIterate, subFormulaSat, careSet)) {
00586         newIterate = mdd_dup(subFormulaSat);
00587       }
00588       else {
00589         newIterate = mdd_or(subFormulaSat, oldIterate, 1, 1);
00590       }
00591     }
00592 
00593     mdd_free(oldIterate);
00594     array_insert(mdd_t *, AbsVertexReadRings(vertexPtr), iterateNumber,
00595                  newIterate);
00596 
00597     /* Set the new approx flag */
00598     array_insert(boolean, AbsVertexReadSubApprox(vertexPtr), iterateNumber,
00599                  AbsVertexReadGlobalApprox(subFormula));
00600 
00601     AbsVertexSetTrueRefine(vertexPtr, trueRefine);
00602 
00603     return result;
00604   }
00605 
00606   /* Recursive call to refine the previous iterate */
00607   previousGoal = mdd_dup(AbsVertexReadGoalSet(varFormula));
00608   refinedGoal = RefineFixedPointIterate(absInfo, vertexPtr, previousGoal,
00609                                         iterateNumber - 1);
00610 
00611   trueRefine = AbsVertexReadTrueRefine(vertexPtr);
00612 
00613   /* 
00614    * Due to the refinement of the previous iterate, convergence might have
00615    * been reached
00616    */
00617   if (iterateNumber > 1) {
00618     mdd_t *ring1 = AbsVertexFetchRing(vertexPtr, iterateNumber - 1);
00619     mdd_t *ring2 = AbsVertexFetchRing(vertexPtr, iterateNumber - 2);
00620     if (AbsMddLEqualModCareSet(ring1, ring2, careSet)) {
00621       mdd_free(previousGoal);
00622       mdd_free(refinedGoal);
00623       mdd_free(oldIterate);
00624       mdd_free(result);
00625 
00626       array_insert(mdd_t *, AbsVertexReadRings(vertexPtr), iterateNumber,
00627                    mdd_dup(AbsVertexFetchRing(vertexPtr, iterateNumber - 1)));
00628 
00629       AbsVertexSetTrueRefine(vertexPtr, trueRefine);
00630 
00631       /* Set the new approx flag */
00632       array_insert(boolean, AbsVertexReadSubApprox(vertexPtr), iterateNumber, 
00633                    AbsVertexReadGlobalApprox(subFormula));
00634 
00635       return SuccessTest(AbsVertexFetchRing(vertexPtr, iterateNumber),
00636                          goalSet, AbsVertexReadPolarity(vertexPtr));
00637     }
00638   }
00639 
00640   mdd_free(previousGoal);
00641   mdd_free(refinedGoal);
00642 
00643   /* Evaluate the sub-formula exactly */
00644   variableValue = AbsVertexFetchRing(vertexPtr, iterateNumber - 1);
00645 
00646   AbsVertexSetSat(varFormula, variableValue);
00647   mdd_free(result);
00648 
00649   AbsVertexSetGlobalApprox(varFormula, 
00650                            AbsVertexFetchSubApprox(vertexPtr, 
00651                                                    iterateNumber - 1));
00652 
00653   /* Schedule the formula for Re-evaluation */
00654   AbsFormulaScheduleEvaluation(varFormula, vertexPtr);
00655 
00656   /* Evaluate the sub-formula this time exactly */
00657   saveExact = AbsOptionsReadExact(AbsVerificationInfoReadOptions(absInfo));
00658   AbsOptionsSetExact(AbsVerificationInfoReadOptions(absInfo), TRUE);
00659   AbsSubFormulaVerify(absInfo, subFormula);
00660   AbsOptionsSetExact(AbsVerificationInfoReadOptions(absInfo), saveExact);
00661 
00662   /* Enforce monotonicity of the approximants */
00663   subFormulaSat = AbsVertexReadSat(subFormula);
00664   if (AbsVertexReadPolarity(vertexPtr)) {
00665     if (AbsMddLEqualModCareSet(subFormulaSat, oldIterate, careSet)) {
00666       newIterate = mdd_dup(subFormulaSat);
00667     }
00668     else {
00669       newIterate = mdd_and(subFormulaSat, oldIterate, 1, 1);
00670     }
00671   }
00672   else {
00673     if (AbsMddLEqualModCareSet(oldIterate, subFormulaSat, careSet)) {
00674       newIterate = mdd_dup(subFormulaSat);
00675     }
00676     else {
00677       newIterate = mdd_or(subFormulaSat, oldIterate, 1, 1);
00678     }
00679   }
00680 
00681   /* Set the new approx flag */
00682   array_insert(boolean, AbsVertexReadSubApprox(vertexPtr), iterateNumber, 
00683                AbsVertexReadGlobalApprox(subFormula));
00684 
00685   /* Recompute the goal set and the iterate */
00686   result = SuccessTest(newIterate, goalSet,
00687                        AbsVertexReadPolarity(vertexPtr));
00688 
00689   /* Some basic sanity check */
00690   assert(AbsVertexReadPolarity(vertexPtr)?
00691          AbsMddLEqualModCareSet(newIterate, oldIterate, careSet):
00692          AbsMddLEqualModCareSet(oldIterate, newIterate, careSet));
00693 
00694   /* Store the new iterate */
00695   mdd_free(oldIterate);
00696   array_insert(mdd_t *, AbsVertexReadRings(vertexPtr), iterateNumber, 
00697                newIterate);
00698 
00699   /* Set the new approx flag */
00700   array_insert(boolean, AbsVertexReadSubApprox(vertexPtr), iterateNumber, 
00701                AbsVertexReadGlobalApprox(subFormula));
00702 
00703   AbsVertexSetTrueRefine(vertexPtr, trueRefine);
00704 
00705   return result;
00706 } /* End of RefineFixedPointIterate */
00707 
00717 static mdd_t *
00718 RefinePreImage(
00719   Abs_VerificationInfo_t *absInfo,
00720   AbsVertexInfo_t *vertexPtr,
00721   mdd_t *goalSet)
00722 {
00723   AbsStats_t      *stats;
00724   AbsVertexInfo_t *subFormula;
00725   Img_ImageInfo_t *imageInfo;
00726   Fsm_Fsm_t       *system;
00727   mdd_t           *careSet;
00728   mdd_t           *result;
00729   mdd_t           *subResult;
00730   mdd_t           *newGoalSet;
00731   mdd_t           *oldTmpCareSet;
00732   mdd_t           *preImage;
00733 
00734   /* Variable initialization */
00735   system = AbsVerificationInfoReadFsm(absInfo);
00736   subFormula = AbsVertexReadLeftKid(vertexPtr);
00737   subResult = AbsVertexReadSat(subFormula);
00738   stats = AbsVerificationInfoReadStats(absInfo);
00739   imageInfo = Fsm_FsmReadOrCreateImageInfo(system, 1, 1);
00740   careSet = mdd_and(AbsVerificationInfoReadCareSet(absInfo),
00741                     AbsVerificationInfoReadTmpCareSet(absInfo), 1, 1);
00742 
00743   /* Propagate the goal set */
00744   newGoalSet = AbsImageReadOrCompute(absInfo, imageInfo, goalSet, subResult);
00745 
00746   /* Store the new care set */
00747   oldTmpCareSet = AbsVerificationInfoReadTmpCareSet(absInfo);
00748   AbsVerificationInfoSetTmpCareSet(absInfo, 
00749                         mdd_one(AbsVerificationInfoReadMddManager(absInfo)));
00750 
00751   /* Refine recursively */
00752   result = AbsSubFormulaRefine(absInfo, subFormula, newGoalSet);
00753 
00754   /* Restore the old temporary careset */
00755   mdd_free(AbsVerificationInfoReadTmpCareSet(absInfo));
00756   AbsVerificationInfoSetTmpCareSet(absInfo, oldTmpCareSet);
00757 
00758   if (!mdd_equal(result, newGoalSet) || 
00759       !AbsVertexReadGlobalApprox(subFormula)) {
00760     mdd_free(AbsVertexReadSat(vertexPtr));
00761     
00762     if (AbsVertexReadSolutions(vertexPtr) == NIL(st_table)) {
00763       /* Initialize the cache */
00764       AbsVertexSetSolutions(vertexPtr, st_init_table(st_ptrcmp, st_ptrhash));
00765     }
00766     
00767     preImage = NIL(mdd_t);
00768     if (AbsEvalCacheLookup(AbsVertexReadSolutions(vertexPtr),
00769                            AbsVertexReadSat(subFormula), careSet, FALSE,
00770                            &preImage, 0)) {
00771       
00772       /* Set the sat */
00773       AbsVertexSetSat(vertexPtr, mdd_dup(preImage));
00774     }
00775     else {
00776       long cpuTime;
00777       
00778       subResult = AbsVertexReadSat(subFormula);
00779       
00780       cpuTime = util_cpu_time();
00781       AbsVertexSetSat(vertexPtr, 
00782                       Img_ImageInfoComputeBwdWithDomainVars(imageInfo, 
00783                                                             subResult,
00784                                                             subResult,
00785                                                             careSet));
00786       AbsStatsReadPreImageCpuTime(stats)+= util_cpu_time() - cpuTime;
00787       
00788       AbsStatsReadExactPreImage(stats)++;
00789       
00790       /* Insert the result in the cache */
00791       AbsEvalCacheInsert(AbsVertexReadSolutions(vertexPtr),
00792                          AbsVertexReadSat(subFormula),
00793                          AbsVertexReadSat(vertexPtr), careSet,
00794                          FALSE, FALSE);
00795       
00796     }
00797     /* Set the new approximation flags */
00798     AbsVertexSetLocalApprox(vertexPtr, FALSE);
00799     AbsVertexSetGlobalApprox(vertexPtr, 
00800                              AbsVertexReadGlobalApprox(subFormula));
00801   } /* If !mdd_equal || !GlobalApprox(subFormula) */
00802   mdd_free(careSet);
00803   mdd_free(newGoalSet);
00804   mdd_free(result);
00805 
00806   result = SuccessTest(AbsVertexReadSat(vertexPtr), goalSet,
00807                        AbsVertexReadPolarity(vertexPtr));
00808 
00809   AbsVertexSetTrueRefine(vertexPtr, 
00810                          AbsVertexReadTrueRefine(subFormula));
00811 
00812   return result;
00813 } /* End of RefinePreImage */
00814 
00832 static boolean
00833 RestoreContainment(
00834   Abs_VerificationInfo_t *absInfo,
00835   AbsVertexInfo_t *vertexPtr)
00836 {
00837   mdd_t *iterateMdd;
00838   mdd_t *iterateMddPrevious;
00839   mdd_t *product;
00840   boolean convergence;
00841   int numIterates;
00842   int index;
00843 
00844   convergence = FALSE;
00845   numIterates = array_n(AbsVertexReadRings(vertexPtr)) - 1;
00846 
00847   if (AbsVertexReadPolarity(vertexPtr)) {
00848     iterateMddPrevious = AbsVertexFetchRing(vertexPtr, numIterates);
00849     
00850     for(index = numIterates - 1; index >= 0; index--) {
00851       iterateMdd = iterateMddPrevious;
00852       iterateMddPrevious = AbsVertexFetchRing(vertexPtr, index);
00853       
00854       if (!AbsMddLEqualModCareSet(iterateMddPrevious, iterateMdd,
00855                                   AbsVerificationInfoReadCareSet(absInfo))) {
00856         product = mdd_and(iterateMddPrevious, iterateMdd, 1, 1);
00857         
00858         /* Add here don't care minimization */
00859         
00860         mdd_free(iterateMddPrevious);
00861         array_insert(mdd_t *, AbsVertexReadRings(vertexPtr), index, product);
00862         iterateMddPrevious = product;
00863       }
00864 
00865       if (index != numIterates - 1 &&
00866           AbsMddLEqualModCareSet(iterateMdd, iterateMddPrevious,
00867                                  AbsVerificationInfoReadCareSet(absInfo))) {
00868         convergence = TRUE;
00869       }
00870     }
00871   }
00872   else {
00873     iterateMdd = AbsVertexFetchRing(vertexPtr, 0);
00874 
00875     for(index = 1; index <= numIterates; index++) {
00876       iterateMddPrevious = iterateMdd;
00877       iterateMdd = AbsVertexFetchRing(vertexPtr, index);
00878 
00879       if (!AbsMddLEqualModCareSet(iterateMddPrevious, iterateMdd,
00880                                   AbsVerificationInfoReadCareSet(absInfo))) {
00881         product = mdd_or(iterateMddPrevious, iterateMdd, 1, 1);
00882         
00883         /* Add here don't care minimization */
00884 
00885         mdd_free(iterateMdd);
00886         array_insert(mdd_t *, AbsVertexReadRings(vertexPtr), index, product);
00887         iterateMdd = product;
00888       }
00889       
00890       if (index != numIterates &&
00891           AbsMddLEqualModCareSet(iterateMdd, iterateMddPrevious,
00892                                  AbsVerificationInfoReadCareSet(absInfo))) {
00893         convergence = TRUE;
00894       }
00895     }
00896   }
00897 
00898   return convergence;
00899 } /* End of RestoreContainment */
00900 
00916 static int
00917 PruneIterateVector(
00918   Abs_VerificationInfo_t *absInfo,
00919   AbsVertexInfo_t *vertexPtr)
00920 {
00921   array_t *newRings;
00922   array_t *newRingApprox;
00923   array_t *newSubApprox;
00924   mdd_t   *current;
00925   mdd_t   *previous;
00926   mdd_t   *careSet;
00927   int     numIterates;
00928   int     index;
00929 
00930   /* Read the care Set */
00931   careSet = AbsVerificationInfoReadCareSet(absInfo);
00932   
00933   /* Read the number of iterates initially in the vertex */
00934   numIterates = array_n(AbsVertexReadRings(vertexPtr)) - 1;
00935   assert(numIterates > 0);
00936   
00937   /* If there are only two iterates, no pruning is needed */
00938   if (numIterates < 2) {
00939     return numIterates;
00940   }
00941 
00942   /* Allocate the new arrays to store the new iterates */
00943   newRings = array_alloc(mdd_t *, 0);
00944   newRingApprox = array_alloc(boolean, 0);
00945   newSubApprox = array_alloc(boolean, 0);
00946 
00947   /* Initial values for the loop */
00948   index = 1;
00949   previous = AbsVertexFetchRing(vertexPtr, index - 1);
00950   current = AbsVertexFetchRing(vertexPtr, index);
00951   array_insert_last(mdd_t *, newRings, mdd_dup(previous));
00952   array_insert_last(boolean, newRingApprox,
00953                     AbsVertexFetchRingApprox(vertexPtr, index - 1));
00954   array_insert_last(boolean, newSubApprox,
00955                     AbsVertexFetchSubApprox(vertexPtr, index - 1));
00956 
00957   /* Traverse the set of iterates */
00958   while (index < numIterates && 
00959          !AbsMddLEqualModCareSet(current, previous, careSet)) {
00960     array_insert_last(mdd_t *, newRings, mdd_dup(current));
00961     array_insert_last(boolean, newRingApprox,
00962                       AbsVertexFetchRingApprox(vertexPtr, index));
00963     array_insert_last(boolean, newSubApprox,
00964                       AbsVertexFetchSubApprox(vertexPtr, index));
00965     index++;
00966     previous = current;
00967     current = AbsVertexFetchRing(vertexPtr, index);
00968   }
00969 
00970   /* Insert the last two elements of the array */
00971   array_insert_last(mdd_t *, newRings, mdd_dup(current));
00972   array_insert_last(boolean, newRingApprox, 
00973                     AbsVertexFetchRingApprox(vertexPtr, index));
00974   array_insert_last(boolean, newSubApprox,
00975                     AbsVertexFetchSubApprox(vertexPtr, index));
00976 
00977   /* Free the arrays stored in the vertex and store the new ones */
00978   arrayForEachItem(mdd_t *, AbsVertexReadRings(vertexPtr), index, current) {
00979     mdd_free(current);
00980   }
00981   array_free(AbsVertexReadRings(vertexPtr));
00982   array_free(AbsVertexReadRingApprox(vertexPtr));
00983   array_free(AbsVertexReadSubApprox(vertexPtr));
00984   
00985   /* Store the new results */
00986   AbsVertexSetRings(vertexPtr, newRings);
00987   AbsVertexSetRingApprox(vertexPtr, newRingApprox);
00988   AbsVertexSetSubApprox(vertexPtr, newSubApprox);
00989   
00990   assert(array_n(newRings) == array_n(newRingApprox));
00991   assert(array_n(newRings) == array_n(newSubApprox));
00992 
00993   return array_n(newRings) - 1;
00994 } /* End of PruneIterateVector */
00995 
01006 static mdd_t *
01007 SuccessTest(
01008   mdd_t *sat,
01009   mdd_t *goalSet,
01010   boolean polarity)
01011 {
01012   mdd_t *result;
01013 
01014   if (polarity) {
01015     result = mdd_and(goalSet, sat, 1, 1);
01016   }
01017   else {
01018     result = mdd_and(goalSet, sat, 1, 0);
01019   }
01020 
01021   return result;
01022 } /* End of SuccessTest */