stats: add a variant for twa_graph_ptr
This is faster than using the abstract interface, and it also supports alternating automata. (This will be tested in the tests for ltlcross's support for alternating automata.) * spot/twaalgos/stats.cc (stats_reachable, sub_stats_reachable): Add code specific to twa_graph_ptr.
This commit is contained in:
parent
64fa6c0026
commit
543e0db9a0
1 changed files with 74 additions and 4 deletions
|
|
@ -84,6 +84,48 @@ namespace spot
|
||||||
twa_sub_statistics& s_;
|
twa_sub_statistics& s_;
|
||||||
bdd seen_;
|
bdd seen_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename SU, typename EU>
|
||||||
|
void dfs(const const_twa_graph_ptr& ge, SU state_update, EU edge_update)
|
||||||
|
{
|
||||||
|
unsigned init = ge->get_init_state_number();
|
||||||
|
unsigned num_states = ge->num_states();
|
||||||
|
// The TODO vector serves two purposes:
|
||||||
|
// - it is a stack of states to process,
|
||||||
|
// - it is a set of processed states.
|
||||||
|
// The lower 31 bits of each entry is a state on the stack. (The
|
||||||
|
// next usable entry on the stack is indicated by todo_pos.) The
|
||||||
|
// 32th bit (i.e., the sign bit) of todo[x] indicates whether
|
||||||
|
// states number x has been seen.
|
||||||
|
std::vector<unsigned> todo(num_states, 0);
|
||||||
|
const unsigned seen = 1 << (sizeof(unsigned)*8-1);
|
||||||
|
const unsigned mask = seen - 1;
|
||||||
|
unsigned todo_pos = 0;
|
||||||
|
for (unsigned i: ge->univ_dests(init))
|
||||||
|
{
|
||||||
|
todo[todo_pos++] = i;
|
||||||
|
todo[i] |= seen;
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
state_update();
|
||||||
|
unsigned cur = todo[--todo_pos] & mask;
|
||||||
|
todo[todo_pos] ^= cur; // Zero the state
|
||||||
|
for (auto& t: ge->out(cur))
|
||||||
|
{
|
||||||
|
edge_update(t.cond);
|
||||||
|
for (unsigned dst: ge->univ_dests(t.dst))
|
||||||
|
if (!(todo[dst] & seen))
|
||||||
|
{
|
||||||
|
todo[dst] |= seen;
|
||||||
|
todo[todo_pos++] |= dst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (todo_pos > 0);
|
||||||
|
};
|
||||||
|
|
||||||
} // anonymous
|
} // anonymous
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -105,8 +147,18 @@ namespace spot
|
||||||
stats_reachable(const const_twa_ptr& g)
|
stats_reachable(const const_twa_ptr& g)
|
||||||
{
|
{
|
||||||
twa_statistics s;
|
twa_statistics s;
|
||||||
stats_bfs d(g, s);
|
auto ge = std::dynamic_pointer_cast<const twa_graph>(g);
|
||||||
d.run();
|
if (!ge)
|
||||||
|
{
|
||||||
|
stats_bfs d(g, s);
|
||||||
|
d.run();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dfs(ge,
|
||||||
|
[&s](){ ++s.states; },
|
||||||
|
[&s](bdd){ ++s.edges; });
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,8 +166,26 @@ namespace spot
|
||||||
sub_stats_reachable(const const_twa_ptr& g)
|
sub_stats_reachable(const const_twa_ptr& g)
|
||||||
{
|
{
|
||||||
twa_sub_statistics s;
|
twa_sub_statistics s;
|
||||||
sub_stats_bfs d(g, s);
|
auto ge = std::dynamic_pointer_cast<const twa_graph>(g);
|
||||||
d.run();
|
if (!ge)
|
||||||
|
{
|
||||||
|
sub_stats_bfs d(g, s);
|
||||||
|
d.run();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dfs(ge,
|
||||||
|
[&s](){ ++s.states; },
|
||||||
|
[&s, &ge](bdd cond)
|
||||||
|
{
|
||||||
|
++s.edges;
|
||||||
|
while (cond != bddfalse)
|
||||||
|
{
|
||||||
|
cond -= bdd_satoneset(cond, ge->ap_vars(), bddtrue);
|
||||||
|
++s.transitions;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue