/** * Non-uniform history dependent CTMDPI time bounded reachability. * Algorithm taken from * * "Continuous-Time Stochastic Games with Time-Bounded Reachability" * * by Tomas Brazdil, Vojtech Forejt, Jan Krcal, Jan Kretinsky, Antonin * Kucera. * * @author Ernst Moritz Hahn ([email protected]) * @param time_bound time bound * @param B reachability set * @return computed probability vector */ double *transient_ctmdpi_hd_non_uni (const double time_bound, const bitset *B) { NDSparseMatrix *ctmdp; unsigned num_rates; double *rates; unsigned *choices_to_rates; unsigned k_bound; double *result; int comparator; BOOL min; if (0.0 == time_bound) { result = time_zero_result(B); } else { comparator = get_comparator(); min = (C_GREATER == comparator) || (C_GREATER_EQUAL == comparator); ctmdp = get_mdpi_state_space(); prepare_ctmdpi(ctmdp, &rates, &num_rates, &choices_to_rates); k_bound = compute_k_bound(rates, num_rates, time_bound); result = ctmdpi_iterate(ctmdp, rates, num_rates, choices_to_rates, k_bound, B, time_bound, min); unprepare_ctmdpi(ctmdp, rates, choices_to_rates); } return result; }
Reachability::Result *VipsBitReachability::reachability(Arg *arg) const{ const Machine &machine = arg->machine; Result *result = new Result(machine); result->timer.start(); result->result = UNREACHABLE; bool found_forbidden = false; VipsBitConstraint::Common common(machine); /* buf contains constraints that have been found but not explored */ CBuf buf(CBuf::QUEUE); /* The set of keys of visited is the set of visited constraints. * Each visited constraint maps to a description of its parent. */ std::map<const VipsBitConstraint*,parent_t,vbcmp_t> visited(get_comparator(common)); /* Find the initial constraints */ { std::set<VipsBitConstraint*> init = common.get_initial_constraints(); result->generated_constraints = result->stored_constraints = init.size(); for(auto it = init.begin(); it != init.end(); ++it){ if((*it)->is_forbidden(common)){ result->trace = new Trace(0); result->result = REACHABLE; found_forbidden = true; } buf.push(*it); visited[*it] = parent_t(); } } while(!found_forbidden && buf.size()){ const VipsBitConstraint *vbc = buf.pop(); VecSet<const Machine::PTransition*> transes = vbc->partred(common); for(int i = 0; !found_forbidden && i < transes.size(); ++i){ VipsBitConstraint *child = vbc->post(common,*transes[i]); if(child){ ++result->generated_constraints; if(visited.count(child)){ common.dealloc(child); }else{ visited[child] = parent_t(transes[i],vbc); buf.push(child); if(child->is_forbidden(common)){ result->result = REACHABLE; found_forbidden = true; /* Construct trace */ { Trace tr(0); const parent_t *pt = &visited[child]; while(pt->parent){ tr.push_front(0,*pt->trans); pt = &visited[pt->parent]; } result->trace = VipsBitConstraint::explicit_vips_trace(tr); } } } } } } result->stored_constraints = visited.size(); /* Cleanup */ /* Destruction of common automatically cleans up the remaining * constraints. */ result->timer.stop(); return result; };
/** * Uniform history dependent CTMDPI time bounded reachability. * Algorithm taken from * * "Efficient computation of time-bounded reachability probabilities in uniform * continuous-time Markov decision processes" * * by C. Baier, B. Haverkort, H. Hermanns, J.-P. Katoen. * * @author Ernst Moritz Hahn ([email protected]) * @param t time bound * @param B reachability set * @return the calculated probability vector */ double *transient_ctmdpi_hd_uni(const double t, const bitset *B) { state_index row; FoxGlynn *fg; unsigned left_end; double *result; unsigned state; double E; const double u = get_underflow(); const double o = get_overflow(); const double epsilon = get_error_bound(); double *P_s_alpha_B; /* if user typed a "<" or "<=" as comparator in the fomula, we * compute the maximal probability, for ">" or ">=" the * minimal one. These are the worst-case probabilities that * is, if it is possible for some state not to fulfill the * formula, it won't fulfill it with these probabilities. */ int comparator = get_comparator(); BOOL min = (C_GREATER == comparator) || (C_GREATER_EQUAL == comparator); const double *non_zeros; const int *row_starts; const int *choice_starts; const unsigned int *cols; double *q; double *q_primed; /* some shortcuts for several values (precision, # of states, * etc.) */ NDSparseMatrix *ctmdp = get_mdpi_state_space(); unsigned num_states = ctmdp->n; if (!uniformize_ctmdpi(ctmdp)) { /* in case of failure, return dummy result */ result = (double *)calloc(num_states, sizeof(double)); return result; } E = ctmdp->rate; P_s_alpha_B = calculate_P_s_alpha_B(ctmdp, B); /* store local pointers of stuff */ non_zeros = ctmdp->non_zeros; row_starts = (int *) ctmdp->row_counts; choice_starts = (int *) ctmdp->choice_counts; cols = ctmdp->cols; /* In case Fox-Glynn algorithm terminated successfully, we proceed */ if ( fox_glynn(E * t, u, o, epsilon, &fg) ) { printf("Fox-Glynn: ltp = %d, rtp = %d, w = %1.15e\n", fg->left, fg->right, fg->total_weight); /* we have to fill the entries for all states with zero, even * for target states. * Corresponds to line 2 or algorithm in paper. */ q = (double *) calloc((size_t) num_states, sizeof(double)); q_primed = (double*)calloc((size_t) num_states, sizeof(double)); /* we have to do this, because for very small rates the FG-algo also * gives the possibility to not doing a jump at all. */ left_end = (0 == fg->left) ? 1 : fg->left; /* start main iteration of algorithm */ result = ctmdpi_iter( num_states, fg, left_end, min, row_starts, choice_starts, non_zeros, q, q_primed, cols, P_s_alpha_B, B ); /* line 15 in paper */ row = state_index_NONE; while ( (row=get_idx_next_non_zero(B,row)) != state_index_NONE ) { result[row] = 1.0; } /* cleanup stuff */ if (result != q){ free(q); q = NULL; } if (result != q_primed){ free(q_primed); q_primed = NULL; } } else { /* Otherwise return a dummy result */ result = (double *) calloc((size_t) num_states, sizeof(double)); for (state = 0; state < (unsigned) ctmdp->n; state++) { result[state] = get_bit_val(B, state); } } /* cleanup stuff */ free(P_s_alpha_B); freeFG(fg); deuniformize_ctmdpi(ctmdp); /* line 16 in paper */ return result; }