introduce the original-classes named property

* doc/org/concepts.org, NEWS: Document it.
* spot/twaalgos/determinize.cc, spot/twaalgos/determinize.hh,
spot/twaalgos/sbacc.cc, spot/twaalgos/sbacc.hh: Use it.
* spot/twa/twagraph.cc: Update it on defrag.
* spot/twa/twa.cc (copy_named_properties_of): Copy it.
* tests/python/det.py: New file.
* tests/Makefile.am: Add it.
* python/spot/impl.i (get_original_states, get_original_classes): New
methods, to help with the tests.
This commit is contained in:
Alexandre Duret-Lutz 2021-12-17 17:51:06 +01:00
parent d8f245a7de
commit 20bcc216a0
11 changed files with 170 additions and 35 deletions

View file

@ -548,6 +548,35 @@ namespace spot
return res;
}
std::vector<unsigned>*
classify(const power_set& states,
const std::vector<unsigned>* original_class)
{
unsigned sz = states.size();
auto classes = new std::vector<unsigned>(sz);
std::vector<std::set<unsigned>> state_sets(sz);
for (const auto& p: states)
{
// Get the set of original stats of this
std::set<unsigned> s;
for (auto& n: p.first.nodes_)
{
unsigned st = n.first;
if (original_class)
st = (*original_class)[st];
s.insert(st);
}
state_sets[p.second] = std::move(s);
}
std::map<std::set<unsigned>, unsigned> seensets;
for (unsigned s = 0; s < sz; ++s)
{
auto p = seensets.emplace(state_sets[s], s);
(*classes)[s] = p.first->second;
}
return classes;
}
class safra_support
{
const std::vector<bdd>& state_supports;
@ -812,7 +841,8 @@ namespace spot
bool pretty_print, bool use_scc,
bool use_simulation, bool use_stutter,
const output_aborter* aborter,
int trans_pruning)
int trans_pruning,
bool want_classes)
{
if (!a->is_existential())
throw std::runtime_error
@ -996,6 +1026,27 @@ namespace spot
if (pretty_print)
res->set_named_prop("state-names", print_debug(aut, seen));
if (want_classes)
{
auto* ptr =
aut->get_named_prop<std::vector<unsigned>>("original-states");
if (ptr && ptr->size() != aut->num_states())
throw std::runtime_error("tgba_determinize(): "
"input's \"original-states\" property "
"has unexpected size");
if (!ptr)
{
ptr =
aut->get_named_prop<std::vector<unsigned>>("original-classes");
if (ptr && ptr->size() != aut->num_states())
throw std::runtime_error("tgba_determinize(): "
"input's \"original-classes\" property "
"has unexpected size");
}
res->set_named_prop("original-classes", classify(seen, ptr));
}
return res;
}
}

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2015-2016, 2019-2020 Laboratoire de Recherche et
// Copyright (C) 2015-2016, 2019-2021 Laboratoire de Recherche et
// Développement de l'Epita.
//
// This file is part of Spot, a model checking library.
@ -81,6 +81,14 @@ namespace spot
/// \param trans_pruning when \a use_simulation is true, \a trans_pruning
/// is passed to the simulation-based reduction to limit
/// the effect of transition pruning.
///
/// \param want_classes If set, define a "original-class" named property
/// as a vector of unsigned. If two states are associated
/// to the same integer, it means they use the same subset
/// of original states as support, so they recognize the
/// same language. If the input define an "original-state"
/// property (or else an "original-class" property), it is
/// taken into account while computing the above support.
SPOT_API twa_graph_ptr
tgba_determinize(const const_twa_graph_ptr& aut,
bool pretty_print = false,
@ -88,5 +96,6 @@ namespace spot
bool use_simulation = true,
bool use_stutter = true,
const output_aborter* aborter = nullptr,
int trans_pruning = -1);
int trans_pruning = -1,
bool want_classes = false);
}

View file

@ -95,7 +95,6 @@ namespace spot
std::vector<std::pair<pair_t, unsigned>> todo;
auto* origin = new std::vector<unsigned>;
origin->reserve(ns);
res->set_named_prop("original-states", origin);
auto new_state =
[&](unsigned state, acc_cond::mark_t m) -> unsigned
@ -186,11 +185,27 @@ namespace spot
}
res->merge_edges();
// Compose original-states with the any previously existing one.
if (auto old_orig_states =
old->get_named_prop<std::vector<unsigned>>("original-states"))
for (auto& s: *origin)
s = (*old_orig_states)[s];
// if we had some origin-classes, compose them, and output that
// instead of original-states.
if (auto old_orig_classes =
old->get_named_prop<std::vector<unsigned>>("original-classes"))
{
for (auto& s: *origin)
s = (*old_orig_classes)[s];
res->set_named_prop("original-classes", origin);
}
else
{
// Otherwise, define original-states, and compose it with any
// previously existing one.
if (auto old_orig_states =
old->get_named_prop<std::vector<unsigned>>("original-states"))
for (auto& s: *origin)
s = (*old_orig_states)[s];
res->set_named_prop("original-states", origin);
}
// If the automaton was marked as not complete or not universal,
// and we have ignored some unreachable state, then it is possible

View file

@ -49,5 +49,10 @@ namespace spot
/// vectors will be composed, so the `original-states[s]` in the
/// output will contains the value of `original-states[y] if state s
/// was created from state y.
///
/// If the input has a property named "original-classes", then the
/// above "original-state" property is replaced by an
/// "original-classes" property such that
/// original-classes[s] is the class of the original state of s.
SPOT_API twa_graph_ptr sbacc(twa_graph_ptr aut);
}