fix several algorithms that incorrectly preserved !weak

This massive set of changes was triggered by issue #546.
In addition to the better handling of !weak, this also adds some
weak properties in a few places.

* spot/twaalgos/product.cc (product_aux): Throw some exception
if an automaton with t or f acceptance has the !weak property.  This
is a cheap sanity check to help detect algorithms that incorrectly
assumed !weak input would necessarily become !weak output.
* spot/twaalgos/hoa.cc (print_hoa): Likewise, also do not assume
that terminal implies very-weak.
* spot/parseaut/parseaut.yy: Add several diagnostics for similar
cases.  E.g., a one-state automaton cannot be declared as !very-weak.
* tests/core/parseaut.test: Check those new diagnostics.
* spot/twa/twa.cc (twa::intersecting_run): Temporary remove the weak
property by setting it to maybe, not to false.
* spot/twaalgos/minimize.cc, spot/twaalgos/parity.cc,
spot/twaalgos/sccfilter.cc, spot/twaalgos/simulation.cc: Account for
the fact that these algorithm may in fact improve the weakness.
* spot/twaalgos/strength.cc: Only look at colors used by the
acceptance condition when deciding weakness.
* spot/twaalgos/synthesis.cc: Declare the strategy as weak.
* bin/randaut.cc: Add weak to automata with t/f acceptance.
* spot/kripke/kripke.hh: Make kripke structures as weak.
* tests/core/acc_word.test, tests/core/alternating.test,
tests/core/complement.test, tests/core/complete.test,
tests/core/ltlsynt.test, tests/core/randomize.test,
tests/core/readsave.test, tests/core/remfin.test,
tests/core/sccsimpl.test, tests/core/strength.test,
tests/core/wdba2.test, tests/ltsmin/kripke.test,
tests/python/automata-io.ipynb, tests/python/automata.ipynb,
tests/python/dbranch.py, tests/python/highlighting.ipynb,
tests/python/kripke.py, tests/python/ltsmin-dve.ipynb,
tests/python/mealy.py, tests/python/simstate.py: Adjust all these test
cases.
* NEWS: Mention the fixes.
This commit is contained in:
Alexandre Duret-Lutz 2023-11-09 22:13:05 +01:00
parent ac05035267
commit 67b5d2aa9a
34 changed files with 287 additions and 164 deletions

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2014-2022 Laboratoire de Recherche et
// Copyright (C) 2014-2023 Laboratoire de Recherche et
// Developpement de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -507,6 +507,11 @@ namespace spot
}
}
if (SPOT_UNLIKELY(aut->prop_weak().is_false()
&& (aut->acc().is_t() || aut->acc().is_f())))
throw std::runtime_error("print_hoa(): automaton is declared not weak, "
"but the acceptance makes this impossible");
metadata md(aut, implicit_labels, state_labels);
if (acceptance == Hoa_Acceptance_States && !md.has_state_acc)
@ -724,7 +729,7 @@ namespace spot
}
if (aut->prop_terminal())
prop(" terminal");
if (aut->prop_very_weak() && (verbose || aut->prop_terminal() != true))
if (aut->prop_very_weak())
prop(" very-weak");
if (aut->prop_weak() && (verbose || (aut->prop_terminal() != true &&
aut->prop_very_weak() != true)))

View file

@ -556,6 +556,16 @@ namespace spot
// add a quick check inside minimize_dfa.
if (a->prop_terminal())
res->prop_terminal(true);
else if (a->num_states() == 1)
{
// If thie automaton has only one state, check w
for (auto& e: a->out(0))
if (e.cond == bddtrue && a->acc().accepting(e.acc))
{
res->prop_terminal(true);
break;
}
}
return res;
}

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2016, 2018, 2019, 2022 Laboratoire de Recherche et
// Copyright (C) 2016, 2018, 2019, 2022, 2023 Laboratoire de Recherche et
// Développement de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -649,6 +649,13 @@ namespace spot
e.acc = acc_cond::mark_t({n});
}
// Reducing the number of colors could turn a non-weak automaton
// into a weak one
if (aut->prop_weak().is_false())
aut->prop_weak(trival::maybe());
if (aut->prop_very_weak().is_false())
aut->prop_very_weak(trival::maybe());
return aut;
}
}

View file

@ -27,6 +27,8 @@
#include <unordered_map>
#include <spot/misc/hash.hh>
using namespace std::string_literals;
namespace spot
{
namespace
@ -102,6 +104,13 @@ namespace spot
enum acc_op { and_acc, or_acc, xor_acc, xnor_acc };
[[noreturn]] static
void report_should_be_weak(const char* what)
{
std::string s = what + " automaton is declared not weak, "
"but the acceptance makes this impossible"s;
throw std::runtime_error(s);
}
static
twa_graph_ptr product_aux(const const_twa_graph_ptr& left,
@ -128,6 +137,13 @@ namespace spot
bool leftweak = left->prop_weak().is_true();
bool rightweak = right->prop_weak().is_true();
if (SPOT_UNLIKELY(!leftweak && left->prop_weak().is_false()
&& (lacc.is_t() || lacc.is_f())))
report_should_be_weak("product: left");
if (SPOT_UNLIKELY(!rightweak && right->prop_weak().is_false()
&& (racc.is_t() || racc.is_f())))
report_should_be_weak("product: right");
// The conjunction of two co-Büchi automata is a co-Büchi automaton.
// The disjunction of two Büchi automata is a Büchi automaton.
//

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2009-2018 Laboratoire de Recherche et Développement
// Copyright (C) 2009-2018, 2023 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -428,6 +428,15 @@ namespace spot
res = scc_filter_apply<state_filter
<acc_filter_mask<false, true>>>(aut, given_si);
res->prop_copy(aut, { true, true, false, true, false, true });
if (res->num_edges() != aut->num_edges())
{
if (res->prop_weak().is_false())
res->prop_weak(trival::maybe());
if (res->prop_very_weak().is_false())
res->prop_very_weak(trival::maybe());
}
if (res->prop_weak().is_true() && res->num_states() <= 1)
res->prop_very_weak(true);
return res;
}
@ -496,6 +505,16 @@ namespace spot
if (!given_si)
delete si;
}
else
if (res->num_edges() != aut->num_edges())
{
if (res->prop_weak().is_false())
res->prop_weak(trival::maybe());
if (res->prop_very_weak().is_false())
res->prop_very_weak(trival::maybe());
}
if (res->prop_weak().is_true() && res->num_states() <= 1)
res->prop_very_weak(true);
return res;
}

View file

@ -761,11 +761,19 @@ namespace spot
delete gb;
res->prop_copy(original_,
{ false, // state-based acc forced below
true, // weakness preserved,
true, // weakness preserved
false, true, // determinism improved
true, // completeness preserved
true, // stutter inv.
});
// weakness can actually be improved
if (res->prop_weak().is_false())
res->prop_weak(trival::maybe());
if (res->prop_very_weak().is_false())
res->prop_very_weak(trival::maybe());
if (res->prop_inherently_weak().is_false())
res->prop_inherently_weak(trival::maybe());
// !unambiguous and !semi-deterministic are not preserved
if (!Cosimulation && nb_minato == nb_minterms)
// Note that nb_minato != nb_minterms does not imply

View file

@ -1,6 +1,6 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2010-2011, 2013-2018 Laboratoire de Recherche et
// Développement de l'Epita (LRDE)
// Copyright (C) 2010-2011, 2013-2018, 2023 Laboratoire de Recherche
// et Développement de l'Epita (LRDE)
//
// This file is part of Spot, a model checking library.
//
@ -43,6 +43,8 @@ namespace spot
if (inweak)
si->determine_unknown_acceptance();
acc_cond::mark_t mask = aut->get_acceptance().used_sets();
bool is_inweak = true;
bool is_weak = true;
bool is_single_state_scc = true;
@ -66,9 +68,9 @@ namespace spot
if (first)
{
first = false;
m = t.acc;
m = t.acc & mask;
}
else if (m != t.acc)
else if (m != (t.acc & mask))
{
is_weak = false;
if (!inweak)

View file

@ -1469,6 +1469,9 @@ namespace spot
edge.acc = {};
}
res->set_acceptance(acc_cond::acc_code::t());
res->prop_weak(true);
if (res->prop_terminal().is_false())
res->prop_terminal(trival::maybe());
res->set_named_prop<bdd>("synthesis-outputs", new bdd(output_bdd));
return ret_sol_exists(res);
@ -1478,6 +1481,7 @@ namespace spot
if (!want_strategy)
return ret_sol_exists(nullptr);
auto res = make_twa_graph(dict);
res->prop_weak(true);
bdd output_bdd = bddtrue;
std::set<formula> ins_f = form2props.aps_of(f_g).first;