dot: support 'u'

* spot/twaalgos/dot.cc: Implement it.
* bin/common_aoutput.cc, NEWS: Mention it.
* tests/python/alternation.ipynb: Test it.
This commit is contained in:
Alexandre Duret-Lutz 2018-05-11 14:50:14 +02:00
parent 13c227a099
commit 60898b6d22
4 changed files with 3296 additions and 1639 deletions

4
NEWS
View file

@ -26,6 +26,10 @@ New in spot 2.5.3.dev (not yet released)
tooltip in SVG figures when the mouse is over the acceptance tooltip in SVG figures when the mouse is over the acceptance
condition. condition.
- print_dot() has a new option "u" to hide "true states" behind
"exiting transitions". This can be used to display alternating
automata in a way many people expect.
- cleanup_parity() and cleanup_parity_here() are smarter and now - cleanup_parity() and cleanup_parity_here() are smarter and now
remove from the acceptance condition the parity colors that are remove from the acceptance condition the parity colors that are
not used in the automaton. not used in the automaton.

View file

@ -88,7 +88,7 @@ static const argp_option options[] =
/**************************************************/ /**************************************************/
{ nullptr, 0, nullptr, 0, "Output format:", 3 }, { nullptr, 0, nullptr, 0, "Output format:", 3 },
{ "dot", 'd', { "dot", 'd',
"1|a|A|b|B|c|C(COLOR)|e|f(FONT)|h|k|n|N|o|r|R|s|t|v|y|+INT|<INT|#", "1|a|A|b|B|c|C(COLOR)|e|f(FONT)|h|k|n|N|o|r|R|s|t|u|v|y|+INT|<INT|#",
OPTION_ARG_OPTIONAL, OPTION_ARG_OPTIONAL,
"GraphViz's format. Add letters for " "GraphViz's format. Add letters for "
"(1) force numbered states, " "(1) force numbered states, "
@ -110,6 +110,7 @@ static const argp_option options[] =
"(R) color acceptance sets by Inf/Fin, " "(R) color acceptance sets by Inf/Fin, "
"(s) with SCCs, " "(s) with SCCs, "
"(t) force transition-based acceptance, " "(t) force transition-based acceptance, "
"(u) hide true states, "
"(v) vertical layout, " "(v) vertical layout, "
"(y) split universal edges by color, " "(y) split universal edges by color, "
"(+INT) add INT to all set numbers, " "(+INT) add INT to all set numbers, "

View file

@ -81,6 +81,7 @@ namespace spot
std::string* name_ = nullptr; // title for the graph std::string* name_ = nullptr; // title for the graph
std::string* graph_name_ = nullptr; // name for the digraph std::string* graph_name_ = nullptr; // name for the digraph
std::map<std::pair<int, int>, int> univ_done; std::map<std::pair<int, int>, int> univ_done;
std::vector<bool> true_states_;
acc_cond::mark_t inf_sets_ = {}; acc_cond::mark_t inf_sets_ = {};
acc_cond::mark_t fin_sets_ = {}; acc_cond::mark_t fin_sets_ = {};
@ -102,6 +103,7 @@ namespace spot
bool opt_all_bullets = false; bool opt_all_bullets = false;
bool opt_ordered_edges_ = false; bool opt_ordered_edges_ = false;
bool opt_numbered_edges_ = false; bool opt_numbered_edges_ = false;
bool opt_hide_true_states_ = false;
bool opt_orig_show_ = false; bool opt_orig_show_ = false;
bool max_states_given_ = false; // related to max_states_ bool max_states_given_ = false; // related to max_states_
bool opt_latex_ = false; bool opt_latex_ = false;
@ -130,6 +132,28 @@ namespace spot
return max_states_given_; return max_states_given_;
} }
void find_true_states()
{
unsigned n = aut_->num_states();
true_states_.resize(n, false);
auto& g = aut_->get_graph();
auto& acc = aut_->acc();
for (unsigned s = 0; s < n; ++s)
{
auto& ss = g.state_storage(s);
if (ss.succ == ss.succ_tail)
{
auto& es = g.edge_storage(ss.succ);
if (es.cond == bddtrue
&& es.src == es.dst
&& acc.accepting(es.acc))
true_states_[s] = true;
}
}
}
void void
parse_opts(const char* options) parse_opts(const char* options)
{ {
@ -267,6 +291,9 @@ namespace spot
case 's': case 's':
opt_scc_ = true; opt_scc_ = true;
break; break;
case 'u':
opt_hide_true_states_ = true;
break;
case 'v': case 'v':
opt_vertical_ = true; opt_vertical_ = true;
break; break;
@ -430,6 +457,13 @@ namespace spot
return tmp_dst.str(); return tmp_dst.str();
} }
template<typename U, typename V>
void print_true_state(U to, V from) const
{
os_ << " T" << to << 'T' << from << " [label=\"\", style=invis, ";
os_ << (opt_vertical_ ? "height=0]\n" : "width=0]\n");
}
void void
print_dst(int dst, bool print_edges = false, print_dst(int dst, bool print_edges = false,
const char* style = nullptr, int color_num = -1) const char* style = nullptr, int color_num = -1)
@ -444,7 +478,15 @@ namespace spot
{ {
for (unsigned d: aut_->univ_dests(dst)) for (unsigned d: aut_->univ_dests(dst))
{ {
os_ << " " << dest << " -> " << d; bool dst_is_hidden_true_state =
opt_hide_true_states_ && true_states_[d];
if (dst_is_hidden_true_state)
print_true_state(d, dest);
os_ << " " << dest << " -> ";
if (dst_is_hidden_true_state)
os_ << 'T' << d << 'T' << dest;
else
os_ << d;
if (style && *style) if (style && *style)
os_ << " [" << style << ']'; os_ << " [" << style << ']';
os_ << '\n'; os_ << '\n';
@ -679,11 +721,20 @@ namespace spot
process_link(const twa_graph::edge_storage_t& t, int number, process_link(const twa_graph::edge_storage_t& t, int number,
bool print_edges) bool print_edges)
{ {
bool dst_is_hidden_true_state =
(t.dst < true_states_.size()) && true_states_[t.dst];
if (print_edges) if (print_edges)
{ {
os_ << " " << t.src << " -> " << (int)t.dst; if (dst_is_hidden_true_state)
print_true_state(t.dst, t.src);
os_ << " " << t.src << " -> ";
if (dst_is_hidden_true_state)
os_ << 'T' << t.dst << 'T' << t.src;
else
os_ << (int)t.dst;
if (aut_->is_univ_dest(t.dst) && highlight_edges_ if (aut_->is_univ_dest(t.dst) && highlight_edges_
&& !opt_shared_univ_dest_) && !opt_shared_univ_dest_ && !dst_is_hidden_true_state)
{ {
auto idx = aut_->get_graph().index_of_edge(t); auto idx = aut_->get_graph().index_of_edge(t);
auto iter = highlight_edges_->find(idx); auto iter = highlight_edges_->find(idx);
@ -746,6 +797,8 @@ namespace spot
void print(const const_twa_graph_ptr& aut) void print(const const_twa_graph_ptr& aut)
{ {
aut_ = aut; aut_ = aut;
if (opt_hide_true_states_)
find_true_states();
sn_ = aut->get_named_prop<std::vector<std::string>>("state-names"); sn_ = aut->get_named_prop<std::vector<std::string>>("state-names");
// We have no names. Do we have product sources? // We have no names. Do we have product sources?
@ -851,6 +904,8 @@ namespace spot
} }
for (auto s: si->states_of(i)) for (auto s: si->states_of(i))
{ {
if (opt_hide_true_states_ && true_states_[s])
continue;
process_state(s); process_state(s);
int trans_num = 0; int trans_num = 0;
unsigned scc_of_s = si->scc_of(s); unsigned scc_of_s = si->scc_of(s);
@ -871,6 +926,8 @@ namespace spot
unsigned ns = aut_->num_states(); unsigned ns = aut_->num_states();
for (unsigned n = 0; n < ns; ++n) for (unsigned n = 0; n < ns; ++n)
{ {
if (opt_hide_true_states_ && true_states_[n])
continue;
if (!si || !si->reachable_state(n)) if (!si || !si->reachable_state(n))
process_state(n); process_state(n);
int trans_num = 0; int trans_num = 0;

File diff suppressed because it is too large Load diff