/** * remove and mark a completed SCC (pops the states from tarjan_stack) */ static void pop_scc (wctx_t *ctx, ref_t root, uint32_t root_low) { alg_local_t *loc = ctx->local; raw_data_t state_data; Debug ("Found SCC with root %zu", root); loc->cnt.scc_count++; // loop and remove states until tarjan_stack.top has lowlink < root_low state_data = dfs_stack_top (loc->tarjan_stack); while ( state_data != NULL ) { // check if state_data belongs to a different SCC state_info_deserialize (loc->target, state_data); if (loc->target_tarjan.lowlink < root_low) break; move_scc (ctx, loc->target->ref); dfs_stack_pop (loc->tarjan_stack); state_data = dfs_stack_top (loc->tarjan_stack); } // move the root of the SCC (since it is not on tarjan_stack) move_scc (ctx, root); }
/* NNDFS dfs_red */ void ndfs_red (wctx_t *ctx, ref_t seed) { alg_local_t *loc = ctx->local; loc->counters.accepting++; //count accepting states ndfs_explore_state_red (ctx); while ( !run_is_stopped(ctx->run) ) { raw_data_t state_data = dfs_stack_top (loc->stack); if (NULL != state_data) { state_info_deserialize (ctx->state, state_data); nndfs_color_t color = nn_get_color (&loc->color_map, ctx->state->ref); if ( nn_color_eq(color, NNBLUE) ) { nn_set_color (&loc->color_map, ctx->state->ref, NNPINK); ndfs_explore_state_red (ctx); loc->red_work.explored++; } else { if (seed == ctx->state->ref) break; dfs_stack_pop (loc->stack); } } else { //backtrack dfs_stack_leave (loc->stack); loc->red_work.level_cur--; state_data = dfs_stack_top (loc->stack); state_info_deserialize (ctx->state, state_data); /* exit search if backtrack hits seed, leave stack the way it was */ if (seed == ctx->state->ref) break; dfs_stack_pop (loc->stack); } } }
/* NDFS dfs_blue */ void ndfs_blue (run_t *run, wctx_t *ctx) { alg_local_t *loc = ctx->local; transition_info_t ti = GB_NO_TRANSITION; ndfs_blue_handle (ctx, ctx->initial, &ti, 0); ctx->counters->trans = 0; //reset trans count while ( !run_is_stopped(run) ) { raw_data_t state_data = dfs_stack_top (loc->stack); if (NULL != state_data) { state_info_deserialize (ctx->state, state_data); nndfs_color_t color = nn_get_color (&loc->color_map, ctx->state->ref); if ( nn_color_eq(color, NNWHITE) ) { if (all_red) bitvector_set ( &loc->stackbits, ctx->counters->level_cur ); nn_set_color (&loc->color_map, ctx->state->ref, NNCYAN); ndfs_explore_state_blue (ctx); } else { if ( all_red && ctx->counters->level_cur != 0 && !nn_color_eq(color, NNPINK) ) bitvector_unset ( &loc->stackbits, ctx->counters->level_cur - 1); dfs_stack_pop (loc->stack); } } else { //backtrack if (0 == dfs_stack_nframes (loc->stack)) return; dfs_stack_leave (loc->stack); ctx->counters->level_cur--; state_data = dfs_stack_top (loc->stack); state_info_deserialize (loc->seed, state_data); if ( all_red && bitvector_is_set(&loc->stackbits, ctx->counters->level_cur) ) { /* exit if backtrack hits seed, leave stack the way it was */ nn_set_color (&loc->color_map, loc->seed->ref, NNPINK); loc->counters.allred++; if ( GBbuchiIsAccepting(ctx->model, state_info_state(loc->seed)) ) loc->counters.accepting++; } else if ( GBbuchiIsAccepting(ctx->model, state_info_state(loc->seed)) ) { /* call red DFS for accepting states */ ndfs_red (ctx, loc->seed->ref); nn_set_color (&loc->color_map, loc->seed->ref, NNPINK); } else { if (all_red && ctx->counters->level_cur > 0) bitvector_unset (&loc->stackbits, ctx->counters->level_cur - 1); nn_set_color (&loc->color_map, loc->seed->ref, NNBLUE); } dfs_stack_pop (loc->stack); } } }
int main() { dfs_stack_t stack = dfs_stack_create (ARRAY_SIZE); size_t x; printf("Filling stack\n"); for (x = 0; x<NUM; x++) { int ar[ARRAY_SIZE]; ar[0] = x; ar[ARRAY_SIZE-1] = -x; dfs_stack_push(stack, ar); if (x%(NUM/FRAMES)==0) { printf("entered frame after: %zu - %zu\n", x, -x); dfs_stack_enter(stack); } } char tmp[256]; ssize_t tmpsz = sizeof tmp; printf("%s\n", dfs_stack_to_string(stack, tmp, &tmpsz)); for (x = 0; x<=FRAMES; x++) { int* ar = dfs_stack_peek_top(stack, x); printf("peek_top(%zu): %d - %d\n", x, ar[0], ar[ARRAY_SIZE-1]); } printf("Emptying stack stack\n"); for (x = 0; x<NUM; x++) { int* ar; if ((ar = dfs_stack_top(stack))==NULL) { dfs_stack_leave(stack); ar = dfs_stack_top(stack); printf("leave frame before: %d - %d\n", ar[0], ar[ARRAY_SIZE-1]); } ar = dfs_stack_pop(stack); } printf("DONE\n"); //pop(stack); dfs_stack_destroy(stack); return 0; }
void ta_dfs (wctx_t *ctx) { alg_shared_t *shared = ctx->run->shared; alg_global_t *sm = ctx->global; while (lb_balance(shared->lb, ctx->id, dfs_stack_size(sm->stack), split_dfs)) { raw_data_t state_data = dfs_stack_top (sm->stack); if (NULL != state_data) { if (grab_waiting(ctx, state_data)) { dfs_stack_enter (sm->stack); increase_level (ctx->counters); ta_explore_state (ctx); } else { dfs_stack_pop (sm->stack); } } else { if (0 == dfs_stack_size (sm->stack)) continue; dfs_stack_leave (sm->stack); ctx->counters->level_cur--; dfs_stack_pop (sm->stack); } } }
void tarjan_run (run_t *run, wctx_t *ctx) { alg_local_t *loc = ctx->local; raw_data_t *addr; raw_data_t state_data; bool on_stack; hash32_t hash; #ifdef HAVE_PROFILER Warning (info, "Using the profiler"); ProfilerStart ("tarjan.perf"); #endif #ifdef SEARCH_COMPLETE_GRAPH int init_state = dlopen_get_worker_initial_state (ctx->id, W); int inits = 0; // loop until every state of the graph has been visited while ( 1 ) { inits ++; // use loc->target as a dummy for the initial state loc->target->ref = init_state; #endif tarjan_init (ctx); // continue until we are done exploring the graph while ( !run_is_stopped (run) ) { state_data = dfs_stack_top (loc->search_stack); if (state_data != NULL) { // there is a state on the current stackframe ==> explore it state_info_deserialize (ctx->state, state_data); // pop the state and continue if it is part of a completed SCC if (state_store_has_color (ctx->state->ref, SCC_STATE, 0)) { dfs_stack_pop (loc->search_stack); continue; } hash = ref_hash (ctx->state->ref); on_stack = fset_find (loc->visited_states, &hash, &ctx->state->ref, (void **) &addr, true); if (!on_stack) { // unseen state ==> initialize and explore HREassert (loc->cnt.tarjan_counter != UINT32_MAX); loc->cnt.tarjan_counter ++; loc->state_tarjan.index = loc->cnt.tarjan_counter; loc->state_tarjan.lowlink = loc->cnt.tarjan_counter; // point visited_states data to stack *addr = state_data; explore_state (ctx); state_info_serialize (ctx->state, state_data); } else { // previously visited state ==> update parent // NB: state is on tarjan_stack state_info_deserialize (ctx->state, *addr); update_parent (ctx, loc->state_tarjan.lowlink); dfs_stack_pop (loc->search_stack); } } else { // there is no state on the current stackframe ==> backtrack // we are done if we backtrack from the initial state if (0 == dfs_stack_nframes (loc->search_stack)) break; // leave the stackframe dfs_stack_leave (loc->search_stack); ctx->counters->level_cur--; // retrieve the parent state from search_stack (to be removed) state_data = dfs_stack_top (loc->search_stack); state_info_deserialize (ctx->state, state_data); Debug ("Backtracking %zu (%d, %d)", ctx->state->ref, loc->state_tarjan.index, loc->state_tarjan.lowlink); if (loc->state_tarjan.index == loc->state_tarjan.lowlink) { // index == lowlink ==> root of the SCC ==> report the SCC pop_scc (ctx, ctx->state->ref, loc->state_tarjan.lowlink); } else { // lowlink < index ==> LIVE SCC ==> move to tarjan_stack move_tarjan (ctx, ctx->state, state_data); update_parent (ctx, loc->state_tarjan.lowlink); } dfs_stack_pop (loc->search_stack); } } #ifdef SEARCH_COMPLETE_GRAPH init_state = dlopen_get_new_initial_state (init_state); if (init_state == -1) { Warning(info, "Number of inits : %d", inits); break; } } #endif #ifdef HAVE_PROFILER Warning(info, "Done profiling"); ProfilerStop(); #endif if (!run_is_stopped(run) && dfs_stack_size(loc->tarjan_stack) != 0) Warning (info, "Tarjan stack not empty: %zu (stack %zu)", dfs_stack_size(loc->tarjan_stack), dfs_stack_size(loc->search_stack)); if (!run_is_stopped(run) && fset_count(loc->visited_states) != 0) Warning (info, "Stack-set not empty: %zu", fset_count(loc->visited_states)); }
/* ENDFS dfs_blue */ void endfs_blue (run_t *run, wctx_t *ctx) { HREassert (ecd, "CNDFS's correctness depends crucially on ECD"); alg_local_t *loc = ctx->local; cndfs_alg_local_t *cloc = (cndfs_alg_local_t *) ctx->local; transition_info_t ti = GB_NO_TRANSITION; uint32_t global_color; int accepting; cloc->successors = NONEC; endfs_handle_blue (ctx, ctx->initial, &ti, 0); ctx->counters->trans = 0; //reset trans count cloc->accepting_depth = 0; alg_global_t *sm = ctx->global; while ( !run_is_stopped(ctx->run) ) { raw_data_t state_data = dfs_stack_top (loc->stack); if (NULL != state_data) { state_info_deserialize (ctx->state, state_data); global_color = state_store_get_colors (ctx->state->ref); if (global_color < CBLUE && !on_stack_accepting_up(ctx, &accepting)) { if (global_color == CWHITE) update_color (ctx, ctx->state->ref, CCYAN, 0); if (all_red) bitvector_set (&loc->stackbits, cur(ctx,REDALL)); bitvector_unset (&loc->stackbits, cur(ctx,INVOL)); endfs_explore_state_blue (ctx); } else { if ( all_red && ctx->counters->level_cur != 0 && global_color != CRED ) bitvector_unset (&loc->stackbits, pred(ctx,REDALL)); dfs_stack_pop (loc->stack); } } else { //backtrack if (0 == dfs_stack_nframes(loc->stack)) break; dfs_stack_leave (loc->stack); ctx->counters->level_cur--; /* call red DFS for accepting states */ state_data = dfs_stack_top (loc->stack); state_info_deserialize (loc->seed, state_data); if (check_cndfs_proviso(ctx)) { reach_explore_all (ctx, loc->seed); continue; } accepting = pins_state_is_accepting(ctx->model, state_info_state(loc->seed)) != 0; /* Mark state GGREEN on backtrack */ update_color (ctx, loc->seed->ref, CBLUE, 1); if ( all_red && bitvector_is_set(&loc->stackbits, cur(ctx,REDALL)) ) { /* all successors are red */ //permute_trans (loc->permute, ctx->state, check, ctx); set_all_red2 (ctx, loc->seed); } else if ( accepting ) { sm->work = loc->seed->ref; endfs_red (ctx); if (Strat_ENDFS == loc->strat) endfs_handle_dangerous (ctx); else cndfs_handle_nonseed_accepting (ctx); sm->work = SIZE_MAX; } else if (all_red && ctx->counters->level_cur > 0 && state_store_get_colors (loc->seed->ref) != CRED) { /* unset the all-red flag (only for non-initial nodes) */ bitvector_unset (&loc->stackbits, pred(ctx,REDALL)); } accepting_down (ctx, loc->seed, accepting); dfs_stack_pop (loc->stack); } } HREassert (run_is_stopped(ctx->run) || fset_count(cloc->pink) == 0); // if the recursive strategy uses global bits (global pruning) // then do simple load balancing (only for the top-level strategy) if ( Strat_ENDFS == loc->strat && run == run->shared->top_level && (Strat_LTLG & sm->rec->local->strat) ) { endfs_lb (ctx); } if (global->exit_status == LTSMIN_EXIT_SUCCESS && ctx->id == 0) { Warning(info," "); Warning(info,"Empty product with LTL!"); Warning(info," "); } }
/* ENDFS dfs_red */ static void endfs_red (wctx_t *ctx) { alg_local_t *loc = ctx->local; cndfs_alg_local_t *cloc = (cndfs_alg_local_t *) ctx->local; size_t seed_level = dfs_stack_nframes (loc->stack); int accepting = 0; int on_stack; size_t count = fset_count(cloc->pink); size_t *level; while ( !run_is_stopped(ctx->run) ) { raw_data_t state_data = dfs_stack_top (loc->stack); if (NULL != state_data) { state_info_deserialize (ctx->state, state_data); // seed is only state on both cyan and pink stack on_stack = ctx->state->ref == loc->seed->ref; if (!on_stack) { on_stack = fset_find (cloc->pink, NULL, &ctx->state->ref, (void**)&level, false); HREassert (on_stack != FSET_FULL); } if (!on_stack && state_store_get_colors(ctx->state->ref) != CRED) { on_stack_accepting_up (ctx, &accepting); //add to stack bitvector_unset (&loc->stackbits, cur(ctx,INVOL)); dfs_stack_push (cloc->in_stack, state_data); if ( Strat_CNDFS == loc->strat && ctx->state->ref != loc->seed->ref && accepting) dfs_stack_push (cloc->out_stack, state_data); endfs_explore_state_red (ctx); } else { if (seed_level == dfs_stack_nframes (loc->stack)) break; dfs_stack_pop (loc->stack); } } else { //backtrack dfs_stack_leave (loc->stack); ctx->counters->level_cur--; /* exit search if backtrack hits seed, leave stack the way it was */ if (seed_level == dfs_stack_nframes(loc->stack)) break; state_data = dfs_stack_top (loc->stack); state_info_deserialize (ctx->state, state_data); if (check_cndfs_proviso(ctx)) { reach_explore_all (ctx, ctx->state); continue; } accepting = pins_state_is_accepting (ctx->model, state_info_state(ctx->state)) != 0; accepting_down (ctx, ctx->state, accepting); dfs_stack_pop (loc->stack); } } if (!run_is_stopped(ctx->run)) { HREassert (fset_count(cloc->pink) == count); } }