void ndfs_blue_handle (void *arg, state_info_t *successor, transition_info_t *ti, int seen) { wctx_t *ctx = (wctx_t *) arg; alg_local_t *loc = ctx->local; nndfs_color_t color = nn_get_color (&loc->color_map, successor->ref); if (proviso == Proviso_Stack) ti->por_proviso = !nn_color_eq(color, NNCYAN); /** * The following lines bear little resemblance to the algorithms in the * respective papers (NNDFS / LNDFS), but we must store all non-red states * on the stack here, in order to calculate all-red correctly later. */ if ( ecd && nn_color_eq(color, NNCYAN) && (GBbuchiIsAccepting(ctx->model, state_info_state(ctx->state)) || GBbuchiIsAccepting(ctx->model, state_info_state(successor))) ) { /* Found cycle in blue search */ ndfs_report_cycle (ctx->run, ctx->model, loc->stack, successor); } else if ((loc->strat == Strat_LNDFS && !state_store_has_color(ctx->state->ref, GRED, loc->rec_bits)) || (loc->strat != Strat_LNDFS && !nn_color_eq(color, NNPINK))) { raw_data_t stack_loc = dfs_stack_push (loc->stack, NULL); state_info_serialize (successor, stack_loc); } (void) ti; (void) seen; }
/* 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); } } }
static inline void set_all_red2 (wctx_t *ctx, state_info_t *state) { if (update_color(ctx, state->ref, CRED, 1)) { ctx->local->counters.allred++; if ( pins_state_is_accepting(ctx->model, state_info_state(state)) ) ctx->local->counters.accepting++; /* count accepting states */ } else { ctx->local->red.allred++; } }
static inline int on_stack_accepting_up (wctx_t *ctx, int *accepting) { cndfs_alg_local_t *cloc = (cndfs_alg_local_t *) ctx->local; size_t *depth; int on_stack; on_stack = fset_find (cloc->pink, NULL, &ctx->state->ref, (void**)&depth, true); HREassert (on_stack != FSET_FULL); if (!on_stack) { *accepting = pins_state_is_accepting(ctx->model, state_info_state(ctx->state)) != 0; Debug ("Added state %zu %s with depth %zu accepting depth", ctx->state->ref, (*accepting ? "(accepting)" : ""), cloc->accepting_depth); *depth = cloc->accepting_depth; // write currect accepting depth cloc->accepting_depth += *accepting; } return on_stack; }
static void ta_handle (void *arg, state_info_t *successor, transition_info_t *ti, int seen) { wctx_t *ctx = (wctx_t*) arg; ta_alg_shared_t *shared = (ta_alg_shared_t *) ctx->run->shared; alg_local_t *loc = ctx->local; ta_alg_local_t *ta_loc = (ta_alg_local_t *) ctx->local; ta_alg_global_t *sm = (ta_alg_global_t *) ctx->global; ta_loc->done = 0; ta_loc->subsumes = 0; // if a successor subsumes one in the set, it cannot be subsumed itself (see invariant paper) ta_loc->work = 0; ta_loc->added_at = LM_NULL_LOC; ta_loc->last = LM_NULL_LOC; ta_loc->successor = successor; lm_lock (shared->lmap, successor->ref); lm_loc_t last = lm_iterate (shared->lmap, successor->ref, ta_covered, ctx); if (!ta_loc->done) { last = (LM_NULL_LOC == ta_loc->last ? last : ta_loc->last); sm->lloc = lm_insert_from (shared->lmap, successor->ref, successor->lattice, TA_WAITING, &last); lm_unlock (shared->lmap, successor->ref); ta_loc->counters.inserts++; if (0) { // quite costly: flops if (ta_loc->work > 0) statistics_unrecord (&ta_loc->counters.lattice_ratio, ta_loc->work); statistics_record (&ta_loc->counters.lattice_ratio, ta_loc->work+1); } ta_queue_state (ctx, successor); ta_loc->counters.updates += LM_NULL_LOC != ta_loc->last; loc->counters.level_size++; } else { lm_unlock (shared->lmap, successor->ref); } action_detect (ctx, ti, successor); if (EXPECT_FALSE(loc->lts != NULL)) { int src = ctx->counters->explored; int *tgt = state_info_state (successor); int tgt_owner = ref_hash (successor->ref) % W; lts_write_edge (loc->lts, ctx->id, &src, tgt_owner, tgt, ti->labels); } ctx->counters->trans++; (void) seen; }
static void endfs_handle_red (void *arg, state_info_t *successor, transition_info_t *ti, int seen) { wctx_t *ctx = (wctx_t *) arg; alg_local_t *loc = ctx->local; cndfs_alg_local_t *cloc = (cndfs_alg_local_t *) ctx->local; int onstack; /* Find cycle back to the seed */ HREassert (cloc->accepting_depth > 0); size_t *level; onstack = ctx->state->ref == loc->seed->ref; if (!onstack) { onstack = fset_find (cloc->pink, NULL, &successor->ref, (void**)&level, false); HREassert (onstack != FSET_FULL); } if ( onstack && *level < cloc->accepting_depth ) ndfs_report_cycle (ctx, ctx->model, loc->stack, successor); /* Mark states dangerous if necessary */ if ( Strat_ENDFS == loc->strat && pins_state_is_accepting(ctx->model, state_info_state(successor)) && state_store_get_colors (successor->ref) != CRED ) state_store_try_color(successor->ref, GDANGEROUS, loc->rec_bits); if ( !onstack && state_store_get_colors (successor->ref) != CRED ) { raw_data_t stack_loc = dfs_stack_push (loc->stack, NULL); state_info_serialize (successor, stack_loc); } // check proviso if (PINS_POR && proviso == Proviso_CNDFS && cloc->successors == NONEC) { if (ti->por_proviso != 0) { // state already fully expanded cloc->successors = SRCINV; } else if (onstack) { // cycle check if (onstack) cloc->successors = CYCLE; } // avoid full exploration (proviso is enforced later in backtrack) ti->por_proviso = 1; // avoid full exploration } (void) seen; }
void timed_run (run_t *run, wctx_t *ctx) { transition_info_t ti = GB_NO_TRANSITION; if ( Strat_PBFS & strategy[0] ) { ta_queue_state = pbfs_queue_state; } if (0 == ctx->id) { // only w1 receives load, as it is propagated later if ( Strat_PBFS & strategy[0] ) { if (ctx->local->lts != NULL) { state_data_t initial = state_info_state(ctx->initial); int src_owner = ref_hash(ctx->initial->ref) % W; lts_write_init (ctx->local->lts, src_owner, initial); } } ta_handle (ctx, ctx->initial, &ti, 0); ctx->counters->trans = 0; //reset trans count } HREbarrier (HREglobal()); switch (get_strategy(run->alg)) { case Strat_TA_PBFS: ta_pbfs (ctx); break; case Strat_TA_SBFS: ta_sbfs (ctx); break; case Strat_TA_BFS: ta_bfs (ctx); break; case Strat_TA_DFS: ta_dfs (ctx); break; default: Abort ("Missing case in timed_run"); } }
/* 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); } }