dotty: colored acceptance sets

This implement several new options for --dot in order to
allow emptiness sets to be output as colored ⓿ or ❶...
Also add a SPOT_DOTDEFAULT environment variable.

* NEWS, src/bin/man/spot-x.x, src/bin/common_aoutput.cc,
src/bin/dstar2tgba.cc: Document the new options.
* doc/org/.dir-locals.el, doc/org/init.el.in: Setup
SPOT_DOTEXTRA and SPOT_DOTDEFAULT for all documents.
* doc/org/autfilt.org, doc/org/dstar2tgba.org, doc/org/ltl2tgba.org,
doc/org/ltldo.org, doc/org/oaut.org, doc/org/randaut.org,
doc/org/satmin.org: Adjust to this new setup.
* src/misc/escape.cc, src/misc/escape.hh (escape_html): New function.
* src/tgba/acc.cc, src/tgba/acc.hh (to_text, to_html): New method.
* src/tgbaalgos/dotty.cc: Implement the new options.
* src/tgbatest/readsave.test, wrap/python/tests/automata.ipynb: More
tests.
* wrap/python/spot.py: Make sure the default argument for
dotty_reachable is None, so that SPOT_DOTDEFAULT is honored.
This commit is contained in:
Alexandre Duret-Lutz 2015-03-17 09:08:20 +01:00
parent 7caf2b83d6
commit 838bfb2ae3
21 changed files with 1500 additions and 1193 deletions

8
NEWS
View file

@ -110,9 +110,11 @@ New in spot 1.99b (not yet released)
- GraphViz output now uses an horizontal layout by default. The
--dot option of the various command-line tools takes an optional
parameter to fine-tune the GraphViz output (including vertical
layout, round states, and named automata). The environment
variable SPOT_DOTEXTRA can also be used to add extra attributes
to the output graph.
layout, round states, named automata, and different ways to
colorize the acceptance sets). The environment
variables SPOT_DOTDEFAULT and SPOT_DOTEXTRA can also be used
to respectively provide a default argument to --dot, and
add extra attributes to the output graph.
- Never claims can now be output in the style usd by Spin since
version 6.2.4 (i.e., using do..od instead of if..fi, and with

View file

@ -8,6 +8,8 @@
(setq org-babel-sh-command (concat "PATH=../../src/bin"
path-separator
"$PATH sh"))
(setenv "SPOT_DOTDEFAULT" "brf(Lato)")
(setenv "SPOT_DOTEXTRA" "node[style=filled, fillcolor=\"#ffffa0\"]")
(org-babel-do-load-languages 'org-babel-load-languages
'((sh . t)
(python . t)

View file

@ -27,7 +27,7 @@ same stream, =autfilt= will process them in batch.
The output format can be controlled using [[file:oaut.org][the common output options]]
(like =--spin=, =--lbtt=, =--dot=, =--hoaf=...).
#+BEGIN_SRC sh :results verbatim :exports both
#+BEGIN_SRC sh :results verbatim :exports code
cat >example.hoa <<EOF
HOA: v1
States: 1
@ -43,13 +43,18 @@ EOF
autfilt example.hoa --dot
#+END_SRC
#+BEGIN_SRC sh :results verbatim :exports results
SPOT_DOTEXTRA= autfilt example.hoa --dot=
#+END_SRC
#+RESULTS:
: digraph G {
: 0 [label="", style=invis, height=0]
: 0 -> 1
: 1 [label="0"]
: 1 -> 1 [label="p0\n{0}"]
: 1 -> 1 [label="!p0"]
: rankdir=LR
: I [label="", style=invis, width=0]
: I -> 0
: 0 [label="0"]
: 0 -> 0 [label="p0\n{0}"]
: 0 -> 0 [label="!p0"]
: }
The =--spin= options implicitly requires a degeneralization:

View file

@ -68,48 +68,58 @@ a Monitor, using the same options as [[file:ltl2tgba.org][=ltl2tgba=]].
For instance here is the conversion to a Büchi automaton (=-B=) in [[http://http://www.graphviz.org/][GraphViz]]'s format:
#+BEGIN_SRC sh :results verbatim :exports both
#+BEGIN_SRC sh :results verbatim :exports code
dstar2tgba -B fagfb
#+END_SRC
#+BEGIN_SRC sh :results verbatim :exports results
SPOT_DOTEXTRA= dstar2tgba -B fagfb --dot=
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
rankdir=LR
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 0 [label="!a"]
0 -> 1 [label="a"]
1 [label="1", peripheries=2]
1 -> 1 [label="b"]
1 -> 2 [label="!b"]
I -> 1
0 [label="0", peripheries=2]
0 -> 0 [label="b"]
0 -> 2 [label="!b"]
1 [label="1"]
1 -> 0 [label="a"]
1 -> 1 [label="!a"]
2 [label="2"]
2 -> 1 [label="b"]
2 -> 0 [label="b"]
2 -> 2 [label="!b"]
}
#+end_example
Which can be rendered as:
Which can be rendered as (note that in this documentation
we use some [[file:aout.org][environement variables]] to produce a more colorful
output by default):
#+NAME: fagfb2ba
#+BEGIN_SRC sh :results verbatim :exports none
dstar2tgba -B fagfb | sed 's/\\/\\\\/'
#+BEGIN_SRC sh :results verbatim :exports code
dstar2tgba -B fagfb
#+END_SRC
#+RESULTS: fagfb2ba
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 0 [label="!a"]
0 -> 1 [label="a"]
1 [label="1", peripheries=2]
1 -> 1 [label="b"]
1 -> 2 [label="!b"]
I -> 1
0 [label="0", peripheries=2]
0 -> 0 [label=<b>]
0 -> 2 [label=<!b>]
1 [label="1"]
1 -> 0 [label=<a>]
1 -> 1 [label=<!a>]
2 [label="2"]
2 -> 1 [label="b"]
2 -> 2 [label="!b"]
2 -> 0 [label=<b>]
2 -> 2 [label=<!b>]
}
#+end_example
@ -153,7 +163,7 @@ T0_S3:
Here is the translation of =GFa & GFb= to a 4-state Streett automaton:
#+BEGIN_SRC sh :results verbatim :exports both
ltlfilt -f 'GFa & GFb' -l | ltl2dstar --automata=streett --ltl2nba=spin:../../src/bin/ltl2tgba@-sD - gfagfb
ltlfilt -f 'GFa & GFb' -l | ltl2dstar --automata=streett --ltl2nba=spin:ltl2tgba@-Ds - gfagfb
cat gfagfb
#+END_SRC
#+RESULTS:
@ -195,42 +205,27 @@ And now its conversion by =dstar2tgba= to a 2-state Büchi automaton.
We don't pass any option to =dstar2tgba= because converting to TGBA in
GraphViz's format is the default:
#+NAME: gfagfb2ba
#+BEGIN_SRC sh :results verbatim :exports code
dstar2tgba gfagfb
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
rankdir=LR
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 1 [label="1"]
1 [label="1"]
1 -> 1 [label="!a & !b"]
1 -> 1 [label="a & !b\n{0}"]
1 -> 1 [label="!a & b\n{1}"]
1 -> 1 [label="a & b\n{0,1}"]
}
#+end_example
#+NAME: gfagfb2ba
#+BEGIN_SRC sh :results verbatim :exports none
dstar2tgba gfagfb | sed 's/\\/\\\\/g'
#+END_SRC
#+RESULTS: gfagfb2ba
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 1 [label="1"]
0 -> 1 [label=<1>]
1 [label="1"]
1 -> 1 [label="!a & !b"]
1 -> 1 [label="a & !b\\n{0}"]
1 -> 1 [label="!a & b\\n{1}"]
1 -> 1 [label="a & b\\n{0,1}"]
1 -> 1 [label=<!a &amp; !b>]
1 -> 1 [label=<a &amp; !b<br/><font color="#5DA5DA">⓿</font>>]
1 -> 1 [label=<!a &amp; b<br/><font color="#F17CB0">❶</font>>]
1 -> 1 [label=<a &amp; b<br/><font color="#5DA5DA">⓿</font><font color="#F17CB0">❶</font>>]
}
#+end_example
@ -355,33 +350,33 @@ head -n 10 |
while read f; do
echo "$f"
ltlfilt -l -f "$f" |
ltl2dstar --ltl2nba=spin:../../src/bin/ltl2tgba@-sD - - |
ltl2dstar --ltl2nba=spin:../../src/bin/ltl2tgba@-Ds - - |
dstar2tgba -B --stats=' DRA: %Sst.; BA: %sst.; det.? %d; complete? %p'
done
#+END_SRC
#+RESULTS:
#+begin_example
c U (c & (a | b | (Xc U (a & Xc))))
DRA: 3st.; BA: 2st.; det.? 1; complete? 0
!b | F!c
DRA: 3st.; BA: 3st.; det.? 1; complete? 1
(!a R F!b) R !b
DRA: 6st.; BA: 5st.; det.? 1; complete? 0
b U !c
DRA: 3st.; BA: 2st.; det.? 1; complete? 0
(b | Fa) R Fc
DRA: 9st.; BA: 6st.; det.? 1; complete? 1
Ga U (Gc R (!a | Gc))
DRA: 7st.; BA: 7st.; det.? 0; complete? 0
GFc
DRA: 3st.; BA: 3st.; det.? 1; complete? 1
(F!c U a) R !a
DRA: 6st.; BA: 5st.; det.? 1; complete? 0
b | G!b
DRA: 4st.; BA: 3st.; det.? 1; complete? 0
!a R (!c & (!a | (F!b U (!a & F!b))))
DRA: 5st.; BA: 4st.; det.? 1; complete? 0
F(a & !b & G!c)
DRA: 2st.; BA: 3st.; det.? 0; complete? 0
GF!c
DRA: 3st.; BA: 3st.; det.? 1; complete? 1
!a | (a R b)
DRA: 3st.; BA: 2st.; det.? 1; complete? 0
Xc R (G!c R (b | G!c))
DRA: 4st.; BA: 2st.; det.? 1; complete? 0
c & G(b | F(a & c))
DRA: 5st.; BA: 3st.; det.? 1; complete? 0
XXFc
DRA: 4st.; BA: 4st.; det.? 1; complete? 1
XFc | Gb
DRA: 5st.; BA: 4st.; det.? 1; complete? 1
G(((!a & Gc) | (a & F!c)) U (!a | Ga))
DRA: 6st.; BA: 5st.; det.? 1; complete? 1
a & !b
DRA: 3st.; BA: 2st.; det.? 1; complete? 0
#+end_example
An important point you should be aware of when comparing these numbers
@ -426,6 +421,6 @@ states and $n$ acceptance pairs. Our translation to TGBA limits this
to $|Q|\cdot(2^n+1)$ states.
Sometimes, as in the [[#streett_to_tgba_example][example for =GFa & GFb=]] the output of this
conversion will happen to be deterministic. Let's say that this is
luck: Spot does not implement any algorithm to preserve the
determinism of Streett automata.
conversion happens to be deterministic. This is pure luck: Spot does
not implement any algorithm to preserve the determinism of Streett
automata.

View file

@ -24,6 +24,9 @@
(setq org-babel-sh-command
(concat "PATH=@abs_top_builddir@/src/bin" path-separator "$PATH sh"))
(setenv "SPOT_DOTDEFAULT" "brf(Lato)")
(setenv "SPOT_DOTEXTRA" "node[style=filled, fillcolor=\"#ffffa0\"]")
(setq org-export-html-home/up-format
"<div id=\"org-div-home-and-up\" style=\"text-align:center;white-space:nowrap;\">
<a accesskey=\"h\" href=\"%s\">UP</a> | <a accesskey=\"H\" href=\"%s\">HOME</a>

View file

@ -14,9 +14,12 @@ option.
Formulas to translate may be specified using [[file:ioltl.org][common input options for
LTL/PSL formulas]].
#+BEGIN_SRC sh :results verbatim :exports both
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -f 'Fa & GFb'
#+END_SRC
#+BEGIN_SRC sh :results verbatim :exports results
SPOT_DOTEXTRA= ltl2tgba -f 'Fa & GFb' --dot=
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
@ -47,23 +50,29 @@ ltl2tgba "Fa & GFb" | dot -Tpdf > tgba.pdf
#+END_SRC
#+RESULTS:
The result would look like this:
The result would look like this (note that in this documentation
we use some [[file:aout.org][environement variables]] to produce a more colorful
output by default)
#+NAME: dotex
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba "Fa & GFb" | sed 's/\\/\\\\/'
ltl2tgba "Fa & GFb"
#+END_SRC
#+RESULTS: dotex
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 1
0 [label="0"]
0 -> 0 [label="b\\n{0}"]
0 -> 0 [label="!b"]
0 -> 0 [label=<b<br/><font color="#5DA5DA">⓿</font>>]
0 -> 0 [label=<!b>]
1 [label="1"]
1 -> 0 [label="a"]
1 -> 1 [label="!a"]
1 -> 0 [label=<a>]
1 -> 1 [label=<!a>]
}
#+end_example
@ -74,53 +83,39 @@ $txt
#+RESULTS:
[[file:dotex.png]]
The string between braces, ={0}=, represents the sets of acceptance
sets a transition belongs to. In this case, there is only one
acceptance set, called =0=, containing a single transition. You may
have many transitions in the same acceptance set, and a transition may
also belong to multiple acceptance sets. An infinite path through
this automaton is accepting iff it visit each acceptance set
infinitely often. Therefore, in the above example, any accepted path
will /necessarily/ leave the initial state after a finite amount of
steps, and then it will verify the property =b= infinitely often. It
is also possible that an automaton do not use any acceptance set at
all, in which any run is accepting.
Characters like ⓿, ❶, etc. denotes the acceptance sets a transition
belongs to. In this case, there is only one acceptance set, called
=0=, containing a single transition. You may have many transitions in
the same acceptance set, and a transition may also belong to multiple
acceptance sets. An infinite path through this automaton is accepting
iff it visit each acceptance set infinitely often. Therefore, in the
above example, any accepted path will /necessarily/ leave the initial
state after a finite amount of steps, and then it will verify the
property =b= infinitely often. It is also possible that an automaton
do not use any acceptance set at all, in which any run is accepting.
Here is a TGBA with multiple acceptance sets (we omit the call to
=dot= to render the output of =ltl2tgba= from now on):
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba 'GFa & GFb'
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
rankdir=LR
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 0 [label="a & b\n{0,1}"]
0 -> 0 [label="!a & !b"]
0 -> 0 [label="!a & b\n{1}"]
0 -> 0 [label="a & !b\n{0}"]
}
#+end_example
#+NAME: dotex2
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba "GFa & GFb" | sed 's/\\/\\\\/'
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba "GFa & GFb"
#+END_SRC
#+RESULTS: dotex2
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 0 [label="a & b\\n{0,1}"]
0 -> 0 [label="!a & !b"]
0 -> 0 [label="!a & b\\n{1}"]
0 -> 0 [label="a & !b\\n{0}"]
0 -> 0 [label=<a &amp; b<br/><font color="#5DA5DA">⓿</font><font color="#F17CB0">❶</font>>]
0 -> 0 [label=<!a &amp; !b>]
0 -> 0 [label=<!a &amp; b<br/><font color="#F17CB0">❶</font>>]
0 -> 0 [label=<a &amp; !b<br/><font color="#5DA5DA">⓿</font>>]
}
#+end_example
@ -130,57 +125,38 @@ $txt
#+RESULTS:
[[file:dotex2.png]]
The above TGBA has two acceptance sets: =0= and =1=. The position of
The above TGBA has two acceptance sets: ⓿ and ❶. The position of
these acceptance sets ensures that atomic propositions =a= and =b= must
be true infinitely often.
A Büchi automaton for the previous formula can be obtained with the
=-B= option:
#+NAME: dotex2ba
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -B 'GFa & GFb'
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
rankdir=LR
I [label="", style=invis, width=0]
I -> 0
0 [label="0", peripheries=2]
0 -> 0 [label="a & b"]
0 -> 1 [label="!b"]
0 -> 2 [label="!a & b"]
1 [label="1"]
1 -> 0 [label="a & b"]
1 -> 1 [label="!b"]
1 -> 2 [label="!a & b"]
2 [label="2"]
2 -> 0 [label="a"]
2 -> 2 [label="!a"]
}
#+end_example
#+NAME: dotex2ba
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba -B 'GFa & GFb' | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: dotex2ba
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0", peripheries=2]
0 -> 0 [label="a & b"]
0 -> 1 [label="!b"]
0 -> 2 [label="!a & b"]
0 -> 0 [label=<a &amp; b>]
0 -> 1 [label=<!b>]
0 -> 2 [label=<!a &amp; b>]
1 [label="1"]
1 -> 0 [label="a & b"]
1 -> 1 [label="!b"]
1 -> 2 [label="!a & b"]
1 -> 0 [label=<a &amp; b>]
1 -> 1 [label=<!b>]
1 -> 2 [label=<!a &amp; b>]
2 [label="2"]
2 -> 0 [label="a"]
2 -> 2 [label="!a"]
2 -> 0 [label=<a>]
2 -> 2 [label=<!a>]
}
#+end_example
@ -201,48 +177,33 @@ is done internally):
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba --dot=t -B 'GFa & GFb'
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
rankdir=LR
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 0 [label="a & b\n{0}"]
0 -> 1 [label="!b\n{0}"]
0 -> 2 [label="!a & b\n{0}"]
1 [label="1"]
1 -> 0 [label="a & b"]
1 -> 1 [label="!b"]
1 -> 2 [label="!a & b"]
2 [label="2"]
2 -> 0 [label="a"]
2 -> 2 [label="!a"]
}
#+end_example
#+NAME: dotex2ba-t
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba --dot=t -B 'GFa & GFb' | sed 's/\\/\\\\/'
ltl2tgba --dot=.t -B 'GFa & GFb'
#+END_SRC
#+RESULTS: dotex2ba-t
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 0 [label="a & b\\n{0}"]
0 -> 1 [label="!b\\n{0}"]
0 -> 2 [label="!a & b\\n{0}"]
0 -> 0 [label=<a &amp; b<br/><font color="#5DA5DA">⓿</font>>]
0 -> 1 [label=<!b<br/><font color="#5DA5DA">⓿</font>>]
0 -> 2 [label=<!a &amp; b<br/><font color="#5DA5DA">⓿</font>>]
1 [label="1"]
1 -> 0 [label="a & b"]
1 -> 1 [label="!b"]
1 -> 2 [label="!a & b"]
1 -> 0 [label=<a &amp; b>]
1 -> 1 [label=<!b>]
1 -> 2 [label=<!a &amp; b>]
2 [label="2"]
2 -> 0 [label="a"]
2 -> 2 [label="!a"]
2 -> 0 [label=<a>]
2 -> 2 [label=<!a>]
}
#+end_example
@ -262,18 +223,28 @@ ltl2tgba --help | sed -n '/Output format:/,/^$/p' | sed '1d;$d'
#+begin_example
-8, --utf8 enable UTF-8 characters in output (ignored with
--lbtt or --spin)
--dot[=c|h|n|N|s|t|v] GraphViz's format (default). Add letters to chose
(c) circular nodes, (h) horizontal layout, (v)
vertical layout, (n) with name, (N) without name,
(s) with SCCs, (t) always transition-based
--dot[=a|b|c|f(FONT)|h|n|N|r|R|s|t|v]
GraphViz's format (default). Add letters for (a)
acceptance display, (b) acceptance sets as
bullets,(c) circular nodes, (f(FONT)) use FONT,
(h) horizontal layout, (v) vertical layout, (n)
with name, (N) without name, (r) rainbow colors
for acceptance set, (R) color acceptance set by
Inf/Fin, (s) with SCCs, (t) force transition-based
acceptance.
-H, --hoaf[=s|t|m|l] Output the automaton in HOA format. Add letters
to select (s) state-based acceptance, (t)
transition-based acceptance, (m) mixed acceptance,
(l) single-line output
-H, --hoaf[=i|s|t|m|l] Output the automaton in HOA format. Add letters
to select (i) use implicit labels for complete
deterministic automata, (s) prefer state-based
acceptance when possible [default], (t) force
transition-based acceptance, (m) mix state and
transition-based acceptance, (l) single-line
output
--lbtt[=t] LBTT's format (add =t to force transition-based
acceptance even on Büchi automata)
--name=FORMAT set the name of the output automaton
-o, --output=FORMAT send output to a file named FORMAT instead of
standard output. The first automaton sent to a
file truncates it unless FORMAT starts with '>>'.
-q, --quiet suppress all normal output
-s, --spin[=6|c] Spin neverclaim (implies --ba). Add letters to
select (6) Spin's 6.2.4 style, (c) comments on
@ -284,50 +255,31 @@ ltl2tgba --help | sed -n '/Output format:/,/^$/p' | sed '1d;$d'
Option =-8= can be used to improve the readability of the output
if your system can display UTF-8 correctly.
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -B8 'GFa & GFb'
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
rankdir=LR
I [label="", style=invis, width=0]
I -> 0
0 [label="0", peripheries=2]
0 -> 0 [label="a∧b"]
0 -> 1 [label="b̅"]
0 -> 2 [label="a̅∧b"]
1 [label="1"]
1 -> 0 [label="a∧b"]
1 -> 1 [label="b̅"]
1 -> 2 [label="a̅∧b"]
2 [label="2"]
2 -> 0 [label="a"]
2 -> 2 [label="a̅"]
}
#+end_example
#+NAME: dotex2ba8
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba -B8 "GFa & GFb" | sed 's/\\/\\\\/'
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -B8 "GFa & GFb"
#+END_SRC
#+RESULTS: dotex2ba8
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0", peripheries=2]
0 -> 0 [label="a∧b"]
0 -> 1 [label="b̅"]
0 -> 2 [label="a̅∧b"]
0 -> 0 [label=<a∧b>]
0 -> 1 [label=<>]
0 -> 2 [label=<a̅∧b>]
1 [label="1"]
1 -> 0 [label="a∧b"]
1 -> 1 [label="b̅"]
1 -> 2 [label="a̅∧b"]
1 -> 0 [label=<a∧b>]
1 -> 1 [label=<>]
1 -> 2 [label=<a̅∧b>]
2 [label="2"]
2 -> 0 [label="a"]
2 -> 2 [label="a̅"]
2 -> 0 [label=<a>]
2 -> 2 [label=<>]
}
#+end_example
@ -423,48 +375,30 @@ automaton.
An example formula where the difference between =-D= and =--small= is
flagrant is =Ga|Gb|Gc=:
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba 'Ga|Gb|Gc'
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
rankdir=LR
I [label="", style=invis, width=0]
I -> 0
0 [label="0", peripheries=2]
0 -> 1 [label="a"]
0 -> 2 [label="b"]
0 -> 3 [label="c"]
1 [label="1", peripheries=2]
1 -> 1 [label="a"]
2 [label="2", peripheries=2]
2 -> 2 [label="b"]
3 [label="3", peripheries=2]
3 -> 3 [label="c"]
}
#+end_example
#+NAME: gagbgc1
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba "Ga|Gb|Gc" | sed 's/\\/\\\\/'
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba "Ga|Gb|Gc"
#+END_SRC
#+RESULTS: gagbgc1
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0", peripheries=2]
0 -> 1 [label="a"]
0 -> 2 [label="b"]
0 -> 3 [label="c"]
1 [label="1", peripheries=2]
1 -> 1 [label="a"]
2 [label="2", peripheries=2]
2 -> 2 [label="b"]
3 [label="3", peripheries=2]
3 -> 3 [label="c"]
0 [label="0"]
0 -> 1 [label=<a>]
0 -> 2 [label=<b>]
0 -> 3 [label=<c>]
1 [label="1"]
1 -> 1 [label=<a>]
2 [label="2"]
2 -> 2 [label=<b>]
3 [label="3"]
3 -> 3 [label=<c>]
}
#+end_example
@ -474,80 +408,46 @@ $txt
#+RESULTS:
[[file:gagbgc1.png]]
#+NAME: gagbgc2
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -D 'Ga|Gb|Gc'
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
rankdir=LR
I [label="", style=invis, width=0]
I -> 6
0 [label="0", peripheries=2]
0 -> 0 [label="c"]
1 [label="1", peripheries=2]
1 -> 0 [label="!b & c"]
1 -> 1 [label="b & c"]
1 -> 2 [label="b & !c"]
2 [label="2", peripheries=2]
2 -> 2 [label="b"]
3 [label="3", peripheries=2]
3 -> 2 [label="!a & b"]
3 -> 3 [label="a & b"]
3 -> 5 [label="a & !b"]
4 [label="4", peripheries=2]
4 -> 0 [label="!a & c"]
4 -> 4 [label="a & c"]
4 -> 5 [label="a & !c"]
5 [label="5", peripheries=2]
5 -> 5 [label="a"]
6 [label="6", peripheries=2]
6 -> 0 [label="!a & !b & c"]
6 -> 1 [label="!a & b & c"]
6 -> 2 [label="!a & b & !c"]
6 -> 3 [label="a & b & !c"]
6 -> 4 [label="a & !b & c"]
6 -> 5 [label="a & !b & !c"]
6 -> 6 [label="a & b & c"]
}
#+end_example
#+NAME: gagbgc2
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba -D 'Ga|Gb|Gc' | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: gagbgc2
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 6
0 [label="0", peripheries=2]
0 -> 0 [label="c"]
0 -> 0 [label=<c>]
1 [label="1", peripheries=2]
1 -> 0 [label="!b & c"]
1 -> 1 [label="b & c"]
1 -> 2 [label="b & !c"]
1 -> 0 [label=<!b &amp; c>]
1 -> 1 [label=<b &amp; c>]
1 -> 2 [label=<b &amp; !c>]
2 [label="2", peripheries=2]
2 -> 2 [label="b"]
2 -> 2 [label=<b>]
3 [label="3", peripheries=2]
3 -> 2 [label="!a & b"]
3 -> 3 [label="a & b"]
3 -> 5 [label="a & !b"]
3 -> 2 [label=<!a &amp; b>]
3 -> 3 [label=<a &amp; b>]
3 -> 5 [label=<a &amp; !b>]
4 [label="4", peripheries=2]
4 -> 0 [label="!a & c"]
4 -> 4 [label="a & c"]
4 -> 5 [label="a & !c"]
4 -> 0 [label=<!a &amp; c>]
4 -> 4 [label=<a &amp; c>]
4 -> 5 [label=<a &amp; !c>]
5 [label="5", peripheries=2]
5 -> 5 [label="a"]
5 -> 5 [label=<a>]
6 [label="6", peripheries=2]
6 -> 0 [label="!a & !b & c"]
6 -> 1 [label="!a & b & c"]
6 -> 2 [label="!a & b & !c"]
6 -> 3 [label="a & b & !c"]
6 -> 4 [label="a & !b & c"]
6 -> 5 [label="a & !b & !c"]
6 -> 6 [label="a & b & c"]
6 -> 0 [label=<!a &amp; !b &amp; c>]
6 -> 1 [label=<!a &amp; b &amp; c>]
6 -> 2 [label=<!a &amp; b &amp; !c>]
6 -> 3 [label=<a &amp; b &amp; !c>]
6 -> 4 [label=<a &amp; !b &amp; c>]
6 -> 5 [label=<a &amp; !b &amp; !c>]
6 -> 6 [label=<a &amp; b &amp; c>]
}
#+end_example
@ -701,47 +601,30 @@ compatible outgoing transition exist.
-MD= (short for =--monitor --deterministic=) will output the minimal
deterministic monitor for the given formula.
#+NAME: monitor1
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -M '(Xa & Fb) | Gc'
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
rankdir=LR
I [label="", style=invis, width=0]
I -> 0
0 [label="0", peripheries=2]
0 -> 1 [label="1"]
0 -> 3 [label="c"]
1 [label="1", peripheries=2]
1 -> 2 [label="a"]
2 [label="2", peripheries=2]
2 -> 2 [label="1"]
3 [label="3", peripheries=2]
3 -> 3 [label="c"]
}
#+end_example
#+NAME: monitor1
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba -M '(Xa & Fb) | Gc' | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: monitor1
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0", peripheries=2]
0 -> 1 [label="1"]
0 -> 3 [label="c"]
1 [label="1", peripheries=2]
1 -> 2 [label="a"]
2 [label="2", peripheries=2]
2 -> 2 [label="1"]
3 [label="3", peripheries=2]
3 -> 3 [label="c"]
0 [label="0"]
0 -> 1 [label=<1>]
0 -> 3 [label=<c>]
1 [label="1"]
1 -> 2 [label=<a>]
2 [label="2"]
2 -> 2 [label=<1>]
3 [label="3"]
3 -> 3 [label=<c>]
}
#+end_example
@ -752,53 +635,33 @@ $txt
#+RESULTS:
[[file:monitor1.png]]
#+NAME: monitor2
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -MD '(Xa & Fb) | Gc'
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
rankdir=LR
I [label="", style=invis, width=0]
I -> 3
0 [label="0", peripheries=2]
0 -> 0 [label="1"]
1 [label="1", peripheries=2]
1 -> 0 [label="a"]
2 [label="2", peripheries=2]
2 -> 2 [label="c"]
3 [label="3", peripheries=2]
3 -> 1 [label="!c"]
3 -> 4 [label="c"]
4 [label="4", peripheries=2]
4 -> 0 [label="a"]
4 -> 2 [label="!a & c"]
}
#+end_example
#+NAME: monitor2
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba -MD '(Xa & Fb) | Gc' | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: monitor2
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 3
0 [label="0", peripheries=2]
0 -> 0 [label="1"]
1 [label="1", peripheries=2]
1 -> 0 [label="a"]
2 [label="2", peripheries=2]
2 -> 2 [label="c"]
3 [label="3", peripheries=2]
3 -> 1 [label="!c"]
3 -> 4 [label="c"]
4 [label="4", peripheries=2]
4 -> 0 [label="a"]
4 -> 2 [label="!a & c"]
0 [label="0"]
0 -> 0 [label=<1>]
1 [label="1"]
1 -> 0 [label=<a>]
2 [label="2"]
2 -> 2 [label=<c>]
3 [label="3"]
3 -> 1 [label=<!c>]
3 -> 4 [label=<c>]
4 [label="4"]
4 -> 0 [label=<a>]
4 -> 2 [label=<!a &amp; c>]
}
#+end_example
@ -811,7 +674,8 @@ $txt
Because they accept all finite executions that could be extended to
match the formula, monitor cannot be used to check for eventualities
such as =F(a)=. Any finite execution can be extended to match =F(a)=.
such as =F(a)=: indeed, any finite execution can be extended to match
=F(a)=.
# LocalWords: ltl tgba num toc PSL Büchi automata SRC GFb invis Acc
# LocalWords: ltlfilt filenames GraphViz vectorial pdf Tpdf dotex

