twa_graph: add a merge_univ_dests() method
and call it after parsing * spot/twa/twagraph.cc, spot/twa/twagraph.hh (twa_graph::merge_univ_dests): New method. * spot/parseaut/parseaut.yy: Call it. * spot/twaalgos/dot.cc: Improve output, now that several edges can use the same universal destination. * tests/core/alternating.test, tests/core/complete.test, tests/core/parseaut.test, tests/python/_altscc.ipynb, tests/python/alternating.py, tests/python/alternation.ipynb: Adjust test case. * doc/org/tut24.org: Adjust example.
This commit is contained in:
parent
3d0a971aa8
commit
12f6c8cf10
11 changed files with 567 additions and 517 deletions
|
|
@ -2423,6 +2423,8 @@ namespace spot
|
|||
fix_acceptance(r);
|
||||
fix_initial_state(r);
|
||||
fix_properties(r);
|
||||
if (r.h->aut && r.h->aut->is_alternating())
|
||||
r.h->aut->merge_univ_dests();
|
||||
return r.h;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -43,10 +43,66 @@ namespace spot
|
|||
delete namer;
|
||||
}
|
||||
|
||||
/// \brief Merge universal destinations
|
||||
///
|
||||
/// If several states have the same universal destination, merge
|
||||
/// them all. Also remove unused destination, and any redundant
|
||||
/// state in each destination.
|
||||
void twa_graph::merge_univ_dests()
|
||||
{
|
||||
auto& g = get_graph();
|
||||
auto& dests = g.dests_vector();
|
||||
auto& edges = g.edge_vector();
|
||||
|
||||
std::vector<unsigned> old_dests;
|
||||
std::swap(dests, old_dests);
|
||||
std::vector<unsigned> seen(old_dests.size(), -1U);
|
||||
std::map<std::vector<unsigned>, unsigned> uniq;
|
||||
|
||||
auto fixup = [&](unsigned& in_dst)
|
||||
{
|
||||
unsigned dst = in_dst;
|
||||
if ((int) dst >= 0) // not a universal edge
|
||||
return;
|
||||
dst = ~dst;
|
||||
unsigned& nd = seen[dst];
|
||||
if (nd == -1U)
|
||||
{
|
||||
std::vector<unsigned>
|
||||
tmp(old_dests.data() + dst + 1,
|
||||
old_dests.data() + dst + 1 + old_dests[dst]);
|
||||
std::sort(tmp.begin(), tmp.end());
|
||||
tmp.erase(std::unique(tmp.begin(), tmp.end()), tmp.end());
|
||||
auto p = uniq.emplace(tmp, 0);
|
||||
if (!p.second)
|
||||
{
|
||||
nd = p.first->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
nd = g.new_univ_dests(tmp.begin(), tmp.end());
|
||||
p.first->second = nd;
|
||||
}
|
||||
}
|
||||
in_dst = nd;
|
||||
};
|
||||
|
||||
unsigned tend = edges.size();
|
||||
for (unsigned t = 1; t < tend; t++)
|
||||
{
|
||||
if (g.is_dead_edge(t))
|
||||
continue;
|
||||
fixup(edges[t].dst);
|
||||
}
|
||||
fixup(init_number_);
|
||||
}
|
||||
|
||||
void twa_graph::merge_edges()
|
||||
{
|
||||
set_named_prop("highlight-edges", nullptr);
|
||||
g_.remove_dead_edges_();
|
||||
if (is_alternating())
|
||||
merge_univ_dests();
|
||||
|
||||
typedef graph_t::edge_storage_t tr_t;
|
||||
g_.sort_edges_([](const tr_t& lhs, const tr_t& rhs)
|
||||
|
|
|
|||
|
|
@ -521,6 +521,11 @@ namespace spot
|
|||
/// extremities and acceptance.
|
||||
void merge_edges();
|
||||
|
||||
/// \brief marge common universal destination
|
||||
///
|
||||
/// This is already called by merge_edges().
|
||||
void merge_univ_dests();
|
||||
|
||||
/// \brief Remove all dead states
|
||||
///
|
||||
/// Dead states are all the states that cannot be part of
|
||||
|
|
|
|||
|
|
@ -360,10 +360,14 @@ namespace spot
|
|||
return bdd_format_formula(aut_->get_dict(), label);
|
||||
}
|
||||
|
||||
std::set<int> done;
|
||||
|
||||
void
|
||||
print_dst(int dst, const char* style = nullptr)
|
||||
{
|
||||
os_ << " " << dst << " [label=<>,width=0,height=0,shape=none]\n";
|
||||
if (!done.emplace(dst).second)
|
||||
return;
|
||||
os_ << " " << dst << " [label=<>,shape=point]\n";
|
||||
for (unsigned d: aut_->univ_dests(dst))
|
||||
{
|
||||
os_ << " " << dst << " -> " << d;
|
||||
|
|
@ -465,7 +469,7 @@ namespace spot
|
|||
}
|
||||
else
|
||||
{
|
||||
os_ << " [dir=none]\n";
|
||||
os_ << " [arrowhead=onormal]\n";
|
||||
print_dst(init);
|
||||
}
|
||||
}
|
||||
|
|
@ -626,11 +630,10 @@ namespace spot
|
|||
os_ << ", " << highlight;
|
||||
}
|
||||
}
|
||||
// No arrow tip of the common part of a universal transition
|
||||
if ((int)t.dst < 0)
|
||||
os_ << ", dir=none";
|
||||
if (aut_->is_univ_dest(t.dst))
|
||||
os_ << ", arrowhead=onormal";
|
||||
os_ << "]\n";
|
||||
if ((int)t.dst < 0) // Universal destination
|
||||
if (aut_->is_univ_dest(t.dst))
|
||||
print_dst(t.dst, highlight.c_str());
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue