Merge branch master (Spot 1.2.5) into next.

* src/bin/dstar2tgba.cc, src/bin/ltlcross.cc, src/bin/randltl.cc,
src/ltltest/reduccmp.test, src/neverparse/neverclaimparse.yy,
src/tgbatest/ltl2ta.test, src/tgbatest/ltl2tgba.cc,
src/tgbatest/ltlcross.test, src/tgbatest/neverclaimread.test,
wrap/python/ajax/ltl2tgba.html: Fix conflicts.
This commit is contained in:
Alexandre Duret-Lutz 2014-08-22 16:45:41 +02:00
commit 700cf88b06
30 changed files with 1029 additions and 163 deletions

View file

@ -260,24 +260,59 @@ namespace spot
// Similarly
// a M b = (a R (b&P(a)))
// (a M b) M c = (a R (b & Pa)) R (c & P(a M b))
// = (a R (b & Pa)) R (c & P(a))
// The rules also apply to F:
// P(F(a)) = P(a)
again:
while (const binop* b = is_binop(f))
// = (a R (b & Pa)) R (c & P(a & b))
//
// The code below therefore implement the following
// rules:
// P(a U b) = P(b)
// P(F(a)) = P(a)
// P(a M b) = P(a & b)
//
// The latter rule INCORRECTLY appears as P(a M b)=P(a)
// in section 3.5 of
// "LTL translation improvements in Spot 1.0",
// A. Duret-Lutz. IJCCBS 5(1/2):31-54, March 2014.
// and was unfortunately implemented this way until Spot
// 1.2.4. A counterexample is given by the formula
// G(Fa & ((a M b) U ((c U !d) M d)))
// that was found by Joachim Klein. Here P((c U !d) M d)
// and P(c U !d) should not both be simplified to P(!d).
for (;;)
{
binop::type op = b->op();
if (op == binop::U)
f = b->second();
else if (op == binop::M)
f = b->first();
if (const binop* b = is_binop(f))
{
binop::type op = b->op();
if (op == binop::U)
{
// P(a U b) = P(b)
f = b->second();
}
else if (op == binop::M)
{
// P(a M b) = P(a & b)
const formula* g =
multop::instance(multop::And,
b->first()->clone(),
b->second()->clone());
int num = dict->register_acceptance_variable(g, this);
a_set &= bdd_ithvar(num);
g->destroy();
return num;
}
else
{
break;
}
}
else if (const unop* u = is_unop(f, unop::F))
{
// P(F(a)) = P(a)
f = u->child();
}
else
break;
}
if (const unop* u = is_unop(f, unop::F))
{
f = u->child();
goto again;
{
break;
}
}
int num = dict->register_acceptance_variable(f, this);
a_set &= bdd_ithvar(num);
@ -1346,8 +1381,7 @@ namespace spot
}
else
{
dest->clone();
const formula* dest2 = unop::instance(op, dest);
const formula* dest2 = unop::instance(op, dest->clone());
if (dest2 == constant::false_instance())
continue;
int x = dict_.register_next_variable(dest2);
@ -1363,48 +1397,48 @@ namespace spot
case unop::NegClosure:
rat_seen_ = true;
{
const formula* c = node->child();
if (mark_all_)
{
op = unop::NegClosureMarked;
has_marked_ = true;
}
bdd f1 = translate_ratexp(c, dict_);
// trace_ltl_bdd(dict_, f1);
const formula* f = node->child();
auto p = dict_.transdfa.succ(f);
res_ = bddtrue;
auto aut = std::get<0>(p);
auto namer = std::get<1>(p);
auto st = std::get<2>(p);
bdd var_set = bdd_existcomp(bdd_support(f1), dict_.var_set);
bdd all_props = bdd_existcomp(f1, dict_.var_set);
if (!aut)
break;
res_ = !all_props &
res_ = bddfalse;
bdd missing = bddtrue;
for (auto i: aut->succ(st))
{
bdd label = i->current_condition();
state* s = i->current_state();
const formula* dest = namer->get_name(aut->state_number(s));
missing -= label;
if (!dest->accepts_eword())
{
const formula* dest2 = unop::instance(op, dest->clone());
if (dest2 == constant::false_instance())
continue;
int x = dict_.register_next_variable(dest2);
dest2->destroy();
res_ |= label & bdd_ithvar(x);
}
}
res_ |= missing &
// stick X(1) to preserve determinism.
bdd_ithvar(dict_.register_next_variable
(constant::true_instance()));
while (all_props != bddfalse)
{
bdd label = bdd_satoneset(all_props, var_set, bddtrue);
all_props -= label;
const formula* dest =
dict_.bdd_to_sere(bdd_exist(f1 & label, dict_.var_set));
// !{ Exp } is false if Exp accepts the empty word.
if (dest->accepts_eword())
{
dest->destroy();
continue;
}
const formula* dest2 = unop::instance(op, dest);
if (dest2 == constant::false_instance())
continue;
int x = dict_.register_next_variable(dest2);
dest2->destroy();
res_ |= label & bdd_ithvar(x);
}
//trace_ltl_bdd(dict_, res_);
}
break;
@ -1479,9 +1513,23 @@ namespace spot
{
res_ = recurse(node->second(), recurring_);
bdd f1 = recurse(node->first());
// r(f1 M f2) = r(f2)(r(f1) + a(f1)X(f1 M f2)) if not recurring
// r(f1 M f2) = r(f2)(r(f1) + a(f1)) if recurring
bdd a = bdd_ithvar(dict_.register_a_variable(node->first()));
// r(f1 M f2) = r(f2)(r(f1) + a(f1&f2)X(f1 M f2)) if not recurring
// r(f1 M f2) = r(f2)(r(f1) + a(f1&f2)) if recurring
//
// Note that the rule above differs from the one given
// in Figure 2 of
// "LTL translation improvements in Spot 1.0",
// A. Duret-Lutz. IJCCBS 5(1/2):31-54, March 2014.
// Both rules should be OK, but this one is a better fit
// to the promises simplifications performed in
// register_a_variable() (see comments in this function).
// We do not want a U (c M d) to generate two different
// promises. Generating c&d also makes the output similar
// to what we would get with the equivalent a U (d U (c & d)).
//
// Here we just appear to emit a(f1 M f2) and the conversion
// to a(f1&f2) is done by register_a_variable().
bdd a = bdd_ithvar(dict_.register_a_variable(node));
if (!recurring_)
a &= bdd_ithvar(dict_.register_next_variable(node));
res_ &= f1 | a;