1 #ifndef VCSN_ALGOS_MINIMIZE_WEIGHTED_HH
2 # define VCSN_ALGOS_MINIMIZE_WEIGHTED_HH
4 # include <unordered_map>
5 # include <unordered_set>
18 namespace detail_weighted
20 template <
typename Aut>
38 using set_t = std::vector<state_t>;
42 constexpr
static const char*
me() {
return "minimize-weighted"; }
81 std::vector<weight_and_state_t>,
105 for (
const auto& wd : wss)
108 const auto& i = res.find(c);
113 i->second =
ws_.add(i->second, wd.first);
114 if (
ws_.is_zero(i->second))
129 : minimizer_(the_minimizer)
130 , num_classes_(num_classes)
137 for (
auto& t : state_output)
140 minimizer_.state_label_output_map(t.weights_and_destinations);
144 std::hash_combine(res, labelset_t::hash(t.label));
145 for (
const auto& cw : map)
147 std::hash_combine(res, cw.first);
148 std::hash_combine(res, weightset_t::hash(cw.second));
163 : minimizer_(the_minimizer)
164 , class_bound_(class_bound)
170 if (a.size() !=
b.size())
172 for (
const auto& cw : a)
174 const auto& cwb =
b.find(cw.first);
177 if (! weightset_t::equals(cw.second, cwb->second))
187 typename state_output_t::const_iterator& i,
194 map = std::move(minimizer_
195 .state_label_output_map(i->weights_and_destinations));
202 typename state_output_t::const_iterator& i,
211 map = std::move(minimizer_
212 .state_label_output_map(i->weights_and_destinations));
227 typename state_output_t::const_iterator ia, ib;
234 ia != as.cend() && ib != bs.cend();
235 next(as, ia, mapa), next(bs, ib, mapb))
236 if (! minimizer_.ls_.equals(ia->label, ib->label)
237 || ! match(mapa, mapb))
240 return (ia == as.cend()) == (ib == bs.cend());
246 :
public std::unordered_map<state_output_t*, set_t,
247 signature_hasher, signature_equal_to>
255 const size_t class_bound)
259 , minimizer_(the_minimizer)
265 class_to_set_.clear();
266 state_to_class_.clear();
273 if (number == class_invalid)
274 number = num_classes_++;
277 state_to_class_[s] = number;
279 if (number < class_to_set_.size())
280 class_to_set_[number] = std::move(set);
283 assert(number == class_to_set_.size());
284 class_to_set_.emplace_back(std::move(set));
293 , ls_(*a_->labelset())
294 , ws_(*a_->weightset())
299 for (
auto s : a_->all_states())
303 for (
auto t : a_->all_out(s))
304 label_to_weights_and_states[a_->label_of(t)]
305 .emplace_back(std::pair<weight_t, state_t>{a_->weight_of(t),
310 for (
auto& l_wss : label_to_weights_and_states)
317 if (l.second <
r.second)
319 else if (
r.second < l.second)
325 std::move(l_wss.second)});
336 std::unordered_set<class_t> classes;
338 const auto& all = a_->all_states();
339 classes.insert(make_class(
set_t{std::begin(all), std::end(all)}));
346 for (
auto i = std::begin(classes), end = std::end(classes);
351 const set_t& c_states = class_to_set_.at(c);
355 if (c_states.size() < 2)
357 i = classes.erase(i);
363 for (
auto s : c_states)
364 signature_to_state[& state_to_state_output_[s]].emplace_back(s);
365 if (2 <= signature_to_state.size())
368 i = classes.erase(i);
369 for (
auto& p: signature_to_state)
371 class_t c2 = make_class(std::move(p.second), c);
393 template <
typename Aut>
405 #endif // !VCSN_ALGOS_MINIMIZE_WEIGHTED_HH
std::enable_if< std::is_same< weightset_t_of< Aut >, b >::value &&labelset_t_of< Aut >::is_free(), partition_automaton< Aut > >::type minimize(const Aut &a, const std::string &algo)
label_to_weights_and_states_t(minimizer &the_minimizer)
weightset_t_of< automaton_t > weightset_t
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
std::vector< weight_and_state_t > weights_and_destinations
bool is_trim(const Aut &a)
Indentation relative functions.
std::vector< state_output_for_label_t > state_output_t
void first(const state_output_t &v, typename state_output_t::const_iterator &i, state_label_output_map_t &map) const
Update the iterator to point to the first non-empty state_output_for_label_t or v.cend(), and update the map to be the one associated to *i, or empty.
state_to_class_t state_to_class_
state_t_of< automaton_t > state_t
label_less(minimizer &the_minimizer)
auto quotient(const Aut &a, typename detail::quotienter< Aut >::class_to_set_t &classes) -> partition_automaton< Aut >
signature_equal_to(minimizer &the_minimizer, size_t class_bound)
label_t_of< automaton_t > label_t
static constexpr class_t class_invalid
An invalid class.
auto minimize_weighted(const Aut &a) -> partition_automaton< Aut >
std::vector< state_t > set_t
signature_multimap(minimizer &the_minimizer, const size_t class_bound)
const state_label_output_map_t state_label_output_map(const std::vector< weight_and_state_t > &wss) const
weight_t_of< automaton_t > weight_t
auto sort(const Aut &a) -> permutation_automaton< Aut >
void next(const state_output_t &v, typename state_output_t::const_iterator &i, state_label_output_map_t &map) const
Update the iterator to point to the next non-empty state_output_for_label_t or v.cend(), and update the map to be the one associated to *i, or empty.
auto map(const std::tuple< Ts...> &ts, Fun f) -> decltype(map_tuple_(f, ts, make_index_sequence< sizeof...(Ts)>()))
Map a function on a tuple, return tuple of the results.
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
std::unordered_map< state_t, class_t > state_to_class_t
std::unordered_map< state_t, state_output_t > state_to_state_output_
bool operator()(const state_output_t *as_, const state_output_t *bs_) const noexcept
void build_classes_()
Build the initial classes, and split until fix point.
static constexpr const char * me()
labelset_t_of< automaton_t > labelset_t
Provide a variadic mul on top of a binary mul(), and one().
const automaton_t & a_
Input automaton, supplied at construction time.
class_to_set_t class_to_set_
bool match(const state_label_output_map_t &a, const state_label_output_map_t &b) const noexcept
std::map< class_t, weight_t > state_label_output_map_t
The output of a given letter from a given state, keeping into account classes and weights...
typename detail::weight_t_of_impl< base_t< ValueSet >>::type weight_t_of
const size_t class_bound_
bool operator()(const label_t &a, const label_t &b) const noexcept
size_t operator()(const state_output_t *state_output_) const noexcept
partition_automaton< automaton_t > operator()()
The minimized automaton.
std::vector< set_t > class_to_set_t
signature_hasher(minimizer &the_minimizer, size_t num_classes)
class_t make_class(set_t &&set, class_t number=class_invalid)
Make a new class with the given set of states.
const minimizer & minimizer_
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
std::shared_ptr< detail::partition_automaton_impl< Aut >> partition_automaton
A partition automaton as a shared pointer.
RatExpSet::value_t less_than(const RatExpSet &rs, const typename RatExpSet::value_t &v)
std::pair< weight_t, state_t > weight_and_state_t
variadic_mul_mixin< detail::r_impl > r
std::unordered_map< state_output_t *, set_t, signature_hasher, signature_equal_to > super_t
void require(bool b, Args &&...args)
If b is not verified, raise an error with args as message.