Add support for W (weak until) and M (strong release) operators.
* src/ltlast/binop.cc, src/ltlast/binop.cc: Add support for these new operators. * src/ltlparse/ltlparse.yy, src/ltlparse/ltlscan.ll: Parse them. * src/ltltest/reduccmp.test: Add new tests for W and M. * src/ltlvisit/basicreduce.cc, src/ltlvisit/contain.cc, src/ltlvisit/lunabbrev.cc, src/ltlvisit/nenoform.cc, src/ltlvisit/randomltl.cc, src/ltlvisit/randomltl.hh, src/ltlvisit/reduce.cc, src/ltlvisite/simpfg.cc, src/ltlvisit/simpfg.hh, src/ltlvisit/syntimpl.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: Add support for W and M. * src/tgbatest/ltl2neverclaim.test: Test never claim output using LBTT, this is more thorough. Also we cannot use -N any more in the spotlbtt.test. * src/tgbatests/ltl2tgba.cc: Define M and W for ELTL. * src/tgbatest/ltl2neverclaim.test: Test W and M, and use -DS instead of -N, because lbtt-translate does not want to translate these operators for tools that masquerade as Spin.
This commit is contained in:
parent
35a57c6dff
commit
0fc0ea3166
25 changed files with 584 additions and 123 deletions
|
|
@ -1,5 +1,5 @@
|
|||
// Copyright (C) 2008, 2009 Laboratoire de Recherche et Développement
|
||||
// de l'Epita (LRDE).
|
||||
// Copyright (C) 2008, 2009, 2010 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
//
|
||||
|
|
@ -124,6 +124,8 @@ namespace spot
|
|||
return;
|
||||
case binop::U:
|
||||
case binop::R:
|
||||
case binop::W:
|
||||
case binop::M:
|
||||
assert(!"unsupported operator");
|
||||
}
|
||||
/* Unreachable code. */
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2009 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2009, 2010 Laboratoire de Recherche et Développement
|
||||
// de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
|
|
@ -155,12 +155,17 @@ namespace spot
|
|||
std::vector<succ_state>::iterator i2;
|
||||
taa_tgba::transition* t = 0;
|
||||
bool contained = false;
|
||||
bool strong = false;
|
||||
|
||||
switch (node->op())
|
||||
{
|
||||
case binop::U: // Strong
|
||||
if (refined_)
|
||||
contained = lcc_->contained(node->second(), node->first());
|
||||
for (i1 = v1.succ_.begin(); i1 != v1.succ_.end(); ++i1)
|
||||
case binop::U:
|
||||
strong = true;
|
||||
// fall thru
|
||||
case binop::W:
|
||||
if (refined_)
|
||||
contained = lcc_->contained(node->second(), node->first());
|
||||
for (i1 = v1.succ_.begin(); i1 != v1.succ_.end(); ++i1)
|
||||
{
|
||||
// Refined rule
|
||||
if (refined_ && contained)
|
||||
|
|
@ -168,60 +173,75 @@ namespace spot
|
|||
(remove(i1->Q.begin(), i1->Q.end(), v1.init_), i1->Q.end());
|
||||
|
||||
i1->Q.push_back(init_); // Add the initial state
|
||||
i1->acc.push_back(node->second());
|
||||
if (strong)
|
||||
i1->acc.push_back(node->second());
|
||||
t = res_->create_transition(init_, i1->Q);
|
||||
res_->add_condition(t, i1->condition->clone());
|
||||
res_->add_acceptance_condition(t, node->second()->clone());
|
||||
if (strong)
|
||||
res_->add_acceptance_condition(t, node->second()->clone());
|
||||
else
|
||||
for (unsigned i = 0; i < i1->acc.size(); ++i)
|
||||
res_->add_acceptance_condition(t, i1->acc[i]->clone());
|
||||
succ_.push_back(*i1);
|
||||
}
|
||||
for (i2 = v2.succ_.begin(); i2 != v2.succ_.end(); ++i2)
|
||||
for (i2 = v2.succ_.begin(); i2 != v2.succ_.end(); ++i2)
|
||||
{
|
||||
t = res_->create_transition(init_, i2->Q);
|
||||
res_->add_condition(t, i2->condition->clone());
|
||||
succ_.push_back(*i2);
|
||||
}
|
||||
return;
|
||||
case binop::R: // Weak
|
||||
if (refined_)
|
||||
contained = lcc_->contained(node->first(), node->second());
|
||||
for (i2 = v2.succ_.begin(); i2 != v2.succ_.end(); ++i2)
|
||||
return;
|
||||
case binop::M: // Strong Release
|
||||
strong = true;
|
||||
case binop::R: // Weak Release
|
||||
if (refined_)
|
||||
contained = lcc_->contained(node->first(), node->second());
|
||||
|
||||
for (i2 = v2.succ_.begin(); i2 != v2.succ_.end(); ++i2)
|
||||
{
|
||||
for (i1 = v1.succ_.begin(); i1 != v1.succ_.end(); ++i1)
|
||||
{
|
||||
std::vector<const formula*> u; // Union
|
||||
std::vector<const formula*> a; // Acceptance conditions
|
||||
std::copy(i1->Q.begin(), i1->Q.end(), ii(u, u.end()));
|
||||
formula* f = i1->condition->clone(); // Refined rule
|
||||
if (!refined_ || !contained)
|
||||
{
|
||||
std::copy(i2->Q.begin(), i2->Q.end(), ii(u, u.end()));
|
||||
f = multop::instance(multop::And, f, i2->condition->clone());
|
||||
std::vector<const formula*> u; // Union
|
||||
std::vector<const formula*> a; // Acceptance conditions
|
||||
std::copy(i1->Q.begin(), i1->Q.end(), ii(u, u.end()));
|
||||
formula* f = i1->condition->clone(); // Refined rule
|
||||
if (!refined_ || !contained)
|
||||
{
|
||||
std::copy(i2->Q.begin(), i2->Q.end(), ii(u, u.end()));
|
||||
f = multop::instance(multop::And, f,
|
||||
i2->condition->clone());
|
||||
}
|
||||
to_free_.push_back(f);
|
||||
t = res_->create_transition(init_, u);
|
||||
res_->add_condition(t, f->clone());
|
||||
succ_state ss = { u, f, a };
|
||||
succ_.push_back(ss);
|
||||
}
|
||||
to_free_.push_back(f);
|
||||
|
||||
t = res_->create_transition(init_, u);
|
||||
res_->add_condition(t, f->clone());
|
||||
succ_state ss = { u, f, a };
|
||||
succ_.push_back(ss);
|
||||
}
|
||||
|
||||
if (refined_) // Refined rule
|
||||
i2->Q.erase
|
||||
(remove(i2->Q.begin(), i2->Q.end(), v2.init_), i2->Q.end());
|
||||
|
||||
|
||||
i2->Q.push_back(init_); // Add the initial state
|
||||
t = res_->create_transition(init_, i2->Q);
|
||||
res_->add_condition(t, i2->condition->clone());
|
||||
if (refined_)
|
||||
|
||||
if (strong)
|
||||
{
|
||||
i2->acc.push_back(node->first());
|
||||
res_->add_acceptance_condition(t, node->first()->clone());
|
||||
}
|
||||
else if (refined_)
|
||||
for (unsigned i = 0; i < i2->acc.size(); ++i)
|
||||
res_->add_acceptance_condition(t, i2->acc[i]->clone());
|
||||
succ_.push_back(*i2);
|
||||
}
|
||||
return;
|
||||
case binop::Xor:
|
||||
case binop::Implies:
|
||||
case binop::Equiv:
|
||||
assert(0); // TBD
|
||||
return;
|
||||
case binop::Xor:
|
||||
case binop::Implies:
|
||||
case binop::Equiv:
|
||||
assert(0); // TBD
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
|
|
|
|||
|
|
@ -393,6 +393,13 @@ namespace spot
|
|||
res_ = f2 | (bdd_ithvar(a) & f1 & bdd_ithvar(x));
|
||||
return;
|
||||
}
|
||||
case binop::W:
|
||||
{
|
||||
// r(f1 W f2) = r(f2) + r(f1)r(X(f1 U f2))
|
||||
int x = dict_.register_next_variable(node);
|
||||
res_ = f2 | (f1 & bdd_ithvar(x));
|
||||
return;
|
||||
}
|
||||
case binop::R:
|
||||
{
|
||||
// r(f1 R f2) = r(f1)r(f2) + r(f2)r(X(f1 U f2))
|
||||
|
|
@ -400,6 +407,14 @@ namespace spot
|
|||
res_ = (f1 & f2) | (f2 & bdd_ithvar(x));
|
||||
return;
|
||||
}
|
||||
case binop::M:
|
||||
{
|
||||
// r(f1 M f2) = r(f1)r(f2) + a(f1)r(f2)r(X(f1 M f2))
|
||||
int a = dict_.register_a_variable(node->first());
|
||||
int x = dict_.register_next_variable(node);
|
||||
res_ = (f1 & f2) | (bdd_ithvar(a) & f2 & bdd_ithvar(x));
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Unreachable code. */
|
||||
assert(0);
|
||||
|
|
@ -449,8 +464,8 @@ namespace spot
|
|||
};
|
||||
|
||||
|
||||
// Check whether a formula has a R or G operator at its top-level
|
||||
// (preceding logical operators do not count).
|
||||
// Check whether a formula has a R, W, or G operator at its
|
||||
// top-level (preceding logical operators do not count).
|
||||
class ltl_possible_fair_loop_visitor: public const_visitor
|
||||
{
|
||||
public:
|
||||
|
|
@ -501,8 +516,10 @@ namespace spot
|
|||
node->second()->accept(*this);
|
||||
return;
|
||||
case binop::U:
|
||||
case binop::M:
|
||||
return;
|
||||
case binop::R:
|
||||
case binop::W:
|
||||
res_ = true;
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2009 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2009, 2010 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
|
||||
|
|
@ -160,7 +160,8 @@ namespace spot
|
|||
bdd f1 = recurse(node->first());
|
||||
bdd f2 = recurse(node->second());
|
||||
|
||||
switch (node->op())
|
||||
binop::type op = node->op();
|
||||
switch (op)
|
||||
{
|
||||
case binop::Xor:
|
||||
res_ = bdd_apply(f1, f2, bddop_xor);
|
||||
|
|
@ -172,39 +173,47 @@ namespace spot
|
|||
res_ = bdd_apply(f1, f2, bddop_biimp);
|
||||
return;
|
||||
case binop::U:
|
||||
case binop::W:
|
||||
{
|
||||
/*
|
||||
f1 U f2 <=> f2 | (f1 & X(f1 U f2))
|
||||
In other words:
|
||||
now <=> f2 | (f1 & next)
|
||||
*/
|
||||
// f1 U f2 <=> f2 | (f1 & X(f1 U f2))
|
||||
// In other words:
|
||||
// now <=> f2 | (f1 & next)
|
||||
int v = fact_.create_state(node);
|
||||
bdd now = bdd_ithvar(v);
|
||||
bdd next = bdd_ithvar(v + 1);
|
||||
fact_.constrain_relation(bdd_apply(now, f2 | (f1 & next),
|
||||
bddop_biimp));
|
||||
/*
|
||||
The rightmost conjunction, f1 & next, doesn't actually
|
||||
encode the fact that f2 should be fulfilled eventually.
|
||||
We declare an acceptance condition for this purpose (see
|
||||
the comment in the unop::F case).
|
||||
*/
|
||||
fact_.declare_acceptance_condition(f2 | !now, node->second());
|
||||
if (op == binop::U)
|
||||
{
|
||||
// The rightmost conjunction, f1 & next, doesn't
|
||||
// actually encode the fact that f2 should be
|
||||
// fulfilled eventually. We declare an acceptance
|
||||
// condition for this purpose (see the comment in
|
||||
// the unop::F case).
|
||||
fact_.declare_acceptance_condition(f2 | !now, node->second());
|
||||
}
|
||||
res_ = now;
|
||||
return;
|
||||
}
|
||||
case binop::R:
|
||||
case binop::M:
|
||||
{
|
||||
/*
|
||||
f1 R f2 <=> f2 & (f1 | X(f1 R f2))
|
||||
In other words:
|
||||
now <=> f2 & (f1 | next)
|
||||
*/
|
||||
// f1 R f2 <=> f2 & (f1 | X(f1 R f2))
|
||||
// In other words:
|
||||
// now <=> f2 & (f1 | next)
|
||||
int v = fact_.create_state(node);
|
||||
bdd now = bdd_ithvar(v);
|
||||
bdd next = bdd_ithvar(v + 1);
|
||||
fact_.constrain_relation(bdd_apply(now, f2 & (f1 | next),
|
||||
bddop_biimp));
|
||||
if (op == binop::M)
|
||||
{
|
||||
// f2 & next, doesn't actually encode the fact that
|
||||
// f1 should be fulfilled eventually. We declare an
|
||||
// acceptance condition for this purpose (see the
|
||||
// comment in the unop::F case).
|
||||
fact_.declare_acceptance_condition(f1 | !now, node->second());
|
||||
}
|
||||
res_ = now;
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue