void final_final_stats_reporting () { /* optionally print counts of all group_next and group_explored sets */ long n_count; double e_count; long total_node_count = 0; long explored_total_node_count = 0; double explored_total_vector_count = 0; for (int i = 0; i < nGrps; i++) { vrel_count (group_next[i], &n_count, &e_count); Print(infoLong, "group_next[%d]: %.*g short vectors %ld nodes", i, DBL_DIG, e_count, n_count); total_node_count += n_count; vset_count (group_explored[i], &n_count, &e_count); Print(infoLong, "group_explored[%d]: %.*g short vectors, %ld nodes", i, DBL_DIG, e_count, n_count); explored_total_node_count += n_count; explored_total_vector_count += e_count; } Print(info, "group_next: %ld nodes total", total_node_count); Print(info, "group_explored: %ld nodes, %.*g short vectors total", explored_total_node_count, DBL_DIG, explored_total_vector_count); if (PINS_USE_GUARDS) { long total_false = 0; long total_true = 0; explored_total_vector_count = 0; for (int i = 0; i < nGuards; i++) { vset_count (label_false[i], &n_count, &e_count); Print(infoLong, "guard_false[%d]: %.*g short vectors, %ld nodes", i, DBL_DIG, e_count, n_count); total_false += n_count; explored_total_vector_count += e_count; vset_count (label_true[i], &n_count, &e_count); Print(infoLong, "guard_true[%d]: %.*g short vectors, %ld nodes", i, DBL_DIG, e_count, n_count); total_true += n_count; explored_total_vector_count += e_count; } Print(info, "guard_false: %ld nodes total", total_false); Print(info, "guard_true: %ld nodes total", total_true); Print(info, "guard: %.*g short vectors total", DBL_DIG, explored_total_vector_count); } }
int vset_count_dbl(vset_t set, long* nodes, long double* elements) { if (elements != NULL) { *elements = 0.0; double e; vset_count(set, nodes, &e); *elements += e; if(vdom_supports_ccount(domain) && isinf(e)) { vset_count_fn = &vset_count_ldbl; vset_count_fn(set, nodes, elements); return LDBL_DIG; } } else { vset_count(set, nodes, NULL); } return DBL_DIG; }
/** * \brief Creates a symbolic parity game from the generated LTS. */ parity_game * compute_symbolic_parity_game(vset_t visited, int *src) { Print(infoShort, "Computing symbolic parity game."); debug_output_enabled = true; // num_vars and player have been pre-computed by init_pbes. parity_game* g = spg_create(domain, N, nGrps, min_priority, max_priority); for(int i=0; i < N; i++) { g->src[i] = src[i]; } vset_copy(g->v, visited); for(size_t i = 0; i < num_vars; i++) { // players Print(infoLong, "Adding nodes for var %zu (player %d).", i, player[i]); add_variable_subset(g->v_player[player[i]], g->v, g->domain, i); // priorities add_variable_subset(g->v_priority[priority[i]], g->v, g->domain, i); } if (log_active(infoLong)) { for(int p = 0; p < 2; p++) { long n_count; double elem_count; vset_count(g->v_player[p], &n_count, &elem_count); Print(infoLong, "player %d: %ld nodes, %.*g elements.", p, n_count, DBL_DIG, elem_count); } for(int p = min_priority; p <= max_priority; p++) { long n_count; double elem_count; vset_count(g->v_priority[p], &n_count, &elem_count); Print(infoLong, "priority %d: %ld nodes, %.*g elements.", p, n_count, DBL_DIG, elem_count); } } for(int i = 0; i < nGrps; i++) { g->e[i] = group_next[i]; } return g; }
/** * \brief Computes the subset of v that belongs to player <tt>player</tt>. * \param vars the indices of variables of player <tt>player</tt>. */ static inline void add_variable_subset(vset_t dst, vset_t src, vdom_t domain, int var_index) { //Warning(info, "add_variable_subset: var_index=%d", var_index); int p_len = 1; int proj[1] = {var_pos}; // position 0 encodes the variable int match[1] = {var_index}; // the variable vset_t u = vset_create(domain, -1, NULL); vset_copy_match_proj(u, src, p_len, proj, variable_projection, match); if (debug_output_enabled && log_active(infoLong)) { double e_count; vset_count(u, NULL, &e_count); if (e_count > 0) Print(infoLong, "add_variable_subset: %d: %.*g states", var_index, DBL_DIG, e_count); } vset_union(dst, u); vset_destroy(u); }
void stats_and_progress_report(vset_t current, vset_t visited, int level) { long n_count; long double e_count; if (sat_strategy == NO_SAT || log_active (infoLong)) { Print(infoShort, "level %d is finished", level); } if (log_active (infoLong) || peak_nodes) { if (current != NULL) { int digs = vset_count_fn (current, &n_count, &e_count); Print(infoLong, "level %d has %.*Lg states ( %ld nodes )", level, digs, e_count, n_count); if (n_count > max_lev_count) max_lev_count = n_count; } int digs = vset_count_fn (visited, &n_count, &e_count); Print(infoLong, "visited %d has %.*Lg states ( %ld nodes )", level, digs, e_count, n_count); if (n_count > max_vis_count) max_vis_count = n_count; if (log_active (debug)) { Debug("transition caches ( grp nds elts ):"); for (int i = 0; i < nGrps; i++) { vrel_count(group_next[i], &n_count, NULL); Debug("( %d %ld ) ", i, n_count); if (n_count > max_trans_count) max_trans_count = n_count; } Debug("\ngroup explored ( grp nds elts ): "); for (int i = 0; i < nGrps; i++) { vset_count(group_explored[i], &n_count, NULL); Debug("( %d %ld) ", i, n_count); if (n_count > max_grp_count) max_grp_count = n_count; } } } if (dot_dir != NULL) { FILE *fp; char *file; file = "%s/current-l%d.dot"; char fcbuf[snprintf(NULL, 0, file, dot_dir, level)]; sprintf(fcbuf, file, dot_dir, level); fp = fopen(fcbuf, "w+"); vset_dot(fp, current); fclose(fp); file = "%s/visited-l%d.dot"; char fvbuf[snprintf(NULL, 0, file, dot_dir, level)]; sprintf(fvbuf, file, dot_dir, level); fp = fopen(fvbuf, "w+"); vset_dot(fp, visited); fclose(fp); for (int i = 0; i < nGrps; i++) { file = "%s/group_next-l%d-k%d.dot"; char fgbuf[snprintf(NULL, 0, file, dot_dir, level, i)]; sprintf(fgbuf, file, dot_dir, level, i); fp = fopen(fgbuf, "w+"); vrel_dot(fp, group_next[i]); fclose(fp); } for (int g = 0; g < nGuards && PINS_USE_GUARDS; g++) { file = "%s/guard_false-l%d-g%d.dot"; char fgfbuf[snprintf(NULL, 0, file, dot_dir, level, g)]; sprintf(fgfbuf, file, dot_dir, level, g); fp = fopen(fgfbuf, "w+"); vset_dot(fp, label_false[g]); fclose(fp); file = "%s/guard_true-l%d-g%d.dot"; char fgtbuf[snprintf(NULL, 0, file, dot_dir, level, g)]; sprintf(fgtbuf, file, dot_dir, level, g); fp = fopen(fgtbuf, "w+"); vset_dot(fp, label_true[g]); fclose(fp); } } }
int main(int argc, char *argv[]){ char *files[2]; RTinitPopt(&argc,&argv,options,1,2,files,NULL,"<model> [<lts>]", "Perform an enumerative reachability analysis of <model>\n" "Run the TorX remote procedure call protocol on <model> (--torx).\n\n" "Options"); if (files[1]) { Warning(info,"Writing output to %s",files[1]); write_lts=1; } else { Warning(info,"No output, just counting the number of states"); write_lts=0; } if (application==RunTorX && write_lts) Fatal(1,error,"A TorX server does not write to a file"); Warning(info,"loading model from %s",files[0]); model_t model=GBcreateBase(); GBsetChunkMethods(model,new_string_index,NULL, (int2chunk_t)SIgetC,(chunk2int_t)SIputC,(get_count_t)SIgetCount); GBloadFile(model,files[0],&model); if (RTverbosity >=2) { fprintf(stderr,"Dependency Matrix:\n"); GBprintDependencyMatrix(stderr,model); } if (matrix) { GBprintDependencyMatrix(stdout,model); exit(0); } lts_type_t ltstype=GBgetLTStype(model); N=lts_type_get_state_length(ltstype); edge_info_t e_info=GBgetEdgeInfo(model); K=e_info->groups; Warning(info,"length is %d, there are %d groups",N,K); state_labels=lts_type_get_state_label_count(ltstype); edge_labels=lts_type_get_edge_label_count(ltstype); Warning(info,"There are %d state labels and %d edge labels",state_labels,edge_labels); if (state_labels&&write_lts&&!write_state) { Fatal(1,error,"Writing state labels, but not state vectors unsupported. " "Writing of state vector is enabled with the option --write-state"); } int src[N]; GBgetInitialState(model,src); Warning(info,"got initial state"); int level=0; switch(application){ case ReachVset: domain=vdom_create_default(N); visited_set=vset_create(domain,0,NULL); next_set=vset_create(domain,0,NULL); if (write_lts){ output=lts_output_open(files[1],model,1,0,1,"viv",NULL); lts_output_set_root_vec(output,(uint32_t*)src); lts_output_set_root_idx(output,0,0); output_handle=lts_output_begin(output,0,0,0); } vset_add(visited_set,src); vset_add(next_set,src); vset_t current_set=vset_create(domain,0,NULL); while (!vset_is_empty(next_set)){ if (RTverbosity >= 1) Warning(info,"level %d has %d states, explored %d states %d trans", level,(visited-explored),explored,trans); level++; vset_copy(current_set,next_set); vset_clear(next_set); vset_enum(current_set,explore_state_vector,model); } long long size; long nodes; vset_count(visited_set,&nodes,&size); Warning(info,"%lld reachable states represented symbolically with %ld nodes",size,nodes); break; case ReachTreeDBS: dbs=TreeDBScreate(N); if(TreeFold(dbs,src)!=0){ Fatal(1,error,"expected 0"); } if (write_lts){ output=lts_output_open(files[1],model,1,0,1,write_state?"vsi":"-ii",NULL); if (write_state) lts_output_set_root_vec(output,(uint32_t*)src); lts_output_set_root_idx(output,0,0); output_handle=lts_output_begin(output,0,0,0); } int limit=visited; while(explored<visited){ if (limit==explored){ if (RTverbosity >= 1) Warning(info,"level %d has %d states, explored %d states %d trans", level,(visited-explored),explored,trans); limit=visited; level++; } TreeUnfold(dbs,explored,src); explore_state_index(model,explored,src); } break; case RunTorX: { torx_struct_t context = { model, ltstype }; torx_ui(&context); return 0; } } if (write_lts){ lts_output_end(output,output_handle); Warning(info,"finishing the writing"); lts_output_close(&output); Warning(info,"state space has %d levels %d states %d transitions",level,visited,trans); } else { printf("state space has %d levels %d states %d transitions\n",level,visited,trans); } return 0; }
int choose_strategy_move(const parity_game* g, const recursive_result* strategy, const int player, const int* src, int* current_player, bool* strategy_play, bool* result, bool* deadlock, int* dst) { int group = -1; vset_t level = vset_create(g->domain, -1, NULL); vset_t tmp = vset_create(g->domain, -1, NULL); vset_t singleton = vset_create(g->domain, -1, NULL); vset_add(singleton, src); // Do a random run through the game, conforming to // the strategy in result. *current_player = (vset_member(g->v_player[player], src) ? player : 1-player); Print(hre_debug, "Using strategy of player %d. The position is owned by player %d.", player, *current_player); if (*current_player==player && vset_member(strategy->win[player], src)) { //printf("Player %d chooses according to his/her winning strategy.\n", player); // Choose a transition according to the strategy of player *strategy_play = true; vset_t strategy_level = vset_create(g->domain, -1, NULL); compute_strategy_level(strategy_level, src, player, strategy); vset_clear(level); for (int i=0; i < g->num_groups; i++) { vset_next(tmp, singleton, g->e[i]); vset_intersect(tmp, strategy_level); if (!vset_is_empty(tmp)) { vset_copy(level, tmp); // Choose a random element: //printf("Choosing a transition from transition group %d.\n", i); group = i; vset_random(level, dst); break; } } // Check for deadlocks if (vset_is_empty(level)) { *deadlock = true; *result = (*current_player != player); Print(infoLong, "Deadlock for player %d, player %s has won, result is %s.", *current_player, (*current_player==1) ? "0 (even / or)" : "1 (odd / and)", *result ? "true" : "false"); } } else { //Print(info, "Not player %d's turn or player %d has no winning strategy. Choosing an arbitrary move for player %d.", // player, player, *current_player); // this states belongs to (1-player) or player does not have a winning strategy *strategy_play = false; vset_t strategy_level = vset_create(g->domain, -1, NULL); /* if (vset_member(result.win[current_player], src)) { // winning move after all compute_strategy_level(strategy_level, src, current_player, result); if (vset_is_empty(strategy_level)) { Print(info, "Unexpected: src is in win[%d], but strategy_level is empty.", current_player); } else { strategy_play = true; } } */ // choose a random move vset_clear(level); for (int i=0; i < g->num_groups; i++) { vset_next(tmp, singleton, g->e[i]); if (*strategy_play && !vset_is_empty(tmp)) { vset_intersect(tmp, strategy_level); if (!vset_is_empty(tmp)) { vset_copy(level, tmp); // Choose a random element: //printf("Choosing a transition from transition group %d.\n", i); group = i; vset_random(level, dst); break; } } else { vset_union(level, tmp); } } // Check for deadlocks if (vset_is_empty(level)) { *deadlock = true; *result = (*current_player != player); Print(infoLong, "Deadlock for player %d, player %s has won, result is %s.", *current_player, (*current_player==1) ? "0 (even / or)" : "1 (odd / and)", *result ? "true" : "false"); } else if (!*strategy_play) { //Print(info, "choose randomly"); long int nodes; bn_int_t states; bn_init(&states); vset_count(level, &nodes, &states); vset_random(level, dst); } } return group; }