ltl_to_tgba_fm: Build a tgba_digraph instead of a tgba_explicit_formula
The conversion is not complete, because the conversion from SERE to DRA used for the closure operator is still building a tgba_explicit_formula. * src/tgbaalgos/ltl2tgba_fm.cc, src/tgbaalgos/ltl2tgba_fm.hh: Return a tgba_digraph. * src/priv/acccompl.cc: Simplify. * src/graph/ngraph.hh: Add a way to iterate over all names. * src/tgba/tgbagraph.hh (compute_support_conditions): Return something useful. It's actually used by the constructor of testing automata. * src/tgbatest/wdba.test: Adjust to the fact that state are not labeled by formulas anymore. * src/bin/ltl2tgba.cc, src/bin/ltl2tgta.cc: Do not try to enable UTF8 on automata anymore.
This commit is contained in:
parent
38887f4960
commit
7b23691629
8 changed files with 77 additions and 97 deletions
|
|
@ -34,6 +34,7 @@
|
||||||
#include "common_post.hh"
|
#include "common_post.hh"
|
||||||
|
|
||||||
#include "ltlast/formula.hh"
|
#include "ltlast/formula.hh"
|
||||||
|
#include "ltlvisit/tostring.hh"
|
||||||
#include "tgba/tgbaexplicit.hh"
|
#include "tgba/tgbaexplicit.hh"
|
||||||
#include "tgbaalgos/dotty.hh"
|
#include "tgbaalgos/dotty.hh"
|
||||||
#include "tgbaalgos/lbtt.hh"
|
#include "tgbaalgos/lbtt.hh"
|
||||||
|
|
@ -231,17 +232,6 @@ namespace
|
||||||
s.c_str());
|
s.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (utf8)
|
|
||||||
{
|
|
||||||
spot::tgba* a = const_cast<spot::tgba*>(aut);
|
|
||||||
if (spot::tgba_explicit_formula* tef =
|
|
||||||
dynamic_cast<spot::tgba_explicit_formula*>(a))
|
|
||||||
tef->enable_utf8();
|
|
||||||
else if (spot::sba_explicit_formula* sef =
|
|
||||||
dynamic_cast<spot::sba_explicit_formula*>(a))
|
|
||||||
sef->enable_utf8();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case Dot:
|
case Dot:
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@
|
||||||
#include "common_post.hh"
|
#include "common_post.hh"
|
||||||
|
|
||||||
#include "ltlparse/public.hh"
|
#include "ltlparse/public.hh"
|
||||||
|
#include "ltlvisit/tostring.hh"
|
||||||
#include "ltlvisit/simplify.hh"
|
#include "ltlvisit/simplify.hh"
|
||||||
#include "tgbaalgos/dotty.hh"
|
#include "tgbaalgos/dotty.hh"
|
||||||
#include "tgbaalgos/ltl2tgba_fm.hh"
|
#include "tgbaalgos/ltl2tgba_fm.hh"
|
||||||
|
|
@ -184,17 +185,6 @@ namespace
|
||||||
s.c_str());
|
s.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (utf8)
|
|
||||||
{
|
|
||||||
spot::tgba* a = const_cast<spot::tgba*>(aut);
|
|
||||||
if (spot::tgba_explicit_formula* tef =
|
|
||||||
dynamic_cast<spot::tgba_explicit_formula*>(a))
|
|
||||||
tef->enable_utf8();
|
|
||||||
else if (spot::sba_explicit_formula* sef =
|
|
||||||
dynamic_cast<spot::sba_explicit_formula*>(a))
|
|
||||||
sef->enable_utf8();
|
|
||||||
}
|
|
||||||
|
|
||||||
bdd ap_set = atomic_prop_collect_as_bdd(f, aut);
|
bdd ap_set = atomic_prop_collect_as_bdd(f, aut);
|
||||||
|
|
||||||
if (ta_type != TGTA)
|
if (ta_type != TGTA)
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,16 @@ namespace spot
|
||||||
return state_to_name.at(s);
|
return state_to_name.at(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool has_state(name n) const
|
||||||
|
{
|
||||||
|
return name_to_state.find(n) != name_to_state.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
state_to_name_t& names()
|
||||||
|
{
|
||||||
|
return state_to_name;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
transition
|
transition
|
||||||
new_transition(name src, name dst, Args&&... args)
|
new_transition(name src, name dst, Args&&... args)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// -*- coding: utf-8 -*-
|
// -*- coding: utf-8 -*-
|
||||||
// Copyright (C) 2012 Laboratoire de Recherche et Developpement de
|
// Copyright (C) 2012, 2014 Laboratoire de Recherche et Developpement
|
||||||
// l'Epita (LRDE)
|
// de l'Epita (LRDE)
|
||||||
//
|
//
|
||||||
// This file is part of Spot, a model checking library.
|
// This file is part of Spot, a model checking library.
|
||||||
//
|
//
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "acccompl.hh"
|
#include "acccompl.hh"
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
@ -60,6 +61,8 @@ namespace spot
|
||||||
if (acc == bddtrue)
|
if (acc == bddtrue)
|
||||||
return all_;
|
return all_;
|
||||||
|
|
||||||
|
assert(acc != bddfalse);
|
||||||
|
|
||||||
// Since we never cache a unique positive bdd, we can reuse the
|
// Since we never cache a unique positive bdd, we can reuse the
|
||||||
// same cache. In fact the only kind of acc we will receive in
|
// same cache. In fact the only kind of acc we will receive in
|
||||||
// this method, are a conjunction of positive acceptance
|
// this method, are a conjunction of positive acceptance
|
||||||
|
|
@ -70,12 +73,13 @@ namespace spot
|
||||||
|
|
||||||
bdd res = all_;
|
bdd res = all_;
|
||||||
bdd cond = acc;
|
bdd cond = acc;
|
||||||
|
bdd neg = bddtrue;
|
||||||
while (cond != bddtrue)
|
while (cond != bddtrue)
|
||||||
{
|
{
|
||||||
res &= bdd_nithvar(bdd_var(cond));
|
neg &= bdd_nithvar(bdd_var(cond));
|
||||||
cond = bdd_high(cond);
|
cond = bdd_high(cond);
|
||||||
}
|
}
|
||||||
|
res &= neg;
|
||||||
cache_[acc] = res;
|
cache_[acc] = res;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
|
||||||
|
|
@ -360,9 +360,12 @@ namespace spot
|
||||||
return neg_acceptance_conditions_;
|
return neg_acceptance_conditions_;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bdd compute_support_conditions(const state*) const
|
virtual bdd compute_support_conditions(const state* s) const
|
||||||
{
|
{
|
||||||
return bddtrue;
|
bdd sum = bddfalse;
|
||||||
|
for (auto& t: out(state_number(s)))
|
||||||
|
sum |= t.cond;
|
||||||
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over all transitions, and merge those with compatible
|
/// Iterate over all transitions, and merge those with compatible
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,9 @@
|
||||||
#include "ltl2tgba_fm.hh"
|
#include "ltl2tgba_fm.hh"
|
||||||
#include "tgba/bddprint.hh"
|
#include "tgba/bddprint.hh"
|
||||||
#include "tgbaalgos/scc.hh"
|
#include "tgbaalgos/scc.hh"
|
||||||
|
#include "tgba/tgbaexplicit.hh"
|
||||||
//#include "tgbaalgos/dotty.hh"
|
//#include "tgbaalgos/dotty.hh"
|
||||||
|
#include "priv/acccompl.hh"
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
@ -403,33 +405,6 @@ namespace spot
|
||||||
return multop::instance(multop::OrRat, v);
|
return multop::instance(multop::OrRat, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
conj_bdd_to_acc(tgba_explicit_formula* a, bdd b,
|
|
||||||
state_explicit_formula::transition* t)
|
|
||||||
{
|
|
||||||
assert(b != bddfalse);
|
|
||||||
while (b != bddtrue)
|
|
||||||
{
|
|
||||||
int var = bdd_var(b);
|
|
||||||
bdd high = bdd_high(b);
|
|
||||||
if (high == bddfalse)
|
|
||||||
{
|
|
||||||
// Simply ignore negated acceptance variables.
|
|
||||||
b = bdd_low(b);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const formula* ac = var_to_formula(var);
|
|
||||||
|
|
||||||
if (!a->has_acceptance_condition(ac))
|
|
||||||
a->declare_acceptance_condition(ac->clone());
|
|
||||||
a->add_acceptance_condition(t, ac);
|
|
||||||
b = high;
|
|
||||||
}
|
|
||||||
assert(b != bddfalse);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const translated&
|
const translated&
|
||||||
ltl_to_bdd(const formula* f, bool mark_all, bool recurring = false);
|
ltl_to_bdd(const formula* f, bool mark_all, bool recurring = false);
|
||||||
|
|
||||||
|
|
@ -2048,7 +2023,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tgba_explicit_formula*
|
tgba_digraph*
|
||||||
ltl_to_tgba_fm(const formula* f, bdd_dict* dict,
|
ltl_to_tgba_fm(const formula* f, bdd_dict* dict,
|
||||||
bool exprop, bool symb_merge, bool branching_postponement,
|
bool exprop, bool symb_merge, bool branching_postponement,
|
||||||
bool fair_loop_approx, const atomic_prop_set* unobs,
|
bool fair_loop_approx, const atomic_prop_set* unobs,
|
||||||
|
|
@ -2128,14 +2103,15 @@ namespace spot
|
||||||
bdd all_events = observable_events | unobservable_events;
|
bdd all_events = observable_events | unobservable_events;
|
||||||
|
|
||||||
|
|
||||||
tgba_explicit_formula* a = new tgba_explicit_formula(dict);
|
tgba_digraph* a = new tgba_digraph(dict);
|
||||||
|
auto namer = a->create_namer<const formula*, formula_ptr_hash>();
|
||||||
|
|
||||||
// This is in case the initial state is equivalent to true...
|
// This is in case the initial state is equivalent to true...
|
||||||
if (symb_merge)
|
if (symb_merge)
|
||||||
f2 = fc.canonize(f2);
|
f2 = fc.canonize(f2);
|
||||||
|
|
||||||
formulae_to_translate.insert(f2);
|
formulae_to_translate.insert(f2);
|
||||||
a->set_init_state(f2);
|
a->set_init_state(namer->new_state(f2));
|
||||||
|
|
||||||
while (!formulae_to_translate.empty())
|
while (!formulae_to_translate.empty())
|
||||||
{
|
{
|
||||||
|
|
@ -2273,7 +2249,8 @@ namespace spot
|
||||||
|
|
||||||
// Check for an arc going to 1 (True). Register it first, that
|
// Check for an arc going to 1 (True). Register it first, that
|
||||||
// way it will be explored before others during model checking.
|
// way it will be explored before others during model checking.
|
||||||
dest_map::const_iterator i = dests.find(constant::true_instance());
|
auto truef = constant::true_instance();
|
||||||
|
dest_map::const_iterator i = dests.find(truef);
|
||||||
// COND_FOR_TRUE is the conditions of the True arc, so we
|
// COND_FOR_TRUE is the conditions of the True arc, so we
|
||||||
// can remove them from all other arcs. It might sounds that
|
// can remove them from all other arcs. It might sounds that
|
||||||
// this is not needed when exprop is used, but in fact it is
|
// this is not needed when exprop is used, but in fact it is
|
||||||
|
|
@ -2296,7 +2273,7 @@ namespace spot
|
||||||
// When translating LTL for an event-based logic with
|
// When translating LTL for an event-based logic with
|
||||||
// unobservable events, the 1 state should accept all events,
|
// unobservable events, the 1 state should accept all events,
|
||||||
// even unobservable events.
|
// even unobservable events.
|
||||||
if (unobs && now == constant::true_instance())
|
if (unobs && now == truef)
|
||||||
cond_for_true = all_events;
|
cond_for_true = all_events;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2308,44 +2285,38 @@ namespace spot
|
||||||
assert(fair_loop_approx || j->first == bddtrue);
|
assert(fair_loop_approx || j->first == bddtrue);
|
||||||
cond_for_true = j->second;
|
cond_for_true = j->second;
|
||||||
}
|
}
|
||||||
if (!a->has_state(constant::true_instance()))
|
if (!namer->has_state(truef))
|
||||||
formulae_to_translate.insert(constant::true_instance());
|
{
|
||||||
state_explicit_formula::transition* t =
|
formulae_to_translate.insert(truef);
|
||||||
a->create_transition(now, constant::true_instance());
|
namer->new_state(truef);
|
||||||
t->condition = cond_for_true;
|
}
|
||||||
|
namer->new_transition(now, truef, cond_for_true, bddtrue);
|
||||||
}
|
}
|
||||||
// Register other transitions.
|
// Register other transitions.
|
||||||
for (i = dests.begin(); i != dests.end(); ++i)
|
for (i = dests.begin(); i != dests.end(); ++i)
|
||||||
{
|
{
|
||||||
const formula* dest = i->first;
|
const formula* dest = i->first;
|
||||||
|
if (dest == truef)
|
||||||
|
continue;
|
||||||
|
|
||||||
// The cond_for_true optimization can cause some
|
// The cond_for_true optimization can cause some
|
||||||
// transitions to be removed. So we have to remember
|
// transitions to be removed. So we have to remember
|
||||||
// whether a formula is actually reachable.
|
// whether a formula is actually reachable.
|
||||||
bool reachable = false;
|
bool reachable = false;
|
||||||
|
|
||||||
// Will this be a new state?
|
// Will this be a new state?
|
||||||
bool seen = a->has_state(dest);
|
bool seen = namer->has_state(dest);
|
||||||
|
|
||||||
if (dest != constant::true_instance())
|
for (auto& j: i->second)
|
||||||
{
|
{
|
||||||
for (prom_map::const_iterator j = i->second.begin();
|
bdd cond = j.second - cond_for_true;
|
||||||
j != i->second.end(); ++j)
|
if (cond == bddfalse) // Skip false transitions.
|
||||||
{
|
continue;
|
||||||
bdd cond = j->second - cond_for_true;
|
if (!reachable && !seen)
|
||||||
if (cond == bddfalse) // Skip false transitions.
|
namer->new_state(dest);
|
||||||
continue;
|
|
||||||
state_explicit_formula::transition* t =
|
|
||||||
a->create_transition(now, dest);
|
|
||||||
t->condition = cond;
|
|
||||||
d.conj_bdd_to_acc(a, j->first, t);
|
|
||||||
reachable = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// "1" is reachable.
|
|
||||||
reachable = true;
|
reachable = true;
|
||||||
|
namer->new_transition(now, dest, cond, j.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reachable && !seen)
|
if (reachable && !seen)
|
||||||
formulae_to_translate.insert(dest);
|
formulae_to_translate.insert(dest);
|
||||||
else
|
else
|
||||||
|
|
@ -2353,9 +2324,21 @@ namespace spot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto n: namer->names())
|
||||||
|
n->destroy();
|
||||||
|
delete namer;
|
||||||
|
|
||||||
dict->register_propositions(fc.used_vars(), a);
|
dict->register_propositions(fc.used_vars(), a);
|
||||||
|
a->set_acceptance_conditions(d.a_set);
|
||||||
// Turn all promises into real acceptance conditions.
|
// Turn all promises into real acceptance conditions.
|
||||||
a->complement_all_acceptance_conditions();
|
acc_compl ac(a->all_acceptance_conditions(),
|
||||||
|
a->neg_acceptance_conditions());
|
||||||
|
|
||||||
|
unsigned ns = a->num_states();
|
||||||
|
for (unsigned s = 0; s < ns; ++s)
|
||||||
|
for (auto& t: a->out(s))
|
||||||
|
t.acc = ac.reverse_complement(t.acc);
|
||||||
|
|
||||||
|
|
||||||
if (!simplifier)
|
if (!simplifier)
|
||||||
// This should not be deleted before we have registered all propositions.
|
// This should not be deleted before we have registered all propositions.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// -*- coding: utf-8 -*-
|
// -*- coding: utf-8 -*-
|
||||||
// Copyright (C) 2010, 2011, 2012, 2013 Laboratoire de Recherche et
|
// Copyright (C) 2010, 2011, 2012, 2013, 2014 Laboratoire de Recherche et
|
||||||
// Développement de l'Epita (LRDE).
|
// Développement de l'Epita (LRDE).
|
||||||
// Copyright (C) 2003, 2004, 2005, 2006 Laboratoire d'Informatique de
|
// Copyright (C) 2003, 2004, 2005, 2006 Laboratoire d'Informatique de
|
||||||
// Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
|
// Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
|
||||||
|
|
@ -24,14 +24,14 @@
|
||||||
# define SPOT_TGBAALGOS_LTL2TGBA_FM_HH
|
# define SPOT_TGBAALGOS_LTL2TGBA_FM_HH
|
||||||
|
|
||||||
#include "ltlast/formula.hh"
|
#include "ltlast/formula.hh"
|
||||||
#include "tgba/tgbaexplicit.hh"
|
#include "tgba/tgbagraph.hh"
|
||||||
#include "ltlvisit/apcollect.hh"
|
#include "ltlvisit/apcollect.hh"
|
||||||
#include "ltlvisit/simplify.hh"
|
#include "ltlvisit/simplify.hh"
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
/// \ingroup tgba_ltl
|
/// \ingroup tgba_ltl
|
||||||
/// \brief Build a spot::tgba_explicit* from an LTL formula.
|
/// \brief Build a spot::tgba_digraph* from an LTL formula.
|
||||||
///
|
///
|
||||||
/// This is based on the following paper.
|
/// This is based on the following paper.
|
||||||
/** \verbatim
|
/** \verbatim
|
||||||
|
|
@ -122,7 +122,7 @@ namespace spot
|
||||||
\endverbatim */
|
\endverbatim */
|
||||||
///
|
///
|
||||||
/// \return A spot::tgba_explicit that recognizes the language of \a f.
|
/// \return A spot::tgba_explicit that recognizes the language of \a f.
|
||||||
SPOT_API tgba_explicit_formula*
|
SPOT_API tgba_digraph*
|
||||||
ltl_to_tgba_fm(const ltl::formula* f, bdd_dict* dict,
|
ltl_to_tgba_fm(const ltl::formula* f, bdd_dict* dict,
|
||||||
bool exprop = false, bool symb_merge = true,
|
bool exprop = false, bool symb_merge = true,
|
||||||
bool branching_postponement = false,
|
bool branching_postponement = false,
|
||||||
|
|
|
||||||
|
|
@ -120,14 +120,14 @@ while read f; do
|
||||||
|
|
||||||
# If the labels of the state have only digits, assume the minimization
|
# If the labels of the state have only digits, assume the minimization
|
||||||
# worked.
|
# worked.
|
||||||
x=`../ltl2tgba -f -Rm "!($f)" |
|
../ltl2tgba -kt -Rm "!($f)" > out1
|
||||||
grep -v -- '->' |
|
../ltl2tgba -kt -R3 "!($f)" > out2
|
||||||
sed -n 's/.*label="\(..*\)".*/\1/p' |
|
if cmp out1 out2; then
|
||||||
tr -d '0-9\n'`
|
echo "OK !($f)";
|
||||||
case $x in
|
else
|
||||||
"") echo "wrongly minimized !($f)"; success=false;;
|
echo "wrongly minimized !($f)";
|
||||||
*) echo "OK !($f)";;
|
success=false;
|
||||||
esac
|
fi
|
||||||
done < non-obligations.txt
|
done < non-obligations.txt
|
||||||
|
|
||||||
$success
|
$success
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue