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:
commit
700cf88b06
30 changed files with 1029 additions and 163 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue