twa: introduce intersects() and friends

* spot/twa/twa.hh, spot/twa/twa.cc (intersects, intersecting_run,
intersecting_word): New functions.
* NEWS: Mention them.
* doc/org/tut51.org, tests/python/bugdet.py: Use them.
This commit is contained in:
Alexandre Duret-Lutz 2016-11-13 11:23:12 +01:00
parent bdad288c70
commit c225747749
5 changed files with 138 additions and 64 deletions

View file

@ -25,6 +25,7 @@
#include <spot/twaalgos/gtec/gtec.hh>
#include <spot/twaalgos/word.hh>
#include <spot/twaalgos/remfin.hh>
#include <spot/twa/twaproduct.hh>
#include <utility>
namespace spot
@ -44,6 +45,20 @@ namespace spot
get_dict()->unregister_all_my_variables(this);
}
namespace
{
const_twa_ptr remove_fin_maybe(const const_twa_ptr& a)
{
if (!a->acc().uses_fin_acceptance())
return a;
auto aa = std::dynamic_pointer_cast<const twa_graph>(a);
if (!aa)
aa = make_twa_graph(a, twa::prop_set::all());
return remove_fin(aa);
}
}
state*
twa::project_state(const state* s,
const const_twa_ptr& t) const
@ -59,15 +74,7 @@ namespace spot
// FIXME: This should be improved based on properties of the
// automaton. For instance we do not need couvreur99 is we know
// the automaton is weak.
auto a = shared_from_this();
if (a->acc().uses_fin_acceptance())
{
auto aa = std::dynamic_pointer_cast<const twa_graph>(a);
if (!aa)
aa = make_twa_graph(a, prop_set::all());
a = remove_fin(aa);
}
return !couvreur99(a)->check();
return !couvreur99(remove_fin_maybe(shared_from_this()))->check();
}
twa_run_ptr
@ -86,15 +93,7 @@ namespace spot
twa_word_ptr
twa::accepting_word() const
{
auto a = shared_from_this();
if (a->acc().uses_fin_acceptance())
{
auto aa = std::dynamic_pointer_cast<const twa_graph>(a);
if (!aa)
aa = make_twa_graph(a, prop_set::all());
a = remove_fin(aa);
}
if (auto run = a->accepting_run())
if (auto run = remove_fin_maybe(shared_from_this())->accepting_run())
{
auto w = make_twa_word(run->reduce());
w->simplify();
@ -106,6 +105,36 @@ namespace spot
}
}
bool
twa::intersects(const_twa_ptr other) const
{
auto a1 = remove_fin_maybe(shared_from_this());
auto a2 = remove_fin_maybe(other);
return !otf_product(a1, a2)->is_empty();
}
twa_run_ptr
twa::intersecting_run(const_twa_ptr other, bool from_other) const
{
auto a = shared_from_this();
if (from_other)
other = remove_fin_maybe(other);
else
a = remove_fin_maybe(a);
auto run = otf_product(a, other)->accepting_run();
if (!run)
return nullptr;
return run->project(from_other ? other : a);
}
twa_word_ptr
twa::intersecting_word(const_twa_ptr other) const
{
auto a1 = remove_fin_maybe(shared_from_this());
auto a2 = remove_fin_maybe(other);
return otf_product(a1, a2)->accepting_word();
}
void
twa::set_named_prop(std::string s, std::nullptr_t)
{

View file

@ -824,17 +824,23 @@ namespace spot
///@}
/// \brief Check whether the language of the automaton is empty.
///
/// If you are calling this method on a product of two automata,
/// consider using intersects() instead.
virtual bool is_empty() const;
/// \brief Return an accepting run if one exists.
///
/// Note that this method currently onky works for Fin-less
/// Note that this method currently only works for Fin-less
/// acceptance. For acceptance conditions that contain Fin
/// acceptance, you can either rely on is_empty() and not use any
/// accepting run, or remove Fin acceptance using remove_fin() and
/// compute an accepting run on that larger automaton.
///
/// Return nullptr if no accepting run were found.
///
/// If you are calling this method on a product of two automata,
/// consider using intersecting_run() instead.
virtual twa_run_ptr accepting_run() const;
/// \brief Return an accepting word if one exists.
@ -843,8 +849,44 @@ namespace spot
/// acceptance.
///
/// Return nullptr if no accepting word were found.
///
/// If you are calling this method on a product of two automata,
/// consider using intersecting_word() instead.
virtual twa_word_ptr accepting_word() const;
/// \brief Check whether the language of this automaton intersects
/// that of the \a other automaton.
virtual bool intersects(const_twa_ptr other) const;
/// \brief Return an accepting run recognizing a word accepted by
/// two automata.
///
/// If \a from_other is true, the returned run will be over the
/// \a other automaton. Otherwise, the run will be over this
/// automaton.
///
/// Note that this method currently only works if the automaton
/// from which the accepting run is extracted uses Fin-less acceptance.
/// (The other automaton can have any acceptance condition.)
///
/// For acceptance conditions that contain Fin acceptance, you can
/// either rely on intersects() and not use any accepting run, or
/// remove Fin acceptance using remove_fin() and compute an
/// intersecting run on this larger automaton.
///
/// Return nullptr if no accepting run were found.
virtual twa_run_ptr intersecting_run(const_twa_ptr other,
bool from_other = false) const;
/// \brief Return a word accepted by two automata.
///
/// Note that this method DOES works with Fin
/// acceptance.
///
/// Return nullptr if no accepting word were found.
virtual twa_word_ptr intersecting_word(const_twa_ptr other) const;
private:
acc_cond acc_;