hoa: add option 'b' to build an alias-based basis for all labels
Related to issue #563. * spot/twaalgos/hoa.hh (create_alias_basis): New function. * spot/twaalgos/hoa.cc (create_alias_basis): New function. (print_hoa): Add support for option 'b' and create_alias_basis in this case. * bin/common_aoutput.cc, NEWS: Document -Hb. * tests/core/readsave.test, tests/python/aliases.py: Add test cases.
This commit is contained in:
parent
03a4f01184
commit
7e228e86ee
6 changed files with 129 additions and 12 deletions
|
|
@ -20,6 +20,7 @@
|
|||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <spot/twa/twa.hh>
|
||||
#include <spot/twa/twagraph.hh>
|
||||
|
|
@ -30,6 +31,7 @@
|
|||
#include <spot/tl/formula.hh>
|
||||
#include <spot/kripke/fairkripke.hh>
|
||||
#include <spot/kripke/kripkegraph.hh>
|
||||
#include <spot/twaalgos/split.hh>
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
|
|
@ -70,7 +72,8 @@ namespace spot
|
|||
if (bdd_is_cube(a))
|
||||
alias_cubes_.emplace_back(a, i);
|
||||
bdd neg = !a;
|
||||
aliases_map_[neg.id()] = i;
|
||||
// do not overwrite an existing alias with a negation
|
||||
aliases_map_.emplace(neg.id(), i);
|
||||
if (bdd_is_cube(neg))
|
||||
alias_cubes_.emplace_back(neg, i);
|
||||
}
|
||||
|
|
@ -464,6 +467,7 @@ namespace spot
|
|||
bool verbose = false;
|
||||
bool state_labels = false;
|
||||
bool v1_1 = false;
|
||||
bool alias_basis = false;
|
||||
|
||||
if (opt)
|
||||
while (*opt)
|
||||
|
|
@ -486,6 +490,9 @@ namespace spot
|
|||
v1_1 = false;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
alias_basis = true;
|
||||
break;
|
||||
case 'i':
|
||||
implicit_labels = true;
|
||||
break;
|
||||
|
|
@ -520,6 +527,27 @@ namespace spot
|
|||
throw std::runtime_error("print_hoa(): automaton is declared not weak, "
|
||||
"but the acceptance makes this impossible");
|
||||
|
||||
// If we were asked to create an alias basis, make sure we save
|
||||
// existing aliases, so we can restore it before we exit this
|
||||
// function.
|
||||
std::vector<std::pair<std::string, bdd>> old_aliases;
|
||||
if (aut->ap().size() <= 1)
|
||||
alias_basis = false;
|
||||
if (alias_basis)
|
||||
{
|
||||
if (auto* aliases = get_aliases(aut))
|
||||
old_aliases = *aliases;
|
||||
create_alias_basis(std::const_pointer_cast<twa_graph>(aut));
|
||||
}
|
||||
// restore the old aliases using a unique_ptr-based scope guard,
|
||||
// because there are too many ways to exit this function.
|
||||
auto restore_aliases = [&old_aliases, alias_basis, aut](void*) {
|
||||
if (alias_basis)
|
||||
set_aliases(std::const_pointer_cast<twa_graph>(aut), old_aliases);
|
||||
};
|
||||
std::unique_ptr<void, decltype(restore_aliases)>
|
||||
restore_aliases_guard((void*)1, restore_aliases);
|
||||
|
||||
metadata md(aut, implicit_labels, state_labels);
|
||||
|
||||
if (acceptance == Hoa_Acceptance_States && !md.has_state_acc)
|
||||
|
|
@ -1013,7 +1041,8 @@ namespace spot
|
|||
}
|
||||
|
||||
void
|
||||
set_aliases(twa_ptr g, std::vector<std::pair<std::string, bdd>> aliases)
|
||||
set_aliases(twa_ptr g,
|
||||
const std::vector<std::pair<std::string, bdd>>& aliases)
|
||||
{
|
||||
if (aliases.empty())
|
||||
{
|
||||
|
|
@ -1027,4 +1056,17 @@ namespace spot
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
create_alias_basis(const twa_graph_ptr& aut)
|
||||
{
|
||||
edge_separator es;
|
||||
es.add_to_basis(aut);
|
||||
std::vector<std::pair<std::string, bdd>> aliases;
|
||||
unsigned n = 0;
|
||||
for (bdd b: es.basis())
|
||||
aliases.emplace_back(std::to_string(n++), b);
|
||||
std::reverse(aliases.begin(), aliases.end());
|
||||
set_aliases(aut, aliases);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ namespace spot
|
|||
/// \param os The output stream to print on.
|
||||
/// \param g The automaton to output.
|
||||
/// \param opt a set of characters each corresponding to a possible
|
||||
/// option: (i) implicit labels for complete and
|
||||
/// option: (b) create an alias basis if more >=2 AP
|
||||
/// are used, (i) implicit labels for complete and
|
||||
/// deterministic automata, (k) state labels when possible,
|
||||
/// (s) state-based acceptance when possible, (t)
|
||||
/// transition-based acceptance, (m) mixed acceptance, (l)
|
||||
|
|
@ -62,7 +63,8 @@ namespace spot
|
|||
///
|
||||
/// Pass an empty vector to remove existing aliases.
|
||||
SPOT_API void
|
||||
set_aliases(twa_ptr g, std::vector<std::pair<std::string, bdd>> aliases);
|
||||
set_aliases(twa_ptr g,
|
||||
const std::vector<std::pair<std::string, bdd>>& aliases);
|
||||
|
||||
/// \ingroup twa_io
|
||||
/// \brief Help printing BDDs as text, using aliases.
|
||||
|
|
@ -164,4 +166,18 @@ namespace spot
|
|||
}
|
||||
};
|
||||
|
||||
/// \ingroup twa_io
|
||||
/// \brief Create an alias basis
|
||||
///
|
||||
/// This use spot::edge_separator to build a set of alias that can
|
||||
/// be used as a basis for all labels of the automaton.
|
||||
///
|
||||
/// Such a basis can be used to shorten the size of an output file
|
||||
/// when printing in HOA format (actually, calling print_hoa() with
|
||||
/// option 'b' will call this function). Such a basis may also be
|
||||
/// useful to help visualize an automaton (using spot::print_dot's
|
||||
/// `@` option) when its labels are too large.
|
||||
SPOT_API void
|
||||
create_alias_basis(const twa_graph_ptr& aut);
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue