dot: add an option to output id= attributes

This will be handy latter to develop widgets with interactive
highlighting of automata.

* spot/twaalgos/dot.cc: Implement it.
* bin/common_aoutput.cc, NEWS, doc/org/oaut.org,
doc/org/spot.css: Document it.
* tests/core/alternating.test, tests/core/readsave.test,
tests/core/sccdot.test: Test it.
This commit is contained in:
Alexandre Duret-Lutz 2021-09-02 22:43:22 +02:00
parent d5bbeceeb2
commit 4855d3c877
8 changed files with 230 additions and 112 deletions

8
NEWS
View file

@ -129,6 +129,14 @@ New in spot 2.9.8.dev (not yet released)
- print_dot() will display states from player 1 using a diamond - print_dot() will display states from player 1 using a diamond
shape. shape.
- print_dot() has a new option "i" to define id=... attributes for
states (S followed by the state number), edges (E followed by the
edge number), and SCCs (SCC followed by SCC number). The option
"i(graphid)" will also set the id of the graph. These id
attributes are useful if an automaton is converted into SVG and
one needs to refer to some particular state/edge/SCC with CSS or
javascript. See https://spot.lrde.epita.fr/oaut.html#SVG-and-CSS
- spot::postproc has new configuration variables that define - spot::postproc has new configuration variables that define
thresholds to disable some costly operation in order to speedup thresholds to disable some costly operation in order to speedup
the processing of large automata. (Those variables are typically the processing of large automata. (Those variables are typically

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2012-2020 Laboratoire de Recherche et Développement // Copyright (C) 2012-2021 Laboratoire de Recherche et Développement
// de l'Epita (LRDE). // de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
@ -97,7 +97,8 @@ 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|E|f(FONT)|h|k|K|n|N|o|r|R|s|t|u|v|y|+INT|<INT|#", "1|a|A|b|B|c|C(COLOR)|e|E|f(FONT)|h|i(ID)|"
"k|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, "
@ -113,6 +114,7 @@ static const argp_option options[] =
"(f(FONT)) use FONT, " "(f(FONT)) use FONT, "
"(g) hide edge labels, " "(g) hide edge labels, "
"(h) horizontal layout, " "(h) horizontal layout, "
"(i) or (i(GRAPHID)) add IDs, "
"(k) use state labels when possible, " "(k) use state labels when possible, "
"(K) use transition labels (default), " "(K) use transition labels (default), "
"(n) show name, " "(n) show name, "

View file

@ -26,7 +26,7 @@ ltl2tgba --help | sed -n 's/ *$//g;/Output format:/,/^$/p' | sed '1d;$d'
'unambiguous', 'stutter-invariant', 'unambiguous', 'stutter-invariant',
'stutter-sensitive-example', 'semi-determinism', 'stutter-sensitive-example', 'semi-determinism',
or 'strength'. or 'strength'.
-d, --dot[=1|a|A|b|B|c|C(COLOR)|e|E|f(FONT)|h|k|K|n|N|o|r|R|s|t|u|v|y|+INT|<INT|#] -d, --dot[=1|a|A|b|B|c|C(COLOR)|e|E|f(FONT)|h|i(ID)|k|K|n|N|o|r|R|s|t|u|v|y|+INT|<INT|#]
GraphViz's format. Add letters for (1) force GraphViz's format. Add letters for (1) force
numbered states, (a) show acceptance condition numbered states, (a) show acceptance condition
(default), (A) hide acceptance condition, (b) (default), (A) hide acceptance condition, (b)
@ -35,16 +35,17 @@ ltl2tgba --help | sed -n 's/ *$//g;/Output format:/,/^$/p' | sed '1d;$d'
nodes, (C) color nodes with COLOR, (d) show nodes, (C) color nodes with COLOR, (d) show
origins when known, (e) force elliptic nodes, (E) origins when known, (e) force elliptic nodes, (E)
force rEctangular nodes, (f(FONT)) use FONT, (g) force rEctangular nodes, (f(FONT)) use FONT, (g)
hide edge labels, (h) horizontal layout, (k) use hide edge labels, (h) horizontal layout, (i) or
state labels when possible, (K) use transition (i(GRAPHID)) add IDs, (k) use state labels when
labels (default), (n) show name, (N) hide name, possible, (K) use transition labels (default), (n)
(o) ordered transitions, (r) rainbow colors for show name, (N) hide name, (o) ordered transitions,
acceptance sets, (R) color acceptance sets by (r) rainbow colors for acceptance sets, (R) color
Inf/Fin, (s) with SCCs, (t) force transition-based acceptance sets by Inf/Fin, (s) with SCCs, (t)
acceptance, (u) hide true states, (v) vertical force transition-based acceptance, (u) hide true
layout, (y) split universal edges by color, (+INT) states, (v) vertical layout, (y) split universal
add INT to all set numbers, (<INT) display at most edges by color, (+INT) add INT to all set numbers,
INT states, (#) show internal edge numbers (<INT) display at most INT states, (#) show
internal edge numbers
-H, --hoaf[=1.1|i|k|l|m|s|t|v] Output the automaton in HOA format -H, --hoaf[=1.1|i|k|l|m|s|t|v] Output the automaton in HOA format
(default). Add letters to select (1.1) version (default). Add letters to select (1.1) version
1.1 of the format, (i) use implicit labels for 1.1 of the format, (i) use implicit labels for
@ -584,9 +585,47 @@ The dot output can also be customized via two environment variables:
#+BEGIN_SRC sh :exports code #+BEGIN_SRC sh :exports code
export SPOT_DOTDEFAULT='Brf(Lato)C(#ffffa0)' export SPOT_DOTDEFAULT='Brf(Lato)C(#ffffa0)'
export SPOT_DOTEXTRA='edge[arrowhead=vee, arrowsize=.7]' export SPOT_DOTEXTRA='node[fontsize=12] fontsize=12 stylesheet="spot.css" edge[arrowhead=vee, arrowsize=.7, fontsize=12]'
#+END_SRC #+END_SRC
** SVG and CSS
:PROPERTIES:
:CUSTOM_ID: SVG-and-CSS
:END:
Each state, edge, or SCC in an automaton has a unique number. When
passing option =i= to the dot printer, this unique number will be used
to form a unique =id= attribute for these elements: a prefix =S= (for
state), =E= (for edge), or "SCC=" is simply added to the unique
number. Additionally, using =i(graphid)= will define =graphid= as
that =id= of the automaton. GraphViz will keep these identifier in
the generated SVG, so this makes it possible to modify rendering
of the automaton using CSS or javascript.
As an example, the CSS file we use on this page contains:
#+BEGIN_SRC css
#iddemo #E3 path{animation:flashstroke 1s linear infinite;}
@keyframes flashstroke{50%{stroke:red;stroke-width:1.5;}}
#iddemo #E3 polygon{animation:flashfill 1s linear infinite;}
@keyframes flashfill{50%{stroke:red;stroke-width:1.5;fill:red}}
#+END_SRC
therefore the third edge of any graph whose =id= is =iddemo= will
be animated:
#+NAME: oaut-dot4
#+BEGIN_SRC sh :exports code
ltl2tgba -G -D 'GFa <-> XGb' --dot='i(iddemo).'
#+END_SRC
#+BEGIN_SRC dot :file oaut-dot4.svg :var txt=oaut-dot4 :exports results
$txt
#+END_SRC
#+RESULTS:
[[file:oaut-dot4.svg]]
** Working with =dot2tex= ** Working with =dot2tex=
:PROPERTIES: :PROPERTIES:
:CUSTOM_ID: dot2tex :CUSTOM_ID: dot2tex

View file

@ -100,3 +100,7 @@ g#version{transform-origin:50% 50%;animation-duration:3s;animation-name:animspot
88%{transform:scale(1.1)} 88%{transform:scale(1.1)}
100%{transform:scale(1)} 100%{transform:scale(1)}
} }
#iddemo #E3 path{animation:flashstroke 1s linear infinite;}
@keyframes flashstroke{50%{stroke:red;stroke-width:1.5;}}
#iddemo #E3 polygon{animation:flashfill 1s linear infinite;}
@keyframes flashfill{50%{stroke:red;stroke-width:1.5;fill:red}}

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2011, 2012, 2014-2020 Laboratoire de Recherche // Copyright (C) 2011, 2012, 2014-2021 Laboratoire de Recherche
// et Développement de l'Epita (LRDE). // et Développement de l'Epita (LRDE).
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6), // Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre // département Systèmes Répartis Coopératifs (SRC), Université Pierre
@ -115,6 +115,8 @@ namespace spot
const char* nl_ = "\\n"; const char* nl_ = "\\n";
const char* label_pre_ = "label=\""; const char* label_pre_ = "label=\"";
char label_post_ = '"'; char label_post_ = '"';
bool opt_id_ = false;
std::string opt_id_graph_;
const_twa_graph_ptr aut_; const_twa_graph_ptr aut_;
std::string opt_font_; std::string opt_font_;
@ -279,6 +281,18 @@ namespace spot
case 'h': case 'h':
opt_vertical_ = false; opt_vertical_ = false;
break; break;
case 'i':
if (*options == '(')
{
auto* end = strchr(++options, ')');
if (!end)
throw std::runtime_error
("unclosed \"i(...\" for print_dot()");
opt_id_graph_ = std::string(options, end - options);
options = end + 1;
}
opt_id_ = true;
break;
case 'k': case 'k':
opt_state_labels_ = true; opt_state_labels_ = true;
break; break;
@ -516,8 +530,19 @@ namespace spot
os_ << 'T' << d << 'T' << dest; os_ << 'T' << d << 'T' << dest;
else else
os_ << d; os_ << d;
if (style && *style) if ((style && *style) || opt_id_)
os_ << " [" << style << ']'; {
os_ << " [";
const char* sep = "";
if (style && *style)
{
os_ << style;
sep = ",";
}
if (opt_id_)
os_ << sep << "id=\"E" << dest << 'E' << d << '\"';
os_ << ']';
}
os_ << '\n'; os_ << '\n';
} }
univ = 2; univ = 2;
@ -628,6 +653,12 @@ namespace spot
<< "\"\n node [fontname=\"" << opt_font_ << "\"\n node [fontname=\"" << opt_font_
<< "\"]\n edge [fontname=\"" << opt_font_ << "\"]\n edge [fontname=\"" << opt_font_
<< "\"]\n"; << "\"]\n";
if (opt_id_)
{
if (!opt_id_graph_.empty())
escape_str(os_ << " id=\"", opt_id_graph_) << "\"\n";
os_ << " node [id=\"S\\N\"]\n";
}
// Always copy the environment variable into a static string, // Always copy the environment variable into a static string,
// so that we (1) look it up once, but (2) won't crash if the // so that we (1) look it up once, but (2) won't crash if the
// environment is changed. // environment is changed.
@ -805,8 +836,15 @@ namespace spot
os_ << '#' << aut_->get_graph().index_of_edge(t); os_ << '#' << aut_->get_graph().index_of_edge(t);
os_ << '"'; os_ << '"';
} }
if (opt_id_)
{
unsigned index = aut_->get_graph().index_of_edge(t);
os_ << ", id=\"E" << index << '"';
// Somehow \E must appear as \\E in tooltip in
// graphviz 2.43.0; this looks like a bug.
os_ << ", tooltip=\"\\\\E\\n#" << index << '"';
}
} }
std::string highlight; std::string highlight;
int color_num = -1; int color_num = -1;
if (highlight_edges_) if (highlight_edges_)
@ -966,6 +1004,8 @@ namespace spot
// May only occur if the call to // May only occur if the call to
// determine_unknown_acceptance() above is removed. // determine_unknown_acceptance() above is removed.
os_ << " color=orange\n"; os_ << " color=orange\n";
if (opt_id_)
os_ << " id=\"SCC" << i << "\"\n";
if (name_ || opt_show_acc_) if (name_ || opt_show_acc_)
{ {

View file

@ -55,76 +55,87 @@ EOF
test "1 2 4" = "`autfilt --stats='%u %[s]u %[e]u' alt.hoa`" test "1 2 4" = "`autfilt --stats='%u %[s]u %[e]u' alt.hoa`"
autfilt --has-univ-branch --has-exist-branch --dot=bans alt.hoa >alt.dot autfilt --has-univ-branch --has-exist-branch --dot=bansi alt.hoa >alt.dot
aho='arrowhead=onormal'
b='style=bold,'
tE='tooltip="\\E'
cat >expect.dot <<EOF cat >expect.dot <<EOF
digraph "" { digraph "" {
rankdir=LR rankdir=LR
label="Fin(⓿)\n[co-Büchi]" label="Fin(⓿)\n[co-Büchi]"
labelloc="t" labelloc="t"
node [shape="box",style="rounded",width="0.5"] node [shape="box",style="rounded",width="0.5"]
node [id="S\N"]
I [label="", style=invis, width=0] I [label="", style=invis, width=0]
I -> -11 [arrowhead=onormal] I -> -11 [$aho]
subgraph cluster_0 { subgraph cluster_0 {
color=green color=green
id="SCC0"
label="" label=""
2 [label="G(a)"] 2 [label="G(a)"]
} }
subgraph cluster_1 { subgraph cluster_1 {
color=red color=red
id="SCC1"
label="" label=""
1 [label="FG(a)\n⓿"] 1 [label="FG(a)\n⓿"]
} }
subgraph cluster_2 { subgraph cluster_2 {
color=green color=green
id="SCC2"
label="" label=""
6 [label="t"] 6 [label="t"]
} }
subgraph cluster_3 { subgraph cluster_3 {
color=red color=red
id="SCC3"
label="" label=""
4 [label="F(b)\n⓿"] 4 [label="F(b)\n⓿"]
} }
subgraph cluster_4 { subgraph cluster_4 {
color=green color=green
id="SCC4"
label="" label=""
3 [label="GF(b)"] 3 [label="GF(b)"]
-8 [label=<>,shape=point,width=0.05,height=0.05] -8 [label=<>,shape=point,width=0.05,height=0.05]
} }
subgraph cluster_5 { subgraph cluster_5 {
color=red color=red
id="SCC5"
label="" label=""
5 [label="((a) U (b))\n⓿"] 5 [label="((a) U (b))\n⓿"]
} }
subgraph cluster_6 { subgraph cluster_6 {
color=black color=black
id="SCC6"
label="" label=""
0 [label="((((a) U (b)) && GF(b)) && FG(a))"] 0 [label="((((a) U (b)) && GF(b)) && FG(a))"]
} }
-11 [label=<>,shape=point,width=0.05,height=0.05] -11 [label=<>,shape=point,width=0.05,height=0.05]
-11 -> 0 -11 -> 0 [id="E-11E0"]
-11 -> 2 -11 -> 2 [id="E-11E2"]
0 -> -1 [label="b", arrowhead=onormal] 0 -> -1 [label="b", id="E1", $tE\n#1", $aho]
-1 [label=<>,shape=point,width=0.05,height=0.05] -1 [label=<>,shape=point,width=0.05,height=0.05]
-1 -> 1 -1 -> 1 [id="E-1E1"]
-1 -> 3 -1 -> 3 [id="E-1E3"]
0 -> -4 [label="a & !b", style=bold, color="#E31A1C", arrowhead=onormal] 0 -> -4 [label="a & !b", id="E2", $tE\n#2", $b color="#E31A1C", $aho]
-4 [label=<>,shape=point,width=0.05,height=0.05] -4 [label=<>,shape=point,width=0.05,height=0.05]
-4 -> 1 [style=bold, color="#E31A1C"] -4 -> 1 [$b color="#E31A1C",id="E-4E1"]
-4 -> 3 [style=bold, color="#E31A1C"] -4 -> 3 [$b color="#E31A1C",id="E-4E3"]
-4 -> 5 [style=bold, color="#E31A1C"] -4 -> 5 [$b color="#E31A1C",id="E-4E5"]
1 -> 2 [label="a"] 1 -> 2 [label="a", id="E3", $tE\n#3"]
1 -> 1 [label="1"] 1 -> 1 [label="1", id="E4", $tE\n#4"]
2 -> 2 [label="a"] 2 -> 2 [label="a", id="E5", $tE\n#5"]
3 -> 3 [label="b"] 3 -> 3 [label="b", id="E6", $tE\n#6"]
3 -> -8 [label="!b", style=bold, color="#FF7F00", arrowhead=onormal] 3 -> -8 [label="!b", id="E7", $tE\n#7", $b color="#FF7F00", $aho]
-8 -> 3 [style=bold, color="#FF7F00"] -8 -> 3 [$b color="#FF7F00",id="E-8E3"]
-8 -> 4 [style=bold, color="#FF7F00"] -8 -> 4 [$b color="#FF7F00",id="E-8E4"]
4 -> 6 [label="b"] 4 -> 6 [label="b", id="E8", $tE\n#8"]
4 -> 4 [label="!b"] 4 -> 4 [label="!b", id="E9", $tE\n#9"]
5 -> 6 [label="b"] 5 -> 6 [label="b", id="E10", $tE\n#10"]
5 -> 5 [label="a & !b"] 5 -> 5 [label="a & !b", id="E11", $tE\n#11"]
6 -> 6 [label="1"] 6 -> 6 [label="1", id="E12", $tE\n#12"]
} }
EOF EOF
@ -502,7 +513,6 @@ EOF
run 0 autfilt --dot='baryf(Lato)' ex6 > ex6.dot run 0 autfilt --dot='baryf(Lato)' ex6 > ex6.dot
style='arrowhead=onormal'
cat >expect6.dot<<EOF cat >expect6.dot<<EOF
digraph "" { digraph "" {
rankdir=LR rankdir=LR
@ -513,20 +523,20 @@ digraph "" {
node [fontname="Lato"] node [fontname="Lato"]
edge [fontname="Lato"] edge [fontname="Lato"]
I [label="", style=invis, width=0] I [label="", style=invis, width=0]
I -> -1 [arrowhead=onormal] I -> -1 [$aho]
-1 [label=<>,shape=point,width=0.05,height=0.05] -1 [label=<>,shape=point,width=0.05,height=0.05]
-1 -> 0 -1 -> 0
-1 -> 1 -1 -> 1
0 [label=<0>] 0 [label=<0>]
0 -> 0 [label=<!a &amp; !c>] 0 -> 0 [label=<!a &amp; !c>]
0 -> -1.1 [label=<a &amp; b &amp; !c>, style=bold, color="#FF4DA0", $style] 0 -> -1.1 [label=<a &amp; b &amp; !c>, $b color="#FF4DA0", $aho]
-1.1 [label=<>,shape=point,width=0.05,height=0.05] -1.1 [label=<>,shape=point,width=0.05,height=0.05]
-1.1 -> 0 [style=bold, color="#FF4DA0"] -1.1 -> 0 [$b color="#FF4DA0"]
-1.1 -> 1 [style=bold, color="#FF4DA0"] -1.1 -> 1 [$b color="#FF4DA0"]
0 -> -1.2 [label=<a &amp; !c>, style=bold, color="#FF7F00", arrowhead=onormal] 0 -> -1.2 [label=<a &amp; !c>, $b color="#FF7F00", $aho]
-1.2 [label=<>,shape=point,width=0.05,height=0.05] -1.2 [label=<>,shape=point,width=0.05,height=0.05]
-1.2 -> 0 [style=bold, color="#FF7F00"] -1.2 -> 0 [$b color="#FF7F00"]
-1.2 -> 1 [style=bold, color="#FF7F00"] -1.2 -> 1 [$b color="#FF7F00"]
1 [label=<1>] 1 [label=<1>]
1 -> 1 [label=<b>] 1 -> 1 [label=<b>]
} }
@ -608,16 +618,16 @@ digraph "SLAA for c R (c | G(a & b) | (F!b & F!a))" {
} }
0 -> 4 [label=<c>] 0 -> 4 [label=<c>]
0 -> 0 [label=<!a &amp; !b &amp; !c>] 0 -> 0 [label=<!a &amp; !b &amp; !c>]
0 -> -1 [label=<a &amp; b &amp; !c>, arrowhead=onormal] 0 -> -1 [label=<a &amp; b &amp; !c>, $aho]
-1 -> 0 -1 -> 0
-1 -> 1 -1 -> 1
0 -> -4 [label=<a &amp; !b &amp; !c>, arrowhead=onormal] 0 -> -4 [label=<a &amp; !b &amp; !c>, $aho]
-4 -> 0 -4 -> 0
-4 -> 2 -4 -> 2
0 -> -7 [label=<!a &amp; b &amp; !c>, arrowhead=onormal] 0 -> -7 [label=<!a &amp; b &amp; !c>, $aho]
-7 -> 0 -7 -> 0
-7 -> 3 -7 -> 3
0 -> -10 [label=<a &amp; b &amp; !c>, arrowhead=onormal] 0 -> -10 [label=<a &amp; b &amp; !c>, $aho]
-10 -> 0 -10 -> 0
-10 -> 2 -10 -> 2
-10 -> 3 -10 -> 3
@ -701,17 +711,17 @@ digraph "SLAA for c R (c | G(a & b) | (F!b & F!a))" {
} }
0 -> 4 [label=<c>] 0 -> 4 [label=<c>]
0 -> 0 [label=<!a &amp; !b &amp; !c>] 0 -> 0 [label=<!a &amp; !b &amp; !c>]
0 -> -1 [label=<a &amp; b &amp; !c>, arrowhead=onormal] 0 -> -1 [label=<a &amp; b &amp; !c>, $aho]
-1 -> 0 -1 -> 0
-1 -> 1 -1 -> 1
0 -> -4 [label=<a &amp; !b &amp; !c>, arrowhead=onormal] 0 -> -4 [label=<a &amp; !b &amp; !c>, $aho]
-4 -> 0 -4 -> 0
-4 -> 2 -4 -> 2
0 -> -7 [label=<!a &amp; b &amp; !c>, arrowhead=onormal] 0 -> -7 [label=<!a &amp; b &amp; !c>, $aho]
-7 -> 0 -7 -> 0
-7 -> 3 -7 -> 3
1 -> 1 [label=<a &amp; b>] 1 -> 1 [label=<a &amp; b>]
1 -> -10 [label=<a &amp; b &amp; !c>, arrowhead=onormal] 1 -> -10 [label=<a &amp; b &amp; !c>, $aho]
-10 -> 0 -10 -> 0
-10 -> 2 -10 -> 2
-10 -> 3 -10 -> 3
@ -756,17 +766,17 @@ digraph "" {
I [label="", style=invis, width=0] I [label="", style=invis, width=0]
I -> 0 I -> 0
0 [label=<0>] 0 [label=<0>]
0 -> -1.1 [label=<b &amp; c>, style=bold, color="#FF4DA0", arrowhead=onormal] 0 -> -1.1 [label=<b &amp; c>, $b color="#FF4DA0", $aho]
-1.1 [label=<>,shape=point,width=0.05,height=0.05] -1.1 [label=<>,shape=point,width=0.05,height=0.05]
-1.1 -> 1 [style=bold, color="#FF4DA0"] -1.1 -> 1 [$b color="#FF4DA0"]
-1.1 -> 2 [style=bold, color="#FF4DA0"] -1.1 -> 2 [$b color="#FF4DA0"]
1 [label=<1>] 1 [label=<1>]
1 -> -1.1 [label=<a &amp; b>, style=bold, color="#FF4DA0", arrowhead=onormal] 1 -> -1.1 [label=<a &amp; b>, $b color="#FF4DA0", $aho]
2 [label=<2>] 2 [label=<2>]
2 -> -1.2 [label=<!a &amp; !b &amp; !c>, style=bold, color="#FF7F00", $style] 2 -> -1.2 [label=<!a &amp; !b &amp; !c>, $b color="#FF7F00", $aho]
-1.2 [label=<>,shape=point,width=0.05,height=0.05] -1.2 [label=<>,shape=point,width=0.05,height=0.05]
-1.2 -> 1 [style=bold, color="#FF7F00"] -1.2 -> 1 [$b color="#FF7F00"]
-1.2 -> 2 [style=bold, color="#FF7F00"] -1.2 -> 2 [$b color="#FF7F00"]
} }
EOF EOF
@ -803,20 +813,20 @@ digraph "" {
I [label="", style=invis, width=0] I [label="", style=invis, width=0]
I -> 0 I -> 0
0 [label=<0>] 0 [label=<0>]
0 -> -1.1 [label=<b &amp; c>, style=bold, color="#FF4DA0", arrowhead=onormal] 0 -> -1.1 [label=<b &amp; c>, $b color="#FF4DA0", $aho]
-1.1 [label=<>,shape=point,width=0.05,height=0.05] -1.1 [label=<>,shape=point,width=0.05,height=0.05]
-1.1 -> 1 [style=bold, color="#FF4DA0"] -1.1 -> 1 [$b color="#FF4DA0"]
-1.1 -> 2 [style=bold, color="#FF4DA0"] -1.1 -> 2 [$b color="#FF4DA0"]
1 [label=<1>] 1 [label=<1>]
1 -> -1.3 [label=<a &amp; b>, style=bold, color="#6A3D9A", arrowhead=onormal] 1 -> -1.3 [label=<a &amp; b>, $b color="#6A3D9A", $aho]
-1.3 [label=<>,shape=point,width=0.05,height=0.05] -1.3 [label=<>,shape=point,width=0.05,height=0.05]
-1.3 -> 1 [style=bold, color="#6A3D9A"] -1.3 -> 1 [$b color="#6A3D9A"]
-1.3 -> 2 [style=bold, color="#6A3D9A"] -1.3 -> 2 [$b color="#6A3D9A"]
2 [label=<2>] 2 [label=<2>]
2 -> -1.2 [label=<!a &amp; !b &amp; !c>, style=bold, color="#FF7F00", $style] 2 -> -1.2 [label=<!a &amp; !b &amp; !c>, $b color="#FF7F00", $aho]
-1.2 [label=<>,shape=point,width=0.05,height=0.05] -1.2 [label=<>,shape=point,width=0.05,height=0.05]
-1.2 -> 1 [style=bold, color="#FF7F00"] -1.2 -> 1 [$b color="#FF7F00"]
-1.2 -> 2 [style=bold, color="#FF7F00"] -1.2 -> 2 [$b color="#FF7F00"]
} }
EOF EOF
@ -881,10 +891,10 @@ digraph "SLAA for G((b & Fa) | (!b & G!a))" {
-4 [label=<>,shape=point,width=0.05,height=0.05] -4 [label=<>,shape=point,width=0.05,height=0.05]
} }
0 -> 0 [label=<a &amp; b>] 0 -> 0 [label=<a &amp; b>]
0 -> -1 [label=<!a &amp; b>, arrowhead=onormal] 0 -> -1 [label=<!a &amp; b>, $aho]
-1 -> 0 -1 -> 0
-1 -> 1 -1 -> 1
0 -> -4 [label=<!a &amp; !b>, arrowhead=onormal] 0 -> -4 [label=<!a &amp; !b>, $aho]
-4 -> 0 -4 -> 0
-4 -> 2 -4 -> 2
1 -> 3 [label=<a>] 1 -> 3 [label=<a>]

View file

@ -314,34 +314,38 @@ EOF
autfilt -H input | autfilt -H input |
SPOT_DEFAULT_FORMAT=dot \ SPOT_DEFAULT_FORMAT=dot \
SPOT_DOTDEFAULT=vcsnaA \ SPOT_DOTDEFAULT=vcsnaAi \
SPOT_DOTEXTRA='/* hello world */' \ SPOT_DOTEXTRA='/* hello world */' \
autfilt >output autfilt >output
cat >expected <<EOF cat >expected <<EOF
digraph "" { digraph "" {
node [shape="circle"] node [shape="circle"]
node [id="S\N"]
/* hello world */ /* hello world */
I [label="", style=invis, height=0] I [label="", style=invis, height=0]
I -> 3 I -> 3
subgraph cluster_0 { subgraph cluster_0 {
color=green color=green
id="SCC0"
1 [label="s1", peripheries=2] 1 [label="s1", peripheries=2]
} }
subgraph cluster_1 { subgraph cluster_1 {
color=green color=green
id="SCC1"
0 [label="s0", peripheries=2] 0 [label="s0", peripheries=2]
} }
subgraph cluster_2 { subgraph cluster_2 {
color=black color=black
id="SCC2"
3 [label="s3"] 3 [label="s3"]
} }
0 -> 0 [label="b"] 0 -> 0 [label="b", id="E1", tooltip="\\\\E\n#1"]
1 -> 1 [label="a"] 1 -> 1 [label="a", id="E2", tooltip="\\\\E\n#2"]
2 [label="s2"] 2 [label="s2"]
2 -> 0 [label="b"] 2 -> 0 [label="b", id="E3", tooltip="\\\\E\n#3"]
3 -> 1 [label="a"] 3 -> 1 [label="a", id="E4", tooltip="\\\\E\n#4"]
3 -> 0 [label="b"] 3 -> 0 [label="b", id="E5", tooltip="\\\\E\n#5"]
} }
EOF EOF
@ -371,7 +375,7 @@ digraph "G(Fa & Fb)" {
EOF EOF
diff output expected diff output expected
ltl2tgba -dban 'GFa & GFb' >output ltl2tgba -d'bani(foo)' 'GFa & GFb' >output
cat output cat output
cat >expected <<EOF cat >expected <<EOF
digraph "G(Fa & Fb)" { digraph "G(Fa & Fb)" {
@ -379,13 +383,15 @@ digraph "G(Fa & Fb)" {
label="G(Fa & Fb)\nInf(⓿)&Inf(❶)\n[gen. Büchi 2]" label="G(Fa & Fb)\nInf(⓿)&Inf(❶)\n[gen. Büchi 2]"
labelloc="t" labelloc="t"
node [shape="circle"] node [shape="circle"]
id="foo"
node [id="S\N"]
I [label="", style=invis, width=0] I [label="", style=invis, width=0]
I -> 0 I -> 0
0 [label="0"] 0 [label="0"]
0 -> 0 [label="!a & !b"] 0 -> 0 [label="!a & !b", id="E1", tooltip="\\\\E\n#1"]
0 -> 0 [label="a & !b\n⓿"] 0 -> 0 [label="a & !b\n⓿", id="E2", tooltip="\\\\E\n#2"]
0 -> 0 [label="!a & b\n❶"] 0 -> 0 [label="!a & b\n❶", id="E3", tooltip="\\\\E\n#3"]
0 -> 0 [label="a & b\n⓿❶"] 0 -> 0 [label="a & b\n⓿❶", id="E4", tooltip="\\\\E\n#4"]
} }
EOF EOF
diff output expected diff output expected

View file

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (C) 2015, 2017, 2018, 2020 Laboratoire de Recherche et # Copyright (C) 2015, 2017, 2018, 2020, 2021 Laboratoire de Recherche
# Développement de l'Epita # et Développement de l'Epita
# #
# This file is part of Spot, a model checking library. # This file is part of Spot, a model checking library.
# #
@ -68,7 +68,7 @@ State: 10
--END-- --END--
EOF EOF
run 0 autfilt --dot=as in.hoa > out.dot run 0 autfilt --dot=asi in.hoa > out.dot
# The important stuff is the color=xxx lines # The important stuff is the color=xxx lines
cat <<EOF >expected cat <<EOF >expected
@ -77,79 +77,88 @@ digraph "" {
label="(Inf(0)&Inf(1)) & Fin(2)\n[Streett-like 3]" label="(Inf(0)&Inf(1)) & Fin(2)\n[Streett-like 3]"
labelloc="t" labelloc="t"
node [shape="ellipse",width="0.5",height="0.5"] node [shape="ellipse",width="0.5",height="0.5"]
node [id="S\N"]
I [label="", style=invis, width=0] I [label="", style=invis, width=0]
I -> 1 I -> 1
subgraph cluster_0 { subgraph cluster_0 {
color=grey color=grey
id="SCC0"
label="" label=""
5 [label="5"] 5 [label="5"]
6 [label="6"] 6 [label="6"]
} }
subgraph cluster_1 { subgraph cluster_1 {
color=grey color=grey
id="SCC1"
label="" label=""
0 [label="0"] 0 [label="0"]
} }
subgraph cluster_2 { subgraph cluster_2 {
color=green color=green
id="SCC2"
label="" label=""
9 [label="9"] 9 [label="9"]
10 [label="10"] 10 [label="10"]
} }
subgraph cluster_3 { subgraph cluster_3 {
color=green color=green
id="SCC3"
label="" label=""
8 [label="8"] 8 [label="8"]
} }
subgraph cluster_4 { subgraph cluster_4 {
color=green color=green
id="SCC4"
label="" label=""
7 [label="7"] 7 [label="7"]
} }
subgraph cluster_5 { subgraph cluster_5 {
color=black color=black
id="SCC5"
label="" label=""
2 [label="2"] 2 [label="2"]
} }
subgraph cluster_6 { subgraph cluster_6 {
color=red color=red
id="SCC6"
label="" label=""
4 [label="4"] 4 [label="4"]
} }
subgraph cluster_7 { subgraph cluster_7 {
color=green color=green
id="SCC7"
label="" label=""
1 [label="1"] 1 [label="1"]
3 [label="3"] 3 [label="3"]
} }
0 -> 0 [label="a & b\n{0,1,2}"] 0 -> 0 [label="a & b\n{0,1,2}", id="E1", tooltip="\\\\E\n#1"]
0 -> 0 [label="!a & !b\n{2}"] 0 -> 0 [label="!a & !b\n{2}", id="E2", tooltip="\\\\E\n#2"]
0 -> 5 [label="a\n{2}"] 0 -> 5 [label="a\n{2}", id="E3", tooltip="\\\\E\n#3"]
1 -> 4 [label="b"] 1 -> 4 [label="b", id="E4", tooltip="\\\\E\n#4"]
1 -> 3 [label="a & !b"] 1 -> 3 [label="a & !b", id="E5", tooltip="\\\\E\n#5"]
2 -> 0 [label="a"] 2 -> 0 [label="a", id="E8", tooltip="\\\\E\n#8"]
2 -> 7 [label="b"] 2 -> 7 [label="b", id="E9", tooltip="\\\\E\n#9"]
3 -> 1 [label="a & b\n{0,1}"] 3 -> 1 [label="a & b\n{0,1}", id="E10", tooltip="\\\\E\n#10"]
4 -> 4 [label="!b\n{1,2}"] 4 -> 4 [label="!b\n{1,2}", id="E6", tooltip="\\\\E\n#6"]
4 -> 2 [label="b"] 4 -> 2 [label="b", id="E7", tooltip="\\\\E\n#7"]
5 -> 6 [label="1"] 5 -> 6 [label="1", id="E11", tooltip="\\\\E\n#11"]
6 -> 5 [label="1"] 6 -> 5 [label="1", id="E12", tooltip="\\\\E\n#12"]
7 -> 7 [label="!a & b\n{0,1}"] 7 -> 7 [label="!a & b\n{0,1}", id="E13", tooltip="\\\\E\n#13"]
7 -> 7 [label="a & b\n{0,2}"] 7 -> 7 [label="a & b\n{0,2}", id="E14", tooltip="\\\\E\n#14"]
7 -> 8 [label="1"] 7 -> 8 [label="1", id="E15", tooltip="\\\\E\n#15"]
8 -> 8 [label="!a & b\n{0,2}"] 8 -> 8 [label="!a & b\n{0,2}", id="E16", tooltip="\\\\E\n#16"]
8 -> 8 [label="a & b\n{0,1}"] 8 -> 8 [label="a & b\n{0,1}", id="E17", tooltip="\\\\E\n#17"]
8 -> 9 [label="1"] 8 -> 9 [label="1", id="E18", tooltip="\\\\E\n#18"]
9 -> 9 [label="!a & b\n{0,2}"] 9 -> 9 [label="!a & b\n{0,2}", id="E19", tooltip="\\\\E\n#19"]
9 -> 10 [label="a & b\n{0,1}"] 9 -> 10 [label="a & b\n{0,1}", id="E20", tooltip="\\\\E\n#20"]
10 -> 9 [label="!a & b\n{0,1}"] 10 -> 9 [label="!a & b\n{0,1}", id="E21", tooltip="\\\\E\n#21"]
10 -> 10 [label="a & b\n{0,2}"] 10 -> 10 [label="a & b\n{0,2}", id="E22", tooltip="\\\\E\n#22"]
} }
EOF EOF
diff out.dot expected diff out.dot expected
# While we are here, make sure scc_filter remove those grey SCCs. # While we are here, make sure scc_filter removes those grey SCCs.
autfilt --small -x simul=0 in.hoa -H > out.hoa autfilt --small -x simul=0 in.hoa -H > out.hoa
cat >expected.hoa <<EOF cat >expected.hoa <<EOF
HOA: v1 HOA: v1