hoa: extract the alias formating code for reuse

* spot/twaalgos/hoa.hh (hoa_alias_formater): New class.
* spot/twaalgos/hoa.cc: Implement hoa_alias_formater using the code
that was previously in metadata::encode_label, and use it in place.
This commit is contained in:
Alexandre Duret-Lutz 2022-02-03 14:09:01 +01:00
parent f759697e1c
commit 4506643632
2 changed files with 321 additions and 196 deletions

View file

@ -24,6 +24,7 @@
#include <spot/twa/fwd.hh>
#include <vector>
#include <utility>
#include <functional>
#include <bddx.h>
namespace spot
@ -62,4 +63,105 @@ 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);
/// \ingroup twa_io
/// \brief Help printing BDDs as text, using aliases.
class SPOT_API hoa_alias_formater final
{
public:
typedef std::vector<std::pair<std::string, bdd>> aliases_t;
private:
aliases_t* aliases_;
std::unordered_map<int, unsigned> aliases_map_;
std::vector<std::pair<bdd, unsigned>> alias_cubes_;
const char* false_str_;
const char* true_str_;
const char* or_str_;
const char* and_str_;
const char* not_str_;
const char* lpar_str_;
const char* rpar_str_;
std::function<std::string(int)> ap_printer_;
public:
/// \brief Initialize this class from the aliases defined
/// for an automaton.
///
/// The aliases are taken from the named-property "aliases",
/// defined in the automaton. If no such named-property exist,
/// the aliases() method will return a null pointer.
///
/// Note that any alias that uses an atomic proposition not
/// registered in the automaton is not only ignored, but also
/// removed from the alias list stored in the automaton.
///
/// The \a or_str, \a and_str, and \ap_printer arguments are
/// used to print operators OR, AND, and to print atomic propositions
/// that are not aliases. \a lpar_str and \a rpar_str are used
/// to group conjuncts that appear in a disjunction.
hoa_alias_formater(const const_twa_graph_ptr& aut,
const char* false_str,
const char* true_str,
const char* or_str,
const char* and_str,
const char* not_str,
const char* lpar_str,
const char* rpar_str,
std::function<std::string(int)> ap_printer);
/// \brief Attempt to format a BDD label using aliases.
///
/// The returned pair should be interpreted as a disjunction
/// between an expression involving aliases, and a BDD that could
/// not be expressed using aliases.
///
/// The conversion works in several attempts, in the following order:
///
/// - If an alias A exists for \a label, `"@A"` is returned.
///
/// - If an alias A exists for the negation of \a label, `"!@A`
/// is returned.
///
/// - If \a label is true or false, `true_str` or `false_str`
/// are returned as specified at construction.
///
/// - If \a label can be built as a disjunction of positive
/// aliases, such a disjunction is returned as `"@A | @B | @C"`.
///
/// - If \a label can be built from a conjunction of
/// aliases or negated aliases, it is returned as
/// `"@A&!@B&@C"`. Note that this check first
/// attempt to use aliases that represent cubes before trying
/// other aliases.
///
/// - Otherwise \a label is split in irredundant-sum-of-products
/// and each clause is encoded as a conjunctions of (possibly
/// negated) aliases using only those that are cubes. Any
/// remaining literal is encoded with the ap_printer() function
/// passed to the constructor.
///
/// The aliases to be used are those returned by the aliases()
/// method. The vector returned by aliases() is scanned from
/// position \a aliases_start. As this vector is stored in the
/// opposite order of how aliases should be stored in the HOA
/// output, adjusting \a aliases_start is helpful to encode an
/// aliases using only previously defined aliases (i.e., aliases
/// that appear later in the sequence returned by aliases()).
std::string
encode_label(bdd label, unsigned aliases_start = 0);
/// \brief Retrieve the list of aliases.
///
/// This points to the same list that the automaton's "aliasaes"
/// named properties points to. Will return `nullptr` if no
/// aliases are defined.
///
/// \note Aliases involving atomic propositions that are not
/// declared in the automaton have been removed by this class'
/// constructor.
aliases_t* aliases()
{
return aliases_;
}
};
}