View file

@ -312,13 +312,16 @@ the following words, then the string on the right is appended.
So for instance you can type just
#+BEGIN_SRC sh :results verbatim :exports both
#+BEGIN_SRC sh :results verbatim :exports code
ltldo ltl2ba -f a
#+END_SRC
to obtain a Dot output (this is the default output format for =ltldo=)
for the neverclaim produced by =ltl2ba -f a=.
#+BEGIN_SRC sh :results verbatim :exports result
SPOT_DOTEXTRA= ltldo ltl2ba -f a --dot=
#+END_SRC
#+RESULTS:
: digraph G {
: rankdir=LR

View file

@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
y# -*- coding: utf-8 -*-
#+TITLE: Common output options for automata
#+SETUPFILE: setup.org
#+HTML_LINK_UP: tools.html
@ -18,16 +18,22 @@ ltl2tgba --help | sed -n '/Output format:/,/^$/p' | sed '1d;$d'
#+begin_example
-8, --utf8 enable UTF-8 characters in output (ignored with
--lbtt or --spin)
--dot[=c|h|n|N|s|t|v] GraphViz's format (default). Add letters for (a)
acceptance display, (c) circular nodes, (h)
horizontal layout, (v) vertical layout, (n) with
name, (N) without name, (s) with SCCs, (t) force
transition-based acceptance.
-H, --hoaf[=s|t|m|l] Output the automaton in HOA format. Add letters
to select (s) prefer state-based acceptance when
possible [default], (t) force transition-based
acceptance, (m) mix state and transition-based
acceptance, (l) single-line output
--dot[=a|b|c|f(FONT)|h|n|N|r|R|s|t|v]
GraphViz's format (default). Add letters for (a)
acceptance display, (b) acceptance sets as
bullets,(c) circular nodes, (f(FONT)) use FONT,
(h) horizontal layout, (v) vertical layout, (n)
with name, (N) without name, (r) rainbow colors
for acceptance set, (R) color acceptance set by
Inf/Fin, (s) with SCCs, (t) force transition-based
acceptance.
-H, --hoaf[=i|s|t|m|l] Output the automaton in HOA format. Add letters
to select (i) use implicit labels for complete
deterministic automata, (s) prefer state-based
acceptance when possible [default], (t) force
transition-based acceptance, (m) mix state and
transition-based acceptance, (l) single-line
output
--lbtt[=t] LBTT's format (add =t to force transition-based
acceptance even on Büchi automata)
--name=FORMAT set the name of the output automaton
@ -118,148 +124,161 @@ represent. Here is a picture of these two automata:
#+NAME: hoafex
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba --dot=cn '(Ga -> Gb) W c' 'a U b' | dot | gvpack |
ltl2tgba --dot=.cn '(Ga -> Gb) W c' 'a U b' | dot | gvpack |
perl -pe 's/\\\n//g;s/\\/\\\\/g;s/graph G/graph cluster/g'
#+END_SRC
#+RESULTS: hoafex
#+begin_example
digraph root {
graph [bb="0,0,425,231.06",
graph [bb="0,0,427,231.07",
fontname=Lato,
labelloc=t,
lheight=0.21,
rankdir=LR
];
node [label="\\N",
shape=circle
node [fillcolor="#ffffa0",
fontname=Lato,
label="\\N",
shape=circle,
style=filled
];
edge [fontname=Lato];
subgraph cluster {
graph [bb="",
label="(Gb | F!a) W c",
fontname=Lato,
label=<(Gb | F!a) W c>,
labelloc=t,
lheight=0.21,
lp="196.5,196.66",
lwidth=1.14,
lp="197.5,196.66",
lwidth=1.19,
rankdir=LR
];
node [height="",
node [fillcolor="#ffffa0",
fontname=Lato,
height="",
label="\\N",
pos="",
shape=circle,
style="",
style=filled,
width=""
];
edge [label="",
edge [fontname=Lato,
label="",
lp="",
pos=""
];
I [height=0.013889,
label="",
pos="1,49.162",
pos="1,49.168",
style=invis,
width=0.013889];
1 [height=0.5,
label=1,
pos="56,49.162",
pos="56,49.168",
width=0.5];
I -> 1 [pos="e,37.942,49.324 1.1549,49.324 2.6725,49.324 15.097,49.324 27.628,49.324"];
1 -> 1 [label="!a & !c\\n{0}",
1 -> 1 [label=<!a &amp; !c<br/><font color="#5DA5DA">⓿</font>>,
lp="56,100.32",
pos="e,62.379,66.361 49.621,66.361 48.319,76.181 50.445,85.324 56,85.324 59.472,85.324 61.604,81.752 62.398,76.677"];
pos="e,62.379,66.362 49.621,66.362 48.319,76.182 50.445,85.324 56,85.324 59.472,85.324 61.604,81.753 62.398,76.677"];
0 [height=0.5,
label=0,
pos="189,121.16",
pos="190,121.17",
width=0.5];
1 -> 0 [label="a & b & !c",
lp="122.5,113.82",
pos="e,171.82,115.02 70.135,60.558 76.501,65.71 84.4,71.688 92,76.324 114.85,90.263 142.72,102.89 162.53,111.19"];
1 -> 0 [label=<a &amp; b &amp; !c>,
lp="123,113.83",
pos="e,172.99,115.19 70.127,60.572 76.491,65.727 84.391,71.704 92,76.324 115.21,90.42 143.57,103.1 163.61,111.38"];
2 [height=0.5,
label=2,
pos="189,34.162",
pos="190,34.168",
width=0.5];
1 -> 2 [label="a & !c",
lp="122.5,64.823",
pos="e,174.09,44.491 73.626,53.241 93.026,57.118 125.9,61.52 153,54.324 157.19,53.213 161.39,51.47 165.37,49.466"];
1 -> 2 [label=<a &amp; !c>,
lp="123,64.824",
pos="e,175.09,44.492 73.8,53.268 93.402,57.17 126.62,61.596 154,54.324 158.19,53.213 162.39,51.47 166.37,49.467"];
3 [height=0.5,
label=3,
pos="375,34.162",
pos="377,34.168",
width=0.5];
1 -> 3 [label=c,
lp="240.5,9.8235",
pos="e,359.03,25.984 66.028,34.328 72.163,25.634 81.128,15.425 92,10.324 114,0 275.42,0.3271 310,7.3235 323.76,10.107 338.24,15.942 349.94,21.478"];
0 -> 0 [label="b\\n{0}",
lp="189,172.32",
pos="e,197.63,137.24 180.37,137.24 178.11,147.47 180.99,157.32 189,157.32 194.26,157.32 197.3,153.08 198.14,147.27"];
2 -> 1 [label="!a & !c\\n{0}",
lp="122.5,35.324",
pos="e,68.596,36.184 172.36,26.591 166.44,24.064 159.55,21.586 153,20.324 126.38,15.197 117.5,11.13 92,20.324 86.432,22.331 81.123,25.651 76.398,29.343"];
2 -> 2 [label="a & !c",
lp="189,77.824",
pos="e,197.63,50.24 180.37,50.24 178.11,60.474 180.99,70.324 189,70.324 194.26,70.324 197.3,66.082 198.14,60.273"];
2 -> 3 [label="!a & c",
lp="292,105.82",
pos="e,363.94,48.712 202.25,46.94 217.46,61.618 244.99,85.026 274,94.324 289.24,99.207 295.12,100.21 310,94.324 329.12,86.764 345.87,70.495 357.43,56.803"];
1 -> 3 [label=<c>,
lp="242,9.8246",
pos="e,361.03,25.984 66.027,34.327 72.161,25.632 81.127,15.423 92,10.325 114.02,0 277.48,0.3418 312,7.3246 325.76,10.108 340.24,15.943 351.94,21.478"];
0 -> 0 [label=<b<br/><font color="#5DA5DA">⓿</font>>,
lp="190,172.33",
pos="e,198.98,137.24 181.02,137.24 178.68,147.48 181.67,157.33 190,157.33 195.47,157.33 198.63,153.08 199.5,147.28"];
2 -> 1 [label=<!a &amp; !c<br/><font color="#5DA5DA">⓿</font>>,
lp="123,35.324",
pos="e,68.596,36.186 173.36,26.591 167.44,24.066 160.55,21.587 154,20.324 126.94,15.113 117.92,10.98 92,20.324 86.432,22.331 81.123,25.651 76.398,29.343"];
2 -> 2 [label=<a &amp; !c>,
lp="190,77.824",
pos="e,198.98,50.24 181.02,50.24 178.68,60.475 181.67,70.324 190,70.324 195.47,70.324 198.63,66.083 199.5,60.274"];
2 -> 3 [label=<!a &amp; c>,
lp="294,105.83",
pos="e,365.94,48.712 203.15,46.686 218.52,61.348 246.56,84.98 276,94.324 291.25,99.165 297.12,100.21 312,94.324 331.12,86.764 347.87,70.495 359.43,56.803"];
4 [height=0.5,
label=4,
pos="292,34.162",
pos="294,34.168",
width=0.5];
2 -> 4 [label="a & c",
lp="240.5,41.824",
pos="e,273.78,34.324 207.13,34.324 222.59,34.324 245.58,34.324 263.59,34.324"];
3 -> 3 [label="1\\n{0}",
lp="375,85.324",
pos="e,382.03,50.988 367.97,50.988 366.41,60.949 368.75,70.324 375,70.324 379,70.324 381.4,66.475 382.2,61.092"];
4 -> 3 [label="!a",
lp="333.5,41.824",
pos="e,356.85,34.324 310.18,34.324 320.81,34.324 334.69,34.324 346.8,34.324"];
4 -> 4 [label=a,
lp="292,77.824",
pos="e,299.03,50.988 284.97,50.988 283.41,60.949 285.75,70.324 292,70.324 296,70.324 298.4,66.475 299.2,61.092"];
2 -> 4 [label=<a &amp; c>,
lp="242,41.824",
pos="e,275.95,34.324 208.3,34.324 224.08,34.324 247.64,34.324 265.91,34.324"];
3 -> 3 [label=<1<br/><font color="#5DA5DA">⓿</font>>,
lp="377,85.324",
pos="e,384.03,50.989 369.97,50.989 368.41,60.949 370.75,70.324 377,70.324 381,70.324 383.4,66.477 384.2,61.093"];
4 -> 3 [label=<!a>,
lp="335.5,41.824",
pos="e,358.85,34.324 312.18,34.324 322.81,34.324 336.69,34.324 348.8,34.324"];
4 -> 4 [label=<a>,
lp="294,77.824",
pos="e,301.03,50.989 286.97,50.989 285.41,60.949 287.75,70.324 294,70.324 298,70.324 300.4,66.477 301.2,61.093"];
}
subgraph cluster_gv1 {
graph [bb="",
label="a U b",
fontname=Lato,
label=<a U b>,
labelloc=t,
lheight=0.21,
lp="80.5,88.5",
lwidth=0.43,
lp="81.5,88.5",
lwidth=0.47,
rankdir=LR
];
node [height="",
node [fillcolor="#ffffa0",
fontname=Lato,
height="",
label="\\N",
peripheries="",
pos="",
shape=circle,
style="",
style=filled,
width=""
];
edge [label="",
edge [fontname=Lato,
label="",
lp="",
pos=""
];
I_gv1 [height=0.013889,
label="",
pos="261,156.16",
pos="261,156.17",
style=invis,
width=0.013889];
"1_gv1" [height=0.5,
label=1,
pos="316,156.16",
pos="316,156.17",
width=0.5];
I_gv1 -> "1_gv1" [pos="e,297.94,156.16 261.15,156.16 262.67,156.16 275.1,156.16 287.63,156.16"];
"1_gv1" -> "1_gv1" [label="a & !b",
lp="316,199.66",
pos="e,322.38,173.2 309.62,173.2 308.32,183.02 310.44,192.16 316,192.16 319.47,192.16 321.6,188.59 322.4,183.51"];
I_gv1 -> "1_gv1" [pos="e,297.94,156.17 261.15,156.17 262.67,156.17 275.1,156.17 287.63,156.17"];
"1_gv1" -> "1_gv1" [label=<a &amp; !b>,
lp="316,199.67",
pos="e,322.38,173.21 309.62,173.21 308.32,183.03 310.44,192.17 316,192.17 319.47,192.17 321.6,188.6 322.4,183.52"];
"0_gv1" [height=0.72222,
label=0,
peripheries=2,
pos="399,156.16",
pos="401,156.17",
width=0.72222];
"1_gv1" -> "0_gv1" [label=b,
lp="355.5,163.66",
pos="e,376.81,156.16 334.18,156.16 343.61,156.16 355.6,156.16 366.64,156.16"];
"1_gv1" -> "0_gv1" [label=<b>,
lp="356.5,163.67",
pos="e,379,156.17 334.2,156.17 344.16,156.17 357,156.17 368.7,156.17"];
"0_gv1" -> "0_gv1" [label=1,
lp="399,203.66",
pos="e,406.68,177.15 391.32,177.15 390.37,187.25 392.93,196.16 399,196.16 402.89,196.16 405.34,192.5 406.35,187.22"];
lp="401,203.67",
pos="e,409.01,176.75 392.99,176.75 391.89,187.01 394.55,196.17 401,196.17 405.13,196.17 407.71,192.41 408.74,187.01"];
}
}
#+end_example
@ -457,10 +476,14 @@ of Promela syntax.)
The =--dot= option (which usually is the default) causes automata to be
output in GraphViz's format.
#+BEGIN_SRC sh :results verbatim :exports both
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba '(Ga -> Gb) W c'
#+END_SRC
#+BEGIN_SRC sh :results verbatim :exports result
SPOT_DOTEXTRA= ltl2tgba '(Ga -> Gb) W c' --dot=
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
@ -492,7 +515,7 @@ picture. For instance use =dot -Tpng= or =dot -Tpdf=.
#+NAME: oaut-dot1
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba '(Ga -> Gb) W c' | sed 's/\\/\\\\/'
SPOT_DOTEXTRA= ltl2tgba '(Ga -> Gb) W c' --dot= | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: oaut-dot1
@ -533,7 +556,14 @@ This output can be customized by passing optional characters to the
of the default horizontal layout), =c= requests circle states, =s=
causes strongly-connected components to be displayed, =n= causes the
name (see below) of the automaton to be displayed, and =a= causes the
acceptance condition to be shown as well.
acceptance condition to be shown as well. Option =b= causes sets to
be ouput as bullets (e.g., ⓿ instead of ={0}=); option =r= (for
rainbow) causes sets to be displayed in different colors, while option
=R= also uses colors, but it chooses them depending on whether a set
is used with Fin-acceptance, Inf-acceptance, or both. Finally option
=f(FONT)= is used to select a fontname: is is often necessary when =b=
is used to ensure the characters ⓿, ❶, etc. are all selected from the
same font.
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba --dot=vcsna '(Ga -> Gb) W c'
@ -544,6 +574,7 @@ digraph G {
label="(Gb | F!a) W c\nInf(0)"
labelloc="t"
node [shape="circle"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, height=0]
I -> 1
subgraph cluster_0 {
@ -584,83 +615,50 @@ digraph G {
#+NAME: oaut-dot2
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba --dot=vcsna '(Ga -> Gb) W c' | sed 's/\\/\\\\/'
SPOT_DOTEXTRA= ltl2tgba --dot=vcsna '(Ga -> Gb) W c' | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: oaut-dot2
#+begin_example
digraph G {
rankdir=LR
label="Fin(2) & (Inf(0)&Inf(1))"
label="(Gb | F!a) W c\\nInf(0)"
labelloc="t"
node [shape="circle"]
I [label="", style=invis, width=0]
I [label="", style=invis, height=0]
I -> 1
subgraph cluster_0 {
color=grey
label=""
5 [label="5"]
6 [label="6"]
}
subgraph cluster_1 {
color=orange
color=green
label=""
0 [label="0"]
}
subgraph cluster_1 {
color=green
label=""
3 [label="3"]
}
subgraph cluster_2 {
color=orange
label=""
9 [label="9"]
10 [label="10"]
}
subgraph cluster_3 {
color=green
label=""
8 [label="8"]
}
subgraph cluster_4 {
color=green
label=""
7 [label="7"]
}
subgraph cluster_5 {
color=black
label=""
2 [label="2"]
}
subgraph cluster_6 {
color=red
label=""
4 [label="4"]
}
subgraph cluster_7 {
subgraph cluster_3 {
color=green
label=""
1 [label="1"]
3 [label="3"]
2 [label="2"]
}
0 -> 0 [label="a & b\\n{0,1,2}"]
0 -> 0 [label="!a & !b\\n{2}"]
0 -> 5 [label="a\\n{2}"]
1 -> 4 [label="b"]
1 -> 3 [label="a & !b"]
2 -> 0 [label="a"]
2 -> 7 [label="b"]
3 -> 1 [label="a & b\\n{0,1}"]
4 -> 4 [label="!b\\n{1,2}"]
4 -> 2 [label="b"]
5 -> 6 [label="1"]
6 -> 5 [label="1"]
7 -> 7 [label="!a & b\\n{0,1}"]
7 -> 7 [label="a & b\\n{0,2}"]
7 -> 8 [label="1"]
8 -> 8 [label="!a & b\\n{0,2}"]
8 -> 8 [label="a & b\\n{0,1}"]
8 -> 9 [label="1"]
9 -> 9 [label="!a & b\\n{0,2}"]
9 -> 10 [label="a & b\\n{0,1}"]
10 -> 9 [label="!a & b\\n{0,1}"]
10 -> 10 [label="a & b\\n{0,2}"]
0 -> 0 [label="b\\n{0}"]
1 -> 0 [label="a & b & !c"]
1 -> 1 [label="!a & !c\\n{0}"]
1 -> 2 [label="a & !c"]
1 -> 3 [label="c"]
2 -> 1 [label="!a & !c\\n{0}"]
2 -> 2 [label="a & !c"]
2 -> 3 [label="!a & c"]
2 -> 4 [label="a & c"]
3 -> 3 [label="1\\n{0}"]
4 -> 3 [label="!a"]
4 -> 4 [label="a"]
}
#+end_example
@ -686,7 +684,7 @@ Here is an example involving all colors:
#+NAME: oaut-dot3
#+BEGIN_SRC sh :results verbatim :exports none
autfilt --dot=cas <<EOF | sed 's/\\/\\\\/'
SPOT_DOTEXTRA= autfilt --dot=cas <<EOF | sed 's/\\/\\\\/'
HOA: v1
States: 10
Start: 1
@ -803,6 +801,30 @@ $txt
#+RESULTS:
[[file:oaut-dot3.png]]
The dot output can also be customized via two environment variables:
- =SPOT_DOTDEFAULT= contains default arguments for the =--dot= option
(for when it is used implicitly, or used as just =--dot= without
argument). For instance after =export SPOT_DOTDEFAULT=vcsn=, using
=--dot= is equivalent to =--dot=vcsn=. However using =--dot=xyz=
(for any value of =xyz=, even empty) will ignore the
=SPOT_DOTDEFAULT= variable. If the argument of =--dot= contains
a dot character, then this dot is replaced by the contents of
=SPOT_DOTDEFAULT=. So ~--dot=.a~ would be equivalent to =--dot=vcsna=
with our example definition of =SPOT_DOTDEFAULT=.
- =SPOT_DOTEXTRA= may contains an arbitrary string that will be emitted
in the dot output before the first state. This can be used to modify
any attribute. For instance (except for this page, where we had
do demonstrate the various options of =--dot=, and a few pages where
we show the =--dot= output verbatim) all the automata displayed in
this documentation are generated with the following environment
variables set:
#+BEGIN_SRC sh :results verbatim :exports code
export SPOT_DOTDEFAULT='brf(Lato)'
export SPOT_DOTEXTRA='node[style=filled, fillcolor="#ffffa0"]'
#+END
* Statistics
The =--stats= option takes format string parameter to specify what and
@ -877,37 +899,18 @@ By default, =ltl2tgba= will use the input format as name. Other tools
have no default name. This name can be changed using the =--name= option,
that takes a format string similar to the one of =--stats=.
#+NAME: oaut-name
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba --name='TGBA for %f' --dot=n 'a U b'
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
rankdir=LR
label="TGBA for a U b"
labelloc="t"
I [label="", style=invis, width=0]
I -> 1
0 [label="0", peripheries=2]
0 -> 0 [label="1"]
1 [label="1"]
1 -> 0 [label="b"]
1 -> 1 [label="a & !b"]
}
#+end_example
#+NAME: oaut-name
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba --name='TGBA for %f' --dot=n 'a U b' | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: oaut-name
#+begin_example
digraph G {
rankdir=LR
label="TGBA for a U b"
labelloc="t"
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 1
0 [label="0", peripheries=2]

View file

@ -9,56 +9,52 @@ By default, it will generate a random TGBA with 10 states, no
acceptance sets, and using a set of atomic proposition you have to
supply.
#+NAME: randaut1
#+BEGIN_SRC sh :results verbatim :exports code
randaut a b
#+END_SRC
#+NAME: randaut1
#+BEGIN_SRC sh :results verbatim :exports none
randaut a b | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: randaut1
#+begin_example
digraph G {
0 [label="", style=invis, height=0]
0 -> 1
1 [label="0", peripheries=2]
1 -> 2 [label="!a & !b"]
1 -> 3 [label="!a & b"]
2 [label="4", peripheries=2]
2 -> 4 [label="a & b"]
2 -> 5 [label="a & b"]
2 -> 3 [label="a & b"]
2 -> 6 [label="!a & b"]
3 [label="2", peripheries=2]
3 -> 3 [label="a & b"]
3 -> 7 [label="!a & b"]
3 -> 2 [label="!a & b"]
3 -> 6 [label="!a & b"]
4 [label="6", peripheries=2]
4 -> 8 [label="!a & !b"]
4 -> 6 [label="!a & !b"]
4 -> 7 [label="a & b"]
4 -> 9 [label="!a & b"]
5 [label="5", peripheries=2]
5 -> 2 [label="!a & b"]
5 -> 10 [label="a & !b"]
6 [label="3", peripheries=2]
6 -> 3 [label="!a & !b"]
6 -> 9 [label="!a & !b"]
7 [label="7", peripheries=2]
7 -> 9 [label="!a & b"]
8 [label="1", peripheries=2]
8 -> 1 [label="!a & b"]
8 -> 6 [label="!a & !b"]
9 [label="8", peripheries=2]
9 -> 3 [label="a & b"]
9 -> 10 [label="a & b"]
9 -> 7 [label="a & !b"]
9 -> 8 [label="!a & b"]
10 [label="9", peripheries=2]
10 -> 10 [label="a & !b"]
10 -> 5 [label="a & !b"]
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 8 [label=<!a &amp; !b>]
0 -> 4 [label=<!a &amp; !b>]
1 [label="1"]
1 -> 2 [label=<a &amp; !b>]
1 -> 7 [label=<!a &amp; !b>]
1 -> 4 [label=<!a &amp; b>]
2 [label="2"]
2 -> 2 [label=<!a &amp; !b>]
2 -> 0 [label=<a &amp; !b>]
2 -> 5 [label=<a &amp; !b>]
3 [label="3"]
3 -> 6 [label=<!a &amp; b>]
4 [label="4"]
4 -> 8 [label=<a &amp; !b>]
4 -> 2 [label=<!a &amp; b>]
4 -> 3 [label=<a &amp; b>]
4 -> 7 [label=<!a &amp; b>]
5 [label="5"]
5 -> 9 [label=<!a &amp; !b>]
5 -> 3 [label=<a &amp; !b>]
5 -> 7 [label=<!a &amp; !b>]
6 [label="6"]
6 -> 7 [label=<!a &amp; !b>]
6 -> 1 [label=<!a &amp; b>]
7 [label="7"]
7 -> 3 [label=<!a &amp; !b>]
8 [label="8"]
8 -> 8 [label=<!a &amp; b>]
9 [label="9"]
9 -> 0 [label=<!a &amp; b>]
9 -> 6 [label=<!a &amp; b>]
}
#+end_example
@ -86,26 +82,27 @@ variance $(S-1)d(1-d)$.
In particular =-d0= will cause all states to have 1 successors, and
=-d1= will cause all states to be interconnected.
#+NAME: randaut2
#+BEGIN_SRC sh :results verbatim :exports code
randaut -S3 -d0 2
#+END_SRC
#+NAME: randaut2
#+BEGIN_SRC sh :results verbatim :exports none
randaut -S3 -d0 2 | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: randaut2
#+begin_example
digraph G {
0 [label="", style=invis, height=0]
0 -> 1
1 [label="0", peripheries=2]
1 -> 2 [label="!p0 & !p1"]
2 [label="2", peripheries=2]
2 -> 3 [label="!p0 & p1"]
3 [label="1", peripheries=2]
3 -> 2 [label="p0 & p1"]
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 2 [label=<!p0 &amp; !p1>]
1 [label="1"]
1 -> 1 [label=<!p0 &amp; !p1>]
2 [label="2"]
2 -> 1 [label=<!p0 &amp; !p1>]
}
#+end_example
@ -115,32 +112,33 @@ $txt
#+RESULTS:
[[file:randaut2.png]]
#+NAME: randaut3
#+BEGIN_SRC sh :results verbatim :exports code
randaut -S3 -d1 2
#+END_SRC
#+NAME: randaut3
#+BEGIN_SRC sh :results verbatim :exports none
randaut -S3 -d1 2 | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: randaut3
#+begin_example
digraph G {
0 [label="", style=invis, height=0]
0 -> 1
1 [label="0", peripheries=2]
1 -> 2 [label="!p0 & !p1"]
1 -> 1 [label="!p0 & !p1"]
1 -> 3 [label="p0 & p1"]
2 [label="2", peripheries=2]
2 -> 2 [label="p0 & !p1"]
2 -> 3 [label="p0 & !p1"]
2 -> 1 [label="!p0 & !p1"]
3 [label="1", peripheries=2]
3 -> 1 [label="!p0 & !p1"]
3 -> 3 [label="!p0 & !p1"]
3 -> 2 [label="p0 & p1"]
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 2 [label=<!p0 &amp; !p1>]
0 -> 0 [label=<!p0 &amp; !p1>]
0 -> 1 [label=<!p0 &amp; !p1>]
1 [label="1"]
1 -> 1 [label=<p0 &amp; p1>]
1 -> 2 [label=<p0 &amp; !p1>]
1 -> 0 [label=<p0 &amp; !p1>]
2 [label="2"]
2 -> 1 [label=<!p0 &amp; !p1>]
2 -> 0 [label=<p0 &amp; !p1>]
2 -> 2 [label=<p0 &amp; !p1>]
}
#+end_example
@ -171,29 +169,29 @@ The generation of acceptance sets is controlled with the following three paramet
In addition, =-B= (or =--ba=) is a shorthand for =-A1 --state-acc=.
#+BEGIN_SRC sh :results verbatim :exports code
randaut -S3 -d0.5 -A2 -a0.2 2
#+END_SRC
#+NAME: randaut4
#+BEGIN_SRC sh :results verbatim :exports none
randaut -S3 -d0.5 -A2 -a0.2 2 | sed 's/\\/\\\\/'
#+BEGIN_SRC sh :results verbatim :exports code
randaut -S3 -d0.5 -A3 -a0.5 2
#+END_SRC
#+RESULTS: randaut4
#+begin_example
digraph G {
0 [label="", style=invis, height=0]
0 -> 1
1 [label="0"]
1 -> 2 [label="!p0 & !p1\\n{1}"]
1 -> 3 [label="!p0 & p1"]
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 1 [label=<!p0 &amp; !p1>]
0 -> 0 [label=<!p0 &amp; !p1<br/><font color="#FAA43A">❷</font>>]
1 [label="1"]
1 -> 2 [label=<!p0 &amp; p1<br/><font color="#F17CB0">❶</font><font color="#FAA43A">❷</font>>]
2 [label="2"]
2 -> 1 [label="!p0 & !p1\\n{0}"]
2 -> 2 [label="!p0 & !p1"]
3 [label="1"]
3 -> 2 [label="!p0 & p1\\n{1}"]
3 -> 3 [label="!p0 & p1"]
2 -> 2 [label=<!p0 &amp; !p1<br/><font color="#5DA5DA">⓿</font>>]
2 -> 1 [label=<p0 &amp; !p1<br/><font color="#5DA5DA">⓿</font><font color="#F17CB0">❶</font>>]
}
#+end_example
@ -204,29 +202,28 @@ $txt
[[file:randaut4.png]]
#+BEGIN_SRC sh :results verbatim :exports code
randaut -S3 -d0.4 -B -a0.5 2
#+END_SRC
#+NAME: randaut5
#+BEGIN_SRC sh :results verbatim :exports none
randaut -S3 -d0.4 -B -a0.5 2 | sed 's/\\/\\\\/'
#+BEGIN_SRC sh :results verbatim :exports code
randaut -S3 -d0.4 -B -a0.7 2
#+END_SRC
#+RESULTS: randaut5
#+begin_example
digraph G {
0 [label="", style=invis, height=0]
0 -> 1
1 [label="0", peripheries=2]
1 -> 2 [label="!p0 & !p1\\n{0}"]
1 -> 1 [label="!p0 & p1\\n{0}"]
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 2 [label=<!p0 &amp; !p1>]
1 [label="1"]
1 -> 2 [label=<!p0 &amp; p1>]
2 [label="2", peripheries=2]
2 -> 3 [label="!p0 & p1\\n{0}"]
2 -> 1 [label="p0 & !p1\\n{0}"]
3 [label="1"]
3 -> 3 [label="p0 & !p1"]
3 -> 1 [label="p0 & !p1"]
2 -> 1 [label=<!p0 &amp; !p1>]
2 -> 0 [label=<p0 &amp; !p1>]
}
#+end_example
@ -250,31 +247,31 @@ Boolean formulas over the given atomic propositions, such that the
sum of all these formulas is $\top$. The resulting automaton is
therefore deterministic and complete.
#+NAME: randaut6
#+BEGIN_SRC sh :results verbatim :exports code
randaut -D -S3 -d0.6 -A2 -a0.5 2
#+END_SRC
#+NAME: randaut6
#+BEGIN_SRC sh :results verbatim :exports none
randaut -D -S3 -d0.6 -A2 -a0.5 2 | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: randaut6
#+begin_example
digraph G {
0 [label="", style=invis, height=0]
0 -> 1
1 [label="0"]
1 -> 2 [label="p0\\n{1}"]
1 -> 3 [label="!p0\\n{0,1}"]
2 [label="1"]
2 -> 3 [label="!p0 & p1"]
2 -> 1 [label="!p0 & !p1\\n{0}"]
2 -> 2 [label="p0\\n{0,1}"]
3 [label="2"]
3 -> 3 [label="p0 & p1\\n{1}"]
3 -> 1 [label="p0 & !p1\\n{0}"]
3 -> 2 [label="!p0"]
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 1 [label=<p0>]
0 -> 2 [label=<!p0>]
1 [label="1"]
1 -> 2 [label=<p0<br/><font color="#F17CB0">❶</font>>]
1 -> 0 [label=<!p0<br/><font color="#5DA5DA">⓿</font>>]
2 [label="2"]
2 -> 2 [label=<!p0 &amp; p1<br/><font color="#5DA5DA">⓿</font>>]
2 -> 0 [label=<!p0 &amp; !p1<br/><font color="#F17CB0">❶</font>>]
2 -> 1 [label=<p0<br/><font color="#5DA5DA">⓿</font>>]
}
#+end_example

View file

@ -96,6 +96,7 @@ ltl2tgba -D -x sat-minimize "GF(a <-> XXb)" --stats='states=%s, det=%d'
We can draw it:
#+NAME: gfaexxb3
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -D -x sat-minimize "GF(a <-> XXb)"
#+END_SRC
@ -103,57 +104,32 @@ ltl2tgba -D -x sat-minimize "GF(a <-> XXb)"
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 1 [label="!b\n{0}"]
0 -> 1 [label="a & b"]
0 -> 2 [label="!a & b"]
0 -> 1 [label=<!a &amp; !b<br/><font color="#5DA5DA">⓿</font>>]
0 -> 2 [label=<!a &amp; b>]
0 -> 3 [label=<a &amp; b>]
0 -> 3 [label=<a &amp; !b<br/><font color="#5DA5DA">⓿</font>>]
1 [label="1"]
1 -> 1 [label="a & b\n{0}"]
1 -> 1 [label="a & !b"]
1 -> 2 [label="!a & !b"]
1 -> 3 [label="!a & b\n{0}"]
1 -> 0 [label=<a &amp; b>]
1 -> 0 [label=<a &amp; !b<br/><font color="#5DA5DA">⓿</font>>]
1 -> 1 [label=<!a &amp; b>]
1 -> 1 [label=<!a &amp; !b<br/><font color="#5DA5DA">⓿</font>>]
2 [label="2"]
2 -> 0 [label="a & !b"]
2 -> 1 [label="b\n{0}"]
2 -> 3 [label="!a & !b"]
2 -> 0 [label=<a &amp; !b>]
2 -> 1 [label=<!a &amp; b<br/><font color="#5DA5DA">⓿</font>>]
2 -> 1 [label=<!a &amp; !b>]
2 -> 3 [label=<a &amp; b<br/><font color="#5DA5DA">⓿</font>>]
3 [label="3"]
3 -> 0 [label="a & b"]
3 -> 0 [label="a & !b\n{0}"]
3 -> 3 [label="!a & b"]
3 -> 3 [label="!a & !b\n{0}"]
}
#+end_example
#+NAME: gfaexxb3
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba -D -x sat-minimize "GF(a <-> XXb)" | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: gfaexxb3
#+begin_example
digraph G {
rankdir=LR
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 1 [label="!b\\n{0}"]
0 -> 1 [label="a & b"]
0 -> 2 [label="!a & b"]
1 [label="1"]
1 -> 1 [label="a & b\\n{0}"]
1 -> 1 [label="a & !b"]
1 -> 2 [label="!a & !b"]
1 -> 3 [label="!a & b\\n{0}"]
2 [label="2"]
2 -> 0 [label="a & !b"]
2 -> 1 [label="b\\n{0}"]
2 -> 3 [label="!a & !b"]
3 [label="3"]
3 -> 0 [label="a & b"]
3 -> 0 [label="a & !b\\n{0}"]
3 -> 3 [label="!a & b"]
3 -> 3 [label="!a & !b\\n{0}"]
3 -> 2 [label=<!a &amp; b<br/><font color="#5DA5DA">⓿</font>>]
3 -> 2 [label=<!a &amp; !b>]
3 -> 3 [label=<a &amp; b<br/><font color="#5DA5DA">⓿</font>>]
3 -> 3 [label=<a &amp; !b>]
}
#+end_example
@ -168,82 +144,45 @@ acceptance. If we want a traditional Büchi automaton, with
state-based acceptance, we only need to add the =-B= option. The
result will of course be slightly bigger.
#+NAME: gfaexxb4
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -BD -x sat-minimize "GF(a <-> XXb)"
#+END_SRC
#+RESULTS:
#+begin_example
digraph G {
rankdir=LR
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 0 [label="!a & b"]
0 -> 1 [label="!a & !b"]
0 -> 2 [label="a & !b"]
0 -> 3 [label="a & b"]
1 [label="1"]
1 -> 0 [label="!a & b\n{0}"]
1 -> 2 [label="a & !b\n{0}"]
1 -> 3 [label="a & b\n{0}"]
1 -> 4 [label="!a & !b\n{0}"]
2 [label="2"]
2 -> 4 [label="!a\n{0}"]
2 -> 5 [label="a\n{0}"]
3 [label="3"]
3 -> 1 [label="!a & !b"]
3 -> 2 [label="a & !b"]
3 -> 4 [label="!a & b"]
3 -> 5 [label="a & b"]
4 [label="4"]
4 -> 0 [label="!a & !b"]
4 -> 1 [label="!a & b"]
4 -> 2 [label="a & b"]
4 -> 3 [label="a & !b"]
5 [label="5"]
5 -> 1 [label="b"]
5 -> 4 [label="!a & !b"]
5 -> 5 [label="a & !b"]
}
#+end_example
#+NAME: gfaexxb4
#+BEGIN_SRC sh :results verbatim :exports none
ltl2tgba -BD -x sat-minimize "GF(a <-> XXb)" | sed 's/\\/\\\\/'
#+END_SRC
#+RESULTS: gfaexxb4
#+begin_example
digraph G {
rankdir=LR
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
node[style=filled, fillcolor="#ffffa0"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 0 [label="!a & b"]
0 -> 1 [label="!a & !b"]
0 -> 2 [label="a & !b"]
0 -> 3 [label="a & b"]
0 -> 0 [label=<!a &amp; b>]
0 -> 1 [label=<!b>]
0 -> 2 [label=<a &amp; b>]
1 [label="1"]
1 -> 0 [label="!a & b\\n{0}"]
1 -> 2 [label="a & !b\\n{0}"]
1 -> 3 [label="a & b\\n{0}"]
1 -> 4 [label="!a & !b\\n{0}"]
1 -> 4 [label=<!a<br/><font color="#5DA5DA">⓿</font>>]
1 -> 5 [label=<a<br/><font color="#5DA5DA">⓿</font>>]
2 [label="2"]
2 -> 4 [label="!a\\n{0}"]
2 -> 5 [label="a\\n{0}"]
2 -> 1 [label=<!b>]
2 -> 4 [label=<!a &amp; b>]
2 -> 5 [label=<a &amp; b>]
3 [label="3"]
3 -> 1 [label="!a & !b"]
3 -> 2 [label="a & !b"]
3 -> 4 [label="!a & b"]
3 -> 5 [label="a & b"]
3 -> 0 [label=<!a<br/><font color="#5DA5DA">⓿</font>>]
3 -> 1 [label=<a &amp; !b<br/><font color="#5DA5DA">⓿</font>>]
3 -> 2 [label=<a &amp; b<br/><font color="#5DA5DA">⓿</font>>]
4 [label="4"]
4 -> 0 [label="!a & !b"]
4 -> 1 [label="!a & b"]
4 -> 2 [label="a & b"]
4 -> 3 [label="a & !b"]
4 -> 0 [label=<!a &amp; !b>]
4 -> 1 [label=<a &amp; b>]
4 -> 2 [label=<a &amp; !b>]
4 -> 3 [label=<!a &amp; b>]
5 [label="5"]
5 -> 1 [label="b"]
5 -> 4 [label="!a & !b"]
5 -> 5 [label="a & !b"]
5 -> 1 [label=<a &amp; b>]
5 -> 3 [label=<!a &amp; b>]
5 -> 4 [label=<!a &amp; !b>]
5 -> 5 [label=<a &amp; !b>]
}
#+end_example

View file

@ -51,10 +51,13 @@ static const argp_option options[] =
{
/**************************************************/
{ 0, 0, 0, 0, "Output format:", 3 },
{ "dot", OPT_DOT, "a|c|h|n|N|s|t|v", OPTION_ARG_OPTIONAL,
{ "dot", OPT_DOT, "a|b|c|f(FONT)|h|n|N|r|R|s|t|v", OPTION_ARG_OPTIONAL,
"GraphViz's format (default). Add letters for "
"(a) acceptance display, (c) circular nodes, (h) horizontal layout, "
"(v) vertical layout, (n) with name, (N) without name, (s) with SCCs, "
"(a) acceptance display, (b) acceptance sets as bullets,"
"(c) circular nodes, (f(FONT)) use FONT, (h) horizontal layout, "
"(v) vertical layout, (n) with name, (N) without name, "
"(r) rainbow colors for acceptance set, "
"(R) color acceptance set by Inf/Fin, (s) with SCCs, "
"(t) force transition-based acceptance.", 0 },
{ "hoaf", 'H', "i|s|t|m|l", OPTION_ARG_OPTIONAL,
"Output the automaton in HOA format. Add letters to select "

View file

@ -73,10 +73,13 @@ static const argp_option options[] =
"of the given property)", 0 },
/**************************************************/
{ 0, 0, 0, 0, "Output format:", 3 },
{ "dot", OPT_DOT, "a|c|h|n|N|s|t|v", OPTION_ARG_OPTIONAL,
"GraphViz's format (default). Add letters for (a) acceptance display, "
"(c) circular nodes, (h) horizontal layout, (v) vertical layout, "
"(n) with name, (N) without name, (s) with SCCs, "
{ "dot", OPT_DOT, "a|b|c|f(FONT)|h|n|N|r|R|s|t|v", OPTION_ARG_OPTIONAL,
"GraphViz's format (default). Add letters for "
"(a) acceptance display, (b) acceptance sets as bullets,"
"(c) circular nodes, (f(FONT)) use FONT, (h) horizontal layout, "
"(v) vertical layout, (n) with name, (N) without name, "
"(r) rainbow colors for acceptance set, "
"(R) color acceptance set by Inf/Fin, (s) with SCCs, "
"(t) force transition-based acceptance.", 0 },
{ "hoaf", 'H', "i|s|t|m|l", OPTION_ARG_OPTIONAL,
"Output the automaton in HOA format. Add letters to select "

View file

@ -11,6 +11,15 @@ spot-x \- Common fine-tuning options.
[ENVIRONMENT VARIABLES]
.TP
\fBSPOT_DOTDEFAULT\fR
Whenever the \f(CW--dot\fR option is used without argument (even
implicitely), the contents of this variable is used as default
argument. If you have some default setting in \fBSPOT_DOTDEFAULT\fR
but want to alter them temporarily for one call, use
\f(CW--dot=.yyy\fR: the dot character will be replaced by the contents
of the \f(CWSPOT_DOTDEFAULT\fR environment variable.
.TP
\fBSPOT_DOTEXTRA\fR
The contents of this variable is added to any dot output, immediately

View file

@ -77,6 +77,31 @@ namespace spot
return os;
}
std::ostream&
escape_html(std::ostream& os, const std::string& str)
{
for (auto i: str)
switch (i)
{
case '&':
os << "&amp;";
break;
case '"':
os << "&quot;";
break;
case '<':
os << "&lt;";
break;
case '>':
os << "&gt;";
break;
default:
os << i;
break;
}
return os;
}
std::ostream&
escape_str(std::ostream& os, const std::string& str)
{

View file

@ -46,6 +46,13 @@ namespace spot
SPOT_API std::ostream&
escape_latex(std::ostream& os, const std::string& str);
/// \brief Escape special HTML characters.
///
/// The following characters are rewritten:
/// <code>&gt; &lt; &quot; &amp;</code>
SPOT_API std::ostream&
escape_html(std::ostream& os, const std::string& str);
/// \brief Escape characters <code>"</code>, <code>\\</code>, and
/// <code>\\n</code> in \a str.
SPOT_API std::ostream&

View file

@ -48,9 +48,16 @@ namespace spot
namespace
{
void default_set_printer(std::ostream& os, int v)
{
os << v;
}
template<bool html>
static void
print_code(std::ostream& os,
const acc_cond::acc_code& code, unsigned pos)
const acc_cond::acc_code& code, unsigned pos,
std::function<void(std::ostream&, int)> set_printer)
{
const char* op = " | ";
auto& w = code[pos];
@ -59,7 +66,7 @@ namespace spot
switch (w.op)
{
case acc_cond::acc_op::And:
op = " & ";
op = html ? " &amp; " : " & ";
case acc_cond::acc_op::Or:
{
unsigned sub = pos - w.size;
@ -73,7 +80,7 @@ namespace spot
first = false;
else
os << op;
print_code(os, code, pos);
print_code<html>(os, code, pos, set_printer);
pos -= code[pos].size;
}
if (!top)
@ -102,8 +109,10 @@ namespace spot
{
if (a & 1)
{
os << and_ << "Inf(" << negated << level << ')';
and_ = "&";
os << and_ << "Inf(" << negated;
set_printer(os, level);
os << ')';
and_ = html ? "&amp;" : "&";
}
a >>= 1;
++level;
@ -135,7 +144,9 @@ namespace spot
{
if (a & 1)
{
os << or_ << "Fin(" << negated << level << ')';
os << or_ << "Fin(" << negated;
set_printer(os, level);
os << ')';
or_ = "|";
}
a >>= 1;
@ -746,13 +757,69 @@ namespace spot
return used_in_cond;
}
std::pair<acc_cond::mark_t, acc_cond::mark_t>
acc_cond::acc_code::used_inf_fin_sets() const
{
if (is_true() || is_false())
return {0U, 0U};
acc_cond::mark_t used_fin = 0U;
acc_cond::mark_t used_inf = 0U;
auto pos = &back();
auto end = &front();
while (pos > end)
{
switch (pos->op)
{
case acc_cond::acc_op::And:
case acc_cond::acc_op::Or:
--pos;
break;
case acc_cond::acc_op::Fin:
case acc_cond::acc_op::FinNeg:
used_fin |= pos[-1].mark;
pos -= 2;
break;
case acc_cond::acc_op::Inf:
case acc_cond::acc_op::InfNeg:
used_inf |= pos[-1].mark;
pos -= 2;
break;
}
}
return {used_inf, used_fin};
}
std::ostream&
acc_cond::acc_code::to_html(std::ostream& os,
std::function<void(std::ostream&, int)>
set_printer) const
{
if (empty())
os << 't';
else
print_code<true>(os, *this, size() - 1,
set_printer ? set_printer : default_set_printer);
return os;
}
std::ostream&
acc_cond::acc_code::to_text(std::ostream& os,
std::function<void(std::ostream&, int)>
set_printer) const
{
if (empty())
os << 't';
else
print_code<false>(os, *this, size() - 1,
set_printer ? set_printer : default_set_printer);
return os;
}
std::ostream& operator<<(std::ostream& os,
const spot::acc_cond::acc_code& code)
{
if (code.empty())
os << 't';
else
print_code(os, code, code.size() - 1);
return os;
return code.to_text(os);
}
}

View file

@ -660,6 +660,24 @@ namespace spot
// Return the set of sets appearing in the condition.
acc_cond::mark_t used_sets() const;
// Return the sets used as Inf or Fin in the acceptance condition
std::pair<acc_cond::mark_t, acc_cond::mark_t> used_inf_fin_sets() const;
// Print the acceptance as HTML. The set_printer function can
// be used to implement customized output for set numbers.
std::ostream&
to_html(std::ostream& os,
std::function<void(std::ostream&, int)>
set_printer = nullptr) const;
// Print the acceptance as text. The set_printer function can
// be used to implement customized output for set numbers.
std::ostream&
to_text(std::ostream& os,
std::function<void(std::ostream&, int)>
set_printer = nullptr) const;
// Calls to_text
SPOT_API
friend std::ostream& operator<<(std::ostream& os, const acc_code& code);
};

View file

@ -31,11 +31,16 @@
#include "tgba/formula2bdd.hh"
#include "tgbaalgos/sccinfo.hh"
#include <cstdlib>
#include <cstring>
#include <ctype.h>
namespace spot
{
namespace
{
constexpr int MAX_BULLET = 20;
class dotty_output
{
std::ostream& os_;
@ -46,74 +51,229 @@ namespace spot
bool opt_show_acc_ = false;
bool mark_states_ = false;
bool opt_scc_ = false;
bool opt_html_labels_ = false;
const_tgba_digraph_ptr aut_;
std::vector<std::string>* sn_;
std::string* name_ = nullptr;
acc_cond::mark_t inf_sets_ = 0U;
acc_cond::mark_t fin_sets_ = 0U;
bool opt_rainbow = false;
bool opt_bullet = false;
bool opt_all_bullets = false;
std::string opt_font_;
const char* const palette9[9] =
{
"#5DA5DA", /* blue */
"#F17CB0", /* pink */
"#FAA43A", /* orange */
"#B276B2", /* purple */
"#60BD68", /* green */
"#F15854", /* red */
"#B2912F", /* brown */
"#4D4D4D", /* gray */
"#DECF3F", /* yellow */
};
const char*const* palette = palette9;
int palette_mod = 9;
public:
void
parse_opts(const char* options)
{
const char* orig = options;
while (char c = *options++)
switch (c)
{
case '.':
{
static const char* def = getenv("SPOT_DOTDEFAULT");
// Prevent infinite recursions...
if (orig == def)
throw std::runtime_error
(std::string("SPOT_DOTDEFAULT should not contain '.'"));
if (def)
parse_opts(def);
break;
}
case 'a':
opt_show_acc_ = true;
break;
case 'b':
opt_bullet = true;
break;
case 'c':
opt_circles_ = true;
break;
case 'h':
opt_horizontal_ = true;
break;
case 'f':
if (*options != '(')
throw std::runtime_error
(std::string("invalid font specification for dotty()"));
{
auto* end = strchr(++options, ')');
if (!end)
throw std::runtime_error
(std::string("invalid font specification for dotty()"));
opt_font_ = std::string(options, end - options);
options = end + 1;
}
break;
case 'n':
opt_name_ = true;
break;
case 'N':
opt_name_ = false;
break;
case 'r':
opt_html_labels_ = true;
opt_rainbow = true;
break;
case 'R':
opt_html_labels_ = true;
opt_rainbow = false;
break;
case 's':
opt_scc_ = true;
break;
case 'v':
opt_horizontal_ = false;
break;
case 't':
opt_force_acc_trans_ = true;
break;
default:
throw std::runtime_error
(std::string("unknown option for dotty(): ") + c);
}
}
dotty_output(std::ostream& os, const char* options)
: os_(os)
{
if (options)
while (char c = *options++)
switch (c)
{
case 'a':
opt_show_acc_ = true;
break;
case 'c':
opt_circles_ = true;
break;
case 'h':
opt_horizontal_ = true;
break;
case 'n':
opt_name_ = true;
break;
case 'N':
opt_name_ = false;
break;
case 's':
opt_scc_ = true;
break;
case 'v':
opt_horizontal_ = false;
break;
case 't':
opt_force_acc_trans_ = true;
break;
default:
throw std::runtime_error
(std::string("unknown option for dotty(): ") + c);
}
parse_opts(options ? options : ".");
}
void
output_set(std::ostream& os, int v) const
{
if (opt_bullet && (v >= 0) & (v <= MAX_BULLET))
{
static const char* const tab[MAX_BULLET + 1] = {
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"", "", "", "",
"",
};
os << tab[v];
}
else
{
os << v;
}
}
const char*
html_set_color(int v) const
{
if (opt_rainbow)
return palette[v % palette_mod];
// Color according to Fin/Inf
if (inf_sets_.has(v))
{
if (fin_sets_.has(v))
return palette[2];
else
return palette[0];
}
else
{
return palette[1];
}
}
void
output_html_set_aux(std::ostream& os, int v) const
{
os << "<font color=\"" << html_set_color(v) << "\">";
output_set(os, v);
os << "</font>";
}
void
output_html_set(int v) const
{
output_html_set_aux(os_, v);
}
void
start()
{
if (opt_html_labels_)
std::tie(inf_sets_, fin_sets_) =
aut_->get_acceptance().used_inf_fin_sets();
if (opt_bullet && aut_->acc().num_sets() <= MAX_BULLET)
opt_all_bullets = true;
os_ << "digraph G {\n";
if (opt_horizontal_)
os_ << " rankdir=LR\n";
if (name_ || opt_show_acc_)
{
os_ << " label=\"";
if (name_)
if (!opt_html_labels_)
{
escape_str(os_, *name_);
os_ << " label=\"";
if (name_)
{
escape_str(os_, *name_);
if (opt_show_acc_)
os_ << "\\n";
}
if (opt_show_acc_)
os_ << "\\n";
aut_->get_acceptance().to_text
(os_, [this](std::ostream& os, int v)
{
this->output_set(os, v);
});
os_ << "\"\n";
}
if (opt_show_acc_)
os_ << aut_->get_acceptance();
os_ << "\"\n labelloc=\"t\"\n";
else
{
os_ << " label=<";
if (name_)
{
escape_html(os_, *name_);
if (opt_show_acc_)
os_ << "<br/>";
}
if (opt_show_acc_)
aut_->get_acceptance().to_html
(os_, [this](std::ostream& os, int v)
{
this->output_html_set_aux(os, v);
});
os_ << ">\n";
}
os_ << " labelloc=\"t\"\n";
}
if (opt_circles_)
os_ << " node [shape=\"circle\"]\n";
if (!opt_font_.empty())
os_ << " fontname=\"" << opt_font_
<< "\"\n node [fontname=\"" << opt_font_
<< "\"]\n edge [fontname=\"" << opt_font_
<< "\"]\n";
// Any extra text passed in the SPOT_DOTEXTRA environment
// variable should be output at the end of the "header", so
// that our setup can be overridden.
static const char* extra = getenv("SPOT_DOTEXTRA");
if (extra)
if (extra && *extra)
os_ << " " << extra << '\n';
os_ << " I [label=\"\", style=invis, ";
os_ << (opt_horizontal_ ? "width" : "height");
@ -144,15 +304,53 @@ namespace spot
process_link(const tgba_digraph::trans_storage_t& t)
{
std::string label = bdd_format_formula(aut_->get_dict(), t.cond);
label = escape_str(label);
if (!mark_states_)
if (auto a = t.acc)
{
label += "\\n";
label += aut_->acc().format(a);
}
os_ << " " << t.src << " -> " << t.dst
<< " [label=\"" + label + "\"]\n";
os_ << " " << t.src << " -> " << t.dst;
if (!opt_html_labels_)
{
os_ << " [label=\"";
escape_str(os_, label);
if (!mark_states_)
if (auto a = t.acc)
{
os_ << "\\n";
if (!opt_all_bullets)
os_ << '{';
const char* space = "";
for (auto v: a.sets())
{
if (!opt_all_bullets)
os_ << space;
output_set(os_, v);
space = ",";
}
if (!opt_all_bullets)
os_ << '}';
}
os_ << "\"]\n";
}
else
{
os_ << " [label=<";
escape_html(os_, label);
if (!mark_states_)
if (auto a = t.acc)
{
os_ << "<br/>";
if (!opt_all_bullets)
os_ << '{';
const char* space = "";
for (auto v: a.sets())
{
if (!opt_all_bullets)
os_ << space;
output_html_set(v);
space = ",";
}
if (!opt_all_bullets)
os_ << '}';
}
os_ << ">]\n";
}
}
void print(const const_tgba_digraph_ptr& aut)

View file

@ -308,7 +308,7 @@ State: 3 "s3"
EOF
$autfilt -H input |
SPOT_DOTEXTRA='/* hello world */' $autfilt --dot=vcsn >output
SPOT_DOTDEFAULT=vcsn SPOT_DOTEXTRA='/* hello world */' $autfilt >output
cat >expected <<EOF
digraph G {
@ -360,20 +360,46 @@ digraph G {
EOF
diff output expected
$ltl2tgba --dot=an 'GFa & GFb' >output
$ltl2tgba --dot=ban 'GFa & GFb' >output
cat output
cat >expected <<EOF
digraph G {
rankdir=LR
label="G(Fa & Fb)\\nInf(0)&Inf(1)"
label="G(Fa & Fb)\nInf(⓿)&Inf(❶)"
labelloc="t"
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 0 [label="a & b\n{0,1}"]
0 -> 0 [label="a & b\n⓿❶"]
0 -> 0 [label="!a & !b"]
0 -> 0 [label="!a & b\n{1}"]
0 -> 0 [label="a & !b\n{0}"]
0 -> 0 [label="!a & b\n❶"]
0 -> 0 [label="a & !b\n⓿"]
}
EOF
diff output expected
SPOT_DOTDEFAULT=bra $ltl2tgba --dot='c.f(Lato)' 'GFa & GFb' >output
cat output
zero='<font color="#5DA5DA">⓿</font>'
one='<font color="#F17CB0">❶</font>'
cat >expected <<EOF
digraph G {
rankdir=LR
label=<Inf($zero)&amp;Inf($one)>
labelloc="t"
node [shape="circle"]
fontname="Lato"
node [fontname="Lato"]
edge [fontname="Lato"]
I [label="", style=invis, width=0]
I -> 0
0 [label="0"]
0 -> 0 [label=<a &amp; b<br/>$zero$one>]
0 -> 0 [label=<!a &amp; !b>]
0 -> 0 [label=<!a &amp; b<br/>$one>]
0 -> 0 [label=<a &amp; !b<br/>$zero>]
}
EOF
diff output expected

View file

@ -31,7 +31,7 @@ def _ostream_to_svg(ostr):
res = dotty.communicate()
return res[0].decode('utf-8')
def _render_automaton_as_svg(a, opt=""):
def _render_automaton_as_svg(a, opt=None):
ostr = ostringstream()
dotty_reachable(ostr, a, opt)
return _ostream_to_svg(ostr)
@ -47,7 +47,7 @@ def _render_formula_as_svg(a):
dotty(ostr, a)
return SVG(_ostream_to_svg(ostr))
def _render_tgba_as_svg(a, opt=""):
def _render_tgba_as_svg(a, opt=None):
# Load the SVG function only if we need it. This way the bindings
# can still be used outside of IPython if IPython is not
# installed.

File diff suppressed because it is too large Load diff