* src/tgbatest/ltl2tgba.cc: Add some option for the reduction of

automata.
* src/tgbatest/spotlbtt.test, src/tgbatest/Makefile.am: Add some
test for reduction of automata.
* src/tgbaalgos/reductgba_sim_del.cc, src/tgbaalgos/reductgba_sim.cc,
src/tgbaalgos/reductgba_sim.hh: Compute some simulation relation
to reduce a tgba.
* src/tgba/tgbareduc.cc, src/tgba/tgbareduc.hh: A implementation
of tgba for the reduction.
* src/tgbaalgos/Makefile.am, src/tgba/Makefile.am:
Add the reduction of automata.
* src/ltlvisit/syntimpl.cc, src/ltlvisit/basereduc.cc:
Lot of mistake are corrected.
* src/ltlvisit/syntimpl.hh, src/ltlvisit/reducform.cc,
src/ltlvisit/reducform.hh, src/ltltest/reduc.cc: Adjust.
* src/ltltest/equals.cc, src/ltltest/reduccmp.test,
src/ltltest/Makefile.am: Add a test for reduction.
This commit is contained in:
martinez 2004-06-15 16:24:02 +00:00
parent 383f7e170a
commit 8d3606ff07
20 changed files with 3155 additions and 133 deletions

View file

@ -23,7 +23,9 @@
#include "ltlast/allnodes.hh"
#include <cassert>
#include "ltlvisit/clone.hh"
#include "ltlvisit/destroy.hh"
#include "ltlvisit/dump.hh"
namespace spot
{
@ -85,6 +87,33 @@ namespace spot
result_ = c;
}
formula*
param_case(multop* mo, unop::type op, multop::type op_child)
{
formula* result;
multop::vec* res1 = new multop::vec;
multop::vec* resGF = new multop::vec;
unsigned mos = mo->size();
for (unsigned i = 0; i < mos; ++i)
if (is_GF(mo->nth(i)))
resGF->push_back(clone(mo->nth(i)));
else
res1->push_back(clone(mo->nth(i)));
destroy(mo);
multop::vec* res3 = new multop::vec;
if (res1->size())
res3->push_back(unop::instance(op,
multop::instance(op_child, res1)));
else
delete res1;
if (resGF->size())
res3->push_back(multop::instance(op_child, resGF));
else
delete resGF;
result = multop::instance(op_child, res3);
return result;
}
void
visit(unop* uo)
{
@ -112,30 +141,10 @@ namespace spot
// X(f1 & GF(f2)) = X(f1) & GF(F2)
// X(f1 | GF(f2)) = X(f1) | GF(F2)
mo = dynamic_cast<multop*>(result_);
if (mo && mo->size() == 2)
if (mo)
{
// FIXME: This is incomplete. It should be done for
// multops of any size.
if (is_GF(mo->nth(0)))
{
multop::vec* res = new multop::vec;
res->push_back(unop::instance(unop::F,
basic_reduce(mo->nth(1))));
res->push_back(basic_reduce(mo->nth(0)));
result_ = multop::instance(mo->op(), res);
destroy(mo);
return;
}
if (is_GF(mo->nth(1)))
{
multop::vec* res = new multop::vec;
res->push_back(unop::instance(unop::F,
basic_reduce(mo->nth(0))));
res->push_back(basic_reduce(mo->nth(1)));
result_ = multop::instance(mo->op(), res);
destroy(mo);
return;
}
result_ = param_case(mo, unop::X, mo->op());
return;
}
result_ = unop::instance(unop::X, result_);
@ -161,34 +170,12 @@ namespace spot
// F(f1 & GF(f2)) = F(f1) & GF(F2)
mo = dynamic_cast<multop*>(result_);
if (mo && mo->op() == multop::And
// FIXME: This is incomplete. It should be done for
// "And"s of any size.
&& mo->size() == 2)
if (mo && mo->op() == multop::And)
{
if (is_GF(mo->nth(0)))
{
multop::vec* res = new multop::vec;
res->push_back(unop::instance(unop::F,
basic_reduce(mo->nth(1))));
res->push_back(basic_reduce(mo->nth(0)));
result_ = multop::instance(mo->op(), res);
destroy(mo);
return;
}
if (is_GF(mo->nth(1)))
{
multop::vec* res = new multop::vec;
res->push_back(unop::instance(unop::F,
basic_reduce(mo->nth(0))));
res->push_back(basic_reduce(mo->nth(1)));
result_ = multop::instance(mo->op(), res);
destroy(mo);
return;
}
result_ = param_case(mo, unop::F, multop::And);
return;
}
result_ = unop::instance(unop::F, result_);
return;
@ -222,31 +209,10 @@ namespace spot
// G(f1 | GF(f2)) = G(f1) | GF(F2)
mo = dynamic_cast<multop*>(result_);
if (mo && mo->op() == multop::Or
// FIXME: This is incomplete. It should be done for
// "Or"s of any size.
&& mo->size() == 2)
if (mo && mo->op() == multop::Or)
{
if (is_GF(mo->nth(0)))
{
multop::vec* res = new multop::vec;
res->push_back(unop::instance(unop::F,
basic_reduce(mo->nth(1))));
res->push_back(basic_reduce(mo->nth(0)));
result_ = multop::instance(mo->op(), res);
destroy(mo);
return;
}
if (is_GF(mo->nth(1)))
{
multop::vec* res = new multop::vec;
res->push_back(unop::instance(unop::F,
basic_reduce(mo->nth(0))));
res->push_back(basic_reduce(mo->nth(1)));
result_ = multop::instance(mo->op(), res);
destroy(mo);
return;
}
result_ = param_case(mo, unop::G, multop::Or);
return;
}
result_ = unop::instance(unop::G, result_);
@ -385,17 +351,17 @@ namespace spot
if (uo && uo->op() == unop::X)
{
// Xa & Xb = X(a & b)
tmpX->push_back(basic_reduce(uo->child()));
tmpX->push_back(clone(uo->child()));
}
else if (is_FG(*i))
{
// FG(a) & FG(b) = FG(a & b)
unop* uo2 = dynamic_cast<unop*>(uo->child());
tmpFG->push_back(basic_reduce(uo2->child()));
tmpFG->push_back(clone(uo2->child()));
}
else
{
tmpOther->push_back(basic_reduce(*i));
tmpOther->push_back(clone(*i));
}
}
else if (bo)
@ -414,7 +380,7 @@ namespace spot
&& ftmp == bo2->second())
{
tmpUright
->push_back(basic_reduce(bo2->first()));
->push_back(clone(bo2->first()));
if (j != i)
{
destroy(*j);
@ -428,7 +394,7 @@ namespace spot
instance(multop::
And,
tmpUright),
basic_reduce(ftmp)));
clone(ftmp)));
}
else if (bo->op() == binop::R)
{
@ -444,7 +410,7 @@ namespace spot
&& ftmp == bo2->first())
{
tmpRright
->push_back(basic_reduce(bo2->second()));
->push_back(clone(bo2->second()));
if (j != i)
{
destroy(*j);
@ -454,19 +420,19 @@ namespace spot
}
tmpR
->push_back(binop::instance(binop::R,
basic_reduce(ftmp),
clone(ftmp),
multop::
instance(multop::And,
tmpRright)));
}
else
{
tmpOther->push_back(basic_reduce(*i));
tmpOther->push_back(clone(*i));
}
}
else
{
tmpOther->push_back(basic_reduce(*i));
tmpOther->push_back(clone(*i));
}
destroy(*i);
}
@ -489,17 +455,17 @@ namespace spot
if (uo && uo->op() == unop::X)
{
// Xa | Xb = X(a | b)
tmpX->push_back(basic_reduce(uo->child()));
tmpX->push_back(clone(uo->child()));
}
else if (is_GF(*i))
{
// GF(a) | GF(b) = GF(a | b)
unop* uo2 = dynamic_cast<unop*>(uo->child());
tmpGF->push_back(basic_reduce(uo2->child()));
tmpGF->push_back(clone(uo2->child()));
}
else
{
tmpOther->push_back(basic_reduce(*i));
tmpOther->push_back(clone(*i));
}
}
else if (bo)
@ -518,7 +484,7 @@ namespace spot
&& ftmp == bo2->first())
{
tmpUright
->push_back(basic_reduce(bo2->second()));
->push_back(clone(bo2->second()));
if (j != i)
{
destroy(*j);
@ -527,7 +493,7 @@ namespace spot
}
}
tmpU->push_back(binop::instance(binop::U,
basic_reduce(ftmp),
clone(ftmp),
multop::
instance(multop::Or,
tmpUright)));
@ -546,7 +512,7 @@ namespace spot
&& ftmp == bo2->second())
{
tmpRright
->push_back(basic_reduce(bo->first()));
->push_back(clone(bo2->first()));
if (j != i)
{
destroy(*j);
@ -559,16 +525,16 @@ namespace spot
multop::
instance(multop::Or,
tmpRright),
basic_reduce(ftmp)));
clone(ftmp)));
}
else
{
tmpOther->push_back(basic_reduce(*i));
tmpOther->push_back(clone(*i));
}
}
else
{
tmpOther->push_back(basic_reduce(*i));
tmpOther->push_back(clone(*i));
}
destroy(*i);
}
@ -582,23 +548,27 @@ namespace spot
res->clear();
delete res;
if (tmpX->size())
if (tmpX && tmpX->size())
tmpOther->push_back(unop::instance(unop::X,
multop::instance(mo->op(),
tmpX)));
else
else if (tmpX && !tmpX->size())
delete tmpX;
if (tmpU->size())
if (tmpU && tmpU->size())
tmpOther->push_back(multop::instance(mo->op(), tmpU));
else
else if (tmpU && !tmpU->size())
delete tmpU;
if (tmpR->size())
if (tmpR && tmpR->size())
tmpOther->push_back(multop::instance(mo->op(), tmpR));
else
else if (tmpR && !tmpR->size())
delete tmpR;
if (tmpGF && tmpGF->size())
{
formula* ftmp
@ -608,6 +578,10 @@ namespace spot
tmpGF)));
tmpOther->push_back(ftmp);
}
else if (tmpGF && !tmpGF->size())
delete tmpGF;
if (tmpFG && tmpFG->size())
{
formula* ftmp
@ -617,6 +591,9 @@ namespace spot
tmpFG)));
tmpOther->push_back(ftmp);
}
else if (tmpFG && !tmpFG->size())
delete tmpFG;
result_ = multop::instance(op, tmpOther);

View file

@ -311,6 +311,7 @@ namespace spot
destroy(f2);
f2 = f1;
}
if (opt & (Reduce_Syntactic_Implications
| Reduce_Eventuality_And_Universality))
{
@ -322,9 +323,9 @@ namespace spot
// Run basic_reduce again.
//
// Consider `F b & g' were g is an eventual formula rewritten
// as `g = F c' Then basic_reduce with rewrite it
// as F(b & c).
// Consider `FG b & g' were g is an eventual formula rewritten
// as `g = FG c' Then basic_reduce with rewrite it
// as FG(b & c).
if (opt & Reduce_Basics)
{
f1 = basic_reduce(f2);

View file

@ -59,6 +59,23 @@ namespace spot
/// \brief Check whether a formula is eventual.
///
/// FIXME: Describe what eventual formulae are. Cite paper.
/// This comes from
/// \verbatim
/// @InProceedings{ etessami.00.concur,
/// author = {Kousha Etessami and Gerard J. Holzmann},
/// title = {Optimizing {B\"u}chi Automata},
/// booktitle = {Proceedings of the 11th International Conference on
/// Concurrency Theory (Concur'2000)},
/// pages = {153--167},
/// year = {2000},
/// editor = {C. Palamidessi},
/// volume = {1877},
/// series = {Lecture Notes in Computer Science},
/// publisher = {Springer-Verlag}
/// }
/// \endverbatim
bool is_eventual(const formula* f);
/// \brief Check whether a formula is universal.

View file

@ -72,41 +72,46 @@ namespace spot
visit(const unop* uo)
{
const formula* f1 = uo->child();
switch (uo->op())
if (uo->op() == unop::F)
{
case unop::Not:
case unop::X:
eventual = recurse_ev(f1);
eventual = true;
universal = recurse_un(f1);
return;
case unop::F:
eventual = true;
return;
case unop::G:
universal = true;
return;
}
/* Unreachable code. */
assert(0);
if (uo->op() == unop::G)
{
universal = true;
eventual = recurse_ev(f1);
}
}
void
visit(const binop* bo)
{
const formula* f1 = bo->first();
const formula* f2 = bo->second();
switch (bo->op())
{
case binop::Xor:
case binop::Equiv:
case binop::Implies:
universal = recurse_un(f1) & recurse_un(f2);
eventual = recurse_ev(f1) & recurse_ev(f2);
return;
case binop::U:
if (f1 == constant::true_instance())
universal = recurse_un(f1) & recurse_un(f2);
if ((f1 == constant::true_instance()) ||
(recurse_ev(f1)))
eventual = true;
return;
case binop::R:
if (f1 == constant::false_instance())
eventual = recurse_ev(f1) & recurse_ev(f2);
if ((f1 == constant::false_instance()))
//||
//(recurse_un(f1)))
universal = true;
if (!universal)
universal = recurse_un(f1) & recurse_un(f2);
return;
}
/* Unreachable code. */

View file

@ -28,7 +28,20 @@ namespace spot
{
namespace ltl
{
// FIXME: Cite paper.
/// This comes from
/// \verbatim
/// @InProceedings{ somenzi.00.cav,
/// author = {Fabio Somenzi and Roderick Bloem},
/// title = {Efficient {B\"u}chi Automata for {LTL} Formulae},
/// booktitle = {Proceedings of the 12th International Conference on
/// Computer Aided Verification (CAV'00)},
/// pages = {247--263},
/// year = {2000},
/// volume = {1855},
/// series = {Lecture Notes in Computer Science},
/// publisher = {Springer-Verlag}
/// }
/// \endverbatim
/// \brief Syntactic implication.
bool syntactic_implication(const formula* f1, const formula* f2);