reduce_parity: expose the internal vectors of colors
* spot/twaalgos/parity.cc, spot/twaalgos/parity.hh: Add a reduce_parity_data class for access to the vectors of colors computed by reduce_parity. * python/spot/impl.i: Add bindings for std::vector<int>.
This commit is contained in:
parent
b0c299b9e9
commit
67722db78f
3 changed files with 64 additions and 35 deletions
|
|
@ -520,6 +520,7 @@ namespace std {
|
||||||
%template(vectorbdd) vector<bdd>;
|
%template(vectorbdd) vector<bdd>;
|
||||||
%template(aliasvector) vector<pair<string, bdd>>;
|
%template(aliasvector) vector<pair<string, bdd>>;
|
||||||
%template(vectorstring) vector<string>;
|
%template(vectorstring) vector<string>;
|
||||||
|
%template(vectorint) vector<int>;
|
||||||
%template(pair_formula_vectorstring) pair<spot::formula, vector<string>>;
|
%template(pair_formula_vectorstring) pair<spot::formula, vector<string>>;
|
||||||
%template(atomic_prop_set) set<spot::formula>;
|
%template(atomic_prop_set) set<spot::formula>;
|
||||||
%template(relabeling_map) map<spot::formula, spot::formula>;
|
%template(relabeling_map) map<spot::formula, spot::formula>;
|
||||||
|
|
|
||||||
|
|
@ -387,27 +387,15 @@ namespace spot
|
||||||
return aut;
|
return aut;
|
||||||
}
|
}
|
||||||
|
|
||||||
twa_graph_ptr
|
reduce_parity_data::reduce_parity_data(const const_twa_graph_ptr& aut,
|
||||||
reduce_parity(const const_twa_graph_ptr& aut, bool colored, bool layered)
|
bool layered)
|
||||||
{
|
{
|
||||||
return reduce_parity_here(make_twa_graph(aut, twa::prop_set::all()),
|
if (!aut->acc().is_parity(parity_max, parity_odd, true))
|
||||||
colored, layered);
|
input_is_not_parity("reduce_parity_data");
|
||||||
}
|
|
||||||
|
|
||||||
twa_graph_ptr
|
|
||||||
reduce_parity_here(twa_graph_ptr aut, bool colored, bool layered)
|
|
||||||
{
|
|
||||||
unsigned num_sets = aut->num_sets();
|
|
||||||
if (!colored && num_sets == 0)
|
|
||||||
return aut;
|
|
||||||
|
|
||||||
bool current_max;
|
|
||||||
bool current_odd;
|
|
||||||
if (!aut->acc().is_parity(current_max, current_odd, true))
|
|
||||||
input_is_not_parity("reduce_parity");
|
|
||||||
if (!aut->is_existential())
|
if (!aut->is_existential())
|
||||||
throw std::runtime_error
|
throw std::runtime_error
|
||||||
("reduce_parity_here() does not support alternation");
|
("reduce_parity_data() does not support alternation");
|
||||||
|
unsigned num_sets = aut->num_sets();
|
||||||
|
|
||||||
// The algorithm assumes "max odd" or "max even" parity. "min"
|
// The algorithm assumes "max odd" or "max even" parity. "min"
|
||||||
// parity is handled by converting it to "max" while the algorithm
|
// parity is handled by converting it to "max" while the algorithm
|
||||||
|
|
@ -466,8 +454,8 @@ namespace spot
|
||||||
//
|
//
|
||||||
// -2 means the edge was never assigned a color.
|
// -2 means the edge was never assigned a color.
|
||||||
unsigned evs = aut->edge_vector().size();
|
unsigned evs = aut->edge_vector().size();
|
||||||
std::vector<int> piprime1(evs, -2); // k=1
|
piprime1.resize(evs, -2); // k=1
|
||||||
std::vector<int> piprime2(evs, -2); // k=0
|
piprime2.resize(evs, -2); // k=0
|
||||||
bool sba = aut->prop_state_acc().is_true();
|
bool sba = aut->prop_state_acc().is_true();
|
||||||
|
|
||||||
auto rec =
|
auto rec =
|
||||||
|
|
@ -481,7 +469,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
int piri; // π(Rᵢ)
|
int piri; // π(Rᵢ)
|
||||||
int color; // corresponding color, to deal with "min" kind
|
int color; // corresponding color, to deal with "min" kind
|
||||||
if (current_max)
|
if (parity_max)
|
||||||
{
|
{
|
||||||
piri = color = si.acc_sets_of(scc).max_set() - 1;
|
piri = color = si.acc_sets_of(scc).max_set() - 1;
|
||||||
}
|
}
|
||||||
|
|
@ -538,11 +526,28 @@ namespace spot
|
||||||
};
|
};
|
||||||
scc_and_mark_filter filter1(aut, {});
|
scc_and_mark_filter filter1(aut, {});
|
||||||
rec(filter1, rec);
|
rec(filter1, rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
twa_graph_ptr
|
||||||
|
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, layered);
|
||||||
|
}
|
||||||
|
|
||||||
|
twa_graph_ptr
|
||||||
|
reduce_parity_here(twa_graph_ptr aut, bool colored, bool layered)
|
||||||
|
{
|
||||||
|
unsigned num_sets = aut->num_sets();
|
||||||
|
if (!colored && num_sets == 0)
|
||||||
|
return aut;
|
||||||
|
|
||||||
|
reduce_parity_data pd(aut, layered);
|
||||||
|
|
||||||
// compute the used range for each vector.
|
// compute the used range for each vector.
|
||||||
int min1 = num_sets;
|
int min1 = num_sets;
|
||||||
int max1 = -2;
|
int max1 = -2;
|
||||||
for (int m : piprime1)
|
for (int m : pd.piprime1)
|
||||||
{
|
{
|
||||||
if (m <= -2)
|
if (m <= -2)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -559,7 +564,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
int min2 = num_sets;
|
int min2 = num_sets;
|
||||||
int max2 = -2;
|
int max2 = -2;
|
||||||
for (int m : piprime2)
|
for (int m : pd.piprime2)
|
||||||
{
|
{
|
||||||
if (m <= -2)
|
if (m <= -2)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -575,13 +580,13 @@ namespace spot
|
||||||
{
|
{
|
||||||
std::swap(size1, size2);
|
std::swap(size1, size2);
|
||||||
std::swap(min1, min2);
|
std::swap(min1, min2);
|
||||||
std::swap(piprime1, piprime2);
|
std::swap(pd.piprime1, pd.piprime2);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned new_num_sets = size1;
|
unsigned new_num_sets = size1;
|
||||||
if (current_max)
|
if (pd.parity_max)
|
||||||
{
|
{
|
||||||
for (int& m : piprime1)
|
for (int& m : pd.piprime1)
|
||||||
if (m > -2)
|
if (m > -2)
|
||||||
m -= min1;
|
m -= min1;
|
||||||
else
|
else
|
||||||
|
|
@ -589,7 +594,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int& m : piprime1)
|
for (int& m : pd.piprime1)
|
||||||
if (m > -2)
|
if (m > -2)
|
||||||
m = new_num_sets - (m - min1) - 1;
|
m = new_num_sets - (m - min1) - 1;
|
||||||
else
|
else
|
||||||
|
|
@ -597,8 +602,8 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
// The parity style changes if we shift colors by an odd number.
|
// The parity style changes if we shift colors by an odd number.
|
||||||
bool new_odd = current_odd ^ (min1 & 1);
|
bool new_odd = pd.parity_odd ^ (min1 & 1);
|
||||||
if (!current_max)
|
if (!pd.parity_max)
|
||||||
// Switching from min<->max changes the parity style every time
|
// Switching from min<->max changes the parity style every time
|
||||||
// the number of colors is even. If the input was "min", we
|
// the number of colors is even. If the input was "min", we
|
||||||
// switched once to "max" to apply the reduction and once again
|
// switched once to "max" to apply the reduction and once again
|
||||||
|
|
@ -607,7 +612,7 @@ namespace spot
|
||||||
new_odd ^= !(num_sets & 1) ^ !(new_num_sets & 1);
|
new_odd ^= !(num_sets & 1) ^ !(new_num_sets & 1);
|
||||||
if (!colored)
|
if (!colored)
|
||||||
{
|
{
|
||||||
new_odd ^= current_max;
|
new_odd ^= pd.parity_max;
|
||||||
new_num_sets -= 1;
|
new_num_sets -= 1;
|
||||||
|
|
||||||
// It seems we have nothing to win by changing automata with a
|
// It seems we have nothing to win by changing automata with a
|
||||||
|
|
@ -617,18 +622,18 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
aut->set_acceptance(new_num_sets,
|
aut->set_acceptance(new_num_sets,
|
||||||
acc_cond::acc_code::parity(current_max, new_odd,
|
acc_cond::acc_code::parity(pd.parity_max, new_odd,
|
||||||
new_num_sets));
|
new_num_sets));
|
||||||
if (colored)
|
if (colored)
|
||||||
for (auto& e: aut->edges())
|
for (auto& e: aut->edges())
|
||||||
{
|
{
|
||||||
unsigned n = aut->edge_number(e);
|
unsigned n = aut->edge_number(e);
|
||||||
e.acc = acc_cond::mark_t({unsigned(piprime1[n])});
|
e.acc = acc_cond::mark_t({unsigned(pd.piprime1[n])});
|
||||||
}
|
}
|
||||||
else if (current_max)
|
else if (pd.parity_max)
|
||||||
for (auto& e: aut->edges())
|
for (auto& e: aut->edges())
|
||||||
{
|
{
|
||||||
unsigned n = piprime1[aut->edge_number(e)];
|
unsigned n = pd.piprime1[aut->edge_number(e)];
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
e.acc = acc_cond::mark_t({});
|
e.acc = acc_cond::mark_t({});
|
||||||
else
|
else
|
||||||
|
|
@ -637,7 +642,7 @@ namespace spot
|
||||||
else
|
else
|
||||||
for (auto& e: aut->edges())
|
for (auto& e: aut->edges())
|
||||||
{
|
{
|
||||||
unsigned n = piprime1[aut->edge_number(e)];
|
unsigned n = pd.piprime1[aut->edge_number(e)];
|
||||||
if (n >= new_num_sets)
|
if (n >= new_num_sets)
|
||||||
e.acc = acc_cond::mark_t({});
|
e.acc = acc_cond::mark_t({});
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <spot/misc/common.hh>
|
#include <spot/misc/common.hh>
|
||||||
#include <spot/twa/fwd.hh>
|
#include <spot/twa/fwd.hh>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
@ -194,5 +195,27 @@ namespace spot
|
||||||
SPOT_API twa_graph_ptr
|
SPOT_API twa_graph_ptr
|
||||||
reduce_parity_here(twa_graph_ptr aut,
|
reduce_parity_here(twa_graph_ptr aut,
|
||||||
bool colored = false, bool layered = false);
|
bool colored = false, bool layered = false);
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// \brief Internal data computed by the reduce_parity function
|
||||||
|
///
|
||||||
|
/// `piprime1` and `piprime2` have the size of `aut`'s edge vector,
|
||||||
|
/// represent two possible colorations of the edges. piprime1 assumes
|
||||||
|
/// that terminal cases of the recursion are odd, and piprime2 assumes
|
||||||
|
/// they are even.
|
||||||
|
///
|
||||||
|
/// reduce_parity() actually compare the range of values in these
|
||||||
|
/// two vectors to limit the number of colors.
|
||||||
|
struct SPOT_API reduce_parity_data
|
||||||
|
{
|
||||||
|
bool parity_max; ///< Whether the input automaton is parity max
|
||||||
|
bool parity_odd; ///< Whether the input automaton is parity odd
|
||||||
|
std::vector<int> piprime1;
|
||||||
|
std::vector<int> piprime2;
|
||||||
|
|
||||||
|
reduce_parity_data(const const_twa_graph_ptr& aut, bool layered = false);
|
||||||
|
};
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue