3 #include <unordered_map>
4 #include <unordered_set>
20 namespace detail_signature
22 template <
typename Aut>
26 "minimize: signature: requires Boolean weights");
39 using set_t = std::vector<state_t>;
43 constexpr
static const char*
me() {
return "minimize-signature"; }
78 for (
auto& t : state_output)
85 for (
auto s : t.to_states)
86 bits.set(state_to_class_.at(s));
111 if (as.size() != bs.size())
115 for (
auto i = as.cbegin(), i_end = as.cend(), j = bs.cbegin();
119 if (! ls_.equal(i->label, j->label))
122 a_bits.reset(); b_bits.reset();
123 for (
auto s : i->to_states)
124 a_bits.set(state_to_class_.at(s));
125 for (
auto s : j->to_states)
126 b_bits.set(state_to_class_.at(s));
127 if (a_bits != b_bits)
156 class_to_set_.clear();
157 state_to_class_.clear();
169 if (number == class_invalid)
170 number = num_classes_++;
173 state_to_class_[s] = number;
175 if (number < class_to_set_.size())
176 class_to_set_[number] = std::move(set);
179 assert(number == class_to_set_.size());
180 class_to_set_.emplace_back(std::move(set));
189 , ls_(*a_->labelset())
194 for (
auto s : a_->all_states())
197 using label_to_states_t
201 label_to_states_t label_to_states;
202 for (
auto t : a_->all_out(s))
203 label_to_states[a_->label_of(t)].emplace_back(a_->dst_of(t));
207 for (
auto& l_ss : label_to_states)
211 std::move(l_ss.second)});
231 std::unordered_set<class_t>
classes;
233 const auto& all = a_->all_states();
234 classes.insert(
make_class(set_t{std::begin(all), std::end(all)}));
237 for (
bool go_on =
true; go_on; )
240 for (
auto i = std::begin(classes), end = std::end(classes);
245 const set_t& c_states = class_to_set_.at(c);
252 signature_equal_to{*
this}};
253 for (
auto s : c_states)
254 sig_to_state[s].emplace_back(s);
256 if (2 <= sig_to_state.size())
260 i = classes.erase(i);
264 for (
auto& p: sig_to_state)
266 bool singleton = p.second.size() == 1;
282 template <
typename Aut>
std::vector< state_t > set_t
state_to_class_t state_to_class_
boost::dynamic_bitset<> dynamic_bitset
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
std::shared_ptr< const detail::label_base > label
partition_automaton_t< Aut > quotient_t
The return type when calling quotient on Aut.
bool operator()(const state_output_t &as, const state_output_t &bs) const noexcept
Functor to compare Values of ValueSets.
state_t_of< automaton_t > state_t
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
auto quotient(const Aut &a, typename detail::quotienter< Aut >::class_to_set_t &cs) -> quotient_t< Aut >
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
std::vector< state_t > to_states
std::unordered_map< state_t, set_t, signature_hasher, signature_equal_to > signature_multimap
Cluster states per signature.
void hash_combine(std::size_t &seed, const T &v)
class_to_set_t & classes()
The partition, as a list of classes.
size_t operator()(const state_output_t &state_output) const noexcept
vcsn::enable_if_t< std::is_same< weightset_t_of< Aut >, b >::value &&labelset_t_of< Aut >::is_free(), quotient_t< Aut > > minimize(const Aut &a, const std::string &algo="auto")
static constexpr class_t class_invalid
An invalid class.
Provide a variadic mul on top of a binary mul(), and one().
class_to_set_t class_to_set_
bool operator()(const state_t &a, const state_t &b) const noexcept
auto minimize_signature(const Aut &a) -> quotient_t< Aut >
void hash_combine_hash(std::size_t &seed, size_t h)
std::unordered_map< state_t, class_t > state_to_class_t
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
signature_equal_to(const minimizer &m)
signature_hasher(const minimizer &m)
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.
const minimizer & minimizer_
automaton_t a_
Input automaton, supplied at construction time.
bool is_trim(const Aut &a)
Whether all its states are useful.
size_t operator()(state_t s) const noexcept
std::vector< set_t > class_to_set_t
label_t_of< automaton_t > label_t
static constexpr const char * me()
std::unordered_map< state_t, state_output_t > state_to_state_output_
Sort of a transition map for each state: state -> vector of (label, destination states).
Indentation relative functions.
const minimizer & minimizer_
class_t make_class(set_t &&set, class_t number=class_invalid)
Make a new class with the given set of states.
auto sort(const Aut &a) -> permutation_automaton< Aut >
std::vector< state_output_for_label_t > state_output_t
void build_classes_()
Build the initial classes, and split until fix point.
labelset_t_of< automaton_t > labelset_t