Commit 700cf88b authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

Merge branch master (Spot 1.2.5) into next.

* src/bin/dstar2tgba.cc, src/bin/ltlcross.cc, src/bin/randltl.cc,
src/ltltest/reduccmp.test, src/neverparse/neverclaimparse.yy,
src/tgbatest/ltl2ta.test, src/tgbatest/ltl2tgba.cc,
src/tgbatest/ltlcross.test, src/tgbatest/neverclaimread.test,
wrap/python/ajax/ltl2tgba.html: Fix conflicts.
parents edb220af 3152c1a6
New in spot 1.2.4a (not yet released)
New in spot 1.2.5a (not yet released)
* Major changes (including backward incompatible changes):
......@@ -87,6 +87,56 @@ New in spot 1.2.4a (not yet released)
automata (when viewed explictely), using the above and non
longuer supported tgba_bdd_concrete class.
New in spot 1.2.5 (2014-08-21)
* New features:
- The online ltl2tgba translator will automatically attempt to
parse a formula using LBT's syntax if it cannot parse it using
the normal infix syntax. It also has an option to display
formulas using LBT's syntax.
- ltl2tgba and dstar2tgba have a new experimental option --hoaf to
output automata in the Hanoï Omega Automaton Format whose
current draft is at http://adl.github.io/hoaf/
The corresponding C++ function is spot::hoaf_reachable() in
tgbaalgos/hoaf.hh.
- 'randltl 4' is now a shorthand for 'randltl p0 p1 p2 p3'.
- ltlcross has a new option --save-bogus=FILENAME to save any
formula for which a problem (other than timeout) was detected
during translation or using the resulting automatas.
* Documentation:
- The man page for ltl2tgba has some new notes and references
about TGBA and about monitors.
* Bug fixes:
- Fix incorrect simplification of promises in the translation
of the M operator (you may suffer from the bug even if you do
not use this operator as some LTL patterns are automatically
reduced to it).
- Fix simplification of bounded repetition in SERE formulas.
- Fix incorrect translation of PSL formulas of the form !{f} where
f is unsatisifable. A similar bug was fixed for {f} in Spot
1.1.4, but for some reason it was not fixed for !{f}.
- Fix parsing of neverclaims produced by Modella.
- Fix a memory leak in the little-used conversion from
transition-based alternating automata to tgba.
- Fix a harmless uninitialized read in BuDDy.
- When writing to the terminal, ltlcross used to display each
formula in bright white, to make them stand out. It turns out
this was actually hiding the formulas for people using a
terminal with white background... This version displays formula
in bright blue instead.
- 'randltl -n -1 --seed 0' and 'randltl -n -1 --seed 1' used to
generate nearly the same list of formulas, shifted by one,
because the PRNG write reset with an incremented seed between
each output formula. The PRNG is now reset only once.
New in spot 1.2.4 (2014-05-15)
* New features:
......
......@@ -2,6 +2,7 @@ We are grateful to these people for their comments, help, or
suggestions.
Akim Demaille
Caroline Lemieux
Christian Dax
Ernesto Posse
Étienne Renault
......
......@@ -21,7 +21,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AC_PREREQ([2.61])
AC_INIT([spot], [1.2.4a], [spot@lrde.epita.fr])
AC_INIT([spot], [1.2.5a], [spot@lrde.epita.fr])
AC_CONFIG_AUX_DIR([tools])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.11 gnu tar-ustar color-tests parallel-tests])
......
......@@ -610,9 +610,9 @@ automaton as well.
** =--stop-on-error=
The =--stop-on-error= will cause =ltlcross= to abort on the first
detected error. This include failure to start some translator, read
its output, or failure to passe the sanity checks. Timeouts are
The =--stop-on-error= option will cause =ltlcross= to abort on the
first detected error. This include failure to start some translator,
read its output, or failure to passe the sanity checks. Timeouts are
allowed.
One use for this option is when =ltlcross= is used in combination with
......@@ -627,6 +627,30 @@ to remove duplicate formulas will keep growing).
randltl -n -1 --tree-size 10..25 a b c | ltlcross --stop-on-error 'ltl2tgba --lbtt %f >%T' 'ltl3ba -f %s >%N'
#+END_SRC
** =--save-bogus=FILENAME=
The =--save-bogus=FILENAME= will save any formula for which an error
was detected (either some translation failed, or some problem was
detected using the resulting automata) in =FILENAME=. Again, timeouts
are not considered to be errors, and therefore not reported in this
file.
The main use for this feature is in conjunction with =randltl='s
generation of random formulas. For instance the following command
will run the translators on an infinite number of formulas, saving
any problematic formula in =bugs.ltl=.
#+BEGIN_SRC sh :export code :eval no
randltl -n -1 --tree-size 10..25 a b c | ltlcross --save-bogus=bugs.ltl 'ltl2tgba --lbtt %f >%T' 'ltl3ba -f %s >%N'
#+END_SRC
You can periodically check the contents of =bugs.ltl=, and then run
=ltlcross= only on those formulas to look at the problems:
#+BEGIN_SRC sh :export code :eval no
ltlcross -F bugs.ltl 'ltl2tgba --lbtt %f >%T' 'ltl3ba -f %s >%N'
#+END_SRC
** =--no-check=
The =--no-check= option disables all sanity checks, and only use the supplied
......
......@@ -19,6 +19,15 @@ randltl a b c
Note that the result does not always use all atomic propositions.
If you do not care about how the atomic propositions are named,
you can give a nonnegative number instead:
#+BEGIN_SRC sh :results verbatim :exports both
randltl 3
#+END_SRC
#+RESULTS:
: G(Gp1 W (Gp1 M p2))
The syntax of the formula output can be changed using the
[[file:ioltl.org][common output options]]:
......@@ -40,16 +49,16 @@ like =p0=, =p1=, etc... (Atomic proposition named differently will be
output by Spot in double-quotes, but this is not supported by LBT.)
#+BEGIN_SRC sh :results verbatim :exports both
randltl -l p1 p2 p3
randltl -8 p1 p2 p3
randltl -s p1 p2 p3
randltl --wring p1 p2 p3
randltl -l 3
randltl -8 3
randltl -s 3
randltl --wring 3
#+END_SRC
#+RESULTS:
: G W G p2 M G p2 p3
: □(□p2 W (□p2 M p3))
: []((p3 U (p3 && []p2)) V ([]p2 || (p3 U (p3 && []p2))))
: (G(((p3=1) U ((p3=1) * (G(p2=1)))) R ((G(p2=1)) + ((p3=1) U ((p3=1) * (G(p2=1)))))))
: G W G p1 M G p1 p2
: □(□p1 W (□p1 M p2))
: []((p2 U (p2 && []p1)) V ([]p1 || (p2 U (p2 && []p1))))
: (G(((p2=1) U ((p2=1) * (G(p1=1)))) R ((G(p1=1)) + ((p2=1) U ((p2=1) * (G(p1=1)))))))
As you might guess from the above result, for a given set of atomic
propositions (and on the same computer) the generated formula will
......
......@@ -418,17 +418,14 @@ export SPOT_SATLOG=stats.csv
ltlfilt -f "Ga R (F!b & (c U b))" -l |
ltl2dstar --ltl2nba=spin:../../src/bin/ltl2tgba@-Ds - - |
dstar2tgba -D -x sat-minimize,sat-acc=2 --stats='input(states=%S) output(states=%s, acc-sets=%a, det=%d)'
echo
cat stats.csv
#+END_SRC
#+RESULTS:
: input(states=11) output(states=5, acc-sets=2, det=1)
:
: 9,8,35,64,44064,9043076,930,22,290,21
: 7,7,33,56,14504,2191905,224,4,106,4
: 6,6,28,48,10512,1358243,137,0,44,1
: 5,,,,7200,782342,78,1,26,2
: 9,8,35,64,44064,9043076,978,26,277,21
: 7,7,33,56,14504,2191905,237,7,113,4
: 6,6,28,48,10512,1358243,145,4,45,2
: 5,,,,7200,782342,82,3,31,2
The generated CSV file use the following columns:
- the n passed to the SAT-based minimization algorithm
......
#+TITLE: Command-line tools installed by Spot 1.2.4
#+TITLE: Command-line tools installed by Spot 1.2.5
#+EMAIL spot@lrde.epita.fr
#+OPTIONS: H:2 num:nil toc:t
......
// -*- coding: utf-8 -*-
// Copyright (C) 2013, 2014 Laboratoire de Recherche et Développement de
// l'Epita (LRDE).
// Copyright (C) 2013, 2014 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
//
......@@ -34,6 +34,7 @@
#include "ltlast/formula.hh"
#include "tgbaalgos/dotty.hh"
#include "tgbaalgos/lbtt.hh"
#include "tgbaalgos/hoaf.hh"
#include "tgbaalgos/neverclaim.hh"
#include "tgbaalgos/save.hh"
#include "tgbaalgos/stats.hh"
......@@ -71,6 +72,10 @@ static const argp_option options[] =
/**************************************************/
{ 0, 0, 0, 0, "Output format:", 3 },
{ "dot", OPT_DOT, 0, 0, "GraphViz's format (default)", 0 },
{ "hoaf", 'H', "s|t|m|l", OPTION_ARG_OPTIONAL,
"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", 0 },
{ "lbtt", OPT_LBTT, "t", OPTION_ARG_OPTIONAL,
"LBTT's format (add =t to force transition-based acceptance even"
" on Büchi automata)", 0 },
......@@ -121,9 +126,10 @@ const struct argp_child children[] =
{ 0, 0, 0, 0 }
};
enum output_format { Dot, Lbtt, Lbtt_t, Spin, Spot, Stats } format = Dot;
enum output_format { Dot, Lbtt, Lbtt_t, Spin, Spot, Stats, Hoa } format = Dot;
bool utf8 = false;
const char* stats = "";
const char* hoaf_opt = 0;
spot::option_map extra_options;
static int
......@@ -141,6 +147,10 @@ parse_opt(int key, char* arg, struct argp_state*)
case 'F':
jobs.emplace_back(arg, true);
break;
case 'H':
format = Hoa;
hoaf_opt = arg;
break;
case 'M':
type = spot::postprocessor::Monitor;
break;
......@@ -317,6 +327,9 @@ namespace
case Lbtt_t:
spot::lbtt_reachable(std::cout, aut, false);
break;
case Hoa:
spot::hoaf_reachable(std::cout, aut, hoaf_opt) << '\n';
break;
case Spot:
spot::tgba_save_reachable(std::cout, aut);
break;
......
......@@ -39,6 +39,7 @@
#include "tgbaalgos/lbtt.hh"
#include "tgbaalgos/neverclaim.hh"
#include "tgbaalgos/save.hh"
#include "tgbaalgos/hoaf.hh"
#include "tgbaalgos/stats.hh"
#include "tgbaalgos/translate.hh"
#include "tgba/bddprint.hh"
......@@ -72,6 +73,10 @@ static const argp_option options[] =
{ "csv-escape", OPT_CSV, 0, 0, "quote formula output by %f in --format "
"for use in CSV file", 0 },
{ "dot", OPT_DOT, 0, 0, "GraphViz's format (default)", 0 },
{ "hoaf", 'H', "s|t|m|l", OPTION_ARG_OPTIONAL,
"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", 0 },
{ "lbtt", OPT_LBTT, "t", OPTION_ARG_OPTIONAL,
"LBTT's format (add =t to force transition-based acceptance even"
" on Büchi automata)", 0 },
......@@ -118,9 +123,10 @@ const struct argp_child children[] =
{ 0, 0, 0, 0 }
};
enum output_format { Dot, Lbtt, Lbtt_t, Spin, Spot, Stats } format = Dot;
enum output_format { Dot, Lbtt, Lbtt_t, Spin, Spot, Stats, Hoa } format = Dot;
bool utf8 = false;
const char* stats = "";
const char* hoaf_opt = 0;
spot::option_map extra_options;
static int
......@@ -136,6 +142,10 @@ parse_opt(int key, char* arg, struct argp_state*)
case 'B':
type = spot::postprocessor::BA;
break;
case 'H':
format = Hoa;
hoaf_opt = arg;
break;
case 'M':
type = spot::postprocessor::Monitor;
break;
......@@ -244,6 +254,9 @@ namespace
case Lbtt_t:
spot::lbtt_reachable(std::cout, aut, false);
break;
case Hoa:
spot::hoaf_reachable(std::cout, aut, hoaf_opt, f) << '\n';
break;
case Spot:
spot::tgba_save_reachable(std::cout, aut);
break;
......
......@@ -95,6 +95,7 @@ Exit status:\n\
#define OPT_COLOR 10
#define OPT_NOCOMP 11
#define OPT_OMIT 12
#define OPT_BOGUS 13
static const argp_option options[] =
{
......@@ -160,6 +161,8 @@ static const argp_option options[] =
"colorize output; WHEN can be 'never', 'always' (the default if "
"--color is used without argument), or "
"'auto' (the default if --color is not used)", 0 },
{ "save-bogus", OPT_BOGUS, "FILENAME", 0,
"save formulas for which problems were detected in FILENAME", 0 },
{ 0, 0, 0, 0, 0, 0 }
};
......@@ -188,7 +191,7 @@ ARGMATCH_VERIFY(color_args, color_types);
color_type color_opt = color_if_tty;
const char* bright_red = "\033[01;31m";
const char* bright_white = "\033[01;37m";
const char* bright_blue = "\033[01;34m";
const char* bright_yellow = "\033[01;33m";
const char* reset_color = "\033[m";
......@@ -207,6 +210,8 @@ unsigned products = 1;
bool products_avg = true;
bool opt_omit = false;
bool has_sr = false; // Has Streett or Rabin automata to process.
const char* bogus_output_filename = 0;
std::ofstream* bogus_output = 0;
struct translator_spec
{
......@@ -510,6 +515,14 @@ parse_opt(int key, char* arg, struct argp_state*)
<< "on your platform" << std::endl;
#endif
break;
case OPT_BOGUS:
{
bogus_output = new std::ofstream(arg);
if (!*bogus_output)
error(2, errno, "cannot open '%s'", arg);
bogus_output_filename = arg;
break;
}
case OPT_COLOR:
{
if (arg)
......@@ -850,7 +863,8 @@ namespace
}
spot::const_tgba_ptr
translate(unsigned int translator_num, char l, statistics_formula* fstats)
translate(unsigned int translator_num, char l, statistics_formula* fstats,
bool& problem)
{
output.reset(translator_num);
......@@ -875,11 +889,13 @@ namespace
std::cerr << "warning: timeout during execution of command\n";
++timeout_count;
status_str = "timeout";
problem = false; // A timeout is not a sign of a bug
es = -1;
}
else if (WIFSIGNALED(es))
{
status_str = "signal";
problem = true;
es = WTERMSIG(es);
global_error() << "error: execution terminated by signal "
<< es << ".\n";
......@@ -889,6 +905,7 @@ namespace
{
es = WEXITSTATUS(es);
status_str = "exit code";
problem = true;
global_error() << "error: execution returned exit code "
<< es << ".\n";
end_error();
......@@ -896,6 +913,7 @@ namespace
else
{
status_str = "ok";
problem = false;
es = 0;
switch (output.format)
{
......@@ -907,6 +925,7 @@ namespace
if (!pel.empty())
{
status_str = "parse error";
problem = true;
es = -1;
std::ostream& err = global_error();
err << "error: failed to parse the produced neverclaim.\n";
......@@ -923,6 +942,7 @@ namespace
if (!f)
{
status_str = "no output";
problem = true;
es = -1;
global_error() << "Cannot open " << output.val()
<< std::endl;
......@@ -934,6 +954,7 @@ namespace
if (!res)
{
status_str = "parse error";
problem = true;
es = -1;
global_error() << ("error: failed to parse output in "
"LBTT format: ")
......@@ -951,6 +972,7 @@ namespace
if (!pel.empty())
{
status_str = "parse error";
problem = true;
es = -1;
std::ostream& err = global_error();
err << "error: failed to parse the produced DSTAR"
......@@ -1043,7 +1065,7 @@ namespace
}
};
static void
static bool
check_empty_prod(const spot::const_tgba_ptr& aut_i,
const spot::const_tgba_ptr& aut_j,
size_t i, size_t j, bool icomp, bool jcomp)
......@@ -1086,9 +1108,10 @@ namespace
}
delete res;
delete ec;
return res;
}
static void
static bool
cross_check(const std::vector<spot::scc_map*>& maps, char l, unsigned p)
{
size_t m = maps.size();
......@@ -1141,7 +1164,9 @@ namespace
else
err << "the state-space\n";
end_error();
return true;
}
return false;
}
typedef std::set<spot::state*, spot::state_ptr_less_than> state_set;
......@@ -1204,12 +1229,35 @@ namespace
(*i++)->destroy();
}
int
process_string(const std::string& input,
const char* filename,
int linenum)
{
spot::ltl::parse_error_list pel;
const spot::ltl::formula* f = parse_formula(input, pel);
if (!f || !pel.empty())
{
if (filename)
error_at_line(0, 0, filename, linenum, "parse error:");
spot::ltl::format_parse_errors(std::cerr, input, pel);
if (f)
f->destroy();
return 1;
}
int res = process_formula(f, filename, linenum);
if (res && bogus_output)
*bogus_output << input << std::endl;
return 0;
}
int
process_formula(const spot::ltl::formula* f,
const char* filename = 0, int linenum = 0)
{
(void) filename;
(void) linenum;
static unsigned round = 0;
// If we need LBT atomic proposition in any of the input or
......@@ -1236,7 +1284,7 @@ namespace
if (filename || linenum)
std::cerr << ' ';
if (color_opt)
std::cerr << bright_white;
std::cerr << bright_blue;
std::cerr << fstr << '\n';
if (color_opt)
std::cerr << reset_color;
......@@ -1260,6 +1308,9 @@ namespace
}
}
int problems = 0;
// These store the result of the translation of the positive and
// negative formulas.
size_t m = translators.size();
......@@ -1280,7 +1331,10 @@ namespace
for (size_t n = 0; n < m; ++n)
{
pos[n] = runner.translate(n, 'P', pstats);
bool prob;
pos[n] = runner.translate(n, 'P', pstats, prob);
problems += prob;
// If the automaton is deterministic, compute its complement
// as well. Note that if we have computed statistics
// already, there is no need to call is_deterministic()
......@@ -1318,7 +1372,10 @@ namespace
for (size_t n = 0; n < m; ++n)
{
neg[n] = runner.translate(n, 'N', nstats);
bool prob;
neg[n] = runner.translate(n, 'N', nstats, prob);
problems += prob;
// If the automaton is deterministic, compute its
// complement as well. Note that if we have computed
// statistics already, there is no need to call
......@@ -1345,7 +1402,8 @@ namespace
for (size_t j = 0; j < m; ++j)
if (neg[j])
{
check_empty_prod(pos[i], neg[j], i, j, false, false);
problems +=
check_empty_prod(pos[i], neg[j], i, j, false, false);
// Deal with the extra complemented automata if we
// have some.
......@@ -1363,13 +1421,18 @@ namespace
// translation was not deterministic.
if (i != j && comp_pos[j] && !comp_neg[j])
check_empty_prod(pos[i], comp_pos[j], i, j, false, true);
problems +=
check_empty_prod(pos[i], comp_pos[j],
i, j, false, true);
if (i != j && comp_neg[i] && !comp_neg[i])
check_empty_prod(comp_neg[i], neg[j], i, j, true, false);
problems +=
check_empty_prod(comp_neg[i], neg[j],
i, j, true, false);
if (comp_pos[i] && comp_neg[j] &&
(i == j || (!comp_neg[i] && !comp_pos[j])))
check_empty_prod(comp_pos[i], comp_neg[j],
i, j, true, true);
problems +=
check_empty_prod(comp_pos[i], comp_neg[j],
i, j, true, true);
}
}
else
......@@ -1448,14 +1511,16 @@ namespace
if (!no_checks)
{
// cross-comparison test
cross_check(pos_map, 'P', p);
cross_check(neg_map, 'N', p);
problems += cross_check(pos_map, 'P', p);
problems += cross_check(neg_map, 'N', p);
// consistency check
for (size_t i = 0; i < m; ++i)
if (pos_map[i] && neg_map[i] &&
!(consistency_check(pos_map[i], neg_map[i], statespace)))
{
++problems;
std::ostream& err = global_error();
err << "error: inconsistency between P" << i
<< " and N" << i;
......@@ -1481,7 +1546,7 @@ namespace
// Shall we stop processing formulas now?
abort_run = global_error_flag && stop_on_error;
return 0;
return problems;
}
};
}
......@@ -1499,7 +1564,7 @@ print_stats_csv(const char* filename)
else
{
out = outfile = new std::ofstream(filename);
if (!outfile)
if (!*outfile)
error(2, errno, "cannot open '%s'", filename);
}
......@@ -1537,7 +1602,7 @@ print_stats_json(const char* filename)
else
{
out = outfile = new std::ofstream(filename);
if (!outfile)
if (!*outfile)
error(2, errno, "cannot open '%s'", filename);
}
......@@ -1616,10 +1681,16 @@ main(int argc, char** argv)
if (global_error_flag)
{
std::ostream& err = global_error();
err << ("error: some error was detected during the above runs,\n"
" please search for 'error:' messages in the above "
"trace.")
<< std::endl;
if (bogus_output)
err << ("error: some error was detected during the above runs.\n"
" Check file ")
<< bogus_output_filename
<< " for problematic formulas.";
else
err << ("error: some error was detected during the above runs,\n"
" please search for 'error:' messages in the above"
" trace.");
err << std::endl;
if (timeout_count == 1)
err << "Additionally, 1 timeout occurred." << std::endl;
else if (timeout_count > 1)
......@@ -1636,6 +1707,8 @@ main(int argc, char** argv)
<< " timeouts, but no other problem detected." << std::endl;
}
delete bogus_output;
if (json_output)
print_stats_json(json_output);
if (csv_output)
......
[NAME]
ltl2tgba \- translate LTL/PSL formulas into Büchi automata
[NOTE ON TGBA]