remove_alternation: option to return nullptr if too many sets needed

* spot/twaalgos/alternation.hh, spot/twaalgos/alternation.cc: Add the
new options.
* spot/twaalgos/complement.cc, spot/twaalgos/minimize.cc: Use it.
* tests/core/optba.test: Add a test case from Yann.
* NEWS: Mention those changes.
This commit is contained in:
Alexandre Duret-Lutz 2024-01-24 16:11:25 +01:00
parent 9957aa1a3a
commit 690e5a213d
6 changed files with 857 additions and 7 deletions

View file

@ -347,7 +347,8 @@ namespace spot
}
twa_graph_ptr run(bool named_states, const output_aborter* aborter)
twa_graph_ptr run(bool named_states, const output_aborter* aborter,
bool raise_if_too_many_sets)
{
// First, we classify each SCC into three possible classes:
//
@ -356,6 +357,10 @@ namespace spot
// 3) rejecting of size >1
classify_each_scc();
if (!raise_if_too_many_sets &&
(has_reject_more_ + reject_1_count_) > SPOT_MAX_ACCSETS)
return nullptr;
// Rejecting SCCs of size 1 can be handled using genralized
// Büchi acceptance, using one set per SCC, as in Gastin &
// Oddoux CAV'01. See also Boker & et al. ICALP'10. Larger
@ -367,6 +372,7 @@ namespace spot
// We preserve deterministic-like properties, and
// stutter-invariance.
res->prop_copy(aut_, {false, false, false, true, true, true});
// This will raise an exception if we request too many sets.
res->set_generalized_buchi(has_reject_more_ + reject_1_count_);
// We for easier computation of outgoing sets, we will
@ -502,14 +508,15 @@ namespace spot
twa_graph_ptr remove_alternation(const const_twa_graph_ptr& aut,
bool named_states,
const output_aborter* aborter)
const output_aborter* aborter,
bool raise_if_too_many_sets)
{
if (aut->is_existential())
// Nothing to do, why was this function called at all?
return std::const_pointer_cast<twa_graph>(aut);
alternation_remover ar(aut);
return ar.run(named_states, aborter);
return ar.run(named_states, aborter, raise_if_too_many_sets);
}

View file

@ -100,12 +100,17 @@ namespace spot
/// \param named_states name each state for easier debugging
///
/// \param aborter Return nullptr if the built automaton would
/// be larger than the size specified by the \a aborter.
/// be larger than the size specified by the \a aborter, or
/// if it would require too many acceptance sets.
///
/// \param raise_if_too_many_sets when set to false, return
/// nullptr in cases where we would need too many colors
/// @}
SPOT_API
twa_graph_ptr remove_alternation(const const_twa_graph_ptr& aut,
bool named_states = false,
const output_aborter* aborter = nullptr);
const output_aborter* aborter = nullptr,
bool raise_if_too_many_sets = true);
// Remove universal edges on the fly.

View file

@ -512,7 +512,11 @@ namespace spot
if (!aut->is_existential() || is_universal(aut))
return dualize(aut);
if (is_very_weak_automaton(aut))
return remove_alternation(dualize(aut), aborter);
// removing alternation may need more acceptance sets than we support.
// in this case res==nullptr and we try the other determinization.
if (twa_graph_ptr res = remove_alternation(dualize(aut), false,
aborter, false))
return res;
// Determinize
spot::option_map m;
if (aborter)

View file

@ -681,7 +681,10 @@ namespace spot
else if (is_very_weak_automaton(aut_f))
{
// Very weak automata are easy to complement.
aut_neg_f = remove_alternation(dualize(aut_f));
aut_neg_f = remove_alternation(dualize(aut_f), false,
nullptr, false);
if (!aut_neg_f) // this required too many colors
return nullptr;
}
else
{