예제 #1
0
파일: sat.c 프로젝트: Meijuh/ltsmin
void
reach_sat_loop(reach_proc_t reach_proc, vset_t visited,
               bitvector_t *reach_groups, long *eg_count, long *next_count, long *guard_count)
{
    bitvector_t groups[max_sat_levels];
    int empty_groups[max_sat_levels];
    vset_t old_vis = vset_create(domain, -1, NULL);
    vset_t prev_vis[nGrps];

    for (int k = 0; k < max_sat_levels; k++)
        bitvector_create(&groups[k], nGrps);

    initialize_levels(groups, empty_groups, NULL, reach_groups);

    for (int i = 0; i < max_sat_levels; i++)
        prev_vis[i] = save_sat_levels?vset_create(domain, -1, NULL):NULL;

    while (!vset_equal(old_vis, visited)) {
        vset_copy(old_vis, visited);
        for (int k = 0; k < max_sat_levels; k++) {
            if (empty_groups[k]) continue;
            Warning(infoLong, "Saturating level: %d", k);
            reach_proc(visited, prev_vis[k], &groups[k], eg_count, next_count,guard_count);
            check_invariants(visited, -1);
            if (save_sat_levels) vset_copy(prev_vis[k], visited);
        }
    }

    for (int k = 0; k < max_sat_levels; k++)
        bitvector_free(&groups[k]);

    vset_destroy(old_vis);
    if (save_sat_levels)
        for (int i = 0; i < max_sat_levels; i++) vset_destroy(prev_vis[i]);
}
예제 #2
0
파일: sat.c 프로젝트: Meijuh/ltsmin
void
reach_sat_fix(reach_proc_t reach_proc, vset_t visited,
              bitvector_t *reach_groups, long *eg_count, long *next_count, long *guard_count)
{
    (void) reach_proc;
    (void) guard_count;

    if (PINS_USE_GUARDS)
        Abort("guard-splitting not supported with saturation=sat-fix");

    int level = 0;
    vset_t old_vis = vset_create(domain, -1, NULL);
    vset_t deadlocks = dlk_detect?vset_create(domain, -1, NULL):NULL;
    vset_t dlk_temp = dlk_detect?vset_create(domain, -1, NULL):NULL;

    LACE_ME;
    while (!vset_equal(visited, old_vis)) {
        if (trc_output != NULL) save_level(visited);
        vset_copy(old_vis, visited);
        stats_and_progress_report(NULL, visited, level);
        level++;
        for(int i = 0; i < nGrps; i++){
            if (!bitvector_is_set(reach_groups, i)) continue;
            expand_group_next(i, visited);
            reach_chain_stop();
            (*eg_count)++;
        }
        if (dlk_detect) vset_copy(deadlocks, visited);
        if (USE_PARALLELISM) vset_least_fixpoint_par(visited, visited, group_next, nGrps);
        else vset_least_fixpoint(visited, visited, group_next, nGrps);
        (*next_count)++;
        check_invariants(visited, level);
        if (dlk_detect) {
            for (int i = 0; i < nGrps; i++) {
                vset_prev(dlk_temp, visited, group_next[i],deadlocks);
                reduce(i, dlk_temp);
                vset_minus(deadlocks, dlk_temp);
                vset_clear(dlk_temp);
            }
            deadlock_check(deadlocks, reach_groups);
        }
        vset_reorder(domain);
    }

    vset_destroy(old_vis);
    if (dlk_detect) {
        vset_destroy(deadlocks);
        vset_destroy(dlk_temp);
    }
}
예제 #3
0
파일: sat.c 프로젝트: Meijuh/ltsmin
void
reach_sat(reach_proc_t reach_proc, vset_t visited,
          bitvector_t *reach_groups, long *eg_count, long *next_count, long *guard_count)
{
    (void) reach_proc;
    (void) next_count;
    (void) guard_count;

    if (PINS_USE_GUARDS)
        Abort("guard-splitting not supported with saturation=sat");

    if (act_detect != NULL && trc_output != NULL)
        Abort("Action detection with trace generation not supported");

    for (int i = 0; i < nGrps; i++) {
        if (bitvector_is_set(reach_groups, i)) {
            struct expand_info *ctx = RTmalloc(sizeof(struct expand_info));
            ctx->group = i;
            ctx->group_explored = group_explored[i];
            ctx->eg_count = eg_count;

            vrel_set_expand(group_next[i], expand_group_next_projected, ctx);
        }
    }

    if (trc_output != NULL) save_level(visited);
    stats_and_progress_report(NULL, visited, 0);
    if (USE_PARALLELISM) vset_least_fixpoint_par(visited, visited, group_next, nGrps);
    else vset_least_fixpoint(visited, visited, group_next, nGrps);
    stats_and_progress_report(NULL, visited, 1);

    check_invariants(visited, -1);

    if (dlk_detect) {
        vset_t deadlocks = vset_create(domain, -1, NULL);
        vset_t dlk_temp = vset_create(domain, -1, NULL);
        vset_copy(deadlocks, visited);
        for (int i = 0; i < nGrps; i++) {
            vset_prev(dlk_temp, visited, group_next[i],deadlocks);
            reduce(i, dlk_temp);
            vset_minus(deadlocks, dlk_temp);
            vset_clear(dlk_temp);
        }
        deadlock_check(deadlocks, reach_groups);
        vset_destroy(deadlocks);
        vset_destroy(dlk_temp);
    }
}
예제 #4
0
/**
 * \brief Adds level for player to strategy.
 */
