void lts_to_pg_solve (vset_t visited, int* src) { // converting the LTS to a symbolic parity game, save and solve. vset_destroy (true_states); vset_destroy (false_states); if (pg_output || pgsolve_flag) { rt_timer_t compute_pg_timer = RTcreateTimer (); RTstartTimer (compute_pg_timer); parity_game* g = compute_symbolic_parity_game (visited, src); RTstopTimer (compute_pg_timer); RTprintTimer (info, compute_pg_timer, "computing symbolic parity game took"); if (pg_output) { Print(info, "Writing symbolic parity game to %s.", pg_output); FILE* f = fopen (pg_output, "w"); spg_save (f, g); fclose (f); } if (pgsolve_flag) { spgsolver_options* spg_options = spg_get_solver_options (); rt_timer_t pgsolve_timer = RTcreateTimer (); Print(info, "Solving symbolic parity game for player %d.", spg_options->player); RTstartTimer (pgsolve_timer); recursive_result strategy; parity_game* copy = NULL; if (spg_options->check_strategy) { copy = spg_copy (g); } _Bool result = spg_solve (g, &strategy, spg_options); Print(info, " "); Print(info, "The result is: %s.", result ? "true" : "false"); RTstopTimer (pgsolve_timer); Print(info, " "); RTprintTimer (info, reach_timer, "reachability took "); RTprintTimer (info, compute_pg_timer, "computing game took "); RTprintTimer (info, pgsolve_timer, "solving took "); if (spg_options->strategy_filename != NULL) { Print(info, "Writing winning strategies to %s", spg_options->strategy_filename); FILE* f = fopen (spg_options->strategy_filename, "w"); result_save (f, strategy); fclose (f); } if (spg_options->check_strategy) { check_strategy (copy, &strategy, spg_options->player, result, 10); } } else { spg_destroy (g); } } if (player != 0) { RTfree (player); RTfree (priority); } }
void trc_find_and_write (trc_env_t *env, char *trc_output, ref_t dst_idx, int level, ref_t *parent_ofs, ref_t start_idx) { rt_timer_t timer = RTcreateTimer (); RTstartTimer (timer); /* Other workers may have influenced the trace, writing to parent_ofs. * we artificially limit the length of the trace to 10 times that of the * found one */ size_t max_length = level * 10; ref_t *trace = RTmalloc(sizeof(ref_t) * max_length); if (trace == NULL) Abort("unable to allocate memory for trace"); int i = max_length - 1; ref_t curr_idx = dst_idx; trace[i] = curr_idx; while(curr_idx != start_idx) { i--; if (i < 0) Abort("Trace length 10x longer than initially found trace. Giving up."); curr_idx = parent_ofs[curr_idx]; trace[i] = curr_idx; } Warning (info, "reconstructed trace length: %zu", max_length - i); RTstopTimer (timer); RTprintTimer (info, timer, "constructing the trace took"); trc_write_trace (env, trc_output, &trace[i], max_length - i); RTfree (trace); }
void cndfs_local_setup (run_t *run, wctx_t *ctx) { cndfs_alg_local_t *cloc = (cndfs_alg_local_t *) ctx->local; cloc->timer = RTcreateTimer (); ndfs_local_setup (run, ctx); size_t len = state_info_serialize_int_size (ctx->state); cloc->in_stack = dfs_stack_create (len); cloc->out_stack = dfs_stack_create (len); if ((get_strategy(run->alg) & Strat_TA) == 0) { cloc->pink = fset_create (sizeof(ref_t), sizeof(size_t), FSET_MIN_SIZE, 24); } if (get_strategy(run->alg) & Strat_CNDFS) return; if (run->shared->rec == NULL) { Abort ("Missing recursive strategy for %s!", key_search(strategies, get_strategy(run->alg))); return; } HREassert (ctx->global != NULL, "Run global before local init"); // We also need to finalize the worker initialization: ctx->global->rec = run_init (run->shared->rec, ctx->model); // Recursive strategy maybe unaware of its caller, so here we update its // recursive bits (top-level strategy always has rec_bits == 0, which // is ensured by ndfs_local_setup): ctx->global->rec->local->rec_bits = run->shared->color_bit_shift; cloc->rec = ctx->global->rec->local; }
/** * \brief Creates a new spgsolver_options object. */ spgsolver_options* spg_get_solver_options() { spgsolver_options* options = (spgsolver_options*)RTmalloc(sizeof(spgsolver_options)); switch (attr_strategy) { case CHAIN: options->attr = spg_attractor_chaining; Print(infoLong, "attractor: chaining"); break; #ifdef HAVE_SYLVAN case PAR: options->attr = spg_attractor_par; Print(infoLong, "attractor: par"); break; case PAR2: options->attr = spg_attractor_par2; Print(infoLong, "attractor: par2"); break; #endif default: options->attr = spg_attractor; Print(infoLong, "attractor: default"); break; } options->attr_options = (spg_attr_options*)RTmalloc(sizeof(spg_attr_options)); options->attr_options->dot = false; #ifdef LTSMIN_DEBUG options->attr_options->dot = (dot_flag > 0); options->attr_options->dot_count = 0; #endif options->attr_options->saturation = (saturating_attractor_flag > 0); options->attr_options->timer = RTcreateTimer(); options->strategy_filename = strategy_filename; options->attr_options->compute_strategy = (strategy_filename != NULL); if (options->attr_options->compute_strategy) { if (options->attr == spg_attractor_chaining) { Abort("Computing stategy not supported in chaining attractor. Use, e.g., '--attr=default'."); } Print(info, "Writing winning strategies to %s", strategy_filename); } options->check_strategy = (check_strategy_flag > 0); options->interactive_strategy_play = (interactive_strategy_play_flag > 0); if (player == 0 || player == 1) { options->player = player; } else { Abort("Invalid player: %d", player); } return options; }
void do_output(char *etf_output, vset_t visited) { FILE *tbl_file; rt_timer_t timer = RTcreateTimer(); RTstartTimer(timer); Warning(info, "writing output"); tbl_file = fopen(etf_output, "w"); if (tbl_file == NULL) AbortCall("could not open %s", etf_output); if (vdom_separates_rw(domain)) { /* * This part is necessary because the ETF format does not yet support * read, write and copy. This part should thus be removed when ETF is * extended. */ Warning(info, "Note: ETF format does not yet support read, write and copy."); transitions_short = GBgetTransitionsShort; RTfree (r_projs); RTfree (w_projs); w_projs = r_projs = (ci_list **) dm_rows_to_idx_table (GBgetDMInfo(model)); for (int i = 0; i < nGrps; i++) { vset_destroy(group_explored[i]); group_explored[i] = vset_create(domain, r_projs[i]->count, r_projs[i]->data); vset_project(group_explored[i], visited); } } output_init(tbl_file); output_trans(tbl_file); output_lbls(tbl_file, visited); output_types(tbl_file); fclose(tbl_file); RTstopTimer(timer); RTprintTimer(info, timer, "writing output took"); }
fset_t * fset_create (size_t key_length, size_t data_length, size_t init_size, size_t max_size) { HREassert (true == 1); HREassert (false == 0); HREassert (key_length > 0); HREassert (sizeof(mem_hash_t) == 4);// CACHE_MEM HREassert (max_size < 32); // FULL bit HREassert (init_size <= max_size); // precondition HREassert (init_size >= FSET_MIN_SIZE); // walk the line code fset_t *dbs = RTalign (CACHE_LINE_SIZE, sizeof(fset_t)); dbs->key_length = key_length; dbs->data_length = data_length; dbs->total_length = data_length + key_length; dbs->size_max = 1ULL << max_size; dbs->data = RTalign (CACHE_LINE_SIZE, dbs->total_length * dbs->size_max); dbs->todo_data = RTalign (CACHE_LINE_SIZE, dbs->total_length * dbs->size_max); dbs->hash = RTalignZero (CACHE_LINE_SIZE, sizeof(mem_hash_t) * dbs->size_max); dbs->todo = RTalign (CACHE_LINE_SIZE, 2 * sizeof(mem_hash_t) * dbs->size_max); dbs->delled_data = RTalign (CACHE_LINE_SIZE, data_length); dbs->init_size = 1ULL << init_size; dbs->init_size3 = dbs->init_size * 3; dbs->size = dbs->init_size; dbs->size3 = dbs->init_size3; dbs->mask = dbs->size - 1; dbs->load = 0; dbs->tombs = 0; dbs->resizing = 0; dbs->resizes = 0; dbs->max_grow = dbs->init_size; dbs->max_load = 0; dbs->max_todos = 0; dbs->lookups = 0; dbs->probes = 0; dbs->timer = RTcreateTimer (); //fset_clear (dbs); // mallocZero max_size = (size_t)fset_resize_names[0]; // avoid warning unused return dbs; }
void final_stat_reporting(vset_t visited) { RTprintTimer(info, reach_timer, "reachability took"); if (dlk_detect) Warning(info, "No deadlocks found"); if (act_detect != NULL) { Warning(info, "%d different actions with prefix \"%s\" are found", ErrorActions, act_detect); } long n_count; Print(infoShort, "counting visited states..."); rt_timer_t t = RTcreateTimer(); RTstartTimer(t); char states[128]; long double e_count; int digs = vset_count_fn(visited, &n_count, &e_count); snprintf(states, 128, "%.*Lg", digs, e_count); RTstopTimer(t); RTprintTimer(infoShort, t, "counting took"); RTresetTimer(t); int is_precise = strstr(states, "e") == NULL && strstr(states, "inf") == NULL; Print(infoShort, "state space has%s %s states, %ld nodes", precise && is_precise ? " precisely" : "", states, n_count); if (!is_precise && precise) { if (vdom_supports_precise_counting(domain)) { Print(infoShort, "counting visited states precisely..."); RTstartTimer(t); bn_int_t e_count; vset_count_precise(visited, n_count, &e_count); RTstopTimer(t); RTprintTimer(infoShort, t, "counting took"); size_t len = bn_strlen(&e_count); char e_str[len]; bn_int2string(e_str, len, &e_count); bn_clear(&e_count); Print(infoShort, "state space has precisely %s states (%zu digits)", e_str, strlen(e_str)); } else Warning(info, "vset implementation does not support precise counting"); } RTdeleteTimer(t); if (log_active (infoLong) || peak_nodes) { log_t l; if (peak_nodes) l = info; else l = infoLong; if (max_lev_count == 0) { Print(l, "( %ld final BDD nodes; %ld peak nodes )", n_count, max_vis_count); } else { Print(l, "( %ld final BDD nodes; %ld peak nodes; %ld peak nodes per level )", n_count, max_vis_count, max_lev_count); } if (log_active (debug)) { Debug("( peak transition cache: %ld nodes; peak group explored: " "%ld nodes )\n", max_trans_count, max_grp_count); } } }
int main (int argc, char **argv) { dlts_t lts; rt_timer_t timer; int oldN, oldM, tauN, tauM, N, M, i, j; char *files[2]; HREinitBegin(argv[0]); HREaddOptions(options,"Perform a distributed cycle elimination on the input.\n\nOptions"); lts_lib_setup(); HREselectMPI(); HREinitStart(&argc,&argv,1,2,files,"<input> [<output>]"); MPI_Comm_size (MPI_COMM_WORLD, &nodes); MPI_Comm_rank (MPI_COMM_WORLD, &me); timer = RTcreateTimer (); if (me == 0) Warning (info, "(tau)SCC elimination"); if (me == 0) RTstartTimer (timer); MPI_Barrier (MPI_COMM_WORLD); lts = dlts_read(MPI_COMM_WORLD,files[0]); oldN = lts->state_count[me]; oldM = 0; for (i = 0; i < lts->segment_count; i++) oldM += lts->transition_count[me][i]; MPI_Reduce (&oldN, &i, 1, MPI_INT, MPI_SUM, 0, lts->comm); MPI_Reduce (&oldM, &j, 1, MPI_INT, MPI_SUM, 0, lts->comm); if (me == 0) { oldN = i; oldM = j; Warning (info, "%d states and %d transitions", oldN, oldM); RTstopTimer (timer); RTprintTimer (info, timer, "***** reading the LTS took"); RTresetTimer (timer); RTstartTimer (timer); } MPI_Barrier (MPI_COMM_WORLD); switch (action) { case SCC_COLOR: dlts_elim_tauscc_colours (lts); break; case SCC_GROUP: if (!dlts_elim_tauscc_groups (lts)) { if (me == 0) Abort("cannot get it small enough!"); } MPI_Barrier (MPI_COMM_WORLD); break; default: if (me == 0) Abort("bad action %d", action); MPI_Barrier (MPI_COMM_WORLD); } MPI_Barrier (lts->comm); if (me == 0) { RTstopTimer (timer); RTprintTimer (info, timer, "***** SCC reduction took"); RTresetTimer (timer); RTstartTimer (timer); } // statistics... N = lts->state_count[me]; M = 0; for (i = 0; i < lts->segment_count; i++) M += lts->transition_count[me][i]; MPI_Reduce (&N, &i, 1, MPI_INT, MPI_SUM, 0, lts->comm); MPI_Reduce (&M, &j, 1, MPI_INT, MPI_SUM, 0, lts->comm); if (me == 0) { Warning (info, "LTS initial:%10d states and %10d transitions", oldN, oldM); Warning (info, "LTS reduced:%10d states [%3.3f] and %10d [%3.3f] transitions", i, 100 * i / (float)oldN, j, 100 * j / (float)oldM); } N = Nfinal + Nleft + Nhooked; M = Mfinal + Mhooked; MPI_Reduce (&N, &i, 1, MPI_INT, MPI_SUM, 0, lts->comm); MPI_Reduce (&M, &j, 1, MPI_INT, MPI_SUM, 0, lts->comm); tauN = i; tauM = j; N = Nfinal + Nleft; M = Mfinal; MPI_Reduce (&N, &i, 1, MPI_INT, MPI_SUM, 0, lts->comm); MPI_Reduce (&M, &j, 1, MPI_INT, MPI_SUM, 0, lts->comm); if (me == 0) { Warning (info, "TAU initial:%10d states [%3.3f] and %10d [%3.3f] transitions", tauN, 100 * tauN / (float)oldN, tauM, 100 * tauM / (float)oldM); Warning (info, "TAU reduced:%10d states [%3.3f] and %10d [%3.3f] transitions", i, 100 * i / (float)tauN, j, 100 * j / (float)tauM); } if (files[1]) { if (me == 0) Warning (info, "NOW WRITING"); dlts_writedir (lts, files[1]); } // if (lts != NULL) dlts_free(lts); HREexit(HRE_EXIT_SUCCESS); }
static void actual_main(void *arg) #endif { int argc = ((struct args_t*)arg)->argc; char **argv = ((struct args_t*)arg)->argv; /* initialize HRE */ HREinitBegin(argv[0]); HREaddOptions(options,"Perform a symbolic reachability analysis of <model>\n" "The optional output of this analysis is an ETF " "representation of the input\n\nOptions"); lts_lib_setup(); // add options for LTS library HREinitStart(&argc,&argv,1,2,files,"<model> [<etf>]"); /* initialize HRE on other workers */ init_hre(HREglobal()); /* check for unsupported options */ if (PINS_POR != PINS_POR_NONE) Abort("Partial-order reduction and symbolic model checking are not compatible."); if (inhibit_matrix != NULL && sat_strategy != NO_SAT) Abort("Maximal progress is incompatibale with saturation."); if (files[1] != NULL) { char *ext = strrchr(files[1], '.'); if (ext == NULL || ext == files[1]) { Abort("Output filename has no extension!"); } if (strcasecmp(ext, ".etf") != 0) { // not ETF if (!(vset_default_domain == VSET_Sylvan && strcasecmp(ext, ".bdd") == 0) && !(vset_default_domain == VSET_LDDmc && strcasecmp(ext, ".ldd") == 0)) { Abort("Only supported output formats are ETF, BDD (with --vset=sylvan) and LDD (with --vset=lddmc)"); } if (PINS_USE_GUARDS) { Abort("Exporting symbolic state space not comptabile with " "guard-splitting"); } } } #ifdef HAVE_SYLVAN if (!USE_PARALLELISM) { if (strategy == PAR_P) { strategy = BFS_P; Print(info, "Front-end not thread-safe; using --order=bfs-prev instead of --order=par-prev."); } else if (strategy == PAR) { strategy = BFS; Print(info, "Front-end not thread-safe; using --order=bfs instead of --order=par."); } } #endif /* turn off Lace for now to speed up while not using parallelism */ lace_suspend(); /* initialize the model and PINS wrappers */ init_model(files[0]); /* initialize action detection */ act_label = lts_type_find_edge_label_prefix (ltstype, LTSMIN_EDGE_TYPE_ACTION_PREFIX); if (act_label != -1) action_typeno = lts_type_get_edge_label_typeno(ltstype, act_label); if (act_detect != NULL) init_action_detection(); bitvector_create(&state_label_used, sLbls); if (inv_detect != NULL) init_invariant_detection(); else if (PINS_USE_GUARDS) { for (int i = 0; i < nGuards; i++) { bitvector_set(&state_label_used, i); } } init_maxsum(ltstype); /* turn on Lace again (for Sylvan) */ if (vset_default_domain==VSET_Sylvan || vset_default_domain==VSET_LDDmc) { lace_resume(); } if (next_union) vset_next_fn = vset_next_union_src; init_domain(VSET_IMPL_AUTOSELECT); vset_t initial = vset_create(domain, -1, NULL); int *src = RTmalloc (sizeof(int[N])); GBgetInitialState(model, src); vset_add(initial, src); Print(infoShort, "got initial state"); /* if writing .dot files, open directory first */ if (dot_dir != NULL) { DIR* dir = opendir(dot_dir); if (dir) { closedir(dir); } else if (ENOENT == errno) { Abort("Option 'dot-dir': directory '%s' does not exist", dot_dir); } else { Abort("Option 'dot-dir': failed opening directory '%s'", dot_dir); } } if (vset_dir != NULL) { DIR *dir = opendir(vset_dir); if (dir) { closedir(dir); } else if (errno == ENOENT) { Abort("Option 'save-levels': directory '%s' does not exist", vset_dir); } else { Abort("Option 'save-levels': failed opening directory '%s'", vset_dir); } } init_mu_calculus(); /* determine if we need to generate a symbolic parity game */ #ifdef LTSMIN_PBES bool spg = true; #else bool spg = GBhaveMucalc() ? true : false; #endif /* if spg, then initialize labeling stuff before reachability */ if (spg) { Print(infoShort, "Generating a Symbolic Parity Game (SPG)."); init_spg(model); } /* create timer */ reach_timer = RTcreateTimer(); /* fix level 0 */ visited = vset_create(domain, -1, NULL); vset_copy(visited, initial); /* check the invariants at level 0 */ check_invariants(visited, 0); /* run reachability */ run_reachability(visited, files[1]); /* report states */ final_stat_reporting(visited); /* save LTS */ if (files[1] != NULL) { char *ext = strrchr(files[1], '.'); if (strcasecmp(ext, ".etf") == 0) { do_output(files[1], visited); } else { // if not .etf, then the filename ends with .bdd or .ldd, symbolic LTS do_dd_output (initial, visited, files[1]); } } compute_maxsum(visited, domain); CHECK_MU(visited, src); if (max_mu_count > 0) { Print(info, "Mu-calculus peak nodes: %ld", max_mu_count); } /* optionally print counts of all group_next and group_explored sets */ final_final_stats_reporting (); if (spg) { // converting the LTS to a symbolic parity game, save and solve. lts_to_pg_solve (visited, src); } #ifdef HAVE_SYLVAN /* in case other Lace threads were still suspended... */ if (vset_default_domain!=VSET_Sylvan && vset_default_domain!=VSET_LDDmc) { lace_resume(); } else if (SYLVAN_STATS) { sylvan_stats_report(stderr); } #endif RTfree (src); GBExit(model); }