3 #include <unordered_map>
27 template <Automaton Aut>
31 "minimize: moore: requires Boolean weights");
33 "minimize: moore: requires free labelset");
42 using genset_t = decltype(std::declval<labelset_t>().generators());
49 using set_t = std::vector<state_t>;
54 constexpr
static const char*
me() {
return "minimize-moore"; }
57 constexpr
static class_t class_invalid = -1;
58 unsigned num_classes_ = 0;
75 class_to_set_.clear();
76 state_to_class_.clear();
78 transition_map_.clear();
84 assert(!
set.empty());
86 if (number == class_invalid)
87 number = num_classes_++;
90 state_to_class_[s] = number;
92 if (number < class_to_set_.size())
93 class_to_set_[number] = std::move(set);
96 assert(number == class_to_set_.size());
97 class_to_set_.emplace_back(std::move(set));
107 const auto&
map = transition_map_[s];
108 auto dst =
map.find(l);
109 if (dst == std::end(
map))
110 return class_invalid;
112 return state_to_class_[dst->second.dst];
119 , gs_(a_->labelset()->generators())
132 return class_to_set_;
141 make_class({a_->pre()});
142 make_class({a_->post()});
144 set_t nonfinals, finals;
145 for (
auto s : a_->states())
147 finals.emplace_back(s);
149 nonfinals.emplace_back(s);
150 if (! nonfinals.empty())
151 make_class(std::move(nonfinals));
152 if (! finals.empty())
153 make_class(std::move(finals));
160 for (
class_t c = 0; c < num_classes_; ++c)
162 const set_t& c_states = class_to_set_[c];
168 for (
auto s : c_states)
170 auto c2 = out_class(s, l);
171 target_class_to_c_states[c2].emplace_back(s);
177 if (2 <= target_class_to_c_states.size())
181 for (
auto& p : target_class_to_c_states)
183 make_class(std::move(p.second), num);
200 template <Automaton Aut>
202 std::enable_if_t<!is_free_boolean<Aut>(), quotient_t<Aut>>
205 raise(
"minimize: invalid algorithm"
206 " (non-Boolean or non-free labelset):",
Request for Moore implementation of minimize (B and free).
labelset_t_of< automaton_t > labelset_t
bool is_deterministic(const Aut &aut, state_t_of< Aut > s)
Whether state s is deterministic in aut.
void build_classes_()
Build the initial classes, and split until fix point.
std::unordered_map< state_t, class_t > state_to_class_t
std::unordered_map< class_t, set_t > target_class_to_states_t
void require(Bool b, Args &&...args)
If b is not verified, raise an error with args as message.
Provide a variadic mul on top of a binary mul(), and one().
std::vector< class_t > classes_t
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
std::vector< set_t > class_to_set_t
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
label_t_of< automaton_t > label_t
automaton_t a_
Input automaton, supplied at construction time.
state_to_class_t state_to_class_
class_to_set_t & classes()
The partition, as a list of classes.
minimizer(const Aut &a)
Build the minimizer. Computes the classes.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
class_t make_class(set_t &&set, class_t number=class_invalid)
Make a new class with the given set of states.
transition_map_t transition_map_
state_t_of< automaton_t > state_t
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::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
class_t out_class(state_t s, label_t l)
The destination class of s with l in a.
class_to_set_t class_to_set_
bool is_trim(const Aut &a)
Whether all its states are useful.
decltype(std::declval< labelset_t >().generators()) genset_t
The generators.
static constexpr const char * me()
Request the set implementation (bool weights).
std::vector< state_t > set_t
ATTRIBUTE_NORETURN std::enable_if_t<!is_free_boolean< Aut >), Aut > minimize(const Aut &, brzozowski_tag)
Handling of errors for dyn::minimize.