void update_strategy_levels(recursive_result* result, int player, vset_t level)
{
    if (result->strategy_levels_count[player]==result->strategy_levels_max[player]) {
        result->strategy_levels_max[player] += INIT_STRATEGY_MAX;
        result->strategy_levels[player] = RTrealloc(result->strategy_levels[player], (result->strategy_levels_max[player])*sizeof(vset_t));
    }
    result->strategy_levels[player][result->strategy_levels_count[player]] = vset_create(result->dom, -1, NULL);
    vset_copy(result->strategy_levels[player][result->strategy_levels_count[player]], level);
    //printf("update_strategy_levels: player=%d, index=%d.\n", player, result->strategy_levels_count[player]);
    result->strategy_levels_count[player]++;
    result->strategy_boundaries[player][result->strategy_boundary_count[player]-1]++;
    //printf("update_strategy_levels: levels_count=%d, boundary[boundary_count-1=%d]=%d.\n",
    //       result->strategy_levels_count[player], result->strategy_boundary_count[player]-1,
    //       result->strategy_boundaries[player][result->strategy_boundary_count[player]-1]);
    assert(result->strategy_boundaries[player][result->strategy_boundary_count[player]-1] == result->strategy_levels_count[player]);
}
예제 #5
0
/**
 * \brief Creates an empty result.
 */
recursive_result recursive_result_create(vdom_t dom)
{
    recursive_result result;
    result.dom = dom;
    for(int p=0; p < 2; p++) {
        result.win[p] = vset_create(dom, -1, NULL);

        /* for storing strategy as sequence of level sets: */
        result.strategy_levels_max[p] = INIT_STRATEGY_MAX; // max number of sets per player
        result.strategy_levels_count[p] = 0; // number of sets per player
        result.strategy_levels[p] = RTmalloc((result.strategy_levels_max[p])*sizeof(vset_t)); // level sets, computed by the attractor
        result.strategy_boundary_count[p] = 1;
        result.strategy_boundaries[p] = RTmalloc(INIT_STRATEGY_MAX*sizeof(int)); // boundaries between separate attractor computations
        result.strategy_boundaries[p][0] = 0;
    }
    return result;
}
예제 #6
0
파일: pg.c 프로젝트: Meijuh/ltsmin
/**
 * \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);
}
예제 #7
0
파일: output.c 프로젝트: alaarman/ltsmin
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");
}
예제 #8
0
파일: output.c 프로젝트: alaarman/ltsmin
static void
output_lbls(FILE *tbl_file, vset_t visited)
{
    matrix_t *sl_info = GBgetStateLabelInfo(model);

    nGuards = dm_nrows(sl_info);

    if (dm_nrows(sl_info) != lts_type_get_state_label_count(ltstype))
        Warning(error, "State label count mismatch!");

    for (int i = 0; i < nGuards; i++){
        int len = dm_ones_in_row(sl_info, i);
        int used[len];

        // get projection
        for (int pi = 0, pk = 0; pi < dm_ncols (sl_info); pi++) {
            if (dm_is_set (sl_info, i, pi))
                used[pk++] = pi;
        }

        vset_t patterns = vset_create(domain, len, used);
        map_context ctx;

        vset_project(patterns, visited);
        ctx.tbl_file = tbl_file;
        ctx.mapno = i;
        ctx.len = len;
        ctx.used = used;
        fprintf(tbl_file, "begin map ");
        fprint_ltsmin_ident(tbl_file, lts_type_get_state_label_name(ltstype,i));
        fprintf(tbl_file, ":");
        fprint_ltsmin_ident(tbl_file, lts_type_get_state_label_type(ltstype,i));
        fprintf(tbl_file,"\n");
        vset_enum(patterns, enum_map, &ctx);
        fprintf(tbl_file, "end map\n");
        vset_destroy(patterns);
    }
}
예제 #9
0
/**
 * \brief Combines strategy levels for player.
 */
void
concat_strategy_levels_player (int player, vdom_t domain, vset_t** dst,
                               int* dst_count, int** dst_boundaries,
                               int* dst_boundary_count, vset_t** src,
                               int* src_count, int** src_boundaries,
                               int* src_boundary_count)
{
    //printf("concat_strategy_levels: player=%d, dst_count=%d, src_count=%d, dst_boundary_count=%d, src_boundary_count=%d.\n",
    //       player, dst_count[player], src_count[player], dst_boundary_count[player], src_boundary_count[player]);
    dst[player] = RTrealloc(dst[player], (dst_count[player]+src_count[player])*sizeof(vset_t));
    for (int i = 0; i < src_count[player]; i++) {
        dst[player][dst_count[player] + i] = vset_create(domain, -1, NULL);
        vset_copy(dst[player][dst_count[player] + i], src[player][i]);
    }
    dst_boundaries[player] = RTrealloc(dst_boundaries[player], (dst_boundary_count[player]+src_boundary_count[player])*sizeof(int));
    for (int i = 0; i < src_boundary_count[player]; i++) {
        dst_boundaries[player][dst_boundary_count[player]+i] = src_boundaries[player][i] + dst_count[player];
    }
    dst_count[player] += src_count[player];
    dst_boundary_count[player] += src_boundary_count[player];
    //printf("concat_strategy_levels: player=%d, dst_count=%d, dst_boundary_count=%d.\n",
    //       player, dst_count[player], dst_boundary_count[player]);
}
예제 #10
0
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;
}
예제 #11
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");
            vset_random(level, dst);
        }
    }
    return group;
}
예제 #12
0
파일: pg.c 프로젝트: Meijuh/ltsmin
/**
 * \brief Initialises the data structures for generating symbolic parity games.
 */
void
init_spg(model_t model)
{
    lts_type_t type = GBgetLTStype(model);
    var_pos = 0;
    var_type_no = 0;
    for(int i=0; i<N; i++)
    {
        //Printf(infoLong, "%d: %s (%d [%s])\n", i, lts_type_get_state_name(type, i), lts_type_get_state_typeno(type, i), lts_type_get_state_type(type, i));
#ifdef LTSMIN_PBES
        char* str1 = "string"; // for the PBES language module
#else
        char* str1 = "mu"; // for the mu-calculus PINS layer
#endif
        size_t strlen1 = strlen(str1);
        char* str2 = lts_type_get_state_type(type, i);
        size_t strlen2 = strlen(str2);
        if (strlen1==strlen2 && strncmp(str1, str2, strlen1)==0)
        {
            var_pos = i;
            var_type_no = lts_type_get_state_typeno(type, i);
            if (GBhaveMucalc()) {
                true_index = 0; // enforced by mucalc parser (mucalc-grammar.lemon / mucalc-syntax.c)
                false_index = 1;
            } else { // required for the PBES language module.
                true_index = pins_chunk_put (model, var_type_no, chunk_str("true"));
                false_index = pins_chunk_put (model, var_type_no, chunk_str("false"));
            }
        }
    }
    int p_len = 1;
    int proj[1] = {var_pos}; // position 0 encodes the variable
    variable_projection = vproj_create(domain, p_len, proj);

    num_vars = pins_chunk_count (model, var_type_no); // number of propositional variables
    if (GBhaveMucalc()) {
        num_vars = GBgetMucalcNodeCount(); // number of mu-calculus subformulae
    }
    Print(infoLong, "init_spg: var_type_no=%d, num_vars=%zu", var_type_no, num_vars);
    priority = RTmalloc(num_vars * sizeof(int)); // priority of variables
    player = RTmalloc(num_vars * sizeof(int)); // player of variables
    for(size_t i=0; i<num_vars; i++)
    {
        lts_type_t type = GBgetLTStype(model);
        int state_length = lts_type_get_state_length(type);
        // create dummy state with variable i:
        int state[state_length];
        for(int j=0; j < state_length; j++)
        {
            state[j] = 0;
        }
        state[var_pos] = i;
        int label = GBgetStateLabelLong(model, PG_PRIORITY, state); // priority
        priority[i] = label;
        if (label < min_priority) {
            min_priority = label;
        }
        if (label > max_priority) {
            max_priority = label;
        }
        //Print(infoLong, "  label %d (priority): %d", 0, label);
        label = GBgetStateLabelLong(model, PG_PLAYER, state); // player
        player[i] = label;
        //Print(infoLong, "  label %d (player): %d", 1, label);
    }
    true_states = vset_create(domain, -1, NULL);
    false_states = vset_create(domain, -1, NULL);
}
예제 #13
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);
}
예제 #14
0
static void
init_domain(vset_implementation_t impl) {
    domain = vdom_create_domain(N, impl);

    for (int i = 0; i < dm_ncols(GBgetDMInfo(model)); i++) {
        vdom_set_name(domain, i, lts_type_get_state_name(ltstype, i));
    }

    group_next     = (vrel_t*)RTmalloc(nGrps * sizeof(vrel_t));
    group_explored = (vset_t*)RTmalloc(nGrps * sizeof(vset_t));
    group_tmp      = (vset_t*)RTmalloc(nGrps * sizeof(vset_t));
    r_projs        = (ci_list **)RTmalloc(sizeof(ci_list *[nGrps]));
    w_projs        = (ci_list **)RTmalloc(sizeof(ci_list *[nGrps]));

    l_projs        = (ci_list **)RTmalloc(sizeof(ci_list *[sLbls]));
    label_false    = (vset_t*)RTmalloc(sLbls * sizeof(vset_t));
    label_true     = (vset_t*)RTmalloc(sLbls * sizeof(vset_t));
    label_tmp      = (vset_t*)RTmalloc(sLbls * sizeof(vset_t));

    if (!vdom_separates_rw(domain) && !PINS_USE_GUARDS) {
        read_matrix = GBgetDMInfo(model);
        write_matrix = GBgetDMInfo(model);
        Warning(info, "Using GBgetTransitionsShort as next-state function");
        transitions_short = GBgetTransitionsShort;
    } else if (!vdom_separates_rw(domain) && PINS_USE_GUARDS) {
        read_matrix = GBgetMatrix(model, GBgetMatrixID(model, LTSMIN_MATRIX_ACTIONS_READS));
        write_matrix = GBgetDMInfo(model);
        Warning(info, "Using GBgetActionsShort as next-state function");
        transitions_short = GBgetActionsShort;
    } else if (vdom_separates_rw(domain) && !PINS_USE_GUARDS) {
        read_matrix = GBgetDMInfoRead(model);
        write_matrix = GBgetDMInfoMayWrite(model);
        Warning(info, "Using GBgetTransitionsShortR2W as next-state function");
        transitions_short = GBgetTransitionsShortR2W;
    } else { // vdom_separates_rw(domain) && PINS_USE_GUARDS
        read_matrix = GBgetMatrix(model, GBgetMatrixID(model, LTSMIN_MATRIX_ACTIONS_READS));
        write_matrix = GBgetDMInfoMayWrite(model);
        Warning(info, "Using GBgetActionsShortR2W as next-state function");
        transitions_short = GBgetActionsShortR2W;
    }

    if (PINS_USE_GUARDS) {
        if (no_soundness_check) {
            Warning(info, "Guard-splitting: not checking soundness of the specification, this may result in an incorrect state space!");
        } else {
            Warning(info, "Guard-splitting: checking soundness of specification, this may be slow!");
        }
    }

    r_projs = (ci_list **) dm_rows_to_idx_table (read_matrix);
    w_projs = (ci_list **) dm_rows_to_idx_table (write_matrix);
    for(int i = 0; i < nGrps; i++) {

        if (HREme(HREglobal())==0)
        {
            if (vdom_separates_rw(domain)) {
                group_next[i] = vrel_create_rw (domain, r_projs[i]->count, r_projs[i]->data, w_projs[i]->count, w_projs[i]->data);
            } else {
                group_next[i] = vrel_create (domain, r_projs[i]->count, r_projs[i]->data);
            }

            group_explored[i] = vset_create (domain, r_projs[i]->count, r_projs[i]->data);
            group_tmp[i]      = vset_create (domain, r_projs[i]->count, r_projs[i]->data);

            if (inhibit_matrix != NULL) {
                inhibit_class_count = dm_nrows(inhibit_matrix);
                class_enabled = (vset_t*)RTmalloc(inhibit_class_count * sizeof(vset_t));
                for(int i=0; i<inhibit_class_count; i++) {
                    class_enabled[i] = vset_create(domain, -1, NULL);
                }
            }
        }
    }

    l_projs = (ci_list **) dm_rows_to_idx_table (GBgetStateLabelInfo(model));
    for (int i = 0; i < sLbls; i++) {

        /* Indeed, we skip unused state labels, but allocate memory for pointers
         * (to vset_t's). Is this bad? Maybe a hashmap is worse. */
        if (bitvector_is_set(&state_label_used, i)) {

            if (HREme(HREglobal()) == 0) {
                label_false[i]  = vset_create(domain, l_projs[i]->count, l_projs[i]->data);
                label_true[i]   = vset_create(domain, l_projs[i]->count, l_projs[i]->data);
                label_tmp[i]    = vset_create(domain, l_projs[i]->count, l_projs[i]->data);
            }
        } else {
            label_false[i]  = NULL;
            label_true[i]   = NULL;
            label_tmp[i]    = NULL;
        }
    }

    inv_set = (vset_t *) RTmalloc(sizeof(vset_t[num_inv]));
    for (int i = 0; i < num_inv; i++) {
        inv_set[i] = vset_create (domain, inv_proj[i]->count, inv_proj[i]->data);
        inv_info_prepare (inv_expr[i], inv_parse_env[i], i);
    }
}