dot: add option "k"
Fixes #134. * spot/twaalgos/dot.cc: Implement it. * bin/common_aoutput.cc, spot/twaalgos/dot.hh, NEWS: Document it. * tests/core/readsave.test, tests/python/ltsmin.ipynb: Test it.
This commit is contained in:
parent
5a5f83f468
commit
a9b4560f3d
6 changed files with 528 additions and 451 deletions
|
|
@ -55,6 +55,7 @@ namespace spot
|
|||
bool mark_states_ = false;
|
||||
bool opt_scc_ = false;
|
||||
bool opt_html_labels_ = false;
|
||||
bool opt_state_labels_ = false;
|
||||
const_twa_graph_ptr aut_;
|
||||
std::vector<std::string>* sn_ = nullptr;
|
||||
std::vector<std::pair<unsigned, unsigned>>* sprod_ = nullptr;
|
||||
|
|
@ -192,6 +193,9 @@ namespace spot
|
|||
case 'h':
|
||||
opt_horizontal_ = true;
|
||||
break;
|
||||
case 'k':
|
||||
opt_state_labels_ = true;
|
||||
break;
|
||||
case 'n':
|
||||
opt_name_ = true;
|
||||
break;
|
||||
|
|
@ -319,6 +323,21 @@ namespace spot
|
|||
os_ << '}';
|
||||
}
|
||||
|
||||
std::string
|
||||
state_label(unsigned s) const
|
||||
{
|
||||
bdd label = bddfalse;
|
||||
for (auto& t: aut_->out(s))
|
||||
{
|
||||
label = t.cond;
|
||||
break;
|
||||
}
|
||||
if (label == bddfalse
|
||||
&& incomplete_ && incomplete_->find(s) != incomplete_->end())
|
||||
return "...";
|
||||
return bdd_format_formula(aut_->get_dict(), label);
|
||||
}
|
||||
|
||||
void
|
||||
start()
|
||||
{
|
||||
|
|
@ -440,6 +459,8 @@ namespace spot
|
|||
os_ << "\\n";
|
||||
output_set(acc);
|
||||
}
|
||||
if (opt_state_labels_)
|
||||
escape_str(os_ << "\\n", state_label(s));
|
||||
os_ << '"';
|
||||
}
|
||||
else
|
||||
|
|
@ -456,6 +477,8 @@ namespace spot
|
|||
os_ << "<br/>";
|
||||
output_html_set(acc);
|
||||
}
|
||||
if (opt_state_labels_)
|
||||
escape_html(os_ << "<br/>", state_label(s));
|
||||
os_ << '>';
|
||||
}
|
||||
os_ << "]\n";
|
||||
|
|
@ -470,6 +493,8 @@ namespace spot
|
|||
os_ << (*sprod_)[s].first << ',' << (*sprod_)[s].second;
|
||||
else
|
||||
os_ << s;
|
||||
if (opt_state_labels_)
|
||||
escape_str(os_ << "\\n", state_label(s));
|
||||
os_ << '"';
|
||||
// Use state_acc_sets(), not state_is_accepting() because
|
||||
// on co-Büchi automata we want to mark the rejecting
|
||||
|
|
@ -486,8 +511,10 @@ namespace spot
|
|||
void
|
||||
process_link(const twa_graph::edge_storage_t& t, int number)
|
||||
{
|
||||
std::string label = bdd_format_formula(aut_->get_dict(), t.cond);
|
||||
os_ << " " << t.src << " -> " << t.dst;
|
||||
std::string label;
|
||||
if (!opt_state_labels_)
|
||||
label = bdd_format_formula(aut_->get_dict(), t.cond);
|
||||
if (!opt_html_labels_)
|
||||
{
|
||||
os_ << " [label=\"";
|
||||
|
|
@ -495,7 +522,8 @@ namespace spot
|
|||
if (!mark_states_)
|
||||
if (auto a = t.acc)
|
||||
{
|
||||
os_ << "\\n";
|
||||
if (!opt_state_labels_)
|
||||
os_ << "\\n";
|
||||
output_set(a);
|
||||
}
|
||||
os_ << '"';
|
||||
|
|
@ -507,7 +535,8 @@ namespace spot
|
|||
if (!mark_states_)
|
||||
if (auto a = t.acc)
|
||||
{
|
||||
os_ << "<br/>";
|
||||
if (!opt_state_labels_)
|
||||
os_ << "<br/>";
|
||||
output_html_set(a);
|
||||
}
|
||||
os_ << '>';
|
||||
|
|
@ -533,6 +562,27 @@ namespace spot
|
|||
sprod_ = nullptr;
|
||||
}
|
||||
}
|
||||
if (opt_state_labels_)
|
||||
{
|
||||
// Verify that we can use state labels for this automaton.
|
||||
unsigned n = aut->num_states();
|
||||
for (unsigned s = 0; s < n; ++s)
|
||||
{
|
||||
bool first = true;
|
||||
bdd cond = bddfalse;
|
||||
for (auto& t: aut->out(s))
|
||||
if (first)
|
||||
{
|
||||
cond = t.cond;
|
||||
first = false;
|
||||
}
|
||||
else if (t.cond != cond)
|
||||
{
|
||||
opt_state_labels_ = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
incomplete_ =
|
||||
aut->get_named_prop<std::set<unsigned>>("incomplete-states");
|
||||
if (opt_name_)
|
||||
|
|
@ -541,11 +591,12 @@ namespace spot
|
|||
&& aut_->prop_state_acc().is_true());
|
||||
if (opt_shape_ == ShapeAuto)
|
||||
{
|
||||
if (sn_ || sprod_ || aut->num_states() > 100)
|
||||
if (sn_ || sprod_ || aut->num_states() > 100 || opt_state_labels_)
|
||||
{
|
||||
opt_shape_ = ShapeEllipse;
|
||||
// If all state names are short, prefer circles.
|
||||
if (sn_ && std::all_of(sn_->begin(), sn_->end(),
|
||||
if (!opt_state_labels_ &&
|
||||
sn_ && std::all_of(sn_->begin(), sn_->end(),
|
||||
[](const std::string& s)
|
||||
{ return s.size() <= 2; }))
|
||||
opt_shape_ = ShapeCircle;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015 Laboratoire de Recherche
|
||||
// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 Laboratoire de Recherche
|
||||
// et Developpement de l'Epita (LRDE).
|
||||
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
|
||||
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
|
||||
|
|
@ -39,7 +39,7 @@ namespace spot
|
|||
/// supported: 'v' for vertical output, 'h' for horizontal output,
|
||||
/// 't' force transition-based acceptance, 'N' hide the name of the
|
||||
/// automaton, 'n' shows the name, 'c' uses circle-shaped states,
|
||||
/// 'a' shows the acceptance.
|
||||
/// 'a' shows the acceptance, 'k' uses state-based labels if possible.
|
||||
SPOT_API std::ostream&
|
||||
print_dot(std::ostream& os,
|
||||
const const_twa_ptr& g,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue