Introduce AndRat and OrRat operator.

It was a mistake to try to overload And/Or LTL operator for these when
trivial simplification are performed.  The reason is so simple it is
embarassing: And(f,1)=f is a trivial identity that should not be
applied with AndRat.  E.g. AndRat(a;b, 1) is equal to 0, not a;b.

* src/ltlast/multop.hh, src/ltlast/multop.cc: Add the AndRat and OrRat
operators.
* src/ltlparse/ltlparse.yy: Build them.
* src/ltlvisit/mark.cc, src/ltlvisit/simplify.cc,
src/ltlvisit/tostring.cc, src/tgba/formula2bdd.cc,
src/tgbaalgos/eltl2tgba_lacim.cc, src/tgbaalgos/ltl2taa.cc,
src/tgbaalgos/ltl2tgba_fm.cc, src/tgbaalgos/ltl2tgba_lacim.cc:
Adjust all switches.
This commit is contained in:
Alexandre Duret-Lutz 2012-04-18 19:20:43 +02:00
parent 35b41331f7
commit 691119c188
11 changed files with 916 additions and 759 deletions

View file

@ -47,11 +47,13 @@ namespace spot
is.accepting_eword = false;
case Concat:
case AndNLM:
// Note: AndNLM(p1,p2) is a Boolean formula, but it is
// actually rewritten as And(p1,p2) by trivial identities
// before this constructor is called. So at this point,
// AndNLM is always used with at most one Boolean argument,
// and the result is therefore NOT Boolean.
case AndRat:
// Note: AndNLM(p1,p2) and AndRat(p1,p2) are Boolean
// formulae, but there are actually rewritten as And(p1,p2)
// by trivial identities before this constructor is called.
// So at this point, AndNLM/AndRat are always used with at
// most one Boolean argument, and the result is therefore
// NOT Boolean.
is.boolean = false;
is.ltl_formula = false;
is.eltl_formula = false;
@ -62,6 +64,18 @@ namespace spot
for (unsigned i = 1; i < s; ++i)
props &= (*v)[i]->get_props();
break;
case OrRat:
// Note: OrRat(p1,p2) is a Boolean formula, but its is
// actually rewritten as Or(p1,p2) by trivial identities
// before this constructor is called. So at this point,
// AndNLM is always used with at most one Boolean argument,
// and the result is therefore NOT Boolean.
is.boolean = false;
is.ltl_formula = false;
is.eltl_formula = false;
is.psl_formula = false;
is.eventual = false;
is.universal = false;
case Or:
{
bool ew = (*v)[0]->accepts_eword();
@ -159,10 +173,14 @@ namespace spot
{
case And:
return "And";
case AndRat:
return "AndRat";
case AndNLM:
return "AndNLM";
case Or:
return "Or";
case OrRat:
return "OrRat";
case Concat:
return "Concat";
case Fusion:
@ -173,6 +191,37 @@ namespace spot
return 0;
}
void
gather_bool(multop::vec* v, multop::type op)
{
// Gather all boolean terms.
multop::vec* b = new multop::vec;
multop::vec::iterator i = v->begin();
while (i != v->end())
{
if ((*i)->is_boolean())
{
b->push_back(*i);
i = v->erase(i);
}
else
{
++i;
}
}
// - AndNLM(Exps1...,Bool1,Exps2...,Bool2,Exps3...) =
// AndNLM(Exps1...,Exps2...,Exps3...,And(Bool1,Bool2))
// - AndRat(Exps1...,Bool1,Exps2...,Bool2,Exps3...) =
// AndRat(Exps1...,Exps2...,Exps3...,And(Bool1,Bool2))
// - OrRat(Exps1...,Bool1,Exps2...,Bool2,Exps3...) =
// AndRat(Exps1...,Exps2...,Exps3...,Or(Bool1,Bool2))
if (!b->empty())
v->push_back(multop::instance(op, b));
else
delete b;
}
multop::map multop::instances;
// We match equivalent formulae modulo "ACI rules"
@ -246,7 +295,15 @@ namespace spot
neutral2 = 0;
abs = constant::false_instance();
abs2 = 0;
weak_abs = 0;
break;
case AndRat:
neutral = 0; /* FIXME: we should use 1[*] as neutral */
neutral2 = 0;
abs = constant::false_instance();
abs2 = 0;
weak_abs = constant::empty_word_instance();
gather_bool(v, And);
break;
case AndNLM:
neutral = constant::true_instance();
@ -254,30 +311,7 @@ namespace spot
abs = constant::false_instance();
abs2 = 0;
weak_abs = 0;
// Make a first pass to gather all boolean terms.
{
vec* b = new vec;
vec::iterator i = v->begin();
while (i != v->end())
{
if ((*i)->is_boolean())
{
b->push_back(*i);
i = v->erase(i);
}
else
{
++i;
}
}
// - AndNLM(Exps1...,Bool1,Exps2...,Bool2,Exps3...) =
// AndNLM(Exps1...,Exps2...,Exps3...,And(Bool1,Bool2))
if (!b->empty())
v->push_back(instance(And, b));
else
delete b;
}
gather_bool(v, And);
break;
case Or:
neutral = constant::false_instance();
@ -286,6 +320,14 @@ namespace spot
abs2 = 0;
weak_abs = 0;
break;
case OrRat:
neutral = constant::false_instance();
neutral2 = 0;
abs = 0; // FIXME: should be 1[*].
abs2 = 0;
weak_abs = 0;
gather_bool(v, Or);
break;
case Concat:
neutral = constant::empty_word_instance();
neutral2 = 0;
@ -377,8 +419,8 @@ namespace spot
}
}
// We have a* & [*0] & c = 0
// and a* & [*0] & c* = [*0]
// We have a* && [*0] && c = 0
// and a* && [*0] && c* = [*0]
// So if [*0] has been seen, check if alls term recognize the
// empty word.
if (weak_abs_seen)

View file

@ -41,7 +41,7 @@ namespace spot
class multop : public ref_formula
{
public:
enum type { Or, And, AndNLM, Concat, Fusion };
enum type { Or, OrRat, And, AndRat, AndNLM, Concat, Fusion };
/// List of formulae.
typedef std::vector<formula*> vec;
@ -68,24 +68,27 @@ namespace spot
/// has been passed to spot::ltl::multop. Inside the vector,
/// null pointers are ignored.
///
/// All operators (Or, And, Concat) are associative, and are
/// automatically inlined. Or and And are commutative, so their
/// argument are also sorted, to ensure that "a & b" is equal to
/// "b & a". For Or and And, duplicate arguments are also
/// removed.
/// Most operators (Or, OrRat, And, AndRat, Concat) are
/// associative, and are automatically inlined. Or, OrRat, And,
/// and AndRat are commutative, so their arguments are also
/// sorted, to ensure that "a & b" is equal to "b & a", also
/// duplicate arguments are removed.
///
/// Furthermore this function can perform slight optimizations
/// and may not return an ltl::multop object. For instance if
/// the vector contains only one unique element, this this
/// formula will be returned as-is. Neutral and absorbent element
/// are also taken care of. The following rewriting are performed
/// are also taken care of. The following rewritings are performed
/// (the left patterns are rewritten as shown on the right):
///
/// - And(Exps1...,1,Exps2...) = And(Exps1...,Exps2...)
/// - And(Exps1...,0,Exps2...) = 0
/// - And(Exps1...,[*0],Exps2...) = [*0] if all Expi accept [*0]
/// - And(Exps1...,[*0],Exps2...) = 0 if some Expi reject [*0]
/// - And(Exp) = Exp
/// - AndRat(Exps1...,0,Exps2...) = 0
/// - AndRat(Exps1...,BoolExp1,Exps2...,BoolExps2...) =
/// AndRat(Exps1...,Exps2...,And(BoolExp1,BoolExps2...))
/// - AndRat(Exps1...,[*0],Exps2...) = [*0] if all Expi accept [*0]
/// - AndRat(Exps1...,[*0],Exps2...) = 0 if some Expi reject [*0]
/// - AndNLM(Exps1...,1,Exps2...) = AndNLM(Exps1...,Exps2...)
/// - AndNLM(Exps1...,0,Exps2...) = 0
/// - AndNLM(Exps1...,[*0],Exps2...) = AndNLM(Exps1...,Exps2...)
@ -93,8 +96,11 @@ namespace spot
/// - AndNLM(Exps1...,BoolExp1,Exps2...,BoolExp2,Exps3...) =
/// AndNLM(Exps1...,Exps2...,Exps3...,And(BoolExp1,BoolExp2))
/// - Or(Exps1...,1,Exps2...) = 1
/// - Or(Exps1...,0,Exps2...) = And(Exps1...,Exps2...)
/// - Or(Exps1...,0,Exps2...) = Or(Exps1...,Exps2...)
/// - Or(Exp) = Exp
/// - OrRat(Exps1...,0,Exps2...) = OrRat(Exps1...,Exps2...)
/// - OrRat(Exps1...,BoolExp1,Exps2...,BoolExps2...) =
/// OrRat(Exps1...,Exps2...,Or(BoolExp1,BoolExps2...))
/// - Concat(Exps1...,0,Exps2...) = 0
/// - Concat(Exps1...,[*0],Exps2...) = Concat(Exps1...,Exps2...)
/// - Concat(Exp) = Exp
@ -221,6 +227,26 @@ namespace spot
return is_multop(f, multop::And);
}
/// \brief Cast \a f into a multop if it is an AndRat.
///
/// Return 0 otherwise.
inline
multop*
is_AndRat(const formula* f)
{
return is_multop(f, multop::AndRat);
}
/// \brief Cast \a f into a multop if it is an AndNLM.
///
/// Return 0 otherwise.
inline
multop*
is_AndNLM(const formula* f)
{
return is_multop(f, multop::AndNLM);
}
/// \brief Cast \a f into a multop if it is an Or.
///
/// Return 0 otherwise.
@ -231,6 +257,16 @@ namespace spot
return is_multop(f, multop::Or);
}
/// \brief Cast \a f into a multop if it is an OrRat.
///
/// Return 0 otherwise.
inline
multop*
is_OrRat(const formula* f)
{
return is_multop(f, multop::OrRat);
}
/// \brief Cast \a f into a multop if it is a Concat.
///
/// Return 0 otherwise.

View file

@ -354,7 +354,7 @@ sere: booleanatom
$$ = constant::false_instance();
}
| sere OP_AND sere
{ $$ = multop::instance(multop::And, $1, $3); }
{ $$ = multop::instance(multop::AndRat, $1, $3); }
| sere OP_AND error
{ missing_right_binop($$, $1, @2,
"length-matching and operator"); }
@ -364,7 +364,7 @@ sere: booleanatom
{ missing_right_binop($$, $1, @2,
"non-length-matching and operator"); }
| sere OP_OR sere
{ $$ = multop::instance(multop::Or, $1, $3); }
{ $$ = multop::instance(multop::OrRat, $1, $3); }
| sere OP_OR error
{ missing_right_binop($$, $1, @2, "or operator"); }
| sere OP_CONCAT sere

View file

@ -1,4 +1,4 @@
// Copyright (C) 2010 Laboratoire de Recherche et Développement
// Copyright (C) 2010, 2012 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -89,14 +89,17 @@ namespace spot
multop::vec* res = new multop::vec;
switch (mo->op())
{
case multop::Or:
case multop::OrRat:
case multop::AndNLM:
case multop::AndRat:
case multop::Concat:
case multop::Fusion:
assert(!"unexpected operator");
case multop::Or:
for (unsigned i = 0; i < mos; ++i)
res->push_back(recurse(mo->nth(i)));
break;
case multop::And:
case multop::AndNLM:
{
typedef std::set<std::pair<formula*, formula*> > pset;
pset Epairs, EMpairs;
@ -125,10 +128,12 @@ namespace spot
res->push_back(recurse(f));
break;
case binop::EConcat:
assert(mo->op() == multop::And);
Epairs.insert(std::make_pair(bo->first(),
bo->second()));
break;
case binop::EConcatMarked:
assert(mo->op() == multop::And);
EMpairs.insert(std::make_pair(bo->first(),
bo->second()));
break;

View file

@ -184,6 +184,8 @@ namespace spot
break;
}
case multop::AndNLM:
case multop::AndRat:
case multop::OrRat:
case multop::Concat:
case multop::Fusion:
assert(!"Unsupported operator");
@ -566,6 +568,8 @@ namespace spot
case multop::Concat:
case multop::Fusion:
case multop::AndNLM:
case multop::OrRat:
case multop::AndRat:
break;
}
multop::vec* res = new multop::vec;
@ -583,6 +587,8 @@ namespace spot
case multop::Concat:
case multop::Fusion:
case multop::AndNLM:
case multop::AndRat:
case multop::OrRat:
{
for (unsigned i = 0; i < mos; ++i)
res->push_back(recurse_(mo->nth(i), false));
@ -1765,10 +1771,14 @@ namespace spot
multop::type op = mo->op();
if ((opt_.synt_impl | opt_.containment_checks)
&& (op != multop::AndRat)
&& (op != multop::AndNLM)
&& (op != multop::OrRat)
&& (op != multop::Concat)
&& (op != multop::Concat)
&& (op != multop::Fusion))
{
bool is_and = op != multop::Or; // And or AndNLM
bool is_and = op == multop::And;
constant* neutral = is_and
? constant::false_instance() : constant::true_instance();
@ -1842,7 +1852,7 @@ namespace spot
switch (op)
{
case multop::And:
if (!mo->is_sere_formula())
assert(!mo->is_sere_formula());
{
// a & X(G(a&b...) & c...) = Ga & X(G(b...) & c...)
// a & (Xa W b) = b R a
@ -2247,14 +2257,14 @@ namespace spot
result_ = recurse_destroy(result_);
return;
}
else // SERE
break;
case multop::AndRat:
{
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);
// 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();
@ -2321,7 +2331,8 @@ namespace spot
sum->push_back(r->nth(j)
->clone());
formula* sumf =
multop::instance(multop::Or, sum);
multop::instance(multop::OrRat,
sum);
ares->push_back(sumf);
}
else
@ -2345,7 +2356,7 @@ namespace spot
}
delete s.res_other;
ares->push_back(b);
result_ = multop::instance(multop::And, ares);
result_ = multop::instance(multop::AndRat, ares);
// If we altered the formula in some way, process
// it another time.
if (result_ != mo)
@ -2421,10 +2432,12 @@ namespace spot
}
if (!head1->empty())
{
formula* h = multop::instance(multop::And, head1);
formula* t = multop::instance(multop::And, tail1);
formula* f = multop::instance(multop::Concat,
h, t);
formula* h =
multop::instance(multop::And, head1);
formula* t =
multop::instance(multop::AndRat, tail1);
formula* f =
multop::instance(multop::Concat, h, t);
s.res_other->push_back(f);
}
else
@ -2434,10 +2447,12 @@ namespace spot
}
if (!head2->empty())
{
formula* h = multop::instance(multop::And, head2);
formula* t = multop::instance(multop::And, tail2);
formula* f = multop::instance(multop::Fusion,
h, t);
formula* h =
multop::instance(multop::And, head2);
formula* t =
multop::instance(multop::AndRat, tail2);
formula* f =
multop::instance(multop::Fusion, h, t);
s.res_other->push_back(f);
}
else
@ -2446,9 +2461,9 @@ namespace spot
delete tail2;
}
// {r1;b1}&&{r2;b2} = {r1&&r2};{b1&&b2}
// {r1;b1}&&{r2;b2} = {r1&&r2};{b1b2}
// head3 tail3
// {r1:b1}&&{r2:b2} = {r1&&r2}:{b1&&b2}
// {r1:b1}&&{r2:b2} = {r1&&r2}:{b1b2}
// head4 tail4
multop::vec* head3 = new multop::vec;
multop::vec* tail3 = new multop::vec;
@ -2494,10 +2509,12 @@ namespace spot
}
if (!head3->empty())
{
formula* h = multop::instance(multop::And, head3);
formula* t = multop::instance(multop::And, tail3);
formula* f = multop::instance(multop::Concat,
h, t);
formula* h =
multop::instance(multop::AndRat, head3);
formula* t =
multop::instance(multop::And, tail3);
formula* f =
multop::instance(multop::Concat, h, t);
s.res_other->push_back(f);
}
else
@ -2507,10 +2524,12 @@ namespace spot
}
if (!head4->empty())
{
formula* h = multop::instance(multop::And, head4);
formula* t = multop::instance(multop::And, tail4);
formula* f = multop::instance(multop::Fusion,
h, t);
formula* h =
multop::instance(multop::AndRat, head4);
formula* t =
multop::instance(multop::And, tail4);
formula* f =
multop::instance(multop::Fusion, h, t);
s.res_other->push_back(f);
}
else
@ -2519,7 +2538,8 @@ namespace spot
delete tail4;
}
result_ = multop::instance(multop::And, s.res_other);
result_ =
multop::instance(multop::AndRat, s.res_other);
// If we altered the formula in some way, process
// it another time.
if (result_ != mo)
@ -2975,12 +2995,15 @@ namespace spot
result_ = recurse_destroy(result_);
return;
}
case multop::OrRat:
// FIXME: No simplifications yet.
break;
case multop::AndNLM:
{
mospliter s(mospliter::Split_Bool, res, c_);
if (!s.res_Bool->empty())
{
// b1 & b2 & b3 = b1 && b2 && b3
// b1 & b2 & b3 = b1 ∧ b2 ∧ b3
formula* b = multop::instance(multop::And, s.res_Bool);
// now we just consider b & rest
@ -3001,7 +3024,7 @@ namespace spot
multop::instance(multop::Fusion, b->clone(),
rest);
result_ =
multop::instance(multop::Or, b, brest);
multop::instance(multop::OrRat, b, brest);
}
else
{
@ -3026,9 +3049,9 @@ namespace spot
delete s.res_Bool;
// Look for occurrences of {b;r} or {b:r}. We have
// {b1;r1}&{b2;r2} = {b1&&b2};{r1&r2}
// {b1;r1}&{b2;r2} = {b1b2};{r1&r2}
// head1 tail1
// {b1:r1}&{b2:r2} = {b1&&b2}:{r1&r2}
// {b1:r1}&{b2:r2} = {b1b2}:{r1&r2}
// head2 tail2
multop::vec* head1 = new multop::vec;
@ -3076,11 +3099,12 @@ namespace spot
}
if (!head1->empty())
{
formula* h = multop::instance(multop::And, head1);
formula* h =
multop::instance(multop::And, head1);
formula* t =
multop::instance(multop::AndNLM, tail1);
formula* f = multop::instance(multop::Concat,
h, t);
formula* f =
multop::instance(multop::Concat, h, t);
s.res_other->push_back(f);
}
else
@ -3090,11 +3114,12 @@ namespace spot
}
if (!head2->empty())
{
formula* h = multop::instance(multop::And, head2);
formula* h =
multop::instance(multop::And, head2);
formula* t =
multop::instance(multop::AndNLM, tail2);
formula* f = multop::instance(multop::Fusion,
h, t);
formula* f =
multop::instance(multop::Fusion, h, t);
s.res_other->push_back(f);
}
else
@ -3103,9 +3128,9 @@ namespace spot
delete tail2;
}
// {r1;b1}&{r2;b2} = {r1&r2};{b1&&b2}
// {r1;b1}&{r2;b2} = {r1&r2};{b1b2}
// head3 tail3
// {r1:b1}&{r2:b2} = {r1&r2}:{b1&&b2}
// {r1:b1}&{r2:b2} = {r1&r2}:{b1b2}
// head4 tail4
multop::vec* head3 = new multop::vec;
multop::vec* tail3 = new multop::vec;
@ -3153,9 +3178,10 @@ namespace spot
{
formula* h =
multop::instance(multop::AndNLM, head3);
formula* t = multop::instance(multop::And, tail3);
formula* f = multop::instance(multop::Concat,
h, t);
formula* t =
multop::instance(multop::And, tail3);
formula* f =
multop::instance(multop::Concat, h, t);
s.res_other->push_back(f);
}
else
@ -3167,9 +3193,10 @@ namespace spot
{
formula* h =
multop::instance(multop::AndNLM, head4);
formula* t = multop::instance(multop::And, tail4);
formula* f = multop::instance(multop::Fusion,
h, t);
formula* t =
multop::instance(multop::And, tail4);
formula* f =
multop::instance(multop::Fusion, h, t);
s.res_other->push_back(f);
}
else
@ -3441,6 +3468,8 @@ namespace spot
case multop::Concat:
case multop::Fusion:
case multop::AndNLM:
case multop::AndRat:
case multop::OrRat:
break;
}
break;
@ -3524,6 +3553,8 @@ namespace spot
case multop::Concat:
case multop::Fusion:
case multop::AndNLM:
case multop::AndRat:
case multop::OrRat:
break;
}
break;

View file

@ -60,8 +60,9 @@ namespace spot
KF,
KG,
KOr,
KOrRat,
KAnd,
KAndLM,
KAndRat,
KAndNLM,
KConcat,
KFusion
@ -89,6 +90,7 @@ namespace spot
"F",
"G",
" | ",
" | ",
" & ",
" && ",
" & ",
@ -118,6 +120,7 @@ namespace spot
"<>",
"[]",
" || ",
" || ",
" && ",
" && ", // not supported
" & ", // not supported
@ -623,8 +626,14 @@ namespace spot
case multop::Or:
k = KOr;
break;
case multop::OrRat:
k = KOrRat;
break;
case multop::And:
k = in_ratexp_ ? KAndLM : KAnd;
k = in_ratexp_ ? KAndRat : KAnd;
break;
case multop::AndRat:
k = KAndRat;
break;
case multop::AndNLM:
k = KAndNLM;

View file

@ -1,5 +1,5 @@
// Copyright (C) 2009, 2010 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
// Copyright (C) 2009, 2010, 2012 Laboratoire de Recherche et
// Développement de l'Epita (LRDE).
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris
// 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
// Université Pierre et Marie Curie.
@ -152,6 +152,8 @@ namespace spot
case multop::Concat:
case multop::Fusion:
case multop::AndNLM:
case multop::OrRat:
case multop::AndRat:
assert(!"unsupported operator");
}
assert(op != -1);

View file

@ -1,4 +1,4 @@
// Copyright (C) 2008, 2009, 2010 Laboratoire de Recherche et
// Copyright (C) 2008, 2009, 2010, 2012 Laboratoire de Recherche et
// Développement de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -168,6 +168,8 @@ namespace spot
case multop::Concat:
case multop::Fusion:
case multop::AndNLM:
case multop::AndRat:
case multop::OrRat:
assert(!"unsupported operator");
}
assert(op != -1);

View file

@ -1,5 +1,5 @@
// Copyright (C) 2009, 2010 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
// Copyright (C) 2009, 2010, 2012 Laboratoire de Recherche et
// Développement de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
//
@ -332,6 +332,8 @@ namespace spot
case multop::Concat:
case multop::Fusion:
case multop::AndNLM:
case multop::AndRat:
case multop::OrRat:
assert(!"unsupported operator");
return;
}

View file

@ -243,6 +243,12 @@ namespace spot
return multop::instance(op, v);
}
formula*
conj_bdd_to_sere(bdd b) const
{
return conj_bdd_to_formula(b, multop::AndRat);
}
formula*
bdd_to_formula(bdd f)
{
@ -259,6 +265,22 @@ namespace spot
return multop::instance(multop::Or, v);
}
formula*
bdd_to_sere(bdd f)
{
if (f == bddfalse)
return constant::false_instance();
multop::vec* v = new multop::vec;
minato_isop isop(f);
bdd cube;
while ((cube = isop.next()) != bddfalse)
v->push_back(conj_bdd_to_sere(cube));
return multop::instance(multop::OrRat, v);
}
void
conj_bdd_to_acc(tgba_explicit_formula* a, bdd b,
state_explicit_formula::transition* t)
@ -429,7 +451,7 @@ namespace spot
{
bdd label = bdd_exist(cube, dict_.next_set);
bdd dest_bdd = bdd_existcomp(cube, dict_.next_set);
formula* dest = dict_.conj_bdd_to_formula(dest_bdd);
formula* dest = dict_.conj_bdd_to_sere(dest_bdd);
if (dest == constant::empty_word_instance())
{
out |= label & next_to_concat();
@ -537,12 +559,12 @@ namespace spot
}
else
{
// if "f" accepts the empty words, doing the above would
// if "f" accepts the empty word, doing the above would
// lead to an infinite loop:
// f*;g -> f;f*;g | g
// f;f*;g -> f*;g | ...
//
// So we do in two steps:
// So we do it in three steps:
// 1. translate f,
// 2. append f*;g to all destinations
// 3. add |g
@ -556,8 +578,7 @@ namespace spot
{
bdd label = bdd_exist(cube, dict_.next_set);
bdd dest_bdd = bdd_existcomp(cube, dict_.next_set);
formula* dest =
dict_.conj_bdd_to_formula(dest_bdd);
formula* dest = dict_.conj_bdd_to_sere(dest_bdd);
formula* dest2;
int x;
if (dest == constant::empty_word_instance())
@ -623,7 +644,7 @@ namespace spot
{
delete non_final;
// (a* & b*);c = (a*|b*);c
formula* f = multop::instance(multop::Or, final);
formula* f = multop::instance(multop::OrRat, final);
res_ = recurse_and_concat(f);
f->destroy();
break;
@ -635,7 +656,7 @@ namespace spot
// (F_1 & ... & F_n & N_1 & ... & N_m)
// = (F_1 | ... | F_n);[*] && (N_1 & ... & N_m)
// | (F_1 | ... | F_n) && (N_1 & ... & N_m);[*]
formula* f = multop::instance(multop::Or, final);
formula* f = multop::instance(multop::OrRat, final);
formula* n = multop::instance(multop::AndNLM, non_final);
formula* t = bunop::instance(bunop::Star,
constant::true_instance());
@ -643,9 +664,9 @@ namespace spot
f->clone(), t->clone());
formula* nt = multop::instance(multop::Concat,
n->clone(), t);
formula* ftn = multop::instance(multop::And, ft, n);
formula* fnt = multop::instance(multop::And, f, nt);
formula* all = multop::instance(multop::Or, ftn, fnt);
formula* ftn = multop::instance(multop::AndRat, ft, n);
formula* fnt = multop::instance(multop::AndRat, f, nt);
formula* all = multop::instance(multop::OrRat, ftn, fnt);
res_ = recurse_and_concat(all);
all->destroy();
break;
@ -673,15 +694,15 @@ namespace spot
f, star->clone());
conj->push_back(f);
}
disj->push_back(multop::instance(multop::And, conj));
disj->push_back(multop::instance(multop::AndRat, conj));
}
star->destroy();
formula* all = multop::instance(multop::Or, disj);
formula* all = multop::instance(multop::OrRat, disj);
res_ = recurse_and_concat(all);
all->destroy();
break;
}
case multop::And:
case multop::AndRat:
{
unsigned s = node->size();
@ -707,7 +728,7 @@ namespace spot
node->destroy();
break;
}
case multop::Or:
case multop::OrRat:
{
res_ = bddfalse;
unsigned s = node->size();
@ -749,7 +770,7 @@ namespace spot
{
bdd label = bdd_exist(cube, dict_.next_set);
bdd dest_bdd = bdd_existcomp(cube, dict_.next_set);
formula* dest = dict_.conj_bdd_to_formula(dest_bdd);
formula* dest = dict_.conj_bdd_to_sere(dest_bdd);
if (dest->accepts_eword())
{
@ -786,6 +807,9 @@ namespace spot
tail->destroy();
break;
}
case multop::And:
case multop::Or:
assert(!"not a rational operator");
}
}
@ -891,7 +915,7 @@ namespace spot
all_props -= label;
const formula* dest =
dict_.bdd_to_formula(bdd_exist(res & label, dict_.var_set));
dict_.bdd_to_sere(bdd_exist(res & label, dict_.var_set));
f2a_t::const_iterator i = f2a_.find(dest);
if (i != f2a_.end() && i->second == 0)
@ -1218,8 +1242,7 @@ namespace spot
all_props -= label;
formula* dest =
dict_.bdd_to_formula(bdd_exist(f1 & label,
dict_.var_set));
dict_.bdd_to_sere(bdd_exist(f1 & label, dict_.var_set));
// !{ Exp } is false if Exp accepts the empty word.
if (dest->accepts_eword())
@ -1347,7 +1370,7 @@ namespace spot
all_props -= label;
formula* dest =
dict_.bdd_to_formula(bdd_exist(f1 & label,
dict_.bdd_to_sere(bdd_exist(f1 & label,
dict_.var_set));
const formula* dest2 =
@ -1371,7 +1394,7 @@ namespace spot
{
bdd label = bdd_exist(cube, dict_.next_set);
bdd dest_bdd = bdd_existcomp(cube, dict_.next_set);
formula* dest = dict_.conj_bdd_to_formula(dest_bdd);
formula* dest = dict_.conj_bdd_to_sere(dest_bdd);
if (dest == constant::empty_word_instance())
{
@ -1420,7 +1443,7 @@ namespace spot
{
bdd label = bdd_exist(cube, dict_.next_set);
bdd dest_bdd = bdd_existcomp(cube, dict_.next_set);
formula* dest = dict_.conj_bdd_to_formula(dest_bdd);
formula* dest = dict_.conj_bdd_to_sere(dest_bdd);
formula* dest2 =
binop::instance(op, dest, node->second()->clone());
@ -1478,6 +1501,8 @@ namespace spot
case multop::Concat:
case multop::Fusion:
case multop::AndNLM:
case multop::AndRat:
case multop::OrRat:
assert(!"Not an LTL operator");
break;
}
@ -1699,7 +1724,7 @@ namespace spot
// std::cerr << "Marked: " << t.has_marked << std::endl;
// std::cerr << "Mark all: " << !f->is_marked() << std::endl;
// std::cerr << "Transitions:" << std::endl;
// trace_ltl_bdd(v_.get_dict(), t.symbolic);
// trace_ltl_bdd(d_, t.symbolic);
// std::cerr << "-----" << std::endl;
if (t.has_rational)

View file

@ -1,7 +1,8 @@
// Copyright (C) 2009, 2010 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
// -*- coding: utf-8 -*-
// Copyright (C) 2009, 2010, 2012 Laboratoire de Recherche et
// Développement de l'Epita (LRDE).
// Copyright (C) 2003, 2004 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.
//
// This file is part of Spot, a model checking library.
@ -103,7 +104,7 @@ namespace spot
/*
`x | next', doesn't actually encode the fact that x
should be fulfilled eventually. We ensure this by
creating a new generalized Büchi acceptance set, Acc[x],
creating a new generalized Büchi acceptance set, Acc[x],
and leave out of this set any transition going off NOW
without checking X. Such acceptance conditions are
checked for during the emptiness check.
@ -266,6 +267,8 @@ namespace spot
case multop::Concat:
case multop::Fusion:
case multop::AndNLM:
case multop::AndRat:
case multop::OrRat:
assert(!"unsupported operator");
}
assert(op != -1);