twa: make sure intersection_run and intersection_word use genem
* spot/twa/twa.cc (accepting_word, intersecting_run, intersecting_word): Refactor. * tests/python/contains.ipynb: Adjust.
This commit is contained in:
parent
17f91132f9
commit
84fa824f7e
3 changed files with 52 additions and 27 deletions
4
NEWS
4
NEWS
|
|
@ -13,8 +13,8 @@ New in spot 2.7.3.dev (not yet released)
|
||||||
- Add generic_accepting_run() as a variant of generic_emptiness_check() that
|
- Add generic_accepting_run() as a variant of generic_emptiness_check() that
|
||||||
returns an accepting run in an automaton with any acceptance condition.
|
returns an accepting run in an automaton with any acceptance condition.
|
||||||
|
|
||||||
- twa::accepting_run() now works on automata using Fin in
|
- twa::accepting_run() and twa::intersecting_run() now work on
|
||||||
their acceptance condition.
|
automata using Fin in their acceptance condition.
|
||||||
|
|
||||||
- simulation-based reductions have learned a trick that sometimes
|
- simulation-based reductions have learned a trick that sometimes
|
||||||
improve transition-based output when the input is state-based.
|
improve transition-based output when the input is state-based.
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,14 @@ namespace spot
|
||||||
return std::dynamic_pointer_cast<const twa_graph>(a);
|
return std::dynamic_pointer_cast<const twa_graph>(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const_twa_graph_ptr ensure_twa_graph(const const_twa_ptr& a)
|
||||||
|
{
|
||||||
|
if (auto aa = is_twa_graph(a))
|
||||||
|
return aa;
|
||||||
|
return make_twa_graph(a, twa::prop_set::all());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Make sure automata using Fin acceptance are twa_graph_ptr
|
// Make sure automata using Fin acceptance are twa_graph_ptr
|
||||||
const_twa_graph_ptr fin_to_twa_graph_maybe(const const_twa_ptr& a)
|
const_twa_graph_ptr fin_to_twa_graph_maybe(const const_twa_ptr& a)
|
||||||
{
|
{
|
||||||
|
|
@ -70,15 +78,19 @@ namespace spot
|
||||||
return remove_alternation(aa);
|
return remove_alternation(aa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove alternation.
|
||||||
|
const_twa_graph_ptr ensure_existential_twa_graph(const const_twa_ptr& a)
|
||||||
|
{
|
||||||
|
return remove_alternation(ensure_twa_graph(a));
|
||||||
|
}
|
||||||
|
|
||||||
// Remove Fin-acceptance and alternation.
|
// Remove Fin-acceptance and alternation.
|
||||||
const_twa_ptr remove_fin_maybe(const const_twa_ptr& a)
|
const_twa_ptr remove_fin_maybe(const const_twa_ptr& a)
|
||||||
{
|
{
|
||||||
auto aa = is_twa_graph(a);
|
auto aa = is_twa_graph(a);
|
||||||
if ((!aa || aa->is_existential()) && !a->acc().uses_fin_acceptance())
|
if ((!aa || aa->is_existential()) && !a->acc().uses_fin_acceptance())
|
||||||
return a;
|
return a;
|
||||||
if (!aa)
|
return remove_fin(ensure_existential_twa_graph(a));
|
||||||
aa = make_twa_graph(a, twa::prop_set::all());
|
|
||||||
return remove_fin(remove_alternation(aa));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,7 +109,7 @@ namespace spot
|
||||||
const_twa_ptr a = shared_from_this();
|
const_twa_ptr a = shared_from_this();
|
||||||
if (const_twa_graph_ptr ag = fin_to_twa_graph_maybe(a))
|
if (const_twa_graph_ptr ag = fin_to_twa_graph_maybe(a))
|
||||||
return generic_emptiness_check(ag);
|
return generic_emptiness_check(ag);
|
||||||
return !couvreur99_new_check(remove_fin_maybe(shared_from_this()));
|
return !couvreur99_new_check(ensure_existential_twa_graph(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
twa_run_ptr
|
twa_run_ptr
|
||||||
|
|
@ -115,7 +127,7 @@ namespace spot
|
||||||
twa_word_ptr
|
twa_word_ptr
|
||||||
twa::accepting_word() const
|
twa::accepting_word() const
|
||||||
{
|
{
|
||||||
if (auto run = shared_from_this()->accepting_run())
|
if (auto run = accepting_run())
|
||||||
{
|
{
|
||||||
auto w = make_twa_word(run->reduce());
|
auto w = make_twa_word(run->reduce());
|
||||||
w->simplify();
|
w->simplify();
|
||||||
|
|
@ -136,36 +148,49 @@ namespace spot
|
||||||
// with the generic emptiness.
|
// with the generic emptiness.
|
||||||
if (acc().uses_fin_acceptance() || other->acc().uses_fin_acceptance())
|
if (acc().uses_fin_acceptance() || other->acc().uses_fin_acceptance())
|
||||||
{
|
{
|
||||||
const_twa_graph_ptr g1 = is_twa_graph(self);
|
const_twa_graph_ptr g1 = ensure_existential_twa_graph(self);
|
||||||
const_twa_graph_ptr g2 = is_twa_graph(other);
|
const_twa_graph_ptr g2 = ensure_existential_twa_graph(other);
|
||||||
if (g1 && g2 && g1->is_existential() && g2->is_existential())
|
return !generic_emptiness_check(product(g1, g2));
|
||||||
return !generic_emptiness_check(product(g1, g2));
|
|
||||||
}
|
}
|
||||||
auto a1 = remove_fin_maybe(self);
|
self = remove_fin_maybe(self); // remove alternation, not Fin
|
||||||
auto a2 = remove_fin_maybe(other);
|
other = remove_fin_maybe(other);
|
||||||
return !otf_product(a1, a2)->is_empty();
|
return !otf_product(self, other)->is_empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
twa_run_ptr
|
twa_run_ptr
|
||||||
twa::intersecting_run(const_twa_ptr other, bool from_other) const
|
twa::intersecting_run(const_twa_ptr other, bool from_other) const
|
||||||
{
|
{
|
||||||
auto a = shared_from_this();
|
auto self = shared_from_this();
|
||||||
if (!from_other)
|
if (acc().uses_fin_acceptance() || other->acc().uses_fin_acceptance())
|
||||||
other = remove_fin_maybe(other);
|
{
|
||||||
else
|
const_twa_graph_ptr g1 = ensure_existential_twa_graph(self);
|
||||||
a = remove_fin_maybe(a);
|
const_twa_graph_ptr g2 = ensure_existential_twa_graph(other);
|
||||||
auto run = otf_product(a, other)->accepting_run();
|
auto run = generic_accepting_run(product(g1, g2));
|
||||||
|
if (!run)
|
||||||
|
return nullptr;
|
||||||
|
return run->reduce()->project(from_other ? g2 : g1);
|
||||||
|
}
|
||||||
|
self = remove_fin_maybe(self); // remove alternation, not Fin
|
||||||
|
other = remove_fin_maybe(other);
|
||||||
|
auto run = otf_product(self, other)->accepting_run();
|
||||||
if (!run)
|
if (!run)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return run->project(from_other ? other : a);
|
return run->reduce()->project(from_other ? other : self);
|
||||||
}
|
}
|
||||||
|
|
||||||
twa_word_ptr
|
twa_word_ptr
|
||||||
twa::intersecting_word(const_twa_ptr other) const
|
twa::intersecting_word(const_twa_ptr other) const
|
||||||
{
|
{
|
||||||
auto a1 = remove_fin_maybe(shared_from_this());
|
if (auto run = intersecting_run(other))
|
||||||
auto a2 = remove_fin_maybe(other);
|
{
|
||||||
return otf_product(a1, a2)->accepting_word();
|
auto w = make_twa_word(run);
|
||||||
|
w->simplify();
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
|
|
||||||
|
|
@ -326,7 +326,7 @@
|
||||||
"$\\mathsf{cycle}\\{a; \\lnot a\\}$"
|
"$\\mathsf{cycle}\\{a; \\lnot a\\}$"
|
||||||
],
|
],
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
"<spot.twa_word; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_word > *' at 0x7faa9424d9c0> >"
|
"<spot.twa_word; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_word > *' at 0x7f7c7c425630> >"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 16,
|
"execution_count": 16,
|
||||||
|
|
@ -370,7 +370,7 @@
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
"The following word is only accepted by one automaton: cycle{!a; a; !a}\n"
|
"The following word is only accepted by one automaton: cycle{a; !a}\n"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -505,7 +505,7 @@
|
||||||
"name": "python",
|
"name": "python",
|
||||||
"nbconvert_exporter": "python",
|
"nbconvert_exporter": "python",
|
||||||
"pygments_lexer": "ipython3",
|
"pygments_lexer": "ipython3",
|
||||||
"version": "3.6.7"
|
"version": "3.7.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue