Commit 8754cea2 authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

org: some doc about the hierarchy

* doc/org/, doc/org/hierarchy.tex: New files.
* doc/, doc/org/, NEWS: Add them.
parent cf9ad8eb
......@@ -44,11 +44,11 @@ New in spot (Not yet released)
belonging to these two classes of the temporal hierarchy. Unlike
--syntactic-recurrence and --syntactic-persistence, the new checks
are automata-based and will also match pathological formulas.
* The --format option of ltlfilt/genltl/randltl/ltlgrind learned to
print the class of a formula in the temporal hierarchy of Manna &
Pnueli using %h. Try to classify the Dwyer & al. patterns with:
genltl --dac --format='%[vw]h' | sort | uniq -c
Pnueli using %h. See
## -*- coding: utf-8 -*-
## Copyright (C) 2010, 2011, 2013, 2014, 2015, 2016 Laboratoire de
## Copyright (C) 2010, 2011, 2013, 2014, 2015, 2016, 2017 Laboratoire de
## Recherche et Développement de l'Epita (LRDE).
## Copyright (C) 2003, 2004, 2005 Laboratoire d'Informatique de Paris
## 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
......@@ -83,6 +83,9 @@ ORG_FILES = \
org/ \
org/ \
org/ \
org/ \
org/hierarchy.tex \
$(srcdir)/org/hierarchy.png \
org/ \
org/ \
org/ \
......@@ -127,6 +130,11 @@ $(srcdir)/org/arch.png: org/arch.tex
pdflatex -shell-escape arch.tex && \
rm -f arch.pdf arch.aux arch.log
$(srcdir)/org/hierarchy.png: org/hierarchy.tex
cd $(srcdir)/org && \
pdflatex -shell-escape hierarchy.tex && \
rm -f hierarchy.pdf hierarchy.aux hierarchy.log
$(srcdir)/org-stamp: $(ORG_FILES) $(configure_ac)
$(MAKE) org && touch $@
# -*- coding: utf-8 -*-
#+TITLE: Exploring the temporal hierarchy of Manna & Pnueli
#+DESCRIPTION: Spot command-line tools for exploring the temporal hierarchy of Manna & Pnueli
#+HTML_LINK_UP: tools.html
/A hierarchy of temporal properties/ was defined by Manna & Pnueli in
a [[][PODC'90 paper]].
This hierarchy relates "properties" (i.e., omega-regular languages) to
structural properties of the automata that can recognize them.
* Description of the classes
The hierarchy is built from the classes pictured in the following
diagram, where each class includes everything below it. For instance,
the /recurrence/ class includes the /obligation/ class which also
includes the /safety/ and /guarantee/ classes.
Forget about the LTL properties and about the red letters displayed in
this picture for a moment.
The /reactivity/ class represents all possible omega-regular
languages, i.e., all languages that can be recognized by a
non-deterministic Büchi automaton.
The /recurrence/ subclass contains all properties that can be
recognized by a deterministic Büchi automaton.
The dual class, /persistence/ properties, are those that can
be reresented by a weak Büchi automaton (i.e., in each SCC either
all states are accepting, or all states are rejecting).
The intersection of /recurrence/ and /persistence/ classes form the
/obligation/ properties: those can be recognized by a weak and
deterministic Büchi automaton.
/Guarantee/ properties are a subclass of /obligation/ properties that
can be recognized by terminal Büchi automata (i.e., upon reaching an
accepting state, any suffix will be accepted).
/Safety/ properties are the dual of /Guarantee/ properties: they can
be recognized by a monitor (i.e., an ω-automaton that accepts all its
Finally, at the very bottom is an unnamed class that is contains
/Safety/ properties that are also /Guarantee/ properties: those are
properties that can be represented by monitors in which the only
cycles are self-loops labeled by true.
The "LTL normal forms" displayed in the above figure help to visualize
the type of LTL formulas contained in each of these class. But note
that (1) this hierarchy applies to any omega-regular properties, not
just LTL-defined properties, and (2) the LTL expression displayed in
the figure are actually normal forms in the sense that if an
LTL-defined property belongs to the given class, then there exists an
equivalent LTL property under the stated form, were $p$, $q$, $p_i$
and $q_i$ are subexpressions that may use only Boolean operators, the
next operator ($\mathsf{X}$), and past-LTL operators (which are not
supported by Spot). The combination of these allowed operators only
makes it possible to express constraints on finite prefixes.
/Obligations/ can be thought of as Boolean combinations of /safety/
and /guarentee/ properties, while /reactivity/ properties are Boolean
combinations of /recurrence/ and /persistence/ properties. The
negation of a /safety/ property is a /guarantee/ property (and
vice-versa), and the same duality hold for /persistence/ and
/recurrence/ properties.
The red letters in each of these seven classes are keys used in
Spot to denote the classes.
* Deciding class membership
The =--format=%h= option can be used to display the "class key" of the
most precise class to which a formula belongs.
#+BEGIN_SRC sh :results verbatim :exports both
ltlfilt -f 'a U b' --format=%h
: G
If you find hard to remember the class name corresponding to the class
keys, you can request verbose output with =%[v]h=:
#+BEGIN_SRC sh :results verbatim :exports both
ltlfilt -f 'a U b' --format='%[v]h'
: guarantee
But actually any /guarantee/ property is also an /obligation/, a
/recurrence/, a /persistence/, and a /reactivity/ property. You can
get the complete list of classes using =%[w]h= or =%[vw]h=:
#+BEGIN_SRC sh :results verbatim :exports both
ltlfilt -f 'a U b' --format='%[w]h = %[vw]h'
: GOPRT = guarantee obligation persistence recurrence reactivity
This =--format= option is also supported by =randltl=, =genltl=, and
=ltlgrind=. So for instance if you want to classify the 55 LTL
patterns of [[][Dwyers et al. (FMSP'98)]] using this hierarchy, try:
#+BEGIN_SRC sh :results verbatim :exports both
genltl --dac-patterns --format='%[v]h' | sort | uniq -c
: 1 guarantee
: 2 obligation
: 1 persistence
: 2 reactivity
: 12 recurrence
: 37 safety
In this output, the most precise class is given for each formula, an
the count of formulas for each subclass is given. We have to remember
that the recurrence class also include obligation, safety, and
guarantee properties. In this list, there are no formulas that belong
to the intersection of the /guarantee/ and /safety/ classes (it would
have been listed as =guarantee safety=).
From this list, only 3 formulas are not recurrence properties (i.e.,
not recognized by deterministic Büchi automata): one of them is a
persistence formula, the other two cannot be classified better than in
the /reactivity/ class. Let's pretend we are interested in those
three non-recurrence formulas, we can use =ltlfilt -v --recurrence= to
select them from the =genltl --dac-pattern= output:
#+BEGIN_SRC sh :results verbatim :exports both
genltl --dac-patterns |
ltlfilt -v --recurrence --format='%[v]h, %f'
: persistence, G!p0 | F(p0 & (!p1 W p2))
: reactivity, G(p0 -> ((p1 -> (!p2 U (!p2 & p3 & X(!p2 U p4)))) U (p2 | G(p1 -> (p3 & XFp4)))))
: reactivity, G(p0 -> ((p1 -> (!p2 U (!p2 & p3 & !p4 & X((!p2 & !p4) U p5)))) U (p2 | G(p1 -> (p3 & !p4 & X(!p4 U p5))))))
Similar filtering options exist for other classes. Since these tests
are automata-based, they work with PSL formulas as weil. For instance,
here is how to generate 10 random recurrence PSL formulas that are
not LTL formulas, and that are not obligations:
#+BEGIN_SRC sh :results verbatim :exports both
randltl --psl -n -1 a b |
ltlfilt -v --ltl |
ltlfilt -v --obligation |
ltlfilt --recurrence -n10
((Fb W 0) | (1 U !a)) W ({b[*]}[]-> 0)
GF({[*]}<>-> !a)
{[*]}[]-> X(b M F!Gb)
G!({a[*2]}<>-> (b & F(0 R a)))
FX({[*]} -> GFb)
G({b[*][:*1]} xor (Fb U Fa)) W b
(b R a) & (({1 | [*0]} -> (1 U a)) W 0)
G({[*]}[]-> Fa)
{[*]}[]-> F(1 U b)
0 R !({!a | a[*]}[]-> GXa)
Note that the order of the =ltlfilt= filters could be changed provided
the =-n10= stays at the end. For instance we could first keep all
recurrence before removing obligations and then removing LTL formulas.
The order given above actually starts with the easier checks first and
keep the most complex tests at the end of the pipeline so they are
applied to fewer formulas. Testing whether a formula is an LTL formula
is very cheap, testing if a formula is an obligation is harder (it may
involves a translation to automata and a poweset construction), and
testing whether a formula is a recurrence is the most costly procedure
(it involves a translation as well, plus conversion to deterministic
Rabin automata, and an attempt to convert the automaton back to
deterministic Büchi).
Since option =-o= (for specifying output file) also honors =%=-escape
sequences, we can use it with =%h= to split a list of formulas in 7
possible files. Here is a generation of 200 random LTL formulas
binned into aptly named files:
#+BEGIN_SRC sh :results verbatim :exports both
randltl -n 200 a b -o random-%h.ltl
wc -l random-?.ltl
: 40 random-B.ltl
: 49 random-G.ltl
: 12 random-O.ltl
: 21 random-P.ltl
: 18 random-R.ltl
: 51 random-S.ltl
: 9 random-T.ltl
: 200 total
#+BEGIN_SRC sh :results silent :exports results
rm -f random-?.ltl
* Deciding classes membership syntactically
LTL formulas can also be classified into related classes which we
shall call /syntactic-safety/, /syntactic-guarantee/, etc. See [[][tl.pdf]]
for the grammar of each syntactic class. Any LTL-definable property
of class C can be defined by an LTL formulas in class syntactic-C, but
an LTL formula can describe a property of class C even if that formula
is not in class syntactic-C (we just know that some equivalent formula
is in class syntactic-C).
=ltlfilt= has options like =--syntactic-guarantee=,
=--syntactic-persistence=, etc. to match formulas from this classes.
Here is how to generate 10 random LTL formula that describe safety
properties but that are not in the syntactic-safety class:
#+BEGIN_SRC sh :results verbatim :exports both
randltl -n-1 a b |
ltlfilt -v --syntactic-safety |
ltlfilt --safety -n10
F!(!b <-> FGb)
!Fb xor G((b xor (Xa M b)) U b)
a W F(a -> b)
((0 R Xa) R a) -> Fa
X(Xb & (!Ga R Ga))
(1 U b) | F(Fb W (a <-> FXa))
(a M 1) | (!a W a)
(G!a W ((b M 1) -> Fa)) -> !a
!a -> ((a xor !GFa) W 0)
b M Gb
Since all those formulas describe safety properties, an exercise would
be suggest equivalent formulas that are in the syntactic-safety
fragment. For instance =b M Gb= can be rewritten as just =Gb=, which
belongs to this fragment. In this particular case, =ltlfilt
--simplify= recognizes this:
#+BEGIN_SRC sh :results verbatim :exports both
ltlfilt --simplify -f 'b M Gb'
: Gb
However in the general case Spot is not able to provide the equivalent
formula from the appropriate syntactic class.
* What to do with each class?
** Obligation
Spot implements algorithms from Löding ([[][/Efficient minimization of
deterministic weak ω-automata/, IPL 2001]]) and Dax et al. ([[][/Mechanizing
the powerset constructions for restricted classes of ω-automata/,
ATVA'07]]) in order to detect obligation properties, and produce minimal
weak deterministic automata for them.
When running =ltl2tgba -D= on an formula that represents and
obligation property, you are guaranteed to obtain a minimal (in the
number of states) deterministic weak Büchi automaton that recognizes
it. Note that since the /obligation/ class includes the /safety/ and
/guarantee/ classes, minimal deterministic automata will also be
produced for those classes. Dax et al.'s determinization of obligations
properties combined with Löding's minimization renders obsolete
older algorithms (and tools) that produced minimial deterministic
automata but only for the subclasses of /safety/ or /guarantee/.
If =ltl2tgba= is run without =-D=, the minimal weak deterministic
automaton will only be output if it is smaller than the
non-deterministic automaton the translator could produce before
determinization and minimization.
For instance =Fa R b= is an obligation:
#+BEGIN_SRC sh :results verbatim :exports both
ltlfilt -f 'Fa R b' --format='%[v]h'
: obligation
If we translate it without =-D= we get a 3-state non-deterministic
automaton (here we use =autfilt --highlight-nondet= to show where the
non-determinism occurs):
#+NAME: hier-oblig-1
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba 'Fa R b' | autfilt --highlight-nondet -d
#+BEGIN_SRC dot :file hier-oblig-1.png :cmdline -Tpng :var txt=hier-oblig-1 :exports results
Note that the above automaton uses transition-based acceptance, but
since it is an obligation, using transition-based acceptance will not
improve anything, so we might as well require a Büchi automaton with
=-B= or just state-based acceptance with =-S=:
#+NAME: hier-oblig-1b
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -B 'Fa R b' | autfilt --highlight-nondet -d
#+BEGIN_SRC dot :file hier-oblig-1b.png :cmdline -Tpng :var txt=hier-oblig-1b :exports results
With =ltl2tgba -D= we get a (minimal) deterministic weak Büchi
automaton instead.
#+NAME: hier-oblig-2
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -D 'Fa R b' -d
#+BEGIN_SRC dot :file hier-oblig-2.png :cmdline -Tpng :var txt=hier-oblig-2 :exports results
When we called =ltl2tgba=, without the option =-D=, the two automata
(non-deterministic and deterministic) were constructed, but the
deterministic one was discarded because it was bigger. Using =-D=
forces the deterministic automaton to be used regardless of its size.
The detection and minimization of obligation properties is also used
by =autfilt= when simplifying deterministic automata (they need to be
deterministic so that =autfilt= can easily compute their complement).
For instance, let us use =ltl2dstar= to construct a Streett automaton
for the obligation property =a <-> GXa=:
#+NAME: hier-oblig-3
#+BEGIN_SRC sh :results verbatim :exports code
ltldo 'ltl2dstar --automata=streett' -f 'a <-> GXa' -d.a
#+BEGIN_SRC dot :file hier-oblig-3.png :cmdline -Tpng :var txt=hier-oblig-3 :exports results
We can now minimize this automaton with:
#+NAME: hier-oblig-4
#+BEGIN_SRC sh :results verbatim :exports code
ltldo 'ltl2dstar --automata=streett' -f 'a <-> GXa' | autfilt -D -C -d
#+BEGIN_SRC dot :file hier-oblig-4.png :cmdline -Tpng :var txt=hier-oblig-4 :exports results
Here we have used option =-C= to keep the automaton complete, so that
the comparison with =ltl2dstar= is fair, since =ltl2dstar= always
output complete automata.
** Guarantee
/Guarantee/ properties can be translated into terminal automata.
There is nothing particular in Spot about /guarantee/ properties, they
are all handled like /obligations/.
Again, using =-D= will always produce (minimal) deterministic Büchi
automata, even if they are larger than the non-deterministic version.
The output should be a terminal automaton in either case,
An example is =a U Xb=:
#+BEGIN_SRC sh :results verbatim :exports both
ltlfilt -f 'a U Xb' --format='%[v]h'
: guarantee
#+NAME: hier-guarantee-1
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba 'a U Xb' | autfilt --highlight-nondet -d
#+BEGIN_SRC dot :file hier-guarantee-1.png :cmdline -Tpng :var txt=hier-guarantee-1 :exports results
#+NAME: hier-guarantee-2
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -D 'a U Xb' -d
#+BEGIN_SRC dot :file hier-guarantee-2.png :cmdline -Tpng :var txt=hier-guarantee-2 :exports results
** Safety
/Safety/ properties also form a subclass of /obligation/ properties,
and again there is no code specific to them in the translation.
However, the /safety/ class corresponds to what can be represented
faithfully by monitors, i.e., automata that accept all their infinite
For most safety formula, the acceptance output by =ltl2tgba= will
already be =t= (meaning that all runs are accepting). However since
the translator does not do anything particular about safety formulas,
it is possible to find some pathological formulas for which the
translator outputs a non-deterministic Büchi automaton where not all
run are accepting.
Here is an example:
#+BEGIN_SRC sh :results verbatim :exports both
ltlfilt -f '(a W Gb) M b' --format='%[v]h'
: safety
#+NAME: hier-safety-1
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba '(a W Gb) M b' | autfilt --highlight-nondet -d
#+BEGIN_SRC dot :file hier-safety-1.png :cmdline -Tpng :var txt=hier-safety-1 :exports results
Actually, marking all states of this automaton as accepting would not
be wrong, the translator simply does not know it.
Using =-D= will fix that: it then produces a deterministic automaton
that is guaranteed to be minimal, and will all its runs accepting.
#+NAME: hier-safety-2
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -D '(a W Gb) M b' -d
#+BEGIN_SRC dot :file hier-safety-2.png :cmdline -Tpng :var txt=hier-safety-2 :exports results
But if you are working with safety formula, and know you want to work
with monitors, you can use the =-M= option of =ltl2tgba=. In this
case this will output the same automata, but using the universal
acceptance (i.e. =t=).
#+NAME: hier-safety-1m
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -M '(a W Gb) M b' | autfilt --highlight-nondet -d
#+BEGIN_SRC dot :file hier-safety-1m.png :cmdline -Tpng :var txt=hier-safety-1m :exports results
#+NAME: hier-safety-2m
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -M -D '(a W Gb) M b' -d
#+BEGIN_SRC dot :file hier-safety-2m.png :cmdline -Tpng :var txt=hier-safety-2m :exports results
Note that the =-M= option can be used with formulas that are not
safety properties. In this case, the output monitor will recognize a
language larger than that of the property.
** Recurrence
/Recurrence/ properties can be represented by deterministic Büchi
For the subclass of /obligation/ properties, using =-D= is a sure way
to obain a deterministic automaton (and even a minimal one), but for
the /recurrence/ properties that are not /obligations/ the translator
does not make any special effort to produce deterministic automata,
even with =-D=.
All properties that are not in the /persistence/ class (this
includes the /recurrence/ properties that are not /obligations/)
can benefit from transition-based acceptance: using transition-based
acceptance will often produce shorter automata.
The typical example is =GFa=, which can be translated into a 1-state
transition-based Büchi automaton:
#+BEGIN_SRC sh :results verbatim :exports both
ltlfilt -f 'GFa' --format='%[v]h'
: recurrence
#+NAME: hier-recurrence-1
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba 'GFa' -d
#+BEGIN_SRC dot :file hier-recurrence-1.png :cmdline -Tpng :var txt=hier-recurrence-1 :exports results
Using state-based acceptance, at least two states are required. For instance:
#+NAME: hier-recurrence-2
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -S 'GFa' -d
#+BEGIN_SRC dot :file hier-recurrence-2.png :cmdline -Tpng :var txt=hier-recurrence-2 :exports results
Here is an example of formula for which =ltl2tgba= does not produce a
deterministic automaton, even with =-D=.
#+BEGIN_SRC sh :results verbatim :exports both
ltlfilt -f 'G(Gb | Fa)' --format='%[v]h'
: recurrence
#+NAME: hier-recurrence-3
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -D 'G(Gb | Fa)' | autfilt --highlight-nondet -d
#+BEGIN_SRC dot :file hier-recurrence-3.png :cmdline -Tpng :var txt=hier-recurrence-3 :exports results
One way to obtain a deterministic Büchi automaton (it has to exist, since this is
a /recurrence/ property), is to chain a few algorithms implemented in Spot:
1. determinize the non-deterministic automaton to obtain a
deterministic automaton with parity acceptance: this is done by
using =ltl2tgba -G -D=, with option =-G= indicating that any
acceptance condition may be used.
#+NAME: hier-recurrence-4
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -G -D 'G(Gb | Fa)' -d.a
#+BEGIN_SRC dot :file hier-recurrence-4.png :cmdline -Tpng :var txt=hier-recurrence-4 :exports results
2. transform the parity acceptance into Rabin acceptance: this is
done with =autfilt --generalized-rabin=. Because of the type of
parity acceptance used, the result will actually be Rabin and not
generalized Rabin.
#+NAME: hier-recurrence-5
#+BEGIN_SRC sh :results verbatim :exports code
ltl2tgba -G -D 'G(Gb | Fa)' |
autfilt --generalized-rabin -d.a
#+BEGIN_SRC dot :file hier-recurrence-5.png :cmdline -Tpng :var txt=hier-recurrence-5 :exports results