twaalgos/scc_info: Add states_on_acc_cycle_of() method
* NEWS: Update. * spot/twaalgos/sccinfo.hh: Declare states_on_acc_cycle_of(). * spot/twaalgos/sccinfo.cc: Implement it.
This commit is contained in:
parent
0957317ad7
commit
37c1a19b39
3 changed files with 149 additions and 0 deletions
5
NEWS
5
NEWS
|
|
@ -14,6 +14,11 @@ New in spot 2.4.0.dev (not yet released)
|
||||||
- Rename three methods of spot::scc_info. New names are clearer. The
|
- Rename three methods of spot::scc_info. New names are clearer. The
|
||||||
old names have been deprecated.
|
old names have been deprecated.
|
||||||
|
|
||||||
|
- The new function scc_info::states_on_acc_cycle_of() is able to
|
||||||
|
return all states visited by any accepting cycles of the
|
||||||
|
specified SCC. It must only be called on automata with a
|
||||||
|
Streett-like acceptance condition.
|
||||||
|
|
||||||
Deprecation notices:
|
Deprecation notices:
|
||||||
|
|
||||||
(These functions still work but compilers emit warnings.)
|
(These functions still work but compilers emit warnings.)
|
||||||
|
|
|
||||||
|
|
@ -441,4 +441,122 @@ namespace spot
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<twa_graph_ptr>
|
||||||
|
scc_info::split_on_sets(unsigned scc, acc_cond::mark_t sets) const
|
||||||
|
{
|
||||||
|
std::vector<twa_graph_ptr> res;
|
||||||
|
|
||||||
|
std::vector<bool> seen(aut_->num_states(), false);
|
||||||
|
std::vector<bool> cur(aut_->num_states(), false);
|
||||||
|
|
||||||
|
for (unsigned init: states_of(scc))
|
||||||
|
{
|
||||||
|
if (seen[init])
|
||||||
|
continue;
|
||||||
|
cur.assign(aut_->num_states(), false);
|
||||||
|
|
||||||
|
auto copy = make_twa_graph(aut_->get_dict());
|
||||||
|
copy->copy_acceptance_of(aut_);
|
||||||
|
copy->prop_state_acc(aut_->prop_state_acc());
|
||||||
|
transform_accessible(aut_, copy, [&](unsigned src,
|
||||||
|
bdd& cond,
|
||||||
|
acc_cond::mark_t& m,
|
||||||
|
unsigned dst)
|
||||||
|
{
|
||||||
|
cur[src] = seen[src] = true;
|
||||||
|
if (scc_of(dst) != scc
|
||||||
|
|| (m & sets)
|
||||||
|
|| (seen[dst] && !cur[dst]))
|
||||||
|
{
|
||||||
|
cond = bddfalse;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
init);
|
||||||
|
if (copy->num_edges())
|
||||||
|
res.push_back(copy);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
scc_info::states_on_acc_cycle_of_rec(unsigned scc,
|
||||||
|
acc_cond::mark_t all_fin,
|
||||||
|
acc_cond::mark_t all_inf,
|
||||||
|
unsigned nb_pairs,
|
||||||
|
std::vector<acc_cond::rs_pair>& pairs,
|
||||||
|
std::vector<unsigned>& res,
|
||||||
|
std::vector<unsigned>& old) const
|
||||||
|
{
|
||||||
|
if (!is_rejecting_scc(scc))
|
||||||
|
{
|
||||||
|
acc_cond::mark_t all_acc = acc_sets_of(scc);
|
||||||
|
acc_cond::mark_t fin = all_fin & all_acc;
|
||||||
|
acc_cond::mark_t inf = all_inf & all_acc;
|
||||||
|
|
||||||
|
// Get all Fin acceptance set that appears in the SCC and does not have
|
||||||
|
// their corresponding Inf appearing in the SCC.
|
||||||
|
acc_cond::mark_t m = 0u;
|
||||||
|
if (fin)
|
||||||
|
for (unsigned p = 0; p < nb_pairs; ++p)
|
||||||
|
if (fin & pairs[p].fin && !(inf & pairs[p].inf))
|
||||||
|
m |= pairs[p].fin;
|
||||||
|
|
||||||
|
if (m)
|
||||||
|
for (const twa_graph_ptr& aut : split_on_sets(scc, m))
|
||||||
|
{
|
||||||
|
auto orig_sts = aut->get_named_prop
|
||||||
|
<std::vector<unsigned>>("original-states");
|
||||||
|
|
||||||
|
// Update mapping of state numbers between the current automaton
|
||||||
|
// and the starting one.
|
||||||
|
for (unsigned i = 0; i < orig_sts->size(); ++i)
|
||||||
|
(*orig_sts)[i] = old[(*orig_sts)[i]];
|
||||||
|
|
||||||
|
scc_info si_tmp(aut);
|
||||||
|
unsigned scccount_tmp = si_tmp.scc_count();
|
||||||
|
for (unsigned scc_tmp = 0; scc_tmp < scccount_tmp; ++scc_tmp)
|
||||||
|
si_tmp.states_on_acc_cycle_of_rec(scc_tmp,
|
||||||
|
all_fin,
|
||||||
|
all_inf,
|
||||||
|
nb_pairs,
|
||||||
|
pairs,
|
||||||
|
res,
|
||||||
|
*orig_sts);
|
||||||
|
}
|
||||||
|
|
||||||
|
else // Accepting cycle found.
|
||||||
|
for (unsigned s : states_of(scc))
|
||||||
|
res.push_back(old[s]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned>
|
||||||
|
scc_info::states_on_acc_cycle_of(unsigned scc) const
|
||||||
|
{
|
||||||
|
std::vector<acc_cond::rs_pair> pairs;
|
||||||
|
if (!aut_->acc().is_streett_like(pairs))
|
||||||
|
throw std::runtime_error("states_on_acc_cycle_of only works with "
|
||||||
|
"Streett-like acceptance condition");
|
||||||
|
unsigned nb_pairs = pairs.size();
|
||||||
|
|
||||||
|
std::vector<unsigned> res;
|
||||||
|
if (!is_rejecting_scc(scc))
|
||||||
|
{
|
||||||
|
std::vector<unsigned> old;
|
||||||
|
unsigned nb_states = aut_->num_states();
|
||||||
|
for (unsigned i = 0; i < nb_states; ++i)
|
||||||
|
old.push_back(i);
|
||||||
|
|
||||||
|
acc_cond::mark_t all_fin = 0u;
|
||||||
|
acc_cond::mark_t all_inf = 0u;
|
||||||
|
std::tie(all_inf, all_fin) = aut_->get_acceptance().used_inf_fin_sets();
|
||||||
|
|
||||||
|
states_on_acc_cycle_of_rec(scc, all_fin, all_inf, nb_pairs, pairs, res,
|
||||||
|
old);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -541,6 +541,32 @@ namespace spot
|
||||||
std::vector<bool> weak_sccs() const;
|
std::vector<bool> weak_sccs() const;
|
||||||
|
|
||||||
bdd scc_ap_support(unsigned scc) const;
|
bdd scc_ap_support(unsigned scc) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// \brief: Remove in 'scc', edges containing any mark in 'sets'.
|
||||||
|
///
|
||||||
|
/// Such a deletion may split the SCC, in which case, the function builds
|
||||||
|
/// and returns more than one automaton representing the specified SCC.
|
||||||
|
std::vector<twa_graph_ptr>
|
||||||
|
split_on_sets(unsigned scc, acc_cond::mark_t sets) const;
|
||||||
|
|
||||||
|
/// \brief: Recursive function used by states_on_acc_cycle_of().
|
||||||
|
void
|
||||||
|
states_on_acc_cycle_of_rec(unsigned scc,
|
||||||
|
acc_cond::mark_t all_fin,
|
||||||
|
acc_cond::mark_t all_inf,
|
||||||
|
unsigned nb_pairs,
|
||||||
|
std::vector<acc_cond::rs_pair>& pairs,
|
||||||
|
std::vector<unsigned>& res,
|
||||||
|
std::vector<unsigned>& old) const;
|
||||||
|
public:
|
||||||
|
/// \brief: Get all states visited by any accepting cycles of the 'scc'.
|
||||||
|
///
|
||||||
|
/// Throws an exception if the automaton does not have a 'Streett-like'
|
||||||
|
/// acceptance condition.
|
||||||
|
std::vector<unsigned>
|
||||||
|
states_on_acc_cycle_of(unsigned scc) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue