Beispiel #1
0
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);
    }
}
Beispiel #2
0
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);
}
Beispiel #3
0
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;
}
Beispiel #4
0
/**
 * \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;
}
Beispiel #5
0
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");
}
Beispiel #6
0
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;
}
Beispiel #7
0
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);
        }
    }
}
Beispiel #8
0
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);
}
Beispiel #9
0
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);
}