simplify: add four simplification rules for GF and FG

GF(a|Xb) = GF(a|b)      GF(a|Fb) = GF(a|b)
FG(a&Xb) = FG(a&b)      FG(a&Gb) = FG(a&b)

* src/ltlvisit/simplify.cc: Implement them.
* NEWS, doc/tl/tl.tex: Document them.
* src/ltltest/reduccmp.test: Test then.
This commit is contained in:
Alexandre Duret-Lutz 2013-01-11 16:07:10 +01:00
parent 2580fc6f91
commit e4ecc2d465
4 changed files with 107 additions and 8 deletions

6
NEWS
View file

@ -9,6 +9,12 @@ New in spot 1.0a (not released):
- "P0.init" is parsed as an atomic even without the double quotes, - "P0.init" is parsed as an atomic even without the double quotes,
but it was always output with double quotes. This version will but it was always output with double quotes. This version will
not quote this atomic proposition anymore. 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: * Pruning:
- lbtt has been removed from the distribution. A copy of the last - lbtt has been removed from the distribution. A copy of the last
version we distributed is still available at version we distributed is still available at

View file

@ -1313,9 +1313,11 @@ instead of $\equiv$, and they can be disabled by setting the
The following are simplification rules for unary operators (applied The following are simplification rules for unary operators (applied
from left to right, as usual): from left to right, as usual):
\begin{align*} \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\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 \\ \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(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*} \end{align*}
\begin{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) \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)

View file

@ -1,8 +1,9 @@
#! /bin/sh #! /bin/sh
# Copyright (C) 2009, 2010, 2011, 2012 Laboratoire de Recherche et # -*- coding: utf-8 -*-
# Developpement de l'Epita (LRDE). # 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), # 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. # et Marie Curie.
# #
# This file is part of Spot, a model checking library. # 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 'FX(a)' 'XF(a)'
run 0 $x 'GX(a)' 'XG(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) U X(b)' 'X(a U b)'
run 0 $x 'X(a) R X(b)' 'X(a R b)' run 0 $x 'X(a) R X(b)' 'X(a R b)'
run 0 $x 'Xa & Xb' 'X(a & b)' run 0 $x 'Xa & Xb' 'X(a & b)'

View file

@ -1,5 +1,6 @@
// Copyright (C) 2011, 2012 Laboratoire de Recherche et Developpement // -*- coding: utf-8 -*-
// de l'Epita (LRDE). // Copyright (C) 2011, 2012, 2013 Laboratoire de Recherche et
// Developpement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
// //
@ -1184,6 +1185,47 @@ namespace spot
result_ = recurse_destroy(res); result_ = recurse_destroy(res);
return; 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. // if Fa => a, keep a.
@ -1288,6 +1330,47 @@ namespace spot
result_ = mo; 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 a => Ga, keep a.
if (opt_.containment_checks_stronger if (opt_.containment_checks_stronger