Commit 12f6c8cf authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

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.
parent 3d0a971a
......@@ -107,7 +107,7 @@ for (unsigned s = 0; s < n; ++s)
#+RESULTS: nonalt-one
#+begin_example
Initial state: 4294967292
Initial state: 4294967295
State 0:
edge(0 -> 0)
label = a
......
......@@ -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());
}
......
......@@ -61,34 +61,34 @@ digraph G {
label="Fin(⓿)"
labelloc="t"
I [label="", style=invis, width=0]
I -> -11 [dir=none]
-11 [label=<>,width=0,height=0,shape=none]
I -> -11 [arrowhead=onormal]
-11 [label=<>,shape=point]
-11 -> 0
-11 -> 2
subgraph cluster_0 {
color=green
label=""
6 [label="t"]
2 [label="G(a)"]
}
subgraph cluster_1 {
color=red
label=""
4 [label="F(b)\n⓿"]
1 [label="FG(a)\n⓿"]
}
subgraph cluster_2 {
color=green
label=""
3 [label="GF(b)"]
6 [label="t"]
}
subgraph cluster_3 {
color=green
color=red
label=""
2 [label="G(a)"]
4 [label="F(b)\n"]
}
subgraph cluster_4 {
color=red
color=green
label=""
1 [label="FG(a)\n"]
3 [label="GF(b)"]
}
subgraph cluster_5 {
color=red
......@@ -100,23 +100,23 @@ digraph G {
label=""
0 [label="((((a) U (b)) && GF(b)) && FG(a))"]
}
0 -> -1 [label="b", dir=none]
-1 [label=<>,width=0,height=0,shape=none]
-1 -> 3
0 -> -1 [label="b", arrowhead=onormal]
-1 [label=<>,shape=point]
-1 -> 1
0 -> -4 [label="a & !b", style=bold, color="#F15854", dir=none]
-4 [label=<>,width=0,height=0,shape=none]
-4 -> 5 [style=bold, color="#F15854"]
-4 -> 3 [style=bold, color="#F15854"]
-1 -> 3
0 -> -4 [label="a & !b", style=bold, color="#F15854", arrowhead=onormal]
-4 [label=<>,shape=point]
-4 -> 1 [style=bold, color="#F15854"]
-4 -> 3 [style=bold, color="#F15854"]
-4 -> 5 [style=bold, color="#F15854"]
1 -> 2 [label="a"]
1 -> 1 [label="1"]
2 -> 2 [label="a"]
3 -> 3 [label="b"]
3 -> -8 [label="!b", style=bold, color="#FAA43A", dir=none]
-8 [label=<>,width=0,height=0,shape=none]
-8 -> 4 [style=bold, color="#FAA43A"]
3 -> -8 [label="!b", style=bold, color="#FAA43A", arrowhead=onormal]
-8 [label=<>,shape=point]
-8 -> 3 [style=bold, color="#FAA43A"]
-8 -> 4 [style=bold, color="#FAA43A"]
4 -> 6 [label="b"]
4 -> 4 [label="!b"]
5 -> 6 [label="b"]
......@@ -147,7 +147,7 @@ AP: 1 "a"
properties: trans-labels explicit-labels state-acc univ-branch very-weak
--BODY--
State: 0 "GF(a)"
[t] 1&0
[t] 0&1
State: 1 "F(a)" {0}
[(0)] 2
[t] 1
......@@ -172,7 +172,7 @@ properties: univ-branch trans-labels explicit-labels state-acc complete
properties: very-weak
--BODY--
State: 0 {0}
[t] 1&0
[t] 0&1
State: 1
[0] 2
[t] 1
......
......@@ -203,7 +203,7 @@ properties: deterministic very-weak
--BODY--
State: 0
[!0 | 1] 0
[0&!1] 1&0
[0&!1] 0&1
State: 1 {0}
[0&!1] 1
[!0 | 1] 1
......
......@@ -1946,7 +1946,7 @@ State: 5 "F!((c2))" {0}
[t] 5
State: 6 "GF!((c1))"
[!1] 6
[t] 7&6
[t] 6&7
State: 7 "F!((c1))" {0}
[!1] 11
[t] 7
......@@ -1954,9 +1954,9 @@ State: 8 "((!((c1)) U (!((c1)) && !((p1)))) R F!((p2)))"
[!0&!1&!2] 11
[!1&!2] 10
[!0&!1] 9
[!1] 10&9
[!1] 9&10
[!0] 8
[t] 10&8
[t] 8&10
State: 9 "(!((c1)) U (!((c1)) && !((p1))))" {0}
[!1&!2] 11
[!1] 9
......@@ -2407,8 +2407,8 @@ properties: univ-branch trans-labels explicit-labels state-acc
properties: very-weak
--BODY--
State: 0 "((((a) U (b)) && GF(b)) && FG(a))"
[0] 3&1
[!0&1] 5&3&1
[0] 1&3
[!0&1] 1&3&5
State: 1 "FG(a)" {0}
[1] 2
[t] 1
......@@ -2416,7 +2416,7 @@ State: 2 "G(a)"
[1] 2
State: 3 "GF(b)"
[0] 3
[!0] 4&3
[!0] 3&4
State: 4 "F(b)" {0}
[0] 6
[!0] 4
......@@ -2438,18 +2438,18 @@ properties: deterministic
State: 0
[!0&!1] 0&1
[0&!1] 1
[!0&1] 0&2&1
[!0&1] 0&1&2
[0&1] 0&1
State: 1
[!0&!1] 0&1
[0&!1] 2&1
[0&!1] 1&2
[!0&1] 2
[0&1] 1&1
[0&1] 1
State: 2
[!0&!1] 0&1
[0&!1] 2&1
[0&!1] 1&2
[!0&1] 2
[0&1] 0&2&1
[0&1] 0&1&2
--END--
EOF
......@@ -2613,8 +2613,8 @@ properties: univ-branch trans-labels explicit-labels state-acc
properties: very-weak
--BODY--
State: 0 "((((a) U (b)) && GF(b)) && FG(a))"
[0] 3&1
[!0&1] 5&3&1
[0] 1&3
[!0&1] 1&3&5
State: 1 "FG(a)" {0}
[1] 2
[t] 1
......@@ -2622,7 +2622,7 @@ State: 2 "G(a)"
[1] 2
State: 3 "GF(b)"
[0] 3
[!0] 4&3
[!0] 3&4
State: 4 "F(b)" {0}
[0] 6
[!0] 4
......@@ -2644,18 +2644,18 @@ properties: deterministic
State: 0
[!0&!1] 0&1
[0&!1] 1
[!0&1] 0&2&1
[!0&1] 0&1&2
[0&1] 0&1
State: 1
[!0&!1] 0&1
[0&!1] 2&1
[0&!1] 1&2
[!0&1] 2
[0&1] 1&1
[0&1] 1
State: 2
[!0&!1] 0&1
[0&!1] 2&1
[0&!1] 1&2
[!0&1] 2
[0&1] 0&2&1
[0&1] 0&1&2
--END--
EOF
......
This diff is collapsed.
......@@ -73,6 +73,11 @@ State: 2
aut2 = spot.automaton(h)
h2 = aut2.to_str('hoa')
print(h2)
assert h != h2
# This will sort destination groups
aut.merge_univ_dests()
h = aut.to_str('hoa')
assert h == h2
aut2.set_univ_init_state([0, 1])
......@@ -90,7 +95,7 @@ State: 0
[0] 1&2 {0}
[1] 0&1
State: 1
[0&1] 0&2&1
[0&1] 0&1&2
State: 2
[0 | 1] 2
--END--"""
......@@ -121,7 +126,7 @@ State: 0
[0] 1&2 {0}
[1] 0&1
State: 1
[0&1] 0&2&1
[0&1] 0&1&2
State: 2
[0 | 1] 2
State: 3
......
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment