Commit 82b42494 authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

Generalize G,&,| rewritings to deal with event. and univ. terms.

* src/ltlvisit/simplify.cc (ltl_simplifier): Adjust
code.
* src/ltltest/reduccmp.test: Add some test cases.
parent ab7a1c7a
......@@ -101,8 +101,8 @@ for x in ../reduccmp ../reductaustr; do
run 0 $x '(a R b) | (c R b)' '(a | c) R b'
run 0 $x 'Xa & FGb' 'X(a & FGb)'
run 0 $x 'Xa | FGb' 'Xa | FGb' # We'd prefer 'X(a | FGb)'
run 0 $x 'Xa & GFb' 'Xa & GFb' # 'X(a & GFb)'
run 0 $x 'Xa | FGb' 'X(a | FGb)'
run 0 $x 'Xa & GFb' 'X(a & GFb)'
run 0 $x '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
......@@ -111,8 +111,10 @@ for x in ../reduccmp ../reductaustr; do
# (2) ... it would hinder this useful reduction (that helps to
# produce a smaller automaton)
run 0 $x 'F(f1 & GF(f2)) | F(a & GF(b))' 'F((f1&GFf2)|(a&GFb))'
# FIXME: Don't we want the opposite rewriting
run 0 $x 'Fa & GFb' 'Fa & GFb' # We'd prefer 'F(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...
run 0 $x 'Fa & GFb' 'Fa & GFb'
run 0 $x 'G(a | GFb)' 'Ga | GFb'
# The following is not reduced to F(a & c) & GF(b) for the same
# reason as above.
......@@ -168,8 +170,16 @@ for x in ../reduccmp ../reductaustr; do
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' 'G(a&Fc) & Xb'
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'
# 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)'
;;
esac
......
......@@ -1005,22 +1005,25 @@ namespace spot
}
}
// G(f1|f2|GF(f3)|GF(f4)|FG(f5)|FG(f6)) =
// G(f1|f2) | GF(f3|f4) | FG(f5) | FG(f6)
// FIXME: can this be generalized to Universal formulae?
// G(f1|f2|GF(f3)|GF(f4)|f5|f6) =
// G(f1|f2) | GF(f3|f4) | f5 | f6
// if f5 and f6 are both eventual and universal.
if (result_->kind() == formula::MultOp)
{
multop* mo = static_cast<multop*>(result_);
if (mo->op() == multop::Or)
{
mospliter s(mospliter::Strip_GF | mospliter::Split_FG,
mospliter s(mospliter::Strip_GF |
mospliter::Split_EventUniv,
mo, c_);
s.res_FG->push_back(unop_multop(unop::G, multop::Or,
s.res_other));
s.res_FG->push_back(unop_unop_multop(unop::G, unop::F,
multop::Or,
s.res_GF));
result_ = multop::instance(multop::Or, s.res_FG);
s.res_EventUniv->push_back(unop_multop(unop::G,
multop::Or,
s.res_other));
s.res_EventUniv->push_back(unop_unop_multop(unop::G,
unop::F,
multop::Or,
s.res_GF));
result_ = multop::instance(multop::Or, s.res_EventUniv);
if (result_ != uo)
result_ = recurse_destroy(result_);
return;
......@@ -1553,10 +1556,10 @@ namespace spot
}
delete s.res_EventUniv;
formula* allX = unop_multop(unop::X, multop::And, s.res_X);
// G(a) & G(b) = G(a & b)
formula* allG = unop_multop(unop::G, multop::And, s.res_G);
// Xa & Xb & f1...fn = X(a & b & f1...fn)
// is built at the end of this multop::And case.
// G(a) & F(b) = G(a & b)
// is built at the end of this multop::And case.
// The following three loops perform these rewritings:
// (a U b) & (c U b) = (a & c) U b
......@@ -1700,9 +1703,34 @@ namespace spot
s.res_R_or_M->begin(),
s.res_R_or_M->end());
delete s.res_R_or_M;
// Those "G" formulae that are eventual can be
// postponed inside the X term if there is one.
//
// In effect we rewrite
// Xa&Xb&GFc&GFd&Ge as X(a&b&G(Fc&Fd))&Ge
if (!s.res_X->empty())
{
multop::vec* event = new multop::vec;
for (multop::vec::iterator i = s.res_G->begin();
i != s.res_G->end(); ++i)
if ((*i)->is_eventual())
{
event->push_back(*i);
*i = 0; // Remove it from res_G.
}
s.res_X->push_back(unop_multop(unop::G,
multop::And, event));
}
// G(a) & G(b) & ... = G(a & b & ...)
formula* allG = unop_multop(unop::G, multop::And, s.res_G);
// Xa & Xb & ... = X(a & b & ...)
formula* allX = unop_multop(unop::X, multop::And, s.res_X);
s.res_other->push_back(allX);
s.res_other->push_back(allFG);
s.res_other->push_back(allG);
s.res_other->push_back(allFG);
result_ = multop::instance(multop::And, s.res_other);
// If we altered the formula in some way, process
// it another time.
......@@ -1736,10 +1764,33 @@ namespace spot
s.res_EventUniv->begin(),
s.res_EventUniv->end());
}
else if (!s.res_F->empty())
else if (!s.res_F->empty()
&& s.res_G->empty()
&& s.res_U_or_W->empty()
&& s.res_R_or_M->empty()
&& s.res_other->empty())
{
// If there is no X but some F, do
// Fa | Fb | f1...fn | GF(c) = F(a | b | f1...fn | GF(c))
// If there is no X but some F and only
// eventual&universal formula, do:
// Fa|Fb|f1...fn|GF(c) = F(a|b|f1...fn|GF(c))
//
// The reasoning here is that if we should
// move f1...fn|GF(c) inside the "F" only
// if it allows us to move all terms under F,
// allowing a nice initial self-loop.
//
// For instance:
// F(a|GFb) 3st.6tr. with initial self-loop
// Fa|GFb 4st.8tr. without initial self-loop
//
// However, if other term are presents they will
// prevent the formation of a self-loop, and the
// rewriting is unwelcome:
// F(a|GFb)|Gc 5st.11tr. without initial self-loop
// Fa|GFb|Gc 5st.10tr. without initial self-loop
// (counting the number of "subtransitions"
// or, degeneralizing the automaton amplify
// these differences)
s.res_F->push_back(allGF);
allGF = 0;
s.res_F->insert(s.res_F->end(),
......@@ -1753,9 +1804,10 @@ namespace spot
s.res_EventUniv->end());
}
delete s.res_EventUniv;
formula* allX = unop_multop(unop::X, multop::Or, s.res_X);
// Xa | Xb | f1...fn = X(a | b | f1...fn)
// is built at the end of this multop::Or case.
// F(a) | F(b) = F(a | b)
formula* allF = unop_multop(unop::F, multop::Or, s.res_F);
// is built at the end of this multop::Or case.
// The following three loops perform these rewritings:
// (a U b) | (a U c) = a U (b | c)
......@@ -1882,6 +1934,8 @@ namespace spot
}
}
s.res_other->reserve(s.res_other->size()
+ s.res_G->size()
+ s.res_U_or_W->size()
......@@ -1899,9 +1953,34 @@ namespace spot
s.res_R_or_M->begin(),
s.res_R_or_M->end());
delete s.res_R_or_M;
// Those "F" formulae that are universal can be
// postponed inside the X term if there is one.
//
// In effect we rewrite
// Xa|Xb|FGc|FGd|Fe as X(a|b|F(Gc|Gd))|Fe
if (!s.res_X->empty())
{
multop::vec* univ = new multop::vec;
for (multop::vec::iterator i = s.res_F->begin();
i != s.res_F->end(); ++i)
if ((*i)->is_universal())
{
univ->push_back(*i);
*i = 0; // Remove it from res_F.
}
s.res_X->push_back(unop_multop(unop::F,
multop::Or, univ));
}
// F(a) | F(b) | ... = F(a | b | ...)
formula* allF = unop_multop(unop::F, multop::Or, s.res_F);
// Xa | Xb | ... = X(a | b | ...)
formula* allX = unop_multop(unop::X, multop::Or, s.res_X);
s.res_other->push_back(allX);
s.res_other->push_back(allGF);
s.res_other->push_back(allF);
s.res_other->push_back(allGF);
result_ = multop::instance(multop::Or, s.res_other);
// If we altered the formula in some way, process
// it another time.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment