VIS
|
00001 00024 #include "mcInt.h" 00025 00026 00027 /*---------------------------------------------------------------------------*/ 00028 /* Constant declarations */ 00029 /*---------------------------------------------------------------------------*/ 00030 00031 /*---------------------------------------------------------------------------*/ 00032 /* Stucture declarations */ 00033 /*---------------------------------------------------------------------------*/ 00034 00047 struct McGSHOpSetStruct { 00048 array_t *flags; /* flag array for quick membership test */ 00049 int cnt; /* number of operators in set */ 00050 int last; /* last operator applied */ 00051 int nextToLast; /* next to last operator applied */ 00052 int exBudget; /* allowed number of EXs in budget schedule */ 00053 int exCount; /* EXs applied so far (EUs included) */ 00054 Mc_GSHScheduleType schedule; /* operator schedule */ 00055 }; 00056 00057 00058 /*---------------------------------------------------------------------------*/ 00059 /* Type declarations */ 00060 /*---------------------------------------------------------------------------*/ 00061 00062 typedef struct McGSHOpSetStruct McGSHOpSet_t; 00063 00064 /*---------------------------------------------------------------------------*/ 00065 /* Variable declarations */ 00066 /*---------------------------------------------------------------------------*/ 00067 00068 #ifndef lint 00069 static char rcsid[] UNUSED = "$Id: mcGFP.c,v 1.10 2002/09/16 00:47:16 fabio Exp $"; 00070 #endif 00071 00072 /*---------------------------------------------------------------------------*/ 00073 /* Macro declarations */ 00074 /*---------------------------------------------------------------------------*/ 00075 00083 #define GSHoperatorIsEX(op,set) ((op) == (array_n((set)->flags) - 1)) 00084 00087 /*---------------------------------------------------------------------------*/ 00088 /* Static function prototypes */ 00089 /*---------------------------------------------------------------------------*/ 00090 00091 static int PickOperatorForGSH ARGS((McGSHOpSet_t *set)); 00092 static boolean ConvergedGSH ARGS((mdd_t *Z, mdd_t *zeta, int opIndex, McGSHOpSet_t *opSet, array_t *careStatesArray, Mc_EarlyTermination_t *earlyTermination, boolean *fixpoint)); 00093 static McGSHOpSet_t * AllocOperatorSetGSH ARGS((int n, Mc_GSHScheduleType schedule)); 00094 static void FreeOperatorSetGSH ARGS((McGSHOpSet_t *set)); 00095 static void EmptyOperatorSetGSH ARGS((McGSHOpSet_t *set)); 00096 static boolean IsMemberOperatorSetGSH ARGS((McGSHOpSet_t *set, int opIndex)); 00097 static int SizeOperatorSetGSH ARGS((McGSHOpSet_t *set)); 00098 static int PushOperatorSetGSH ARGS((McGSHOpSet_t *set, int opIndex)); 00099 00103 /*---------------------------------------------------------------------------*/ 00104 /* Definition of internal functions */ 00105 /*---------------------------------------------------------------------------*/ 00106 00107 00128 mdd_t* 00129 McFsmEvaluateEGFormulaUsingGSH( 00130 Fsm_Fsm_t *modelFsm, 00131 mdd_t *invariantMdd, 00132 mdd_t *overapprox, 00133 mdd_t *fairStates, 00134 Fsm_Fairness_t *modelFairness, 00135 array_t *careStatesArray, 00136 Mc_EarlyTermination_t *earlyTermination, 00137 array_t **pOnionRingsArrayForDbg, 00138 Mc_VerbosityLevel verbosity, 00139 Mc_DcLevel dcLevel, 00140 boolean *fixpoint, 00141 Mc_GSHScheduleType schedule) 00142 { 00143 int i,n; 00144 array_t *onionRings; 00145 boolean useRings; 00146 mdd_manager *mddManager; 00147 mdd_t *mddOne; 00148 mdd_t *iterate; 00149 array_t *buechiFairness; 00150 int nPreComps; 00151 int nIterations; 00152 McGSHOpSet_t *operatorSet; 00153 00154 /* Here's how the pOnionRingsArrayForDbg works. It is a pointer to 00155 ** an array of arrays of mdds. There is one entry for every 00156 ** fairness constraint, and this entry is the array of the onion 00157 ** rings of the EU computation that corresponds to this constraint. 00158 ** Every time the EU for a given constraint is recomputed, the 00159 ** corresponding array of rings is renewed. */ 00160 assert(pOnionRingsArrayForDbg == NIL(array_t *) || 00161 *pOnionRingsArrayForDbg == NIL(array_t) || 00162 array_n(*pOnionRingsArrayForDbg) == 0); 00163 00164 useRings = (pOnionRingsArrayForDbg != NIL(array_t *) && 00165 *pOnionRingsArrayForDbg != NIL(array_t)); 00166 00167 /* Initialization. */ 00168 nIterations = 0; 00169 nPreComps = Img_GetNumberOfImageComputation(Img_Backward_c); 00170 onionRings = NIL(array_t); 00171 mddManager = Fsm_FsmReadMddManager(modelFsm); 00172 mddOne = mdd_one(mddManager); 00173 00174 /* If an overapproxiamtion of the greatest fixpoint is given, use it. */ 00175 if(overapprox != NIL(mdd_t)){ 00176 iterate = mdd_and(invariantMdd, overapprox, 1, 1); 00177 } else { 00178 iterate = mdd_dup(invariantMdd); 00179 } 00180 00181 /* See if we need to enter the loop at all. If we wanted to test for 00182 ** early termination here, we should fix the onion rings. */ 00183 if (mdd_is_tautology(iterate, 0)) { 00184 mdd_free(mddOne); 00185 if (fixpoint != NIL(boolean)) *fixpoint = mdd_is_tautology(iterate, 0); 00186 return(iterate); 00187 } 00188 00189 /* Read fairness constraints. */ 00190 buechiFairness = array_alloc(mdd_t *, 0); 00191 if (modelFairness != NIL(Fsm_Fairness_t)) { 00192 if (!Fsm_FairnessTestIsBuchi(modelFairness)) { 00193 (void) fprintf(vis_stdout, 00194 "** mc error: non-Buechi fairness constraints not supported\n"); 00195 array_free(buechiFairness); 00196 mdd_free(iterate); 00197 mdd_free(mddOne); 00198 00199 if (fixpoint != NIL(boolean)) *fixpoint = FALSE; 00200 return NIL(mdd_t); 00201 } else { 00202 int j; 00203 int numBuechi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0); 00204 for (j = 0; j < numBuechi; j++) { 00205 mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j, 00206 careStatesArray, dcLevel); 00207 array_insert_last(mdd_t *, buechiFairness, tmpMdd); 00208 } 00209 } 00210 } else { 00211 array_insert_last(mdd_t *, buechiFairness, mdd_one(mddManager)); 00212 } 00213 00214 /* Initialize set of disabled operators (to the empty set). */ 00215 n = array_n(buechiFairness); 00216 operatorSet = AllocOperatorSetGSH(n, schedule); 00217 00218 /* Iterate until all operators disabled or early termination. */ 00219 while (TRUE) { 00220 mdd_t *oldIterate = iterate; 00221 int opIndex = PickOperatorForGSH(operatorSet); 00222 nIterations++; 00223 if (GSHoperatorIsEX(opIndex,operatorSet)) { 00224 mdd_t *EX = Mc_FsmEvaluateEXFormula(modelFsm, oldIterate, mddOne, 00225 careStatesArray, verbosity, 00226 dcLevel); 00227 iterate = mdd_and(EX, oldIterate, 1, 1); 00228 mdd_free(EX); 00229 } else { 00230 mdd_t *Fi = array_fetch(mdd_t *, buechiFairness, opIndex); 00231 mdd_t *target = mdd_and(Fi, iterate, 1, 1); 00232 00233 /* Dispose of the old set of onion rings for this fairness constraint 00234 ** if it exists, and allocate a fresh array for a new set of rings. */ 00235 if (useRings) { 00236 if (opIndex < array_n(*pOnionRingsArrayForDbg)) { 00237 onionRings = array_fetch(array_t *, *pOnionRingsArrayForDbg, 00238 opIndex); 00239 mdd_array_free(onionRings); 00240 } 00241 onionRings = array_alloc(mdd_t *, 0); 00242 array_insert(array_t *, *pOnionRingsArrayForDbg, opIndex, onionRings); 00243 } 00244 00245 iterate = Mc_FsmEvaluateEUFormula(modelFsm, oldIterate, target, 00246 NIL(mdd_t), mddOne, careStatesArray, 00247 MC_NO_EARLY_TERMINATION, NIL(array_t), 00248 Mc_None_c, onionRings, verbosity, 00249 dcLevel, NIL(boolean)); 00250 mdd_free(target); 00251 } 00252 if (ConvergedGSH(iterate, oldIterate, opIndex, operatorSet, 00253 careStatesArray, earlyTermination, fixpoint)) { 00254 mdd_free(oldIterate); 00255 break; 00256 } 00257 mdd_free(oldIterate); 00258 } 00259 00260 /* Free operator set. */ 00261 FreeOperatorSetGSH(operatorSet); 00262 00263 /* Sanity checks for onion rings and diagnostic prints. */ 00264 if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) { 00265 if (useRings) { 00266 for (i = 0 ; i < array_n(*pOnionRingsArrayForDbg); i++) { 00267 int j; 00268 mdd_t *Fi = array_fetch(mdd_t *, buechiFairness, i); 00269 array_t *onionRings = array_fetch(array_t *, *pOnionRingsArrayForDbg, 00270 i); 00271 /* Early termination with random schedules may leave holes. */ 00272 if (onionRings == NIL(array_t)) continue; 00273 for (j = 0; j < array_n(onionRings); j++) { 00274 mdd_t *ring = array_fetch(mdd_t *, onionRings, j); 00275 if (j == 0) { 00276 if (!mdd_lequal_mod_care_set_array(ring, Fi, 1, 1, 00277 careStatesArray)) { 00278 fprintf(vis_stderr, "** mc error: Problem w/ dbg in EG - "); 00279 fprintf(vis_stderr, 00280 "inner most ring not in Fi (fairness constraint).\n"); 00281 } 00282 } 00283 if (!mdd_lequal_mod_care_set_array(ring, invariantMdd, 1, 1, 00284 careStatesArray)) { 00285 fprintf(vis_stderr, "** mc error: Problem w/ dbg in EG - "); 00286 fprintf(vis_stderr, "onion ring of last EU fails invariant\n"); 00287 } 00288 } 00289 } 00290 } 00291 00292 if (verbosity == McVerbosityMax_c) { 00293 mdd_t *tmpMdd = careStatesArray ? 00294 mdd_and_array(iterate, careStatesArray, 1, 1) : mdd_dup(iterate); 00295 fprintf(vis_stdout, 00296 "--There are %.0f care states satisfying EG formula\n", 00297 mdd_count_onset(mddManager, tmpMdd, 00298 Fsm_FsmReadPresentStateVars(modelFsm))); 00299 #ifdef DEBUG_MC 00300 /* The following 2 lines are just for debug. */ 00301 fprintf(vis_stdout, "EG satisfying minterms :\n"); 00302 (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm); 00303 #endif 00304 mdd_free(tmpMdd); 00305 } else { 00306 fprintf(vis_stdout, "--There are %.0f states satisfying EG formula\n", 00307 mdd_count_onset(mddManager, iterate, 00308 Fsm_FsmReadPresentStateVars(modelFsm))); 00309 } 00310 00311 fprintf(vis_stdout, "--EG: %d iterations, %d preimage computations\n", 00312 nIterations, 00313 Img_GetNumberOfImageComputation(Img_Backward_c) - nPreComps); 00314 } 00315 00316 mdd_array_free(buechiFairness); 00317 mdd_free(mddOne); 00318 00319 return iterate; 00320 00321 } /* McFsmEvaluateEGFormulaUsingGSH */ 00322 00323 00344 mdd_t* 00345 McFsmEvaluateEHFormulaUsingGSH( 00346 Fsm_Fsm_t *modelFsm, 00347 mdd_t *invariantMdd, 00348 mdd_t *overapprox, 00349 mdd_t *fairStates, 00350 Fsm_Fairness_t *modelFairness, 00351 array_t *careStatesArray, 00352 Mc_EarlyTermination_t *earlyTermination, 00353 array_t **pOnionRingsArrayForDbg, 00354 Mc_VerbosityLevel verbosity, 00355 Mc_DcLevel dcLevel, 00356 boolean *fixpoint, 00357 Mc_GSHScheduleType schedule) 00358 { 00359 int i,n; 00360 array_t *onionRings; 00361 boolean useRings; 00362 mdd_manager *mddManager; 00363 mdd_t *mddOne; 00364 mdd_t *iterate; 00365 array_t *buechiFairness; 00366 int nImgComps; 00367 int nIterations; 00368 McGSHOpSet_t *operatorSet; 00369 00370 /* Here's how the pOnionRingsArrayForDbg works. It is a pointer to 00371 ** an array of arrays of mdds. There is one entry for every 00372 ** fairness constraint, and this entry is the array of the onion 00373 ** rings of the ES computation that corresponds to this constraint. 00374 ** Every time the ES for a given constraint is recomputed, the 00375 ** corresponding array of rings is renewed. */ 00376 assert(pOnionRingsArrayForDbg == NIL(array_t *) || 00377 *pOnionRingsArrayForDbg == NIL(array_t) || 00378 array_n(*pOnionRingsArrayForDbg) == 0); 00379 00380 useRings = (pOnionRingsArrayForDbg != NIL(array_t *) && 00381 *pOnionRingsArrayForDbg != NIL(array_t)); 00382 00383 /* Initialization. */ 00384 nIterations = 0; 00385 nImgComps = Img_GetNumberOfImageComputation(Img_Forward_c); 00386 onionRings = NIL(array_t); 00387 mddManager = Fsm_FsmReadMddManager(modelFsm); 00388 mddOne = mdd_one(mddManager); 00389 00390 /* If an overapproxiamtion of the greatest fixpoint is given, use it. */ 00391 if(overapprox != NIL(mdd_t)){ 00392 iterate = mdd_and(invariantMdd, overapprox, 1, 1); 00393 } else { 00394 iterate = mdd_dup(invariantMdd); 00395 } 00396 00397 /* See if we need to enter the loop at all. */ 00398 if (mdd_is_tautology(iterate, 0) || 00399 McCheckEarlyTerminationForOverapprox(earlyTermination, 00400 iterate, careStatesArray)) { 00401 mdd_free(mddOne); 00402 00403 if (fixpoint != NIL(boolean)) *fixpoint = mdd_is_tautology(iterate, 0); 00404 return(iterate); 00405 } 00406 00407 /* Read fairness constraints. */ 00408 buechiFairness = array_alloc(mdd_t *, 0); 00409 if (modelFairness != NIL(Fsm_Fairness_t)) { 00410 if (!Fsm_FairnessTestIsBuchi(modelFairness)) { 00411 (void) fprintf(vis_stdout, 00412 "** mc error: non-Buechi fairness constraints not supported\n"); 00413 array_free(buechiFairness); 00414 mdd_free(iterate); 00415 mdd_free(mddOne); 00416 00417 if (fixpoint != NIL(boolean)) *fixpoint = FALSE; 00418 return NIL(mdd_t); 00419 } else { 00420 int j; 00421 int numBuechi = Fsm_FairnessReadNumConjunctsOfDisjunct(modelFairness, 0); 00422 for (j = 0; j < numBuechi; j++) { 00423 mdd_t *tmpMdd = Fsm_FairnessObtainFinallyInfMdd(modelFairness, 0, j, 00424 careStatesArray, dcLevel); 00425 array_insert_last(mdd_t *, buechiFairness, tmpMdd); 00426 } 00427 } 00428 } else { 00429 array_insert_last(mdd_t *, buechiFairness, mdd_one(mddManager)); 00430 } 00431 00432 /* Initialize set of disabled operators (to the empty set). */ 00433 n = array_n(buechiFairness); 00434 operatorSet = AllocOperatorSetGSH(n, schedule); 00435 00436 /* Iterate until all operators disabled or early termination. */ 00437 while (TRUE) { 00438 mdd_t *oldIterate = iterate; 00439 int opIndex = PickOperatorForGSH(operatorSet); 00440 nIterations++; 00441 if (GSHoperatorIsEX(opIndex,operatorSet)) { 00442 mdd_t *EY = Mc_FsmEvaluateEYFormula(modelFsm, oldIterate, mddOne, 00443 careStatesArray, verbosity, 00444 dcLevel); 00445 iterate = mdd_and(EY, oldIterate, 1, 1); 00446 mdd_free(EY); 00447 } else { 00448 mdd_t *Fi = array_fetch(mdd_t *, buechiFairness, opIndex); 00449 mdd_t *source = mdd_and(Fi, iterate, 1, 1); 00450 00451 /* Dispose of the old set of onion rings for this fairness constraint 00452 ** if it exists, and allocate a fresh array for a new set of rings. */ 00453 if (useRings) { 00454 if (opIndex < array_n(*pOnionRingsArrayForDbg)) { 00455 onionRings = array_fetch(array_t *, *pOnionRingsArrayForDbg, 00456 opIndex); 00457 mdd_array_free(onionRings); 00458 } 00459 onionRings = array_alloc(mdd_t *, 0); 00460 array_insert(array_t *, *pOnionRingsArrayForDbg, opIndex, onionRings); 00461 } 00462 00463 iterate = Mc_FsmEvaluateESFormula(modelFsm, oldIterate, source, 00464 NIL(mdd_t), mddOne, careStatesArray, 00465 MC_NO_EARLY_TERMINATION, NIL(array_t), 00466 Mc_None_c, onionRings, verbosity, 00467 dcLevel, NIL(boolean)); 00468 mdd_free(source); 00469 } 00470 if (ConvergedGSH(iterate, oldIterate, opIndex, operatorSet, 00471 careStatesArray, earlyTermination, fixpoint)) { 00472 mdd_free(oldIterate); 00473 break; 00474 } 00475 mdd_free(oldIterate); 00476 } 00477 00478 /* Free operator set. */ 00479 FreeOperatorSetGSH(operatorSet); 00480 00481 /* Sanity checks for onion rings and diagnostic prints. */ 00482 if (verbosity == McVerbositySome_c || verbosity == McVerbosityMax_c) { 00483 if (useRings) { 00484 for (i = 0 ; i < array_n(*pOnionRingsArrayForDbg); i++) { 00485 int j; 00486 mdd_t *Fi = array_fetch(mdd_t *, buechiFairness, i); 00487 array_t *onionRings = array_fetch(array_t *, *pOnionRingsArrayForDbg, 00488 i); 00489 /* Early termination with random schedules may leave holes. */ 00490 if (onionRings == NIL(array_t)) continue; 00491 for (j = 0; j < array_n(onionRings); j++) { 00492 mdd_t *ring = array_fetch(mdd_t *, onionRings, j); 00493 if (j == 0) { 00494 if (!mdd_lequal_mod_care_set_array(ring, Fi, 1, 1, 00495 careStatesArray)) { 00496 fprintf(vis_stderr, "** mc error: Problem w/ dbg in EH - "); 00497 fprintf(vis_stderr, 00498 "inner most ring not in Fi (fairness constraint).\n"); 00499 } 00500 } 00501 if (!mdd_lequal_mod_care_set_array(ring, invariantMdd, 1, 1, 00502 careStatesArray)) { 00503 fprintf(vis_stderr, "** mc error: Problem w/ dbg in EH - "); 00504 fprintf(vis_stderr, "onion ring of last ES fails invariant\n"); 00505 } 00506 } 00507 } 00508 } 00509 00510 if (verbosity == McVerbosityMax_c) { 00511 mdd_t *tmpMdd = careStatesArray ? 00512 mdd_and_array(iterate, careStatesArray, 1, 1) : mdd_dup(iterate); 00513 fprintf(vis_stdout, 00514 "--There are %.0f care states satisfying EH formula\n", 00515 mdd_count_onset(mddManager, tmpMdd, 00516 Fsm_FsmReadPresentStateVars(modelFsm))); 00517 #ifdef DEBUG_MC 00518 /* The following 2 lines are just for debug. */ 00519 fprintf(vis_stdout, "EH satisfying minterms :\n"); 00520 (void)_McPrintSatisfyingMinterms(tmpMdd, modelFsm); 00521 #endif 00522 mdd_free(tmpMdd); 00523 } else { 00524 fprintf(vis_stdout, "--There are %.0f states satisfying EH formula\n", 00525 mdd_count_onset(mddManager, iterate, 00526 Fsm_FsmReadPresentStateVars(modelFsm))); 00527 } 00528 00529 fprintf(vis_stdout, "--EH: %d iterations, %d image computations\n", 00530 nIterations, 00531 Img_GetNumberOfImageComputation(Img_Forward_c) - nImgComps); 00532 } 00533 00534 mdd_array_free(buechiFairness); 00535 mdd_free(mddOne); 00536 00537 return iterate; 00538 00539 } /* McFsmEvaluateEHFormulaUsingGSH */ 00540 00541 00542 /*---------------------------------------------------------------------------*/ 00543 /* Definition of static functions */ 00544 /*---------------------------------------------------------------------------*/ 00545 00546 00558 static int 00559 PickOperatorForGSH( 00560 McGSHOpSet_t *set) 00561 { 00562 int nop = array_n(set->flags); 00563 int opIndex; 00564 if (set->schedule == McGSH_EL_c) { 00565 int exIndex = nop - 1; 00566 if ((set->last != exIndex) && !array_fetch(int, set->flags, exIndex)) { 00567 opIndex = exIndex; 00568 } else { 00569 if (set->last == exIndex) { 00570 opIndex = (set->nextToLast + 1) % exIndex; 00571 } else { 00572 opIndex = (set->last + 1) % exIndex; 00573 } 00574 while (array_fetch(int, set->flags, opIndex)) 00575 opIndex = (opIndex + 1) % nop; 00576 } 00577 set->nextToLast = set->last; 00578 } else if (set->schedule == McGSH_EL1_c) { 00579 /* EL1 implements a round-robin policy. */ 00580 opIndex = (set->last + 1) % nop; 00581 while (array_fetch(int, set->flags, opIndex)) 00582 opIndex = (opIndex + 1) % nop; 00583 } else if (set->schedule == McGSH_EL2_c) { 00584 /* EL2 differs from EL1 in that it repeats EX to convergence. 00585 * We rely on the fact that EUs are always disabled after their 00586 * application. */ 00587 opIndex = set->last; 00588 while (array_fetch(int, set->flags, opIndex)) 00589 opIndex = (opIndex + 1) % nop; 00590 } else if (set->schedule == McGSH_Budget_c) { 00591 int exIndex = nop - 1; 00592 int newCount = Img_GetNumberOfImageComputation(Img_Backward_c); 00593 if (set->last == exIndex) 00594 set->exBudget--; 00595 else 00596 set->exBudget += newCount - set->exCount; 00597 set->exCount = newCount; 00598 /* (void) printf("budget = %d\n", set->exBudget); */ 00599 if ((set->last != exIndex) && !array_fetch(int, set->flags, exIndex)) { 00600 /* At least one EX after each EU, unless EX is disabled */ 00601 opIndex = exIndex; 00602 set->nextToLast = set->last; 00603 } else { 00604 if (set->last == exIndex) { 00605 if (set->exBudget > 0 && set->nextToLast == exIndex - 1) { 00606 opIndex = exIndex; 00607 } else { 00608 opIndex = (set->nextToLast + 1) % exIndex; 00609 set->nextToLast = set->last; 00610 } 00611 } else { /* EX is disabled */ 00612 opIndex = (set->last + 1) % exIndex; 00613 set->nextToLast = set->last; 00614 } 00615 while (array_fetch(int, set->flags, opIndex)) 00616 opIndex = (opIndex + 1) % nop; 00617 } 00618 if (opIndex == 0) 00619 set->exBudget = 0; 00620 #if 0 00621 opIndex = set->last; 00622 if (opIndex == exIndex && set->exBudget == 0) 00623 opIndex = 0; 00624 while (array_fetch(int, set->flags, opIndex)) 00625 opIndex = (opIndex + 1) % nop; 00626 #endif 00627 } else { 00628 /* The random schedule uses a rather primitive way of selecting a 00629 * random integer. However, as long as the number of operators is 00630 * small, the distribution is acceptably uniform even if we use 00631 * mod to map the result of util_random to 0 ... nop-1. */ 00632 int exIndex = nop - 1; 00633 long rn = util_random(); 00634 int exDisabled = array_fetch(int, set->flags, exIndex); 00635 if ((!exDisabled) && ((rn & 1024) || (set->cnt == exIndex))) { 00636 /* rn & 1024 should be true 50% of the times */ 00637 opIndex = exIndex; 00638 } else { 00639 int enabledEUs = exIndex - (set->cnt - exDisabled); 00640 rn = rn % enabledEUs; 00641 assert(0 <= rn && rn < exIndex); 00642 for (opIndex = 0; TRUE; opIndex++) { 00643 assert(opIndex < exIndex); 00644 if (!array_fetch(int, set->flags, opIndex)) { 00645 if (rn == 0) { 00646 break; 00647 } else { 00648 rn--; 00649 } 00650 } 00651 } 00652 } 00653 } 00654 set->last = opIndex; 00655 return opIndex; 00656 00657 } /* PickOperatorForGSH */ 00658 00659 00676 static boolean 00677 ConvergedGSH( 00678 mdd_t *Z /* new iterate */, 00679 mdd_t *zeta /* old iterate */, 00680 int opIndex /* operator that has been just applied */, 00681 McGSHOpSet_t *opSet /* set of disabled operators */, 00682 array_t *careStatesArray /* array for care states */, 00683 Mc_EarlyTermination_t *earlyTermination /* early termination criterion */, 00684 boolean *fixpoint /* reason for termination */) 00685 { 00686 boolean term_tautology = FALSE; 00687 boolean term_fixpoint = FALSE; 00688 boolean term_early = FALSE; 00689 00690 term_tautology = mdd_is_tautology(Z, 0); 00691 if (!term_tautology) 00692 term_fixpoint = mdd_equal_mod_care_set_array(Z, zeta, careStatesArray); 00693 if (!term_tautology && !term_fixpoint) 00694 term_early = McCheckEarlyTerminationForOverapprox(earlyTermination, Z, 00695 careStatesArray); 00696 if (term_tautology || term_early) { 00697 if (fixpoint != NIL(boolean)) 00698 *fixpoint = term_tautology; 00699 return TRUE; 00700 } else if (term_fixpoint) { 00701 if (PushOperatorSetGSH(opSet,opIndex) == SizeOperatorSetGSH(opSet)) { 00702 if (fixpoint != NIL(boolean)) 00703 *fixpoint = TRUE; 00704 return TRUE; 00705 } else { 00706 return FALSE; 00707 } 00708 } else { 00709 EmptyOperatorSetGSH(opSet); 00710 if (!GSHoperatorIsEX(opIndex,opSet)) { 00711 /* The operator is an EU. Add to set. */ 00712 (void) PushOperatorSetGSH(opSet,opIndex); 00713 } 00714 return FALSE; 00715 } 00716 00717 } /* ConvergedGSH */ 00718 00719 00731 static McGSHOpSet_t * 00732 AllocOperatorSetGSH( 00733 int n, 00734 Mc_GSHScheduleType schedule) 00735 { 00736 int i; 00737 McGSHOpSet_t *set = ALLOC(McGSHOpSet_t, 1); 00738 array_t *flags = set->flags = array_alloc(int, n+1); 00739 for (i = 0; i < n+1; i++) { 00740 array_insert(int, flags, i, 0); 00741 } 00742 set->cnt = 0; 00743 set->schedule = schedule; 00744 if (set->schedule == McGSH_EL_c) { 00745 set->last = n; 00746 set->nextToLast = n - 1; 00747 } else if (set->schedule == McGSH_EL1_c) { 00748 set->last = n; 00749 } else if (set->schedule == McGSH_EL2_c) { 00750 set->last = 0; 00751 } else if (set->schedule == McGSH_Budget_c) { 00752 set->last = n; 00753 set->nextToLast = n - 1; 00754 set->exBudget = 1; 00755 set->exCount = Img_GetNumberOfImageComputation(Img_Backward_c); 00756 } else { 00757 /* The random schedule has no history. Hence, this initialization is 00758 * immaterial. */ 00759 set->last = 0; 00760 } 00761 return set; 00762 00763 } /* AllocOperatorSetGSH */ 00764 00765 00777 static void 00778 FreeOperatorSetGSH( 00779 McGSHOpSet_t *set) 00780 { 00781 array_free(set->flags); 00782 FREE(set); 00783 return; 00784 00785 } /* FreeOperatorSetGSH */ 00786 00787 00801 static void 00802 EmptyOperatorSetGSH( 00803 McGSHOpSet_t *set) 00804 { 00805 int i; 00806 for (i = 0; i < array_n(set->flags); i++) { 00807 array_insert(int, set->flags, i, 0); 00808 } 00809 set->cnt = 0; 00810 return; 00811 00812 } /* EmptyOperatorSetGSH */ 00813 00814 00826 static boolean 00827 IsMemberOperatorSetGSH( 00828 McGSHOpSet_t *set, 00829 int opIndex) 00830 { 00831 return array_fetch(int, set->flags, opIndex); 00832 00833 } /* IsMemberOperatorSetGSH */ 00834 00835 00847 static int 00848 SizeOperatorSetGSH( 00849 McGSHOpSet_t *set) 00850 { 00851 return array_n(set->flags); 00852 00853 } /* SizeOperatorSetGSH */ 00854 00855 00867 static int 00868 PushOperatorSetGSH( 00869 McGSHOpSet_t *set, 00870 int opIndex) 00871 { 00872 assert(opIndex < array_n(set->flags)); 00873 array_insert(int, set->flags, opIndex, 1); 00874 set->cnt++; 00875 return set->cnt; 00876 00877 } /* PushOperatorSetGSH */