We are happy to announce the release of Spot 2.6.
Spot is a library of algorithms for manipulating LTL formulas and omega-automata (objects as commonly used in model checking).
This release contains code contributed by Maximilien Colange, Antoine Martin, and myself. A detailed list of new features in this new release is given at the end of this email. You can find the new release here:
http://www.lrde.epita.fr/dload/spot/spot-2.6.tar.gz
See https://spot.lrde.epita.fr/ for documentation and installation instructions. Note that the unstable Debian packages and stable RPM packages should be available within 24h.
As always, please direct any feedback to spot@lrde.epita.fr.
New in spot 2.6 (2018-07-04)
Command-line tools:
- autfilt learned --is-colored to filter automata that use exactly one acceptance set per mark or transition.
- autfilt learned --has-univ-branching and --has-exist-branching to keep automata that have universal branching, or that make non-deterministic choices.
- autcross' tool specifications now have %M replaced by the name of the input automaton.
- autcross now aborts if there is any parser diagnostic for the input automata (previous versions would use the input automaton whenever the parser would manage to read something).
- ltlcross, ltldo, and autcross learned shorthands to call delag, ltl2dra, ltl2dgra, and nba2dpa.
- When autfilt is asked to build a Büchi automaton from of a chain of many products, as in "autfilt -B --product 1.hoa ... --product n.hoa in.hoa" then it will automatically degeneralize the intermediate products to avoid exceeding the number of supported acceptance sets.
- genltl learned to generate six new families of LTL formulas: --gf-equiv-xn=RANGE GF(a <-> X^n(a)) --gf-implies-xn=RANGE GF(a -> X^n(a)) --sejk-f=RANGE[,RANGE] f(0,j)=(GFa0 U X^j(b)), f(i,j)=(GFai U G(f(i-1,j))) --sejk-j=RANGE (GFa1&...&GFan) -> (GFb1&...&GFbn) --sejk-k=RANGE (GFa1|FGb1)&...&(GFan|FGbn) --sejk-patterns[=RANGE] φ₁,φ₂,φ₃ from Sikert et al's [CAV'16] paper (range should be included in 1..3)
- genltl --ms-example can now take a two-range argument, (as --sejk-f above).
Build:
- ./configure --enable-max-accsets=N let you specify a maximum number of acceptance sets that Spot should support. The default is still 32, but this limit is no longer hardcoded. Larger values will cost additional memory and time.
- We know distribute RPM packages for Fedora 28. See file:///home/adl/git/spot/doc/userdoc/install.html#Fedora
Library:
- The PSL/LTL simplification routine learned the following:
q R Xf = X(q R f) if q is suspendable q U Xf = X(q U f) if q is suspendable {SERE;1} = {1} if {SERE} accepts [*0] {SERE;1} = {SERE} if {SERE} does not accept [*0]
- gf_guarantee_to_ba() is a specialized construction for translating formulas of the form GF(guarantee) to BA or DBA, and fg_safety_to_dca() is a specialized construction for translating formulas of the form FG(safety) to DCA. These are generalizations of some constructions proposed by J. Esparza, J. Křentínský, and S. Sickert (LICS'18).
These are now used by the main translation routine, and can be disabled by passing -x '!gf-guarantee' to ltl2tgba. For example, here are the size of deterministic transition-based generalized Büchi automata constructed from four GF(guarantee) formulas with two versions of Spot, and converted to other types of deterministic automata by other tools distributed with Owl 18.06. "x(y)" means x states and y acceptance sets.
ltl2tgba -D delag ltl2dra 2.5 2.6 18.06 18.06 ------------------------- ----------- ------------- GF(a <-> XXa) 9(1) 4(1) 4(2) 9(4) GF(a <-> XXXa) 27(1) 8(1) 8(2) 25(4) GF(((a & Xb) | XXc) & Xd) 6(1) 4(1) 16(1) 5(2) GF((b | Fa) & (b R Xb)) 6(2) 2(1) 3(4) 3(4)
Note that in the above the automata produced by 'ltl2tgba -D' in version 2.5 were not deterministic (because -D is only a preference). They are deterministic in 2.6 and other tools.
- spot::product() and spot::product_or() learned to produce an automaton with a simpler acceptance condition if one of the argument is a weak automaton. In this case the resulting acceptance condition is (usually) that of the other argument.
- spot::product_susp() and spot::product_or_susp() are new functions for building products between an automaton A and a "suspendable" automaton B. They are also optimized for the case that A is weak.
- When 'generic' acceptance is enabled, the translation routine will split the input formula on Boolean operators into components that are syntactically 'obligation', 'suspendable', or 'something else'. Those will be translated separately and combined with product()/product_susp(). This is inspired by the ways things are done in ltl2dstar or delag, and can be disabled by passing option -xltl-split=0, as in ltl2tgba -G -D -xltl-split=0. Here are the sizes of deterministic automata (except for ltl3tela which produces non-deterministic automata) produced with generic acceptance using two versions of ltl2tgba and other tools for reference.
ltl2tgba -DG delag ltl3tela 2.5 2.6 18.06 1.1.2 ------------ ------- -------- FGa0&GFb0 2(2) 1(2) 1(2) 1(2) (FGa1&GFb1)|FGa0|GFb0 16(6) 1(4) 1(4) 1(9) (FGa2&GFb2)|((FGa1|GFb1)&FGa0&GFb0) 29(8) 1(6) 1(6) 3(11) FGa0|GFb0 5(4) 1(2) 1(2) 1(5) (FGa1|GFb1)&FGa0&GFb0 8(4) 1(4) 1(4) 1(7) (FGa2|GFb2)&((FGa1&GFb1)|FGa0|GFb0) 497(14) 1(6) 1(6) 1(14) GFa1 <-> GFz 4(6) 1(3) 1(4) 1(7) (GFa1 & GFa2) <-> GFz 8(4) 1(3) 1(6) 3(10) (GFa1 & GFa2 & GFa3) <-> GFz 21(4) 1(4) 1(8) 3(13) GFa1 -> GFz 5(4) 1(2) 1(2) 1(5) (GFa1 & GFa2) -> GFz 12(4) 1(3) 1(3) 1(6) (GFa1 & GFa2 & GFa3) -> GFz 41(4) 1(4) 1(4) 1(7) FG(a|b)|FG(!a|Xb) 4(2) 2(2) 2(2) 2(3) FG(a|b)|FG(!a|Xb)|FG(a|XXb) 21(2) 4(3) 4(3) 4(4) FG(a|b)|FG(!a|Xb)|FG(a|XXb)|FG(!a|XXXb) 170(2) 8(4) 8(4) 8(5)
- For 'parity' output, the 'ltl-split' optimization just separates obligation subformulas from the rest, where a determinization is still performed. ltl2tgba -DP ltl3dra ltl2dpa 2.5 2.6 0.2.3 18.06 -------------- ------- ------- FGp0 & (Gp1 | XFp2) 6(2) 4(1) 4(1) 4(2) G!p0 | F(p0 & (!p1 W p2)) 5(2) 4(2) n/a 5(2) (p0 W XXGp0) & GFp1 & FGp2 6(2) 5(2) n/a 6(3)
(The above just show a few cases that were improved. There are many cases where ltl2dpa still produces smaller automata.)
- The automaton postprocessor will now simplify acceptance conditions more aggressively, calling spot::simplify_acceptance() or spot::cleanup_acceptance() depending on the optimization level.
- print_dot(), used to print automata in GraphViz's format, underwent several changes:
* option "a", for printing the acceptance condition, is now enabled by default. Option "A", introduced in Spot 2.4, can be used to hide the acceptance condition in case you do not want it. This change of course affects the --dot option of all the command-line tools, as well as the various way to display automata using the Python bindings.
* when option "1" is used to hide state names and force the display of state numbers, the actual state names is now moved to the "tooltip" field of the state. The SVG files produced by "dot -Tsvg" will show those as popups. This is also done for state labels of Kripke structures.
* the output digraph is now named using the name of the automaton if available, or the empty string otherwise. (Previous versions used to call all digraphs "G".) This name appears as a tooltip in SVG figures when the mouse is over the acceptance condition.
* a new option "u" hides "true states" behind "exiting transitions". This can be used to display alternating automata in a way many people expect.
* a new option "K" cancels the effect of "k" (which uses state labels whenever possible). This is most useful when one want to force transition-labeling of a Kripke structure, where "k" is usually the default.
- spot::twa_graph::merge_states() is a new method that merges states with the exact same outgoing edges. As it performs no reordering of the edges, it is better to call it when you know that the edges in the twa_graph are sorted (e.g. after a call to merge_edges()).
- spot::twa_graph::purge_unreachable_states() now takes a function which is called with the new numbering of states. This is useful to update an external structure that references states of the twa that we want to purge.
- spot::scc_filter() now automatically turns automata marked as inherently-weak into weak automata with state-based acceptance. The acceptance condition is set to Büchi unless the input had co-Büchi or t acceptance. spot::scc_filter_states() will pass inherently-weak automata to spot::scc_filter().
- spot::cleanup_parity() and spot::cleanup_parity_here() are smarter and now remove from the acceptance condition the parity colors that are not used in the automaton.
- spot::contains() and spot::are_equivalent() can be used to check language containement between two automata or formulas. They are most welcome in Python, since we used to redefine them every now and them. Some examples are shown in https://spot.lrde.epita.fr/ipynb/contains.html
- aut1->exclusive_word(aut2) is a new method that returns a word accepted by aut1 or aut2 but not both. The exclusive_run() variant will return. This is useful when comparing automata and looking for differences. See also https://spot.lrde.epita.fr/ipynb/contains.html
- spot::complement_semidet(aut) is a new function that returns the complement of aut, where aut is a semideterministic automaton. The function uses the NCSB complementation algorithm proposed by F. Blahoudek, M. Heizmann, S. Schewe, J. Strejček, and MH. Tsai (TACAS'16).
- spot::remove_alternation() was slightly improved on very-weak alternating automata: the labeling of the outgoing transitions in the resulting TGBA makes it more likely that simulation-based reductions will reduce it.
- When applied to automata that are not WDBA-realizable, spot::minimize_wdba() was changed to produce an automaton recognizing a language that includes the original one. As a consequence spot::minimize_obligation() and spot::is_wdba_realizable() now only need one containement check instead of two.
- Slightly improved log output for the SAT-based minimization functions. The CSV log files now include an additional column with the size of the reference automaton, and they now have a header line. These log files give more details and are more accurate in the case of incremental SAT-solving.
Python:
- New spot.jupyter package. This currently contains a function for displaying several arguments side by side in a Jupyter notebook. See https://spot.lrde.epita.fr/ipynb/alternation.html for some examples.
- Strings are now implicitely converted into formulas when passed as arguments to functions that expect formulas. Previously this was done only for a few functions.
- The Python bindings for sat_minimize() now have display_log and return_log options; these are demonstrated on the new https://spot.lrde.epita.fr/ipynb/satmin.html page.
Bugs fixed:
- Python *.py and *.so files are now always installed into the same directory. This was an issue on systems like Fedora that separate plateform-specific packages from non-plateform-specific ones.
- print_dot() will correctly escape strings containing \n in HTML mode.
- The HOA parser will now accept Alias: declarations that occur before AP:.
- The option --allow-dups of randltl now works properly.
- Converting generalized-co-Büchi to Streett using dnf_to_nca() could produce bogus automata if the input had rejecting SCCs.
Deprecation notices:
- The type spot::acc_cond::mark_t has been overhauled and uses a custom bit-vector to represent acceptance sets instead of storing everything in a "unsigned int". This change is to accomodate configure's --enable-max-accsets=N option and has several effect:
* The following shortcuts are deprecated: acc_cond::mark_t m1 = 0U; acc_cond::mark_t m2 = -1U; instead, use: acc_cond::mark_t m1 = {}; acc_cond::mark_t m2 = acc_cond::mark_t::all();
* acc_cond::mark_t::value_t is deprecated. It is now only defined when --enable-max-accsets=32 (the default) and equal to "unsigned" for backward compatibility reasons.
Backward incompatibilities:
- Functions spot::parity_product() and spot::parity_product_or() were removed. The code was unused, hard to maintain, and bogus.
- The output of print_dot() now include the acceptance condition. Add option "A" (supported since version 2.4) to cancel that.
- Because genltl now supports LTL pattern with two argumens, using --format=%L may output two comma-separated integer. This is an issue if you used to produce CSV files using for instance: genltl --format='%F,%L,%f' ... Make sure to quote %L to protect the potential commas: genltl --format='%F,"%L",%f' ...
- In Spot 2.5 and prior running "ltl2tgba --generic --det" on some formula would attempt to translate it as deterministic TGBA or determinize it into an automaton with parity acceptance. Version 2.5 introduced --parity to force parity acceptance on the output. This version finally gives --generic some more natural semantics: any acceptance condition can be used.