reduce_parity: add layered option
* spot/twaalgos/parity.cc: Implement it. * spot/twaalgos/parity.hh, NEWS: Document it. * tests/python/parity.ipynb: Demonstrate it. This is the only test so far, but more uses are coming.
This commit is contained in:
parent
eb2616efaa
commit
b0c299b9e9
4 changed files with 357 additions and 165 deletions
|
|
@ -388,14 +388,14 @@ namespace spot
|
|||
}
|
||||
|
||||
twa_graph_ptr
|
||||
reduce_parity(const const_twa_graph_ptr& aut, bool colored)
|
||||
reduce_parity(const const_twa_graph_ptr& aut, bool colored, bool layered)
|
||||
{
|
||||
return reduce_parity_here(make_twa_graph(aut, twa::prop_set::all()),
|
||||
colored);
|
||||
colored, layered);
|
||||
}
|
||||
|
||||
twa_graph_ptr
|
||||
reduce_parity_here(twa_graph_ptr aut, bool colored)
|
||||
reduce_parity_here(twa_graph_ptr aut, bool colored, bool layered)
|
||||
{
|
||||
unsigned num_sets = aut->num_sets();
|
||||
if (!colored && num_sets == 0)
|
||||
|
|
@ -507,15 +507,30 @@ namespace spot
|
|||
m.first += (piri - m.first) & 1;
|
||||
m.second += (piri - m.second) & 1;
|
||||
}
|
||||
for (unsigned state: si.states_of(scc))
|
||||
for (auto& e: aut->out(state))
|
||||
if ((sba || si.scc_of(e.dst) == scc) &&
|
||||
((piri >= 0 && e.acc.has(color)) || (piri < 0 && !e.acc)))
|
||||
{
|
||||
unsigned en = aut->edge_number(e);
|
||||
piprime1[en] = m.first;
|
||||
piprime2[en] = m.second;
|
||||
}
|
||||
// Recolor edges. Depending on LAYERED we want to
|
||||
// either recolor all edges for which piprime1 is -2
|
||||
// (uncolored), or only the edges that we were removed
|
||||
// by the previous filter.
|
||||
auto coloredge = [&](auto& e) {
|
||||
unsigned en = aut->edge_number(e);
|
||||
bool recolor = layered
|
||||
? piprime1[en] == -2
|
||||
: (piri >= 0 && e.acc.has(color)) || (piri < 0 && !e.acc);
|
||||
if (recolor)
|
||||
{
|
||||
piprime1[en] = m.first;
|
||||
piprime2[en] = m.second;
|
||||
}
|
||||
};
|
||||
if (sba)
|
||||
// si.edges_of(scc) would be wrong as it can ignore
|
||||
// outgoing edges removed from a previous level.
|
||||
for (unsigned s: si.states_of(scc))
|
||||
for (auto& e: aut->out(s))
|
||||
coloredge(e);
|
||||
else
|
||||
for (auto& e: si.inner_edges_of(scc))
|
||||
coloredge(e);
|
||||
res.first = std::max(res.first, m.first);
|
||||
res.second = std::max(res.second, m.second);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2016-2019 Laboratoire de Recherche et Développement
|
||||
// Copyright (C) 2016-2019, 2022 Laboratoire de Recherche et Développement
|
||||
// de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
|
|
@ -134,7 +134,6 @@ namespace spot
|
|||
colorize_parity_here(twa_graph_ptr aut, bool keep_style = false);
|
||||
/// @}
|
||||
|
||||
|
||||
/// \brief Reduce the parity acceptance condition to use a minimal
|
||||
/// number of colors.
|
||||
///
|
||||
|
|
@ -149,11 +148,51 @@ namespace spot
|
|||
/// the above paper assumes). Otherwise, the smallest or highest
|
||||
/// colors (depending on the parity kind) is removed to simplify the
|
||||
/// acceptance condition.
|
||||
///
|
||||
/// If the input uses state-based acceptance, the output will use
|
||||
/// state-based acceptance as well.
|
||||
///
|
||||
/// A parity automaton, sometimes called a chain automaton, can be
|
||||
/// seen as a stack of layers that are alternatively rejecting and
|
||||
/// accepting. For instance imagine a parity max automaton that is
|
||||
/// strongly connected. Removing the transitions with the maximal
|
||||
/// color might leave a few transitions that were not labeled by
|
||||
/// this maximal color, but that are part of any cycle anymore:
|
||||
/// those transition could have been colored with the maximal color,
|
||||
/// since any cycle going through them would have seen the maximal
|
||||
/// color. (Once your remove this maximal layer,
|
||||
/// your can define the next layer similarly.)
|
||||
///
|
||||
/// When \a layered is true all transition that belong to the same
|
||||
/// layer receive the same color. When layer is `false`, only the
|
||||
/// transition that where used initially to define the layers (i.e,
|
||||
/// the transition with the maximal color in the previous exemple),
|
||||
/// get their color adjusted. The other will receive either no
|
||||
/// color (if \a colored is false), or a useless color (if \a colored
|
||||
/// is true). Here "useless color" means the smallest color
|
||||
/// for parity max, and the largest color for parity min.
|
||||
///
|
||||
/// When \a layered is true, the output of this function is
|
||||
/// comparable to what acd_transform() would produce. The
|
||||
/// difference is that this function preserve the kind (min/max) of
|
||||
/// parity input, while acd_transform() always output a parity min
|
||||
/// automaton. Additionally, this function needs fewer resources
|
||||
/// than acd_transform() because it is already known that the input
|
||||
/// is a parity automaton. In some (historically inaccurate) way,
|
||||
/// reduce_parity() can be seen as a specialized version of
|
||||
/// acd_transform().
|
||||
///
|
||||
/// The reason layered is false by default, is that not introducing
|
||||
/// colors in place where there where none occasionally help with
|
||||
/// simulation-based reductions.
|
||||
///
|
||||
/// @{
|
||||
SPOT_API twa_graph_ptr
|
||||
reduce_parity(const const_twa_graph_ptr& aut, bool colored = false);
|
||||
reduce_parity(const const_twa_graph_ptr& aut,
|
||||
bool colored = false, bool layered = false);
|
||||
|
||||
SPOT_API twa_graph_ptr
|
||||
reduce_parity_here(twa_graph_ptr aut, bool colored = false);
|
||||
reduce_parity_here(twa_graph_ptr aut,
|
||||
bool colored = false, bool layered = false);
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue