diff --git a/src/ltltest/Makefile.am b/src/ltltest/Makefile.am
index f241a6443..51455e8dd 100644
--- a/src/ltltest/Makefile.am
+++ b/src/ltltest/Makefile.am
@@ -60,13 +60,13 @@ lunabbrev_CPPFLAGS = $(AM_CPPFLAGS) -DLUNABBREV
nenoform_SOURCES = equals.cc
nenoform_CPPFLAGS = $(AM_CPPFLAGS) -DNENOFORM
reduc_SOURCES = reduc.cc
-reduccmp_SOURCES = equals.cc
+reduccmp_SOURCES = equalsf.cc
reduccmp_CPPFLAGS = $(AM_CPPFLAGS) -DREDUC
reduceu_SOURCES = equals.cc
reduceu_CPPFLAGS = $(AM_CPPFLAGS) -DREDUC -DEVENT_UNIV
reductau_SOURCES = equals.cc
reductau_CPPFLAGS = $(AM_CPPFLAGS) -DREDUC_TAU
-reductaustr_SOURCES = equals.cc
+reductaustr_SOURCES = equalsf.cc
reductaustr_CPPFLAGS = $(AM_CPPFLAGS) -DREDUC_TAUSTR
syntimpl_SOURCES = syntimpl.cc
tostring_SOURCES = tostring.cc
diff --git a/src/ltltest/equalsf.cc b/src/ltltest/equalsf.cc
new file mode 100644
index 000000000..f4a345814
--- /dev/null
+++ b/src/ltltest/equalsf.cc
@@ -0,0 +1,251 @@
+// -*- coding: utf-8 -*-
+// Copyright (C) 2008, 2009, 2010, 2011, 2012, 2014 Laboratoire de
+// Recherche et Développement de l'Epita (LRDE).
+// Copyright (C) 2003, 2004, 2006 Laboratoire d'Informatique de
+// Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
+// Université Pierre et Marie Curie.
+//
+// This file is part of Spot, a model checking library.
+//
+// Spot is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// Spot is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "ltlparse/public.hh"
+#include "ltlvisit/lunabbrev.hh"
+#include "ltlvisit/tunabbrev.hh"
+#include "ltlvisit/dump.hh"
+#include "ltlvisit/wmunabbrev.hh"
+#include "ltlvisit/nenoform.hh"
+#include "ltlast/allnodes.hh"
+#include "ltlvisit/simplify.hh"
+#include "ltlvisit/tostring.hh"
+
+void
+syntax(char* prog)
+{
+ std::cerr << prog << " [-E] file" << std::endl;
+ exit(2);
+}
+
+int
+main(int argc, char** argv)
+{
+ bool check_first = true;
+
+ if (argc > 1 && !strcmp(argv[1], "-E"))
+ {
+ check_first = false;
+ argv[1] = argv[0];
+ ++argv;
+ --argc;
+ }
+ if (argc != 2)
+ syntax(argv[0]);
+ std::ifstream input(argv[1]);
+
+ std::string s;
+ unsigned line = 0;
+ while (std::getline(input, s))
+ {
+ ++line;
+ std::cerr << line << ": " << s << '\n';
+ if (s[0] == '#') // Skip comments
+ continue;
+ std::vector formulas;
+ {
+ std::istringstream ss(s);
+ std::string form;
+ while (std::getline(ss, form, ','))
+ formulas.push_back(form);
+ }
+
+ unsigned size = formulas.size();
+ if (size == 0) // Skip empty lines
+ continue;
+
+ if (size == 1)
+ {
+ std::cerr << "Not enough formulas on line " << line << '\n';
+ return 2;
+ }
+
+ spot::ltl::parse_error_list p2;
+ const spot::ltl::formula* f2 = spot::ltl::parse(formulas[size - 1], p2);
+
+ if (spot::ltl::format_parse_errors(std::cerr, formulas[size - 1], p2))
+ return 2;
+
+ for (unsigned n = 0; n < size - 1; ++n)
+ {
+
+ spot::ltl::parse_error_list p1;
+ const spot::ltl::formula* f1 = spot::ltl::parse(formulas[n], p1);
+
+ if (check_first &&
+ spot::ltl::format_parse_errors(std::cerr, formulas[n], p1))
+ return 2;
+
+ int exit_code = 0;
+
+ {
+#if defined LUNABBREV || defined TUNABBREV || defined NENOFORM || defined WM
+ const spot::ltl::formula* tmp;
+#endif
+#ifdef LUNABBREV
+ tmp = f1;
+ f1 = spot::ltl::unabbreviate_logic(f1);
+ tmp->destroy();
+ spot::ltl::dump(std::cout, f1);
+ std::cout << std::endl;
+#endif
+#ifdef TUNABBREV
+ tmp = f1;
+ f1 = spot::ltl::unabbreviate_ltl(f1);
+ tmp->destroy();
+ spot::ltl::dump(std::cout, f1);
+ std::cout << std::endl;
+#endif
+#ifdef WM
+ tmp = f1;
+ f1 = spot::ltl::unabbreviate_wm(f1);
+ tmp->destroy();
+ spot::ltl::dump(std::cout, f1);
+ std::cout << std::endl;
+#endif
+#ifdef NENOFORM
+ tmp = f1;
+ f1 = spot::ltl::negative_normal_form(f1);
+ tmp->destroy();
+ spot::ltl::dump(std::cout, f1);
+ std::cout << std::endl;
+#endif
+#ifdef REDUC
+ spot::ltl::ltl_simplifier_options opt(true, true, true,
+ false, false);
+# ifdef EVENT_UNIV
+ opt.favor_event_univ = true;
+# endif
+ spot::ltl::ltl_simplifier simp(opt);
+ {
+ const spot::ltl::formula* tmp;
+ tmp = f1;
+ f1 = simp.simplify(f1);
+
+ if (!simp.are_equivalent(f1, tmp))
+ {
+ std::cerr
+ << "Source and simplified formulae are not equivalent!\n";
+ std::cerr
+ << "Simplified: " << spot::ltl::to_string(f1) << '\n';
+ exit_code = 1;
+ }
+
+ tmp->destroy();
+ }
+ spot::ltl::dump(std::cout, f1);
+ std::cout << std::endl;
+#endif
+#ifdef REDUC_TAU
+ spot::ltl::ltl_simplifier_options opt(false, false, false,
+ true, false);
+ spot::ltl::ltl_simplifier simp(opt);
+ {
+ const spot::ltl::formula* tmp;
+ tmp = f1;
+ f1 = simp.simplify(f1);
+
+ if (!simp.are_equivalent(f1, tmp))
+ {
+ std::cerr
+ << "Source and simplified formulae are not equivalent!\n";
+ std::cerr
+ << "Simplified: " << spot::ltl::to_string(f1) << '\n';
+ exit_code = 1;
+ }
+
+ tmp->destroy();
+ }
+ spot::ltl::dump(std::cout, f1);
+ std::cout << std::endl;
+#endif
+#ifdef REDUC_TAUSTR
+ spot::ltl::ltl_simplifier_options opt(false, false, false,
+ true, true);
+ spot::ltl::ltl_simplifier simp(opt);
+ {
+ const spot::ltl::formula* tmp;
+ tmp = f1;
+ f1 = simp.simplify(f1);
+
+ if (!simp.are_equivalent(f1, tmp))
+ {
+ std::cerr
+ << "Source and simplified formulae are not equivalent!\n";
+ std::cerr
+ << "Simplified: " << spot::ltl::to_string(f1) << '\n';
+ exit_code = 1;
+ }
+
+ tmp->destroy();
+ }
+ spot::ltl::dump(std::cout, f1);
+ std::cout << std::endl;
+#endif
+
+ exit_code |= f1 != f2;
+
+#if (!defined(REDUC) && !defined(REDUC_TAU) && !defined(REDUC_TAUSTR))
+ spot::ltl::ltl_simplifier simp;
+#endif
+
+ if (!simp.are_equivalent(f1, f2))
+ {
+#if (!defined(REDUC) && !defined(REDUC_TAU) && !defined(REDUC_TAUSTR))
+ std::cerr
+ << "Source and destination formulae are not equivalent!\n";
+#else
+ std::cerr
+ << "Simpl. and destination formulae are not equivalent!\n";
+#endif
+ exit_code = 1;
+ }
+
+ if (exit_code)
+ {
+ spot::ltl::dump(std::cerr, f1) << std::endl;
+ spot::ltl::dump(std::cerr, f2) << std::endl;
+ return exit_code;
+ }
+
+ }
+ f1->destroy();
+ }
+ f2->destroy();
+ }
+
+ spot::ltl::atomic_prop::dump_instances(std::cerr);
+ spot::ltl::unop::dump_instances(std::cerr);
+ spot::ltl::binop::dump_instances(std::cerr);
+ spot::ltl::multop::dump_instances(std::cerr);
+ assert(spot::ltl::atomic_prop::instance_count() == 0);
+ assert(spot::ltl::unop::instance_count() == 0);
+ assert(spot::ltl::binop::instance_count() == 0);
+ assert(spot::ltl::multop::instance_count() == 0);
+ return 0;
+}
diff --git a/src/ltltest/reduccmp.test b/src/ltltest/reduccmp.test
index 0ff861728..ab59c8033 100755
--- a/src/ltltest/reduccmp.test
+++ b/src/ltltest/reduccmp.test
@@ -25,368 +25,373 @@
# Check LTL reductions
. ./defs || exit 1
+set -e
-for x in ../reduccmp ../reductaustr; do
+cat >common.txt < !a, 0
+a <-> a, 1
+a ^ a, 0
+a ^ !a, 1
- run 0 $x 'a <-> !a' '0'
- run 0 $x 'a <-> a' '1'
- run 0 $x 'a ^ a' '0'
- run 0 $x 'a ^ !a' '1'
+GFa | FGa, GFa
+XXGa | GFa, GFa
+GFa & FGa, FGa
+XXGa & GFa, XXGa
- run 0 $x 'GFa | FGa' 'GFa'
- run 0 $x 'XXGa | GFa' 'GFa'
- run 0 $x 'GFa & FGa' 'FGa'
- run 0 $x 'XXGa & GFa' 'XXGa'
+# Basic reductions
+X(true), true
+X(false), false
+F(true), true
+F(false), false
- # Basic reductions
- run 0 $x 'X(true)' 'true'
- run 0 $x 'X(false)' 'false'
- run 0 $x 'F(true)' 'true'
- run 0 $x 'F(false)' 'false'
+XGF(f), GF(f)
- run 0 $x 'XGF(f)' 'GF(f)'
+# not reduced
+a R (b W G(c)), a R (b W G(c))
+# not reduced.
+a M ((a&b) R c), a M ((a&b) R c)
+# not reduced.
+(a&b) W (a U c), (a&b) W (a U c)
- case $x in
- *tau*);;
- *)
- run 0 $x 'G(true)' 'true'
- run 0 $x 'G(false)' 'false'
+# Eventuality and universality class reductions
+FFa, Fa
+FGFa, GFa
+b U Fa, Fa
+b U GFa, GFa
+Ga, Ga
- run 0 $x 'a M 1' 'Fa'
- run 0 $x 'a W 0' 'Ga'
- run 0 $x '1 U a' 'Fa'
- run 0 $x '0 R a' 'Ga'
+a U XXXFb, XXXFb
+EOF
- run 0 $x 'G(a R b)' 'G(b)'
+cp common.txt nottau.txt
+cat >>nottau.txt< GFb' 'G(Fa&Fb)|FG(!a&!b)'
+(a U b) & (c U b), (a & c) U b
+(a R b) & (a R c), a R (b & c)
+(a U b) | (a U c), a U (b | c)
+(a R b) | (c R b), (a | c) R b
- run 0 $x 'Gb W a' 'Gb|a'
- run 0 $x 'Fb M Fa' 'Fa & Fb'
+Xa & FGb, X(a & FGb)
+Xa | FGb, X(a | FGb)
+Xa & GFb, X(a & GFb)
+Xa | GFb, X(a | GFb)
+# The following is not reduced to F(a) & GFb. because
+# (1) is does not help the translate the formula into a
+# smaller automaton, and ...
+F(a & GFb), F(a & GFb)
+# (2) ... it would hinder this useful reduction (that helps to
+# produce a smaller automaton)
+F(f1 & GF(f2)) | F(a & GF(b)), F((f1&GFf2)|(a&GFb))
+# FIXME: Don't we want the opposite rewriting?
+# rewriting Fa & GFb as F(a & GFb) seems better, but
+# it not clear how that scales to Fa & Fb & GFc...
+Fa & GFb, Fa & GFb
+G(a | GFb), Ga | GFb
+# The following is not reduced to F(a & c) & GF(b) for the same
+# reason as above.
+F(a & GFb & c), F(a & GFb & c)
+G(a | GFb | c), G(a | c) | GFb
- run 0 $x 'a U (b | G(a) | c)' 'a W (b | c)'
- run 0 $x 'a U (G(a))' 'Ga'
- run 0 $x '(a U b) | (a W c)' 'a W (b | c)'
- run 0 $x '(a U b) | Ga' 'a W b'
+GFa <=> GFb, G(Fa&Fb)|FG(!a&!b)
- run 0 $x 'a R (b & F(a) & c)' 'a M (b & c)'
- run 0 $x 'a R (F(a))' 'Fa'
- run 0 $x '(a R b) & (a M c)' 'a M (b & c)'
- run 0 $x '(a R b) & Fa' 'a M b'
+Gb W a, Gb|a
+Fb M Fa, Fa & Fb
- run 0 $x '(a U b) & (c W b)' '(a & c) U b'
- run 0 $x '(a W b) & (c W b)' '(a & c) W b'
- run 0 $x '(a R b) | (c M b)' '(a | c) R b'
- run 0 $x '(a M b) | (c M b)' '(a | c) M b'
+a U (b | G(a) | c), a W (b | c)
+a U (G(a)), Ga
+(a U b) | (a W c), a W (b | c)
+(a U b) | Ga, a W b
- run 0 $x '(a R b) | Gb' 'a R b'
- run 0 $x '(a M b) | Gb' 'a R b'
- run 0 $x '(a U b) & Fb' 'a U b'
- run 0 $x '(a W b) & Fb' 'a U b'
- run 0 $x '(a M b) | Gb | (c M b)' '(a | c) R b'
+a R (b & F(a) & c), a M (b & c)
+a R (F(a)), Fa
+(a R b) & (a M c), a M (b & c)
+(a R b) & Fa, a M b
- run 0 $x 'GFGa' 'FGa'
- run 0 $x 'b R Ga' 'Ga'
- run 0 $x 'b R FGa' 'FGa'
+(a U b) & (c W b), (a & c) U b
+(a W b) & (c W b), (a & c) W b
+(a R b) | (c M b), (a | c) R b
+(a M b) | (c M b), (a | c) M b
- run 0 $x 'G(!a M a) M 1' '0'
- run 0 $x 'G(!a M a) U 1' '1'
- run 0 $x 'a R (!a M a)' '0'
- run 0 $x 'a W (!a M a)' 'Ga'
+(a R b) | Gb, a R b
+(a M b) | Gb, a R b
+(a U b) & Fb, a U b
+(a W b) & Fb, a U b
+(a M b) | Gb | (c M b), (a | c) R b
- run 0 $x 'F(a U b)' 'Fb'
- run 0 $x 'F(a M b)' 'F(a & b)'
- run 0 $x 'G(a R b)' 'Gb'
- run 0 $x 'G(a W b)' 'G(a | b)'
+GFGa, FGa
+b R Ga, Ga
+b R FGa, FGa
- run 0 $x 'Fa W Fb' 'F(GFa | b)'
- run 0 $x 'Ga M Gb' 'FGa & Gb'
+G(!a M a) M 1, 0
+G(!a M a) U 1, 1
+a R (!a M a), 0
+a W (!a M a), Ga
- run 0 $x 'a & XGa' 'Ga'
- run 0 $x 'a & XG(a&b)' '(XGb)&(Ga)'
- run 0 $x 'a & b & XG(a&b)' 'G(a&b)'
- run 0 $x 'a & b & X(Ga&Gb)' 'G(a&b)'
- run 0 $x 'a & b & XGa &XG(b)' 'G(a&b)'
- run 0 $x 'a & b & XGa & XGc' 'b & Ga & XGc'
- run 0 $x 'a & b & X(G(a&d) & b) & X(Gc)' 'b & Ga & X(b & G(c&d))'
- run 0 $x 'a|b|c|X(F(a|b)|F(c)|Gd)' 'F(a|b|c)|XGd'
- run 0 $x 'b|c|X(F(a|b)|F(c)|Gd)' 'b|c|X(F(a|b|c)|Gd)'
+F(a U b), Fb
+F(a M b), F(a & b)
+G(a R b), Gb
+G(a W b), G(a | b)
- run 0 $x 'a | (Xa R b) | c' '(b W a) | c'
- run 0 $x 'a | (Xa M b) | c' '(b U a) | c'
- run 0 $x 'a | (Xa M b) | (Xa R c)' '(b U a) | (c W a)'
- run 0 $x 'a | (Xa M b) | XF(a)' 'Fa'
- run 0 $x 'a | (Xa R b) | XF(a)' '(b W a) | Fa' # Gb | Fa ?
- run 0 $x 'a & (Xa W b) & c' '(b R a) & c'
- run 0 $x 'a & (Xa U b) & c' '(b M a) & c'
- run 0 $x 'a & (Xa W b) & (Xa U c)' '(b R a) & (c M a)'
- run 0 $x 'a & (Xa W b) & XGa' 'Ga'
- run 0 $x 'a & (Xa U b) & XGa' '(b M a) & Ga' # Fb & Ga ?
- run 0 $x 'a|(c&b&X((b&c) U a))|d' '((b&c) U a)|d'
- run 0 $x 'a|(c&X((b&c) W a)&b)|d' '((b&c) W a)|d'
- run 0 $x 'a&(c|b|X((b|c) M a))&d' '((b|c) M a)&d'
- run 0 $x 'a&(c|X((b|c) R a)|b)&d' '((b|c) R a)&d'
- run 0 $x 'g R (f|g|h)' '(f|h) W g'
- run 0 $x 'g M (f|g|h)' '(f|h) U g'
- run 0 $x 'g U (f&g&h)' '(f&h) M g'
- run 0 $x 'g W (f&g&h)' '(f&h) R g'
+Fa W Fb, F(GFa | b)
+Ga M Gb, FGa & Gb
- # Syntactic implication
- run 0 $x '(a & b) R (a R c)' '(a & b)R c'
- run 0 $x 'a R ((a & b) R c)' '(a & b)R c'
- run 0 $x 'a R ((a & b) M c)' '(a & b)M c'
- run 0 $x 'a M ((a & b) M c)' '(a & b)M c'
- run 0 $x '(a & b) M (a R c)' '(a & b)M c'
- run 0 $x '(a & b) M (a M c)' '(a & b)M c'
+a & XGa, Ga
+a & XG(a&b), (XGb)&(Ga)
+a & b & XG(a&b), G(a&b)
+a & b & X(Ga&Gb), G(a&b)
+a & b & XGa &XG(b), G(a&b)
+a & b & XGa & XGc, b & Ga & XGc
+a & b & X(G(a&d) & b) & X(Gc), b & Ga & X(b & G(c&d))
+a|b|c|X(F(a|b)|F(c)|Gd), F(a|b|c)|XGd
+b|c|X(F(a|b)|F(c)|Gd), b|c|X(F(a|b|c)|Gd)
- run 0 $x 'a U ((a & b) U c)' 'a U c'
- run 0 $x '(a&c) U (b R (c U d))' 'b R (c U d)'
- run 0 $x '(a&c) U (b R (c W d))' 'b R (c W d)'
- run 0 $x '(a&c) U (b M (c U d))' 'b M (c U d)'
- run 0 $x '(a&c) U (b M (c W d))' 'b M (c W d)'
+a | (Xa R b) | c, (b W a) | c
+a | (Xa M b) | c, (b U a) | c
+a | (Xa M b) | (Xa R c), (b U a) | (c W a)
+a | (Xa M b) | XF(a), Fa
+# Gb | Fa ?
+a | (Xa R b) | XF(a), (b W a) | Fa
+a & (Xa W b) & c, (b R a) & c
+a & (Xa U b) & c, (b M a) & c
+a & (Xa W b) & (Xa U c), (b R a) & (c M a)
+a & (Xa W b) & XGa, Ga
+# Fb & Ga ?
+a & (Xa U b) & XGa, (b M a) & Ga
+a|(c&b&X((b&c) U a))|d, ((b&c) U a)|d
+a|(c&X((b&c) W a)&b)|d, ((b&c) W a)|d
+a&(c|b|X((b|c) M a))&d, ((b|c) M a)&d
+a&(c|X((b|c) R a)|b)&d, ((b|c) R a)&d
+g R (f|g|h), (f|h) W g
+g M (f|g|h), (f|h) U g
+g U (f&g&h), (f&h) M g
+g W (f&g&h), (f&h) R g
- run 0 $x '(a R c) R (b & a)' 'c R (b & a)'
- run 0 $x '(a M c) R (b & a)' 'c R (b & a)'
+# Syntactic implication
+(a & b) R (a R c), (a & b)R c
+a R ((a & b) R c), (a & b)R c
+a R ((a & b) M c), (a & b)M c
+a M ((a & b) M c), (a & b)M c
+(a & b) M (a R c), (a & b)M c
+(a & b) M (a M c), (a & b)M c
- run 0 $x 'a W ((a&b) U c)' 'a W c'
- run 0 $x 'a W ((a&b) W c)' 'a W c'
+a U ((a & b) U c), a U c
+(a&c) U (b R (c U d)), b R (c U d)
+(a&c) U (b R (c W d)), b R (c W d)
+(a&c) U (b M (c U d)), b M (c U d)
+(a&c) U (b M (c W d)), b M (c W d)
- run 0 $x '(a M c) M (b&a)' 'c M (b&a)'
+(a R c) R (b & a), c R (b & a)
+(a M c) R (b & a), c R (b & a)
- run 0 $x '((a&c) U b) U c' 'b U c'
- run 0 $x '((a&c) W b) U c' 'b U c'
- run 0 $x '((a&c) U b) W c' 'b W c'
- run 0 $x '((a&c) W b) W c' 'b W c'
- run 0 $x '(a R b) R (c&a)' 'b R (c&a)'
- run 0 $x '(a M b) R (c&a)' 'b R (c&a)'
- run 0 $x '(a R b) M (c&a)' 'b M (c&a)'
- run 0 $x '(a M b) M (c&a)' 'b M (c&a)'
+a W ((a&b) U c), a W c
+a W ((a&b) W c), a W c
- run 0 $x '(a R (b&c)) R (c)' '(a&b&c) R c'
- run 0 $x '(a M (b&c)) R (c)' '(a&b&c) R c'
- run 0 $x '(a R (b&c)) M (c)' '(a R (b&c)) M (c)' # not reduced
- run 0 $x '(a M (b&c)) M (c)' '(a&b&c) M c'
- run 0 $x '(a W (c&b)) W b' '(a W (c&b)) | b'
- run 0 $x '(a U (c&b)) W b' '(a U (c&b)) | b'
- run 0 $x '(a U (c&b)) U b' '(a U (c&b)) | b'
- run 0 $x '(a W (c&b)) U b' '(a W (c&b)) U b' # not reduced
+(a M c) M (b&a), c M (b&a)
+((a&c) U b) U c, b U c
+((a&c) W b) U c, b U c
+((a&c) U b) W c, b W c
+((a&c) W b) W c, b W c
+(a R b) R (c&a), b R (c&a)
+(a M b) R (c&a), b R (c&a)
+(a R b) M (c&a), b M (c&a)
+(a M b) M (c&a), b M (c&a)
- # Eventuality and universality class reductions
- run 0 $x 'Fa M b' 'Fa & b'
- run 0 $x 'GFa M b' 'GFa & b'
+(a R (b&c)) R (c), (a&b&c) R c
+(a M (b&c)) R (c), (a&b&c) R c
+# not reduced
+(a R (b&c)) M (c), (a R (b&c)) M (c)
+(a M (b&c)) M (c), (a&b&c) M c
+(a W (c&b)) W b, (a W (c&b)) | b
+(a U (c&b)) W b, (a U (c&b)) | b
+(a U (c&b)) U b, (a U (c&b)) | b
+# not reduced
+(a W (c&b)) U b, (a W (c&b)) U b
- run 0 $x 'Fa|Xb|GFc' 'Fa | X(b|GFc)'
- run 0 $x 'Fa|GFc' 'F(a|GFc)'
- run 0 $x 'FGa|GFc' 'F(Ga|GFc)'
- run 0 $x 'Ga&Xb&FGc' 'Ga & X(b&FGc)'
- run 0 $x 'Ga&Xb&GFc' 'Ga & X(b&GFc)'
- run 0 $x 'Ga&GFc' 'G(a&Fc)'
- run 0 $x 'G(a|b|GFc|GFd|FGe|FGf)' 'G(a|b)|GF(c|d)|F(Ge|Gf)'
- run 0 $x 'G(a|b)|GFc|GFd|FGe|FGf' 'G(a|b)|GF(c|d)|F(Ge|Gf)'
- run 0 $x 'X(a|b)|GFc|GFd|FGe|FGf' 'X(a|b|GF(c|d)|F(Ge|Gf))'
- run 0 $x 'Xa&Xb&GFc&GFd&Ge' 'X(a&b&G(Fc&Fd))&Ge'
+# Eventuality and universality class reductions
+Fa M b, Fa & b
+GFa M b, GFa & b
- # F comes in front when possible...
- run 0 $x 'GFc|GFd|FGe|FGf' 'F(GF(c|d)|Ge|Gf)'
- run 0 $x 'G(GFc|GFd|FGe|FGf)' 'F(GF(c|d)|Ge|Gf)'
+Fa|Xb|GFc, Fa | X(b|GFc)
+Fa|GFc, F(a|GFc)
+FGa|GFc, F(Ga|GFc)
+Ga&Xb&FGc, Ga & X(b&FGc)
+Ga&Xb&GFc, Ga & X(b&GFc)
+Ga&GFc, G(a&Fc)
+G(a|b|GFc|GFd|FGe|FGf), G(a|b)|GF(c|d)|F(Ge|Gf)
+G(a|b)|GFc|GFd|FGe|FGf, G(a|b)|GF(c|d)|F(Ge|Gf)
+X(a|b)|GFc|GFd|FGe|FGf, X(a|b|GF(c|d)|F(Ge|Gf))
+Xa&Xb&GFc&GFd&Ge, X(a&b&G(Fc&Fd))&Ge
- # Because reduccmp will translate the formula,
- # this also check for an old bug in ltl2tgba_fm.
- run 0 $x '{(c&!c)[->0..1]}!' '0'
+# F comes in front when possible...
+GFc|GFd|FGe|FGf, F(GF(c|d)|Ge|Gf)
+G(GFc|GFd|FGe|FGf), F(GF(c|d)|Ge|Gf)
- # Tricky case that used to break the translator,
- # because it was translating closer on-the-fly
- # without pruning the rational automaton.
- run 0 $x '{(c&!c)[=2]}' '0'
+# Because reduccmp will translate the formula,
+# this also check for an old bug in ltl2tgba_fm.
+{(c&!c)[->0..1]}!, 0
- run 0 $x '{a && b && c*} <>-> d' 'a&b&c&d'
- run 0 $x '{a && b && c[*1..3]} <>-> d' 'a&b&c&d'
- run 0 $x '{a && b && c[->0..2]} <>-> d' 'a&b&c&d'
- run 0 $x '{a && b && c[+]} <>-> d' 'a&b&c&d'
- run 0 $x '{a && b && c[=1]} <>-> d' 'a&b&c&d'
- run 0 $x '{a && b && d[=2]} <>-> d' '0'
- run 0 $x '{a && b && d[*2..]} <>-> d' '0'
- run 0 $x '{a && b && d[->2..4]} <>-> d' '0'
- run 0 $x '{a && { c* : b* : (g|h)*}} <>-> d' 'a & c & b & (g | h) & d'
- run 0 $x '{a && {b;c}} <>-> d' '0'
- run 0 $x '{a && {(b;c):e}} <>-> d' '0'
- run 0 $x '{a && {b*;c*}} <>-> d' '{a && {b*|c*}} <>-> d' # until better
- run 0 $x '{a && {(b*;c*):e}} <>-> d' '{a && {b*|c*} && e} <>-> d' # idem
- run 0 $x '{a && {b*;c}} <>-> d' 'a & c & d'
- run 0 $x '{a && {(b*;c):e}} <>-> d' 'a & c & d & e'
- run 0 $x '{a && {b;c*}} <>-> d' 'a & b & d'
- run 0 $x '{a && {(b;c*):e}} <>-> d' 'a & b & d & e'
- run 0 $x '{{{b1;r1*}&&{b2;r2*}};c}' 'b1&b2&X{{r1*&&r2*};c}'
- run 0 $x '{{b1:r1*}&&{b2:r2*}}' '{{b1&&b2}:{r1*&&r2*}}'
- run 0 $x '{{r1*;b1}&&{r2*;b2}}' '{{r1*&&r2*};{b1&&b2}}'
- run 0 $x '{{r1*:b1}&&{r2*:b2}}' '{{r1*&&r2*}:{b1&&b2}}'
- run 0 $x '{{a;b*;c}&&{d;e*}&&{f*;g}&&{h*}}' \
- '{{f*;g}&&{h*}&&{{a&&d};{e* && {b*;c}}}}'
- run 0 $x '{{{b1;r1*}&{b2;r2*}};c}' 'b1&b2&X{{r1*&r2*};c}'
- run 0 $x '{{b1:(r1;x1*)}&{b2:(r2;x2*)}}' '{{b1&&b2}:{{r1&&r2};{x1*&x2*}}}'
- run 0 $x '{{b1:r1*}&{b2:r2*}}' '{{b1:r1*}&{b2:r2*}}' # Not reduced
- run 0 $x '{{r1*;b1}&{r2*;b2}}' '{{r1*;b1}&{r2*;b2}}' # Not reduced
- run 0 $x '{{r1*:b1}&{r2*:b2}}' '{{r1*:b1}&{r2*:b2}}' # Not reduced
- run 0 $x '{{a;b*;c}&{d;e*}&{f*;g}&{h*}}' \
- '{{f*;g}&{h*}&{{a&&d};{e* & {b*;c}}}}'
- run 0 $x '{a;(b*;c*;([*0]+{d;e}))*}!' '{a;{b|c|{d;e}}*}!'
- run 0 $x '{a&b&c*}|->!Xb' '(X!b | !(a & b)) & (!(a & b) | !c | X(!c R !b))'
- run 0 $x '{[*]}[]->b' 'Gb'
- run 0 $x '{a;[*]}[]->b' 'Gb | !a'
- run 0 $x '{[*];a}[]->b' 'G(b | !a)'
- run 0 $x '{a;b;[*]}[]->c' '!a | X(!b | Gc)'
- run 0 $x '{a;a;[*]}[]->c' '!a | X(!a | Gc)'
- run 0 $x '{s[*]}[]->b' 'b W !s'
- run 0 $x '{s[+]}[]->b' 'b W !s'
- run 0 $x '{s[*2..]}[]->b' '!s | X(b W !s)'
- run 0 $x '{a;b*;c;d*}[]->e' '!a | X(!b R ((e & X(e W !d)) | !c))'
- run 0 $x '{a:b*:c:d*}[]->e' '!a | ((!c | (e W !d)) W !b)'
- run 0 $x '{a|b*|c|d*}[]->e' '(e | !(a | c)) & (e W !b) & (e W !d)'
- run 0 $x '{{[*0] | a};b;{[*0] | a};c;e[*]} []-> f' \
- '{{[*0] | a};b;{[*0] | a}} []-> X((f & X(f W !e)) | !c)'
+# Tricky case that used to break the translator,
+# because it was translating closer on-the-fly
+# without pruning the rational automaton.
+{(c&!c)[=2]}, 0
- run 0 $x '{a&b&c*}<>->!Xb' '(a & b & X!b) | (a & b & c & X(c U !b))'
- run 0 $x '{[*]}<>->b' 'Fb'
- run 0 $x '{a;[*]}<>->b' 'Fb & a'
- run 0 $x '{[*];a}<>->b' 'F(a & b)'
- run 0 $x '{a;b;[*]}<>->c' 'a & X(b & Fc)'
- run 0 $x '{a;a;[*]}<>->c' 'a & X(a & Fc)'
- run 0 $x '{s[*]}<>->b' 'b M s'
- run 0 $x '{s[+]}<>->b' 'b M s'
- run 0 $x '{s[*2..]}<>->b' 's & X(b M s)'
- run 0 $x '{1:a*}!' 'a'
- run 0 $x '{(1;1):a*}!' 'Xa'
- run 0 $x '{a;b*;c;d*}<>->e' 'a & X(b U (c & (e | X(e M d))))'
- run 0 $x '{a:b*:c:d*}<>->e' 'a & ((c & (e M d)) M b)'
- run 0 $x '{a|b*|c|d*}<>->e' '((a | c) & e) | (e M b) | (e M d)'
- run 0 $x '{{[*0] | a};b;{[*0] | a};c;e[*]} <>-> f' \
- '{{[*0] | a};b;{[*0] | a}} <>-> X(c & (f | X(f M e)))'
- run 0 $x '{a;b[*];c[*];e;f*}' 'a & X(b W (c W e))'
- run 0 $x '{a;b*;(a* && (b;c));c*}' 'a & X(b W {a[*] && {b;c}})'
- run 0 $x '{a;a;b[*2..];b}' 'a & X(a & X(b & X(b & Xb)))'
- run 0 $x '!{a;a;b[*2..];b}' '!a | X(!a | X(!b | X(!b | X!b)))'
- run 0 $x '!{a;b[*];c[*];e;f*}' '!a | X(!b M (!c M !e))'
- run 0 $x '!{a;b*;(a* && (b;c));c*}' '!a | X(!b M !{a[*] && {b;c}})'
- run 0 $x '{(a;c*;d)|(b;c)}' '(a & X(c W d)) | (b & Xc)'
- run 0 $x '!{(a;c*;d)|(b;c)}' '(X(!c M !d) | !a) & (X!c | !b)'
- run 0 $x '(Xc R b) & (Xc W 0)' 'b & XGc'
- run 0 $x '{{c*|1}[*0..1]}<>-> v' '{{c[+]|1}[*0..1]}<>-> v'
- run 0 $x '{{b*;c*}[*3..5]}<>-> v' '{{b*;c*}[*0..5]} <>-> v'
- run 0 $x '{{b*&c*}[*3..5]}<>-> v' '{{b[+]|c[+]}[*0..5]} <>-> v'
+{a && b && c*} <>-> d, a&b&c&d
+{a && b && c[*1..3]} <>-> d, a&b&c&d
+{a && b && c[->0..2]} <>-> d, a&b&c&d
+{a && b && c[+]} <>-> d, a&b&c&d
+{a && b && c[=1]} <>-> d, a&b&c&d
+{a && b && d[=2]} <>-> d, 0
+{a && b && d[*2..]} <>-> d, 0
+{a && b && d[->2..4]} <>-> d, 0
+{a && { c* : b* : (g|h)*}} <>-> d, a & c & b & (g | h) & d
+{a && {b;c}} <>-> d, 0
+{a && {(b;c):e}} <>-> d, 0
+# until better
+{a && {b*;c*}} <>-> d, {a && {b*|c*}} <>-> d
+# until better
+{a && {(b*;c*):e}} <>-> d, {a && {b*|c*} && e} <>-> d
+{a && {b*;c}} <>-> d, a & c & d
+{a && {(b*;c):e}} <>-> d, a & c & d & e
+{a && {b;c*}} <>-> d, a & b & d
+{a && {(b;c*):e}} <>-> d, a & b & d & e
+{{{b1;r1*}&&{b2;r2*}};c}, b1&b2&X{{r1*&&r2*};c}
+{{b1:r1*}&&{b2:r2*}}, {{b1&&b2}:{r1*&&r2*}}
+{{r1*;b1}&&{r2*;b2}}, {{r1*&&r2*};{b1&&b2}}
+{{r1*:b1}&&{r2*:b2}}, {{r1*&&r2*}:{b1&&b2}}
+{{a;b*;c}&&{d;e*}&&{f*;g}&&{h*}}, {{f*;g}&&{h*}&&{{a&&d};{e* && {b*;c}}}}
+{{{b1;r1*}&{b2;r2*}};c}, b1&b2&X{{r1*&r2*};c}
+{{b1:(r1;x1*)}&{b2:(r2;x2*)}}, {{b1&&b2}:{{r1&&r2};{x1*&x2*}}}
+# Not reduced
+{{b1:r1*}&{b2:r2*}}, {{b1:r1*}&{b2:r2*}}
+# Not reduced
+{{r1*;b1}&{r2*;b2}}, {{r1*;b1}&{r2*;b2}}
+# Not reduced
+{{r1*:b1}&{r2*:b2}}, {{r1*:b1}&{r2*:b2}}
+{{a;b*;c}&{d;e*}&{f*;g}&{h*}}, {{f*;g}&{h*}&{{a&&d};{e* & {b*;c}}}}
+{a;(b*;c*;([*0]+{d;e}))*}!, {a;{b|c|{d;e}}*}!
+{a&b&c*}|->!Xb, (X!b | !(a & b)) & (!(a & b) | !c | X(!c R !b))
+{[*]}[]->b, Gb
+{a;[*]}[]->b, Gb | !a
+{[*];a}[]->b, G(b | !a)
+{a;b;[*]}[]->c, !a | X(!b | Gc)
+{a;a;[*]}[]->c, !a | X(!a | Gc)
+{s[*]}[]->b, b W !s
+{s[+]}[]->b, b W !s
+{s[*2..]}[]->b, !s | X(b W !s)
+{a;b*;c;d*}[]->e, !a | X(!b R ((e & X(e W !d)) | !c))
+{a:b*:c:d*}[]->e, !a | ((!c | (e W !d)) W !b)
+{a|b*|c|d*}[]->e, (e | !(a | c)) & (e W !b) & (e W !d)
+{{[*0]|a};b;{[*0]|a};c;e[*]}[]->f,{{[*0]|a};b;{[*0]|a}}[]->X((f&X(f W !e))|!c)
- # not reduced
- run 0 $x '{a;(b[*2..4];c*;([*0]+{d;e}))*}!' \
- '{a;(b[*2..4];c*;([*0]+{d;e}))*}!'
- run 0 $x '{((a*;b)+[*0])[*4..6]}!' '{((a*;b))[*0..6]}!'
- run 0 $x '{c[*];e[*]}[]-> a' '{c[*];e[*]}[]-> a'
- ;;
- esac
+{a&b&c*}<>->!Xb, (a & b & X!b) | (a & b & c & X(c U !b))
+{[*]}<>->b, Fb
+{a;[*]}<>->b, Fb & a
+{[*];a}<>->b, F(a & b)
+{a;b;[*]}<>->c, a & X(b & Fc)
+{a;a;[*]}<>->c, a & X(a & Fc)
+{s[*]}<>->b, b M s
+{s[+]}<>->b, b M s
+{s[*2..]}<>->b, s & X(b M s)
+{1:a*}!, a
+{(1;1):a*}!, Xa
+{a;b*;c;d*}<>->e, a & X(b U (c & (e | X(e M d))))
+{a:b*:c:d*}<>->e, a & ((c & (e M d)) M b)
+{a|b*|c|d*}<>->e, ((a | c) & e) | (e M b) | (e M d)
+{{[*0]|a};b;{[*0]|a};c;e[*]}<>->f, {{[*0]|a};b;{[*0]|a}}<>->X(c&(f|X(f M e)))
+{a;b[*];c[*];e;f*}, a & X(b W (c W e))
+{a;b*;(a* && (b;c));c*}, a & X(b W {a[*] && {b;c}})
+{a;a;b[*2..];b}, a & X(a & X(b & X(b & Xb)))
+!{a;a;b[*2..];b}, !a | X(!a | X(!b | X(!b | X!b)))
+!{a;b[*];c[*];e;f*}, !a | X(!b M (!c M !e))
+!{a;b*;(a* && (b;c));c*}, !a | X(!b M !{a[*] && {b;c}})
+{(a;c*;d)|(b;c)}, (a & X(c W d)) | (b & Xc)
+!{(a;c*;d)|(b;c)}, (X(!c M !d) | !a) & (X!c | !b)
+(Xc R b) & (Xc W 0), b & XGc
+{{c*|1}[*0..1]}<>-> v, {{c[+]|1}[*0..1]}<>-> v
+{{b*;c*}[*3..5]}<>-> v, {{b*;c*}[*0..5]} <>-> v
+{{b*&c*}[*3..5]}<>-> v, {{b[+]|c[+]}[*0..5]} <>-> v
+# not reduced
+{a;(b[*2..4];c*;([*0]+{d;e}))*}!, {a;(b[*2..4];c*;([*0]+{d;e}))*}!
+{((a*;b)+[*0])[*4..6]}!, {((a*;b))[*0..6]}!
+{c[*];e[*]}[]-> a, {c[*];e[*]}[]-> a
+EOF
- run 0 $x 'a R (b W G(c))' 'a R (b W G(c))' #not reduced
-
- run 0 $x 'a M ((a&b) R c)' 'a M ((a&b) R c)' #not reduced.
- run 0 $x '(a&b) W (a U c)' '(a&b) W (a U c)' #not reduced.
-
- # Eventuality and universality class reductions
- run 0 $x 'FFa' 'Fa'
- run 0 $x 'FGFa' 'GFa'
- run 0 $x 'b U Fa' 'Fa'
- run 0 $x 'b U GFa' 'GFa'
- run 0 $x 'Ga' 'Ga'
-
- run 0 $x 'a U XXXFb' 'XXXFb'
-done
+run 0 ../reduccmp nottau.txt
+run 0 ../reductaustr common.txt
diff --git a/src/ltltest/uwrm.test b/src/ltltest/uwrm.test
index 4f8fe5e9a..c18e0dc32 100755
--- a/src/ltltest/uwrm.test
+++ b/src/ltltest/uwrm.test
@@ -1,5 +1,5 @@
#! /bin/sh
-# Copyright (C) 2012 Laboratoire de Recherche et Developpement
+# Copyright (C) 2012, 2014 Laboratoire de Recherche et Developpement
# de l'Epita (LRDE).
#
# This file is part of Spot, a model checking library.
@@ -22,52 +22,39 @@
# These formulas comes from an appendix of tl/tl.tex
. ./defs || exit 1
-
set -e
-equiv()
-{
- dst=$1
- shift
- for src in "$@"; do
- ../reduccmp "$src" "$dst"
- done
-}
-
+cat >input.txt<