diff --git a/NEWS b/NEWS index 85d2bcd79..ed911a584 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,12 @@ New in spot 1.0a (not released): - "P0.init" is parsed as an atomic even without the double quotes, but it was always output with double quotes. This version will not quote this atomic proposition anymore. + * Minor improvements: + - Four new LTL simplifications rules: + GF(a|Xb) = GF(a|b) + GF(a|Fb) = GF(a|b) + FG(a&Xb) = FG(a&b) + FG(a&Gb) = FG(a&b) * Pruning: - lbtt has been removed from the distribution. A copy of the last version we distributed is still available at diff --git a/doc/tl/tl.tex b/doc/tl/tl.tex index 0bee4a013..c11702450 100644 --- a/doc/tl/tl.tex +++ b/doc/tl/tl.tex @@ -1313,9 +1313,11 @@ instead of $\equiv$, and they can be disabled by setting the The following are simplification rules for unary operators (applied from left to right, as usual): \begin{align*} - \X\F\G f & \equiv \F\G f & \F\X f & \equiv \X\F f & \G\X f & \equiv \X\G f\\ - \X\G\F f & \equiv \G\F f & \F(f\U g) & \equiv \F g & \G(f \R g) & \equiv \G g \\ - & & \F(f\M g) & \equiv \F (f\AND g) & \G(f \W g) & \equiv \G(f\OR g) + \X\F\G f & \equiv \F\G f & \F\X f & \equiv \X\F f & \G\X f & \equiv \X\G f \\ + \X\G\F f & \equiv \G\F f & \F(f\U g) & \equiv \F g & \G(f \R g) & \equiv \G g \\ + & & \F(f\M g) & \equiv \F (f\AND g) & \G(f \W g) & \equiv \G(f\OR g) \\ + & & \F\G(f\AND \X g) & \equiv \F\G(f\AND g) & \G\F(f\OR \X g) & \equiv \G\F(f\OR g) \\ + & & \F\G(f\AND \G g) & \equiv \F\G(f\AND g) & \G\F(f\OR \F g) & \equiv \G\F(f\OR g) \\ \end{align*} \begin{align*} \G(f_1\OR\ldots\OR f_n \OR \G\F(g_1)\OR\ldots\OR \G\F(g_m)) & \equiv \G(f_1\OR\ldots\OR f_n)\OR \G\F(g_1\OR\ldots\OR g_m) diff --git a/src/ltltest/reduccmp.test b/src/ltltest/reduccmp.test index 417da8d2f..ef5117699 100755 --- a/src/ltltest/reduccmp.test +++ b/src/ltltest/reduccmp.test @@ -1,8 +1,9 @@ #! /bin/sh -# Copyright (C) 2009, 2010, 2011, 2012 Laboratoire de Recherche et -# Developpement de l'Epita (LRDE). +# -*- coding: utf-8 -*- +# Copyright (C) 2009, 2010, 2011, 2012, 2013 Laboratoire de Recherche +# et Developpement de l'Epita (LRDE). # Copyright (C) 2004, 2006 Laboratoire d'Informatique de Paris 6 (LIP6), -# département Systèmes Répartis Coopératifs (SRC), Université Pierre +# département Systèmes Répartis Coopératifs (SRC), Université Pierre # et Marie Curie. # # This file is part of Spot, a model checking library. @@ -98,6 +99,13 @@ for x in ../reduccmp ../reductaustr; do run 0 $x 'FX(a)' 'XF(a)' run 0 $x 'GX(a)' 'XG(a)' + run 0 $x 'GF(a | Xb)' 'GF(a | b)' + run 0 $x 'GF(a | Fb)' 'GF(a | b)' + run 0 $x 'GF(Xa | Fb)' 'GF(a | b)' + run 0 $x 'FG(a & Xb)' 'FG(a & b)' + run 0 $x 'FG(a & Gb)' 'FG(a & b)' + run 0 $x 'FG(Xa & Gb)' 'FG(a & b)' + run 0 $x 'X(a) U X(b)' 'X(a U b)' run 0 $x 'X(a) R X(b)' 'X(a R b)' run 0 $x 'Xa & Xb' 'X(a & b)' diff --git a/src/ltlvisit/simplify.cc b/src/ltlvisit/simplify.cc index 1282cf765..6a572a510 100644 --- a/src/ltlvisit/simplify.cc +++ b/src/ltlvisit/simplify.cc @@ -1,5 +1,6 @@ -// Copyright (C) 2011, 2012 Laboratoire de Recherche et Developpement -// de l'Epita (LRDE). +// -*- coding: utf-8 -*- +// Copyright (C) 2011, 2012, 2013 Laboratoire de Recherche et +// Developpement de l'Epita (LRDE). // // This file is part of Spot, a model checking library. // @@ -1184,6 +1185,47 @@ namespace spot result_ = recurse_destroy(res); return; } + + // FG(a & Xb) = FG(a & b) + // FG(a & Gb) = FG(a & b) + if (const unop* g = is_G(result_)) + if (const multop* m = is_And(g->child())) + if (!m->is_boolean()) + { + m->clone(); + mospliter s(mospliter::Strip_G | mospliter::Strip_X, + m, c_); + if (!s.res_G->empty() || !s.res_X->empty()) + { + result_->destroy(); + s.res_other->insert(s.res_other->begin(), + s.res_G->begin(), + s.res_G->end()); + delete s.res_G; + s.res_other->insert(s.res_other->begin(), + s.res_X->begin(), + s.res_X->end()); + delete s.res_X; + const formula* in = + multop::instance(multop::And, s.res_other); + result_ = + recurse_destroy(unop_unop(unop::F, unop::G, + in)); + return; + } + else + { + for (multop::vec::iterator j = + s.res_other->begin(); + j != s.res_other->end(); ++j) + if (*j) + (*j)->destroy(); + delete s.res_other; + delete s.res_G; + delete s.res_X; + // and continue... + } + } } // if Fa => a, keep a. @@ -1288,6 +1330,47 @@ namespace spot result_ = mo; } } + + // GF(a | Xb) = GF(a | b) + // GF(a | Fb) = GF(a | b) + if (const unop* f = is_F(result_)) + if (const multop* m = is_Or(f->child())) + if (!m->is_boolean()) + { + m->clone(); + mospliter s(mospliter::Strip_F | mospliter::Strip_X, + m, c_); + if (!s.res_F->empty() || !s.res_X->empty()) + { + result_->destroy(); + s.res_other->insert(s.res_other->begin(), + s.res_F->begin(), + s.res_F->end()); + delete s.res_F; + s.res_other->insert(s.res_other->begin(), + s.res_X->begin(), + s.res_X->end()); + delete s.res_X; + const formula* in = + multop::instance(multop::Or, s.res_other); + result_ = + recurse_destroy(unop_unop(unop::G, unop::F, + in)); + return; + } + else + { + for (multop::vec::iterator j = + s.res_other->begin(); + j != s.res_other->end(); ++j) + if (*j) + (*j)->destroy(); + delete s.res_other; + delete s.res_F; + delete s.res_X; + // and continue... + } + } } // if a => Ga, keep a. if (opt_.containment_checks_stronger