Add implication-based rewritings from Babiak et al. (TACAS'12)

* src/ltlvisit/simplify.cc: Implement them here, and augment them
to support M, and W operators.
* src/ltltest/reduccmp.test: Add some tests.
* doc/tl/tl.tex (Simplifications Based on Implications): Document
these rules.
* doc/tl/tl.bib (babiak.12.tacas): New entry.
This commit is contained in:
Alexandre Duret-Lutz 2012-01-10 19:34:41 +01:00
parent ed0dd0b48d
commit 212c7ebdd7
4 changed files with 124 additions and 5 deletions

View file

@ -1,5 +1,5 @@
#! /bin/sh
# Copyright (C) 2009, 2010, 2011 Laboratoire de Recherche et Developpement
#! /bin/sh
# Copyright (C) 2009, 2010, 2011, 2012 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
@ -174,6 +174,20 @@ for x in ../reduccmp ../reductaustr; do
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'
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)'
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)'
run 0 $x 'a W ((a&b) U c)' 'a W c'
run 0 $x 'a W ((a&b) W c)' 'a W c'
run 0 $x '(a M c) M (b&a)' 'c M (b&a)'
# Eventuality and universality class reductions
run 0 $x 'Fa M b' 'Fa & b'
run 0 $x 'GFa M b' 'GFa & b'

View file

@ -1272,9 +1272,16 @@ namespace spot
}
// if a => b, then a U (b U c) = (b U c)
// if a => b, then a U (b W c) = (b W c)
// if b => a, then a U (b U c) = (a U c)
// if a => c, then a U (b R (c U d)) = (b R (c U d))
// if a => c, then a U (b R (c W d)) = (b R (c W d))
// if a => c, then a U (b M (c U d)) = (b M (c U d))
// if a => c, then a U (b M (c W d)) = (b M (c W d))
if (b->kind() == formula::BinOp)
{
binop* bo = static_cast<binop*>(b);
// if a => b, then a U (b U c) = (b U c)
// if a => b, then a U (b W c) = (b W c)
if ((bo->op() == binop::U || bo->op() == binop::W)
&& c_->implication(a, bo->first()))
{
@ -1282,6 +1289,32 @@ namespace spot
result_ = b;
return;
}
// if b => a, then a U (b U c) = (a U c)
if (bo->op() == binop::U
&& c_->implication(bo->first(), a))
{
result_ = recurse_destroy
(binop::instance(binop::U,
a, bo->second()->clone()));
b->destroy();
return;
}
// if a => c, then a U (b R (c U d)) = (b R (c U d))
// if a => c, then a U (b R (c W d)) = (b R (c W d))
// if a => c, then a U (b M (c U d)) = (b M (c U d))
// if a => c, then a U (b M (c W d)) = (b M (c W d))
if ((bo->op() == binop::R || bo->op() == binop::M)
&& bo->second()->kind() == formula::BinOp)
{
binop* cd = static_cast<binop*>(bo->second());
if ((cd->op() == binop::U || cd->op() == binop::W)
&& c_->implication(a, cd->first()))
{
a->destroy();
result_ = b;
return;
}
}
}
break;
@ -1317,13 +1350,30 @@ namespace spot
if (bo->op() == binop::R
&& c_->implication(a, bo->first()))
{
b->destroy();
result_ = recurse_destroy
(binop::instance(binop::R, a,
bo->second()->clone()));
b->destroy();
return;
}
}
if (a->kind() == formula::BinOp)
{
// if b => a then (a R c) R b = c R b
// if b => a then (a M c) R b = c R b
binop* bo = static_cast<binop*>(a);
if ((bo->op() == binop::R || bo->op() == binop::M)
&& c_->implication(b, bo->first()))
{
result_ = recurse_destroy
(binop::instance(binop::R,
bo->second()->clone(),
b));
a->destroy();
return;
}
}
break;
case binop::W:
@ -1347,9 +1397,12 @@ namespace spot
}
// if a => b, then a W (b W c) = (b W c)
// (Beware: even if a => b we do not have a W (b U c) = b U c)
// if b => a, then a W (b U c) = (a W c)
// if b => a, then a W (b W c) = (a W c)
if (b->kind() == formula::BinOp)
{
binop* bo = static_cast<binop*>(b);
// if a => b, then a W (b W c) = (b W c)
if (bo->op() == binop::W
&& c_->implication(a, bo->first()))
{
@ -1357,6 +1410,17 @@ namespace spot
result_ = b;
return;
}
// if b => a, then a W (b U c) = (a W c)
// if b => a, then a W (b W c) = (a W c)
if ((bo->op() == binop::U || bo->op() == binop::W)
&& c_->implication(bo->first(), a))
{
result_ = recurse_destroy
(binop::instance(binop::W,
a, bo->second()->clone()));
b->destroy();
return;
}
}
break;
@ -1400,6 +1464,21 @@ namespace spot
return;
}
}
if (a->kind() == formula::BinOp)
{
// if b => a then (a M c) M b = c M b
binop* bo = static_cast<binop*>(a);
if (bo->op() == binop::M
&& c_->implication(b, bo->first()))
{
result_ = recurse_destroy
(binop::instance(binop::M,
bo->second()->clone(),
b));
a->destroy();
return;
}
}
break;
}
trace << "bo: no inclusion-based rules matched" << std::endl;