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
7
NEWS
7
NEWS
|
|
@ -148,6 +148,13 @@ New in spot 2.11.6.dev (not yet released)
|
||||||
should raise an exception of return nullptr if it requires more
|
should raise an exception of return nullptr if it requires more
|
||||||
acceptance sets than supported.
|
acceptance sets than supported.
|
||||||
|
|
||||||
|
- [Potential backward incompatibility] spot::dualize() does not call
|
||||||
|
cleanup_acceptance() anymore. This change ensures that the dual
|
||||||
|
of a Büchi automaton will always be a co-Büchi automaton.
|
||||||
|
Previously cleanup_acceptance(), which remove unused colors from
|
||||||
|
the acceptance, was sometimes able to simplify co-Büchi to "t",
|
||||||
|
causing surprizes.
|
||||||
|
|
||||||
Python:
|
Python:
|
||||||
|
|
||||||
- The spot.automata() and spot.automaton() functions now accept a
|
- The spot.automata() and spot.automaton() functions now accept a
|
||||||
|
|
|
||||||
1
THANKS
1
THANKS
|
|
@ -15,6 +15,7 @@ David Dokoupil
|
||||||
David Müller
|
David Müller
|
||||||
Dávid Smolka
|
Dávid Smolka
|
||||||
Edmond Irani Liu
|
Edmond Irani Liu
|
||||||
|
Emmanuel Filiot
|
||||||
Ernesto Posse
|
Ernesto Posse
|
||||||
Étienne Renault
|
Étienne Renault
|
||||||
Fabrice Kordon
|
Fabrice Kordon
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include <spot/twaalgos/postproc.hh>
|
#include <spot/twaalgos/postproc.hh>
|
||||||
#include <spot/twaalgos/strength.hh>
|
#include <spot/twaalgos/strength.hh>
|
||||||
#include <spot/twaalgos/sccinfo.hh>
|
#include <spot/twaalgos/sccinfo.hh>
|
||||||
|
#include <spot/twaalgos/cleanacc.hh>
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
@ -510,7 +511,19 @@ namespace spot
|
||||||
complement(const const_twa_graph_ptr& aut, const output_aborter* aborter)
|
complement(const const_twa_graph_ptr& aut, const output_aborter* aborter)
|
||||||
{
|
{
|
||||||
if (!aut->is_existential() || is_universal(aut))
|
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))
|
if (is_very_weak_automaton(aut))
|
||||||
// removing alternation may need more acceptance sets than we support.
|
// removing alternation may need more acceptance sets than we support.
|
||||||
// in this case res==nullptr and we try the other determinization.
|
// in this case res==nullptr and we try the other determinization.
|
||||||
|
|
|
||||||
|
|
@ -308,7 +308,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
if (is_deterministic(aut_))
|
if (is_deterministic(aut_))
|
||||||
{
|
{
|
||||||
res = cleanup_acceptance_here(spot::complete(aut_));
|
res = spot::complete(aut_);
|
||||||
res->set_acceptance(res->num_sets(),
|
res->set_acceptance(res->num_sets(),
|
||||||
res->get_acceptance().complement());
|
res->get_acceptance().complement());
|
||||||
// Complementing the acceptance is likely to break the terminal
|
// Complementing the acceptance is likely to break the terminal
|
||||||
|
|
@ -368,8 +368,6 @@ namespace spot
|
||||||
res->prop_terminal(trival::maybe());
|
res->prop_terminal(trival::maybe());
|
||||||
if (!has_sink)
|
if (!has_sink)
|
||||||
res->prop_complete(true);
|
res->prop_complete(true);
|
||||||
|
|
||||||
cleanup_acceptance_here(res);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -26,23 +26,50 @@ namespace spot
|
||||||
/// \ingroup twa_misc
|
/// \ingroup twa_misc
|
||||||
/// \brief Complement an automaton by dualizing it.
|
/// \brief Complement an automaton by dualizing it.
|
||||||
///
|
///
|
||||||
/// Given an automaton \a aut of any type, produces the dual as output. The
|
/// Given an automaton \a aut of any type, produces the dual as
|
||||||
/// automaton will be completed if it isn't already. If it is deterministic
|
/// output. Before dualization, the automaton will be completed if
|
||||||
/// and complete, complementing the automaton can be done by just
|
/// it isn't already, but any sink state in the output might then be
|
||||||
/// complementing the acceptance condition.
|
/// removed.
|
||||||
///
|
///
|
||||||
/// In particular, this implies that an input that use generalized Büchi will
|
/// Dualizing the automaton is done by interpreting the outgoing
|
||||||
/// be output as generalized co-Büchi.
|
/// 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
|
/// For instance, the dual of a generalized Büchi automaton will be
|
||||||
/// called on existential automata after dualize() to obtain an easier
|
/// a generalized co-Büchi automaton.
|
||||||
/// acceptance condition, but maybe at the cost of losing determinism.
|
///
|
||||||
|
/// 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 deterministic, the output will be deterministic.
|
||||||
/// If the input automaton is existential, the output will be universal.
|
/// If the input automaton is existential, the output will be universal.
|
||||||
/// If the input automaton is universal, the output will be existential.
|
/// If the input automaton is universal, the output will be existential.
|
||||||
/// Finally, if the input automaton is alternating, the result is alternating.
|
/// 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 .
|
/// 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
|
SPOT_API twa_graph_ptr
|
||||||
dualize(const const_twa_graph_ptr& aut);
|
dualize(const const_twa_graph_ptr& aut);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,7 @@ HOA: v1
|
||||||
States: 2
|
States: 2
|
||||||
Start: 0
|
Start: 0
|
||||||
AP: 2 "a" "b"
|
AP: 2 "a" "b"
|
||||||
acc-name: all
|
Acceptance: 3 (Fin(0)|Fin(1)) | Inf(2)
|
||||||
Acceptance: 0 t
|
|
||||||
properties: trans-labels explicit-labels trans-acc complete
|
properties: trans-labels explicit-labels trans-acc complete
|
||||||
properties: deterministic
|
properties: deterministic
|
||||||
--BODY--
|
--BODY--
|
||||||
|
|
@ -114,8 +113,7 @@ HOA: v1
|
||||||
States: 9
|
States: 9
|
||||||
Start: 8
|
Start: 8
|
||||||
AP: 2 "p0" "p1"
|
AP: 2 "p0" "p1"
|
||||||
acc-name: co-Buchi
|
Acceptance: 2 Fin(0) & Fin(1)
|
||||||
Acceptance: 1 Fin(0)
|
|
||||||
properties: trans-labels explicit-labels state-acc univ-branch
|
properties: trans-labels explicit-labels state-acc univ-branch
|
||||||
--BODY--
|
--BODY--
|
||||||
State: 0
|
State: 0
|
||||||
|
|
@ -148,8 +146,7 @@ HOA: v1
|
||||||
States: 9
|
States: 9
|
||||||
Start: 8
|
Start: 8
|
||||||
AP: 2 "p0" "p1"
|
AP: 2 "p0" "p1"
|
||||||
acc-name: co-Buchi
|
Acceptance: 2 Fin(0) & Fin(1)
|
||||||
Acceptance: 1 Fin(0)
|
|
||||||
properties: trans-labels explicit-labels state-acc univ-branch
|
properties: trans-labels explicit-labels state-acc univ-branch
|
||||||
Alias: @a 0&!1
|
Alias: @a 0&!1
|
||||||
Alias: @b !0&!1
|
Alias: @b !0&!1
|
||||||
|
|
|
||||||
|
|
@ -191,8 +191,8 @@ tc.assertEqual(h, """HOA: v1
|
||||||
States: 2
|
States: 2
|
||||||
Start: 1
|
Start: 1
|
||||||
AP: 2 "a" "b"
|
AP: 2 "a" "b"
|
||||||
acc-name: all
|
acc-name: co-Buchi
|
||||||
Acceptance: 0 t
|
Acceptance: 1 Fin(0)
|
||||||
properties: trans-labels explicit-labels state-acc deterministic
|
properties: trans-labels explicit-labels state-acc deterministic
|
||||||
--BODY--
|
--BODY--
|
||||||
State: 0
|
State: 0
|
||||||
|
|
@ -227,8 +227,7 @@ tc.assertEqual(h, """HOA: v1
|
||||||
States: 2
|
States: 2
|
||||||
Start: 1
|
Start: 1
|
||||||
AP: 2 "a" "b"
|
AP: 2 "a" "b"
|
||||||
acc-name: all
|
Acceptance: 2 Fin(0) & Fin(1)
|
||||||
Acceptance: 0 t
|
|
||||||
properties: trans-labels explicit-labels state-acc deterministic
|
properties: trans-labels explicit-labels state-acc deterministic
|
||||||
--BODY--
|
--BODY--
|
||||||
State: 0
|
State: 0
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,8 @@ tc.assertEqual(dd.num_states(), 1)
|
||||||
tc.assertEqual(str(dd.get_acceptance()), 'Inf(1) & Fin(0)')
|
tc.assertEqual(str(dd.get_acceptance()), 'Inf(1) & Fin(0)')
|
||||||
|
|
||||||
e = spot.dualize(b)
|
e = spot.dualize(b)
|
||||||
|
spot.cleanup_acceptance_here(e)
|
||||||
|
tc.assertEqual(str(e.get_acceptance()), 'Fin(0)|Fin(1)')
|
||||||
de = spot.partial_degeneralize(e, [0, 1])
|
de = spot.partial_degeneralize(e, [0, 1])
|
||||||
tc.assertTrue(de.equivalent_to(e))
|
tc.assertTrue(de.equivalent_to(e))
|
||||||
tc.assertEqual(de.num_states(), 4)
|
tc.assertEqual(de.num_states(), 4)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue