Simplify {b && r[*]} as {b && r}; likewise for [->] and [=].
* src/ltlvisit/simplify.cc (simplify_visitor): Do it. * src/ltltest/reduccmp.test: Add more tests. * doc/tl/tl.tex: Document it.
This commit is contained in:
parent
e61c01b826
commit
77084747b9
3 changed files with 317 additions and 216 deletions
|
|
@ -1192,6 +1192,7 @@ The goals in most of these simplification are to:
|
|||
These simplifications are enabled with
|
||||
\verb|ltl_simplifier_options::reduce_basics|'.
|
||||
|
||||
\subsubsection{Basic Simplifications for Temporal Operators}
|
||||
|
||||
The following are simplification rules for unary operators (applied
|
||||
from left to right, as usual):
|
||||
|
|
@ -1264,6 +1265,31 @@ in the OR arguments:
|
|||
&\equiv \F(f_1\OR \ldots \OR f_n \OR \G\F(g_1\OR \ldots \OR g_m)) \\
|
||||
\end{align*}
|
||||
|
||||
\subsubsection{Basic Simplifications for SERE Operators}
|
||||
|
||||
% Cite Symbolic computation of PSL.
|
||||
|
||||
The following simplification rules are used for the $n$-ary operators
|
||||
$\ANDALT$, $\AND$, and $\OR$, and are of course commutative.
|
||||
|
||||
\begin{align*}
|
||||
b \ANDALT r\STAR{\mvar{i}..\mvar{j}} &\equiv
|
||||
\begin{cases}
|
||||
b \ANDALT r &\text{if~} i\le 1\le j\\
|
||||
\0 &\text{else}\\
|
||||
\end{cases}\\
|
||||
b \ANDALT r\EQUAL{\mvar{i}..\mvar{j}} &\equiv
|
||||
\begin{cases}
|
||||
b \ANDALT r &\text{if~} i\le 1\le j\\
|
||||
\0 &\text{else}\\
|
||||
\end{cases}\\
|
||||
b \ANDALT r\GOTO{\mvar{i}..\mvar{j}} &\equiv
|
||||
\begin{cases}
|
||||
b \ANDALT r &\text{if~} i\le 1\le j\\
|
||||
\0 &\text{else}\\
|
||||
\end{cases}\\
|
||||
\end{align*}
|
||||
|
||||
\subsection{Simplifications for Eventual and Universal Formul\ae}
|
||||
\label{sec:eventunivrew}
|
||||
|
||||
|
|
|
|||
|
|
@ -202,6 +202,14 @@ for x in ../reduccmp ../reductaustr; do
|
|||
# without pruning the rational automaton.
|
||||
run 0 $x '{(c&!c)[=2]}' '0'
|
||||
|
||||
run 0 $x '{a && b && c*} <>-> d' 'a&b&c&d'
|
||||
run 0 $x '{a && b && c[*1..3]} <>-> d' 'a&b&c&d'
|
||||
run 0 $x '{a && b && c[->0..2]} <>-> d' 'a&b&c&d'
|
||||
run 0 $x '{a && b && c[+]} <>-> d' 'a&b&c&d'
|
||||
run 0 $x '{a && b && c[=1]} <>-> d' 'a&b&c&d'
|
||||
run 0 $x '{a && b && d[=2]} <>-> d' '0'
|
||||
run 0 $x '{a && b && d[->2..4]} <>-> d' '0'
|
||||
run 0 $x '{a && b && d[*2..]} <>-> d' '0'
|
||||
;;
|
||||
esac
|
||||
|
||||
|
|
|
|||
|
|
@ -1628,8 +1628,7 @@ namespace spot
|
|||
while (f1 != res->end())
|
||||
{
|
||||
multop::vec::iterator f2 = f1;
|
||||
++f2
|
||||
;
|
||||
++f2;
|
||||
while (f2 != res->end())
|
||||
{
|
||||
assert(f1 != f2);
|
||||
|
|
@ -1687,11 +1686,14 @@ namespace spot
|
|||
|
||||
assert(!res->empty());
|
||||
|
||||
if (opt_.reduce_basics)
|
||||
// basics reduction do not concern Boolean formulas,
|
||||
// so don't waste time trying to apply them.
|
||||
if (opt_.reduce_basics && !mo->is_boolean())
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case multop::And:
|
||||
if (!mo->is_sere_formula())
|
||||
{
|
||||
// Gather all operands by type.
|
||||
mospliter s(mospliter::Strip_X |
|
||||
|
|
@ -1832,7 +1834,8 @@ namespace spot
|
|||
binop::instance(binop::U,
|
||||
bo->first()->clone(),
|
||||
bo->second()->clone());
|
||||
assert((*j->second)->kind() == formula::BinOp);
|
||||
assert((*j->second)->kind()
|
||||
== formula::BinOp);
|
||||
bo->destroy();
|
||||
}
|
||||
}
|
||||
|
|
@ -1847,7 +1850,8 @@ namespace spot
|
|||
binop::instance(binop::M,
|
||||
bo->first()->clone(),
|
||||
bo->second()->clone());
|
||||
assert((*j->second)->kind() == formula::BinOp);
|
||||
assert((*j->second)->kind()
|
||||
== formula::BinOp);
|
||||
bo->destroy();
|
||||
}
|
||||
}
|
||||
|
|
@ -1896,9 +1900,11 @@ namespace spot
|
|||
}
|
||||
|
||||
// G(a) & G(b) & ... = G(a & b & ...)
|
||||
formula* allG = unop_multop(unop::G, multop::And, s.res_G);
|
||||
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);
|
||||
formula* allX =
|
||||
unop_multop(unop::X, multop::And, s.res_X);
|
||||
|
||||
s.res_other->push_back(allX);
|
||||
s.res_other->push_back(allG);
|
||||
|
|
@ -1910,6 +1916,67 @@ namespace spot
|
|||
result_ = recurse_destroy(result_);
|
||||
return;
|
||||
}
|
||||
else // SERE
|
||||
{
|
||||
mospliter s(mospliter::Split_Bool, res, c_);
|
||||
if (!s.res_Bool->empty())
|
||||
{
|
||||
// b1 & b2 & b3 = b1 && b2 && b3
|
||||
formula* b = multop::instance(multop::And,
|
||||
s.res_Bool);
|
||||
|
||||
multop::vec* ares = new multop::vec;
|
||||
for (multop::vec::iterator i = s.res_other->begin();
|
||||
i != s.res_other->end(); ++i)
|
||||
switch ((*i)->kind())
|
||||
{
|
||||
case formula::BUnOp:
|
||||
{
|
||||
bunop* r = down_cast<bunop*>(*i);
|
||||
// b && r[*i..j] = b & r if i<=1<=j
|
||||
// = 0 otherwise
|
||||
// likewise for b && r[=i..j]
|
||||
// and b && r[->i..j]
|
||||
if (r->min() > 1 || r->max() < 1)
|
||||
goto returnfalse;
|
||||
ares->push_back(r->child()->clone());
|
||||
r->destroy();
|
||||
*i = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ares->push_back(*i);
|
||||
*i = 0;
|
||||
break;
|
||||
}
|
||||
delete s.res_other;
|
||||
ares->push_back(b);
|
||||
result_ = multop::instance(multop::And, ares);
|
||||
// If we altered the formula in some way, process
|
||||
// it another time.
|
||||
if (result_ != mo)
|
||||
result_ = recurse_destroy(result_);
|
||||
return;
|
||||
returnfalse:
|
||||
b->destroy();
|
||||
for (multop::vec::iterator i = s.res_other->begin();
|
||||
i != s.res_other->end(); ++i)
|
||||
if (*i)
|
||||
(*i)->destroy();
|
||||
for (multop::vec::iterator i = res->begin();
|
||||
i != res->end(); ++i)
|
||||
if (*i)
|
||||
(*i)->destroy();
|
||||
result_ = constant::false_instance();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete s.res_Bool;
|
||||
result_ = multop::instance(multop::And, s.res_other);
|
||||
return;
|
||||
}
|
||||
}
|
||||
case multop::Or:
|
||||
{
|
||||
// Gather all operand by type.
|
||||
|
|
@ -2160,8 +2227,8 @@ namespace spot
|
|||
result_ = recurse_destroy(result_);
|
||||
return;
|
||||
}
|
||||
case multop::Concat:
|
||||
case multop::AndNLM:
|
||||
case multop::Concat:
|
||||
case multop::Fusion:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue