hierarchy: Rewrite is_recurrence(), is_persistence() and add tests
* spot/tl/hierarchy.cc: Rewrite is_recurrence(), is_persistence() * spot/tl/hierarchy.hh: Fix typo. * tests/core/hierarchy.test: Add tests.
This commit is contained in:
parent
d89579321f
commit
7e0fc448c5
3 changed files with 86 additions and 47 deletions
|
|
@ -81,51 +81,50 @@ namespace spot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[noreturn]] static void invalid_spot_pr_check()
|
||||||
|
{
|
||||||
|
throw std::runtime_error("invalid value for SPOT_PR_CHECK "
|
||||||
|
"(should be 1 or 2)");
|
||||||
|
}
|
||||||
|
|
||||||
static prcheck
|
static prcheck
|
||||||
algo_to_perform(bool is_persistence, bool aut_given, prcheck algo)
|
algo_to_perform(bool is_persistence, bool aut_given)
|
||||||
{
|
{
|
||||||
if (algo == prcheck::PR_Auto)
|
static prcheck env_algo = [&]()
|
||||||
{
|
|
||||||
// Check environment variable.
|
|
||||||
static int val_s = []()
|
|
||||||
{
|
{
|
||||||
|
int val;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto s = getenv("SPOT_PR_CHECK");
|
auto s = getenv("SPOT_PR_CHECK");
|
||||||
return s ? std::stoi(s) : 0;
|
val = s ? std::stoi(s) : 0;
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("invalid value for SPOT_PR_CHECK "
|
invalid_spot_pr_check();
|
||||||
"(should be 1 or 2)");
|
|
||||||
}
|
}
|
||||||
}();
|
if (val == 0)
|
||||||
|
|
||||||
if (val_s == 1)
|
|
||||||
{
|
|
||||||
return prcheck::PR_via_CoBuchi;
|
|
||||||
}
|
|
||||||
else if (val_s == 2)
|
|
||||||
{
|
|
||||||
return prcheck::PR_via_Rabin;
|
|
||||||
}
|
|
||||||
else if (!val_s)
|
|
||||||
{
|
{
|
||||||
if (aut_given && !is_persistence)
|
if (aut_given && !is_persistence)
|
||||||
return prcheck::PR_via_Rabin;
|
return prcheck::via_Rabin;
|
||||||
else if ((aut_given && is_persistence) || !aut_given)
|
else if ((aut_given && is_persistence) || !aut_given)
|
||||||
return prcheck::PR_via_CoBuchi;
|
return prcheck::via_CoBuchi;
|
||||||
else
|
else
|
||||||
SPOT_UNREACHABLE();
|
SPOT_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
else if (val == 1)
|
||||||
|
{
|
||||||
|
return prcheck::via_CoBuchi;
|
||||||
|
}
|
||||||
|
else if (val == 2)
|
||||||
|
{
|
||||||
|
return prcheck::via_Rabin;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw std::runtime_error("invalid value for SPOT_PR_CHECK "
|
invalid_spot_pr_check();
|
||||||
"(should be 1 or 2)");
|
|
||||||
}
|
}
|
||||||
}
|
}();
|
||||||
else
|
return env_algo;
|
||||||
return algo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
@ -134,17 +133,20 @@ namespace spot
|
||||||
if (f.is_syntactic_persistence())
|
if (f.is_syntactic_persistence())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
switch (algo_to_perform(true, aut != nullptr, algo))
|
if (algo == prcheck::Auto)
|
||||||
|
algo = algo_to_perform(true, aut != nullptr);
|
||||||
|
|
||||||
|
switch (algo)
|
||||||
{
|
{
|
||||||
case prcheck::PR_via_CoBuchi:
|
case prcheck::via_CoBuchi:
|
||||||
return cobuchi_realizable(f, aut ? aut :
|
return cobuchi_realizable(f, aut ? aut :
|
||||||
ltl_to_tgba_fm(f, make_bdd_dict(), true));
|
ltl_to_tgba_fm(f, make_bdd_dict(), true));
|
||||||
|
|
||||||
case prcheck::PR_via_Rabin:
|
case prcheck::via_Rabin:
|
||||||
return detbuchi_realizable(ltl_to_tgba_fm(formula::Not(f),
|
return detbuchi_realizable(ltl_to_tgba_fm(formula::Not(f),
|
||||||
make_bdd_dict(), true));
|
make_bdd_dict(), true));
|
||||||
|
|
||||||
case prcheck::PR_Auto:
|
case prcheck::Auto:
|
||||||
SPOT_UNREACHABLE();
|
SPOT_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,18 +159,21 @@ namespace spot
|
||||||
if (f.is_syntactic_recurrence())
|
if (f.is_syntactic_recurrence())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
switch (algo_to_perform(false, aut != nullptr, algo))
|
if (algo == prcheck::Auto)
|
||||||
|
algo = algo_to_perform(true, aut != nullptr);
|
||||||
|
|
||||||
|
switch (algo)
|
||||||
{
|
{
|
||||||
case prcheck::PR_via_CoBuchi:
|
case prcheck::via_CoBuchi:
|
||||||
return cobuchi_realizable(formula::Not(f),
|
return cobuchi_realizable(formula::Not(f),
|
||||||
ltl_to_tgba_fm(formula::Not(f),
|
ltl_to_tgba_fm(formula::Not(f),
|
||||||
make_bdd_dict(), true));
|
make_bdd_dict(), true));
|
||||||
|
|
||||||
case prcheck::PR_via_Rabin:
|
case prcheck::via_Rabin:
|
||||||
return detbuchi_realizable(aut ? aut :
|
return detbuchi_realizable(aut ? aut :
|
||||||
ltl_to_tgba_fm(f, make_bdd_dict(), true));
|
ltl_to_tgba_fm(f, make_bdd_dict(), true));
|
||||||
|
|
||||||
case prcheck::PR_Auto:
|
case prcheck::Auto:
|
||||||
SPOT_UNREACHABLE();
|
SPOT_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,11 +226,11 @@ namespace spot
|
||||||
case ocheck::via_WDBA:
|
case ocheck::via_WDBA:
|
||||||
return is_wdba_realizable(f, aut);
|
return is_wdba_realizable(f, aut);
|
||||||
case ocheck::via_CoBuchi:
|
case ocheck::via_CoBuchi:
|
||||||
return (is_persistence(f, aut, prcheck::PR_via_CoBuchi)
|
return (is_persistence(f, aut, prcheck::via_CoBuchi)
|
||||||
&& is_recurrence(f, aut, prcheck::PR_via_CoBuchi));
|
&& is_recurrence(f, aut, prcheck::via_CoBuchi));
|
||||||
case ocheck::via_Rabin:
|
case ocheck::via_Rabin:
|
||||||
return (is_persistence(f, aut, prcheck::PR_via_Rabin)
|
return (is_persistence(f, aut, prcheck::via_Rabin)
|
||||||
&& is_recurrence(f, aut, prcheck::PR_via_Rabin));
|
&& is_recurrence(f, aut, prcheck::via_Rabin));
|
||||||
case ocheck::Auto:
|
case ocheck::Auto:
|
||||||
SPOT_UNREACHABLE();
|
SPOT_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,9 @@ namespace spot
|
||||||
/// if !f is cobuchi_realizable.
|
/// if !f is cobuchi_realizable.
|
||||||
enum class prcheck
|
enum class prcheck
|
||||||
{
|
{
|
||||||
PR_Auto, // FIXME: Remove the useless PR_ prefix since
|
Auto,
|
||||||
PR_via_CoBuchi, // we already have a prcheck:: prefix.
|
via_CoBuchi,
|
||||||
PR_via_Rabin,
|
via_Rabin,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Return true if \a f represents a persistence property.
|
/// \brief Return true if \a f represents a persistence property.
|
||||||
|
|
@ -55,7 +55,7 @@ namespace spot
|
||||||
SPOT_API bool
|
SPOT_API bool
|
||||||
is_persistence(formula f,
|
is_persistence(formula f,
|
||||||
twa_graph_ptr aut = nullptr,
|
twa_graph_ptr aut = nullptr,
|
||||||
prcheck algo = prcheck::PR_Auto);
|
prcheck algo = prcheck::Auto);
|
||||||
|
|
||||||
/// \brief Return true if \a f represents a recurrence property.
|
/// \brief Return true if \a f represents a recurrence property.
|
||||||
///
|
///
|
||||||
|
|
@ -67,7 +67,7 @@ namespace spot
|
||||||
SPOT_API bool
|
SPOT_API bool
|
||||||
is_recurrence(formula f,
|
is_recurrence(formula f,
|
||||||
twa_graph_ptr aut = nullptr,
|
twa_graph_ptr aut = nullptr,
|
||||||
prcheck algo = prcheck::PR_Auto);
|
prcheck algo = prcheck::Auto);
|
||||||
|
|
||||||
/// Enum used to change the behavior of is_obligation().
|
/// Enum used to change the behavior of is_obligation().
|
||||||
enum class ocheck
|
enum class ocheck
|
||||||
|
|
|
||||||
|
|
@ -66,3 +66,37 @@ diff out expected
|
||||||
|
|
||||||
test B = `ltlfilt --format=%h -f '(Gb R (b xor Gb)) W (a W Xa)'`
|
test B = `ltlfilt --format=%h -f '(Gb R (b xor Gb)) W (a W Xa)'`
|
||||||
ltlfilt -q --safety --guarantee -f '(Gb R (b xor Gb)) W (a W Xa)'
|
ltlfilt -q --safety --guarantee -f '(Gb R (b xor Gb)) W (a W Xa)'
|
||||||
|
|
||||||
|
# make sure SPOT_PR_CHECK is read.
|
||||||
|
randltl -n -1 a b c | ltlfilt -v --syntactic-safety --syntactic-guarantee \
|
||||||
|
--syntactic-obligation --syntactic-recurrence --syntactic-persistence \
|
||||||
|
-n 100 > res
|
||||||
|
cat res | SPOT_PR_CHECK=x ltlfilt --recurrence 2>err && exit 1
|
||||||
|
cat res | SPOT_PR_CHECK=9 ltlfilt --recurrence 2>err && exit 1
|
||||||
|
grep SPOT_PR_CHECK err
|
||||||
|
|
||||||
|
# Testing Recurrence.
|
||||||
|
cat res | ltlfilt --recurrence > r0
|
||||||
|
for i in 1 2; do
|
||||||
|
cat res | SPOT_PR_CHECK=$i ltlfilt --recurrence > r$i
|
||||||
|
done
|
||||||
|
diff r0 r2
|
||||||
|
diff r1 r2
|
||||||
|
cat res | ltlfilt -o %h.ltl
|
||||||
|
cat R.ltl O.ltl G.ltl S.ltl B.ltl | sort > rogsb.ltl
|
||||||
|
sort r2 > r3
|
||||||
|
diff r3 rogsb.ltl
|
||||||
|
|
||||||
|
# Testing Persistence.
|
||||||
|
cat res | ltlfilt --persistence > p0
|
||||||
|
for i in 1 2; do
|
||||||
|
cat res | SPOT_PR_CHECK=$i ltlfilt --persistence > p$i
|
||||||
|
done
|
||||||
|
diff p0 p2
|
||||||
|
diff p1 p2
|
||||||
|
cat res | ltlfilt -o %h.ltl
|
||||||
|
cat P.ltl O.ltl G.ltl S.ltl B.ltl | sort > pogsb.ltl
|
||||||
|
sort p2 > p3
|
||||||
|
diff p3 pogsb.ltl
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue