hierarchy: add a new way to check DBA-realizability via DPA

* spot/tl/hierarchy.cc, spot/tl/hierarchy.hh: Here.
* tests/core/hierarchy.test: Test it.
* bin/man/spot-x.x: Document SPOT_PR_CHECK.
* doc/org/hierarchy.org, NEWS: Update.
This commit is contained in:
Alexandre Duret-Lutz 2019-06-12 23:38:17 +02:00
parent 2617c17b45
commit b4da0cf660
6 changed files with 155 additions and 230 deletions

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2017, 2018 Laboratoire de Recherche et Développement de
// Copyright (C) 2017-2019 Laboratoire de Recherche et Développement de
// l'Epita (LRDE)
//
// This file is part of Spot, a model checking library.
@ -65,79 +65,91 @@ namespace spot
return !cobuchi->intersects(not_aut);
}
[[noreturn]] static void invalid_spot_pr_check()
{
throw std::runtime_error("invalid value for SPOT_PR_CHECK "
"(should be 1, 2, or 3)");
}
static prcheck
algo_to_perform(bool is_persistence, bool aut_given)
{
static unsigned value = [&]()
{
int val;
try
{
auto s = getenv("SPOT_PR_CHECK");
val = s ? std::stoi(s) : 0;
}
catch (const std::exception& e)
{
invalid_spot_pr_check();
}
if (val < 0 || val > 3)
invalid_spot_pr_check();
return val;
}();
switch (value)
{
case 0:
if (aut_given && !is_persistence)
return prcheck::via_Parity;
else
return prcheck::via_CoBuchi;
case 1:
return prcheck::via_CoBuchi;
case 2:
return prcheck::via_Rabin;
case 3:
return prcheck::via_Parity;
default:
SPOT_UNREACHABLE();
}
SPOT_UNREACHABLE();
return prcheck::via_Parity;
}
static bool
detbuchi_realizable(const twa_graph_ptr& aut)
{
if (is_universal(aut))
return true;
// if aut is a non-deterministic TGBA, we do
// TGBA->DPA->DRA->(D?)BA. The conversion from DRA to
// BA will preserve determinism if possible.
bool want_old = algo_to_perform(false, true) == prcheck::via_Rabin;
if (want_old)
{
// if aut is a non-deterministic TGBA, we do
// TGBA->DPA->DRA->(D?)BA. The conversion from DRA to
// BA will preserve determinism if possible.
spot::postprocessor p;
p.set_type(spot::postprocessor::Generic);
p.set_pref(spot::postprocessor::Deterministic);
p.set_level(spot::postprocessor::Low);
auto dpa = p.run(aut);
if (dpa->acc().is_generalized_buchi())
{
assert(is_deterministic(dpa));
return true;
}
else
{
auto dra = to_generalized_rabin(dpa);
return rabin_is_buchi_realizable(dra);
}
}
// Converting reduce_parity() will produce a Büchi automaton (or
// an automaton with "t" or "f" acceptance) if the parity
// automaton is DBA-realizable.
spot::postprocessor p;
p.set_type(spot::postprocessor::Generic);
p.set_type(spot::postprocessor::Parity);
p.set_pref(spot::postprocessor::Deterministic);
p.set_level(spot::postprocessor::Low);
auto dpa = p.run(aut);
if (dpa->acc().is_generalized_buchi())
{
assert(is_deterministic(dpa));
return true;
}
else
{
auto dra = to_generalized_rabin(dpa);
return rabin_is_buchi_realizable(dra);
}
return dpa->acc().is_f() || dpa->acc().is_generalized_buchi();
}
}
[[noreturn]] static void invalid_spot_pr_check()
{
throw std::runtime_error("invalid value for SPOT_PR_CHECK "
"(should be 1 or 2)");
}
static prcheck
algo_to_perform(bool is_persistence, bool aut_given)
{
static prcheck env_algo = [&]()
{
int val;
try
{
auto s = getenv("SPOT_PR_CHECK");
val = s ? std::stoi(s) : 0;
}
catch (const std::exception& e)
{
invalid_spot_pr_check();
}
if (val == 0)
{
if (aut_given && !is_persistence)
return prcheck::via_Rabin;
else if (is_persistence || !aut_given)
return prcheck::via_CoBuchi;
else
SPOT_UNREACHABLE();
}
else if (val == 1)
{
return prcheck::via_CoBuchi;
}
else if (val == 2)
{
return prcheck::via_Rabin;
}
else
{
invalid_spot_pr_check();
}
}();
return env_algo;
}
bool
is_persistence(formula f, twa_graph_ptr aut, prcheck algo)
{
@ -161,6 +173,7 @@ namespace spot
ltl_to_tgba_fm(f, make_bdd_dict(), true));
case prcheck::via_Rabin:
case prcheck::via_Parity:
return detbuchi_realizable(ltl_to_tgba_fm(formula::Not(f),
make_bdd_dict(), true));
@ -195,6 +208,7 @@ namespace spot
make_bdd_dict(), true));
case prcheck::via_Rabin:
case prcheck::via_Parity:
return detbuchi_realizable(aut ? aut :
ltl_to_tgba_fm(f, make_bdd_dict(), true));

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2017, 2018 Laboratoire de Recherche et Développement
// Copyright (C) 2017, 2018, 2019 Laboratoire de Recherche et Développement
// de l'Epita (LRDE)
//
// This file is part of Spot, a model checking library.
@ -37,6 +37,9 @@ namespace spot
///
/// If PR_via_CoBuchi, they will check if the formula is cobuchi_realizable.
///
/// If PR_via_Parity, they will check if the formula is
/// detbuchi/cobuchi-realizable by calling reduce_parity() on a DPA.
///
/// Note that is_persistence() and is_recurrence() will work on a formula f
/// or its negation because of the duality of both classes
/// (see https://spot.lrde.epita.fr/hierarchy.html for details).
@ -47,6 +50,7 @@ namespace spot
Auto,
via_CoBuchi,
via_Rabin,
via_Parity,
};
/// \ingroup tl_hier