dualize: should not call cleanup_acceptance_here
Based on a report by Emmanuel Filiot, who was surprized that dualizing Büchi did not always produce co-Büchi. * spot/twaalgos/dualize.cc: Remove the call to cleanup_acceptance_here. * spot/twaalgos/dualize.hh: Improve documentation. * NEWS: Mention the possible backward incompatible change. * tests/core/dualize.test, tests/python/dualize.py, tests/python/pdegen.py: Adjust test cases. * spot/twaalgos/complement.cc (complement): Call cleanup_acceptance_here when dualize() returns a smaller automaton. * THANKS: Add Emmanuel.
This commit is contained in:
parent
60f046a574
commit
1b81ecb80c
8 changed files with 67 additions and 23 deletions
|
|
@ -25,6 +25,7 @@
|
|||
#include <spot/twaalgos/postproc.hh>
|
||||
#include <spot/twaalgos/strength.hh>
|
||||
#include <spot/twaalgos/sccinfo.hh>
|
||||
#include <spot/twaalgos/cleanacc.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
|
@ -510,7 +511,19 @@ namespace spot
|
|||
complement(const const_twa_graph_ptr& aut, const output_aborter* aborter)
|
||||
{
|
||||
if (!aut->is_existential() || is_universal(aut))
|
||||
return dualize(aut);
|
||||
{
|
||||
twa_graph_ptr res = dualize(aut);
|
||||
// There are cases with "t" acceptance that get converted to
|
||||
// Büchi during completion, then dualized to co-Büchi, but the
|
||||
// acceptance is still not used. To try to clean it up in this
|
||||
// case.
|
||||
if (aut->num_sets() == 0 ||
|
||||
// Also dualize removes sink states, but doesn't simplify
|
||||
// the acceptance condition.
|
||||
res->num_states() < aut->num_states())
|
||||
cleanup_acceptance_here(res);
|
||||
return res;
|
||||
}
|
||||
if (is_very_weak_automaton(aut))
|
||||
// removing alternation may need more acceptance sets than we support.
|
||||
// in this case res==nullptr and we try the other determinization.
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ namespace spot
|
|||
}
|
||||
if (is_deterministic(aut_))
|
||||
{
|
||||
res = cleanup_acceptance_here(spot::complete(aut_));
|
||||
res = spot::complete(aut_);
|
||||
res->set_acceptance(res->num_sets(),
|
||||
res->get_acceptance().complement());
|
||||
// Complementing the acceptance is likely to break the terminal
|
||||
|
|
@ -368,8 +368,6 @@ namespace spot
|
|||
res->prop_terminal(trival::maybe());
|
||||
if (!has_sink)
|
||||
res->prop_complete(true);
|
||||
|
||||
cleanup_acceptance_here(res);
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,23 +26,50 @@ namespace spot
|
|||
/// \ingroup twa_misc
|
||||
/// \brief Complement an automaton by dualizing it.
|
||||
///
|
||||
/// Given an automaton \a aut of any type, produces the dual as output. The
|
||||
/// automaton will be completed if it isn't already. If it is deterministic
|
||||
/// and complete, complementing the automaton can be done by just
|
||||
/// complementing the acceptance condition.
|
||||
/// Given an automaton \a aut of any type, produces the dual as
|
||||
/// output. Before dualization, the automaton will be completed if
|
||||
/// it isn't already, but any sink state in the output might then be
|
||||
/// removed.
|
||||
///
|
||||
/// In particular, this implies that an input that use generalized Büchi will
|
||||
/// be output as generalized co-Büchi.
|
||||
/// Dualizing the automaton is done by interpreting the outgoing
|
||||
/// transitions of a state as a Boolean function, and then swapping
|
||||
/// operators ∧ and ̇∨. This first step does not have to be done on
|
||||
/// deterministic automata. Additionally, the acceptance condition
|
||||
/// is dualized by swapping operators ∧ and ̇∨, and swapping Inf and
|
||||
/// Fin.
|
||||
///
|
||||
/// Functions like to_generalized_buchi() or remove_fin() are frequently
|
||||
/// called on existential automata after dualize() to obtain an easier
|
||||
/// acceptance condition, but maybe at the cost of losing determinism.
|
||||
/// For instance, the dual of a generalized Büchi automaton will be
|
||||
/// a generalized co-Büchi automaton.
|
||||
///
|
||||
/// If the input acceptance condition accepts every infinite path
|
||||
/// (such as "t" or "Inf(0)|Fin(0)") and the automaton is not
|
||||
/// complete, then the input automaton will be assumed to have Büchi
|
||||
/// acceptance in order to complete it, and the output will then
|
||||
/// have co-Büchi acceptance.
|
||||
///
|
||||
/// Due to a defect in the way transition-based alternating automata
|
||||
/// are represented in Spot and in the HOA format, existential
|
||||
/// automata with transition-based acceptance will be converted to
|
||||
/// use state-based acceptance before dualization. See
|
||||
/// https://github.com/adl/hoaf/issues/68 for more information.
|
||||
///
|
||||
/// If the input automaton is deterministic, the output will be deterministic.
|
||||
/// If the input automaton is existential, the output will be universal.
|
||||
/// If the input automaton is universal, the output will be existential.
|
||||
/// Finally, if the input automaton is alternating, the result is alternating.
|
||||
/// More can be found on page 22 (Definition 1.6) of \cite loding.98.msc .
|
||||
///
|
||||
/// Functions like to_generalized_buchi() or remove_fin() are frequently
|
||||
/// called on existential automata after dualize() to obtain an easier
|
||||
/// acceptance condition, but maybe at the cost of losing determinism.
|
||||
///
|
||||
/// Up to version 2.11.6, this function used to call
|
||||
/// cleanup_acceptance_here() to simplify the acceptance condition
|
||||
/// after dualization. This caused some surprizes, users expected
|
||||
/// the dual of a Büchi automaton to be a co-Büchi automaton, but
|
||||
/// cleanup_acceptance_here() sometimes reduced the condition to `t`
|
||||
/// when all states where accepting. This function is not called
|
||||
/// anymore since version 2.12.
|
||||
SPOT_API twa_graph_ptr
|
||||
dualize(const const_twa_graph_ptr& aut);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue