17 #ifndef VCSN_ALGORITHMS_MINIMIZATION_HOPCROFT_HXX
18 # define VCSN_ALGORITHMS_MINIMIZATION_HOPCROFT_HXX
26 # include <vaucanson/algebra/implementation/semiring/numerical_semiring.hh>
30 # include <vaucanson/automata/concept/automata_base.hh>
31 # include <vaucanson/misc/usual_macros.hh>
35 # endif // ! VCSN_NDEBUG
42 namespace hopcroft_minimization_det
45 # define HOPCROFT_TYPES() \
46 typedef std::set<hstate_t> hstates_t; \
47 typedef std::vector<hstates_t> partition_t; \
48 typedef std::vector<unsigned> class_of_t; \
49 typedef std::queue<std::pair<hstates_t*, unsigned> > to_treat_t;
54 template <
typename input_t>
57 AUTOMATON_TYPES (input_t);
58 AUTOMATON_FREEMONOID_TYPES (input_t);
61 const input_t& input_;
63 class_of_t& class_of_;
64 std::list<unsigned> maybe_splittable_;
65 std::vector<unsigned> count_for_;
69 : input_ (input), going_in_ (), class_of_(class_of),
70 count_for_ (max_state)
77 maybe_splittable_.clear ();
78 for_all_const_ (hstates_t, i, ss)
80 for (rdelta_iterator t(input_.value(), *i); ! t.done(); t.next())
82 monoid_elt_t w(input_.series_of(*t).structure().monoid(), l);
83 if (input_.series_of(*t).get(w) != input_.series().semiring().wzero_)
85 hstate_t s = input_.src_of(*t);
86 unsigned class_of_state = class_of_[s];
88 if (count_for_[class_of_state] == 0)
89 maybe_splittable_.push_back (class_of_state);
90 count_for_[class_of_state]++;
95 return not going_in_.empty ();
99 void execute (partition_t& partition, to_treat_t& to_treat,
100 unsigned& n_partition)
102 for_all (std::list<unsigned>, inpartition, maybe_splittable_)
104 hstates_t& states = partition[*inpartition];
105 if (states.size () == count_for_[*inpartition])
107 count_for_[*inpartition] = 0;
110 count_for_[*inpartition] = 0;
111 hstates_t states_inter_going_in;
112 hstates_t& states_minus_going_in = partition[n_partition];
115 (states.begin (), states.end (),
116 going_in_.begin (), going_in_.end (),
117 std::insert_iterator<hstates_t> (states_minus_going_in,
118 states_minus_going_in.begin ()));
121 (states.begin(), states.end (),
122 going_in_.begin (), going_in_.end (),
123 std::insert_iterator<hstates_t> (states_inter_going_in,
124 states_inter_going_in.begin ()));
126 assertion (not (states_inter_going_in.empty ()
127 or states_minus_going_in.empty ()));
129 if (states_minus_going_in.size () > states_inter_going_in.size ())
131 states.swap (states_minus_going_in);
132 states_minus_going_in.swap (states_inter_going_in);
135 states.swap (states_inter_going_in);
136 for_all_const_ (hstates_t, istate, states_minus_going_in)
137 class_of_[*istate] = n_partition;
138 to_treat.push (std::make_pair (&states_minus_going_in,
145 template <
typename input_t,
typename output_t>
148 AUTOMATON_TYPES (input_t);
151 const input_t& input_;
153 const class_of_t& class_of_;
158 const class_of_t& class_of)
159 : input_ (input), output_ (output), class_of_ (class_of)
165 src_ = class_of_[representative];
166 for (delta_iterator t(input_.value(), representative); ! t.done(); t.next())
168 output_.add_series_transition (src_, class_of_[input_.dst_of (*t)],
169 input_.series_of (*t));
177 template <
typename A,
typename AI1,
typename AI2>
179 do_hopcroft_minimization_det(
const AutomataBase<A>&,
180 Element<A, AI2>& output,
181 const Element<A, AI1>& input)
183 typedef Element<A, AI1> input_t;
184 typedef Element<A, AI2> output_t;
185 AUTOMATON_TYPES (input_t);
186 AUTOMATON_FREEMONOID_TYPES (input_t);
189 using namespace internal::hopcroft_minimization_det;
193 unsigned max_state = input.states ().back () + 1;
194 partition_t partition (max_state);
195 class_of_t class_of (max_state);
197 unsigned n_partition = 0;
198 const alphabet_t& alphabet =
199 input.structure ().series ().monoid ().alphabet ();
203 hstates_t* finals = 0, * others = 0;
204 int n_finals = -1, n_others = -1,
205 count_finals = 0, count_others = 0;
207 # define add_to_class(Name) \
211 Name = &(partition[n_partition]); \
212 n_ ## Name = n_partition++; \
215 (*Name).insert (*state); \
216 class_of[*state] = n_ ## Name; \
219 for_all_const_states (state, input)
220 if (input.is_final (*state))
221 add_to_class (finals);
223 add_to_class (others);
226 if (n_partition == 0)
228 if (n_partition == 1)
234 if (count_finals > count_others)
235 to_treat.push (std::make_pair (others, n_others));
237 to_treat.push (std::make_pair (finals, n_finals));
241 splitter_functor<input_t> splitter (input, max_state, class_of);
244 while (not to_treat.empty () && n_partition < max_state)
247 hstates_t& states = *(to_treat.front ().first);
251 for_all_const_letters (letter, alphabet)
253 if (not splitter.compute_states_going_in (states, *letter))
255 splitter.execute (partition, to_treat, n_partition);
256 if (n_partition == max_state)
264 for (
unsigned i = 0; i < n_partition; ++i)
267 transition_adder_functor<input_t, output_t>
268 transition_adder (input, output, class_of);
270 typename partition_t::iterator istates = partition.begin ();
271 for (
unsigned i = 0; i < n_partition; ++i, ++istates)
273 hstate_t representative = *(*istates).begin();
275 if (input.is_final (representative))
276 output.set_final (class_of[representative]);
277 transition_adder.execute (representative);
280 for_all_const_initial_states (state, input)
281 output.set_initial (class_of[*state]);
284 # undef HOPCROFT_TYPES
295 template<
typename A,
typename AI>
299 BENCH_TASK_SCOPED(
"minimization_hopcroft");
303 do_hopcroft_minimization_det(a.
structure(), output, a);
313 namespace hopcroft_minimization_undet
316 # define QUOTIENT_TYPES() \
317 typedef std::list<hstate_t> partition_t; \
318 typedef std::vector<partition_t> partition_set_t; \
319 typedef typename partition_t::iterator partition_iterator; \
320 typedef std::vector<unsigned> class_of_t; \
321 typedef std::pair<unsigned, letter_t> pair_t; \
322 typedef std::list<pair_t> to_treat_t;
324 template <
typename input_t>
325 class quotient_splitter
328 AUTOMATON_TYPES(input_t);
329 AUTOMATON_FREEMONOID_TYPES(input_t);
332 typedef std::vector<bool> going_in_t;
334 quotient_splitter (
const automaton_t& input, class_of_t& class_of,
337 alphabet_(input.series().monoid().alphabet()),
339 count_for_(max_states, 0),
340 twin_(max_states, 0),
341 going_in_(max_states, false)
345 bool compute_going_in_states (partition_t& p, letter_t a)
347 for_all_(going_in_t, s, going_in_)
351 semiring_elt_t weight_zero = input_.series().semiring().wzero_;
352 monoid_elt_t w(input_.series().monoid(), a);
354 for_all_(partition_t, s, p)
356 for (rdelta_iterator t(input_.value(), *s); ! t.done(); t.next())
358 series_set_elt_t st = input_.series_of(*t);
359 if (st.get(w) != weight_zero)
361 hstate_t s = input_.src_of(*t);
366 const unsigned i = class_[s];
367 if (count_for_[i] == 0)
368 met_class_.push_back(i);
374 return !met_class_.empty();
378 void split (partition_set_t& parts,
unsigned& max_partitions)
380 for_all_(std::list<unsigned>, klass, met_class_)
383 if (count_for_[*klass] == parts[*klass].size())
386 if (twin_[*klass] == 0)
387 twin_[*klass] = max_partitions++;
388 unsigned new_klass = twin_[*klass];
390 typename partition_t::iterator q;
391 for (
typename partition_t::iterator next = parts[*klass].begin();
392 next != parts[*klass].end();)
398 parts[new_klass].insert(parts[new_klass].end(), *q);
399 class_[*q] = new_klass;
400 parts[*klass].erase(q);
406 void add_new_partitions(to_treat_t& to_treat,
407 const partition_set_t& part)
409 for_all_(std::list<unsigned>, klass, met_class_)
411 if (twin_[*klass] != 0)
413 for_all_const_letters(e, alphabet_)
415 if (find(to_treat.begin(), to_treat.end(), pair_t(*klass, *e)) !=
417 to_treat.push_back(pair_t(twin_[*klass], *e));
419 if (part[*klass].size() < part[twin_[*klass]].size())
420 to_treat.push_back(pair_t(*klass, *e));
422 to_treat.push_back(pair_t(twin_[*klass], *e));
427 for_all_(std::list<unsigned>, klass, met_class_)
429 count_for_[*klass] = 0;
436 const automaton_t& input_;
437 const alphabet_t& alphabet_;
439 std::vector<unsigned> count_for_;
440 std::vector<unsigned> twin_;
441 going_in_t going_in_;
442 std::list<unsigned> met_class_;
447 template <
typename A,
typename AI1,
typename AI2>
449 do_quotient(
const AutomataBase<A>&,
450 const algebra::NumericalSemiring&,
452 Element<A, AI2>& output,
453 const Element<A, AI1>& input)
455 BENCH_TASK_SCOPED(
"do_quotient");
457 typedef Element<A, AI1> input_t;
458 typedef Element<A, AI2> output_t;
459 AUTOMATON_TYPES(input_t);
460 AUTOMATON_FREEMONOID_TYPES(input_t);
463 using namespace internal::hopcroft_minimization_undet;
465 const alphabet_t& alphabet_(input.series().monoid().alphabet());
466 unsigned max_states = 0;
468 for_all_const_states(i, input)
469 max_states = std::max(
unsigned(*i), max_states);
475 unsigned max_partitions = 0;
480 class_of_t class_(max_states);
481 partition_set_t part(max_states);
491 BENCH_TASK_START("initialize partition");
501 for_all_const_states (p, input)
504 if (max_partitions == 0)
507 final = !input.is_final(*p);
511 c = input.is_final(*p) ?
final : (1 -
final);
514 part[c].insert(part[c].end(), *p);
515 max_partitions = std::max(max_partitions, c + 1);
523 BENCH_TASK_START(
"initialize partition");
525 if (max_partitions > 0)
526 for_all_const_letters (e, alphabet_)
527 to_treat.push_back(pair_t(0, *e));
529 if (max_partitions > 1)
530 for_all_const_letters (e, alphabet_)
531 to_treat.push_back(pair_t(1, *e));
538 BENCH_TASK_START("main loop");
540 quotient_splitter<input_t> splitter(input, class_, max_states);
541 while (!to_treat.empty())
543 BENCH_TASK_SCOPED(
"inner loop");
544 pair_t c = to_treat.front();
545 to_treat.pop_front();
546 unsigned p = c.first;
547 letter_t a = c.second;
549 if (!splitter.compute_going_in_states(part[p], a))
552 BENCH_TASK_SCOPED(
"splitter.split");
553 splitter.split(part, max_partitions);
556 BENCH_TASK_SCOPED(
"splitter.add_new_partitions");
557 splitter.add_new_partitions(to_treat, part);
567 BENCH_TASK_START(
"construct output automaton");
570 for (
unsigned i = 0; i < max_partitions; ++i)
573 std::set<unsigned> already_linked;
574 for (
unsigned i = 0; i < max_partitions; ++i)
578 hstate_t s = part[i].front();
580 if (input.is_final(s))
584 for_all_const_letters (e, alphabet_)
586 already_linked.clear();
588 for (delta_iterator t(input.value(), s); ! t.done(); t.next())
590 monoid_elt_t w(input.series_of(*t).structure().monoid(), *e);
591 if (input.series_of(*t).get(w) != input.series().semiring().wzero_)
593 hstate_t out = input.dst_of(*t);
594 unsigned c = class_[out];
595 if (already_linked.find(c) == already_linked.end())
597 already_linked.insert(c);
598 output.add_letter_transition(i, c, *e);
606 for_all_const_initial_states(i, input)
607 output.set_initial(class_[*i]);
612 # undef QUOTIENT_TYPES
619 template <
class S,
class T,
620 typename A,
typename input_t,
typename output_t>
622 do_quotient(
const AutomataBase<A>& ,
626 const input_t& input)
628 AUTOMATON_TYPES(input_t);
629 AUTOMATON_FREEMONOID_TYPES(input_t);
636 typedef set<htransition_t> set_transitions_t;
637 typedef set<hstate_t> set_states_t;
638 typedef set<semiring_elt_t> set_semiring_elt_t;
639 typedef vector<semiring_elt_t> vector_semiring_elt_t;
640 typedef pair<unsigned, letter_t> pair_class_letter_t;
641 typedef pair<hstate_t, semiring_elt_t> pair_state_semiring_elt_t;
642 typedef set<pair_state_semiring_elt_t> set_pair_state_semiring_elt_t;
643 typedef map<semiring_elt_t, unsigned> map_semiring_elt_t;
645 series_set_elt_t null_series = input.series().zero_;
646 semiring_elt_t weight_zero = input.series().semiring().wzero_;
647 monoid_elt_t monoid_identity = input.series().monoid().VCSN_EMPTY_;
648 const alphabet_t& alphabet (input.series().monoid().alphabet());
650 queue<pair_class_letter_t> the_queue;
652 set<unsigned> met_classes;
654 unsigned max_partition = 0;
655 unsigned max_states = 0;
657 for_all_const_states(q, input)
658 max_states = std::max(
unsigned (*q), max_states);
661 max_states = std::max(max_states, 2u);
663 vector< vector<set_pair_state_semiring_elt_t> > inverse (max_states);
665 map<letter_t,
unsigned> pos_of_letter;
667 unsigned max_pos = 0;
669 for_all_const_letters(a, alphabet)
670 pos_of_letter[*a] = max_pos++;
672 set_states_t states_visited;
673 set_semiring_elt_t semiring_had_class;
674 vector<set_states_t> classes (max_states);
675 vector<
unsigned> class_of_state (max_states);
676 vector_semiring_elt_t old_weight (max_states);
677 map_semiring_elt_t class_of_weight;
679 for (
unsigned i = 0; i < max_states; ++i)
680 inverse[i].resize(max_pos);
682 for_all_const_states(q, input)
683 for_all_const_letters(a, alphabet)
686 for_all_const_(set_states_t, r, states_visited)
687 old_weight[*r] = weight_zero;
688 states_visited.clear();
690 for (rdelta_iterator e(input.value(), *q); ! e.done(); e.next())
692 monoid_elt_t w(input.series_of(*e).structure().monoid(), *a);
693 if (input.series_of(*e).get(w) != input.series().semiring().wzero_)
695 hstate_t p = input.src_of(*e);
696 if (states_visited.find(p) != states_visited.end())
697 inverse[*q][pos_of_letter[*a]].
698 erase(pair_state_semiring_elt_t (p, old_weight[p]));
700 states_visited.insert(p);
701 series_set_elt_t sd = input.series_of(*e);
702 monoid_elt_t md (input.structure().series().monoid(), *a);
703 semiring_elt_t wsd = sd.get(md);
704 old_weight[p] += wsd;
705 inverse[*q][pos_of_letter[*a]].
706 insert(pair_state_semiring_elt_t (p, old_weight[p]));
717 unsigned class_non_final (0);
719 for_all_const_states(q, input)
721 if (not input.is_final(*q))
726 class_non_final = max_partition;
729 classes[class_non_final].insert(*q);
730 class_of_state[*q] = class_non_final;
734 semiring_elt_t w = input.get_final(*q).get(monoid_identity);
735 if (semiring_had_class.find(w) == semiring_had_class.end())
737 semiring_had_class.insert(w);
738 classes[max_partition].insert(*q);
739 class_of_weight[w] = max_partition;
740 class_of_state[*q] = max_partition;
745 classes[class_of_weight[w]].insert(*q);
746 class_of_state[*q] = class_of_weight[w];
755 for (
unsigned i = 0; i < max_partition; i++)
756 for_all_const_letters(a, alphabet)
757 the_queue.push(pair_class_letter_t (i, *a));
763 unsigned old_max_partition = max_partition;
765 while(not the_queue.empty())
767 pair_class_letter_t pair = the_queue.front();
770 vector_semiring_elt_t val (max_states);
773 for_all_const_states(q, input)
777 for_all_const_(set_states_t, q, classes[pair.first])
778 for_all_const_(set_pair_state_semiring_elt_t, pair_,
779 inverse[*q][pos_of_letter[pair.second]])
781 unsigned state = pair_->first;
782 if (met_classes.find(class_of_state[state]) ==
784 met_classes.insert(class_of_state[state]);
785 val[state] += pair_->second;
789 for_all_const_(set<unsigned>, class_id, met_classes)
791 if (classes[*class_id].size() == 1)
794 queue<hstate_t> to_erase;
795 semiring_elt_t next_val;
796 semiring_elt_t first_val = val[*(classes[*class_id].begin())];
797 class_of_weight.clear();
798 semiring_had_class.clear();
800 for_all_const_(set_states_t, p, classes[*class_id])
804 if (next_val != first_val)
806 if (semiring_had_class.find(next_val) ==
807 semiring_had_class.end())
809 classes[max_partition].insert(*p);
810 class_of_state[*p] = max_partition;
811 semiring_had_class.insert(next_val);
812 class_of_weight[next_val] = max_partition;
817 classes[class_of_weight[next_val]].insert(*p);
818 class_of_state[*p] = class_of_weight[next_val];
824 while(not to_erase.empty())
826 hstate_t s = to_erase.front();
828 classes[*class_id].erase(s);
832 for (
unsigned i = old_max_partition; i < max_partition; i++)
833 for_all_const_letters(b, alphabet)
834 the_queue.push(pair_class_letter_t(i, *b));
835 old_max_partition = max_partition;
843 typedef vector<series_set_elt_t> vector_series_set_elt_t;
845 std::vector<hstate_t> out_states (max_partition);
848 for(
unsigned i = 0; i < max_partition; i++)
850 out_states[i] = output.add_state();
851 hstate_t a_state = *classes[i].begin();
852 series_set_elt_t a_serie = null_series;
854 for_all_const_(set_states_t, state, classes[i])
855 if(input.is_initial(*state))
856 a_serie += input.get_initial(*state);
858 output.set_initial(out_states[i] , a_serie);
860 if (input.is_final(a_state))
861 output.set_final(out_states[i] , input.get_final(a_state));
865 vector_series_set_elt_t seriesof (max_partition, null_series);
867 for(
unsigned i = 0; i < max_partition; i++)
871 for (delta_iterator e(input.value(), *classes[i].begin()); ! e.done(); e.next())
873 series_set_elt_t se = input.series_of(*e);
874 unsigned cs = class_of_state[input.dst_of(*e)];
876 if (met_classes.find(cs) == met_classes.end())
878 met_classes.insert(cs);
885 for_all_const_(set<unsigned>, cs, met_classes)
886 if (seriesof[*cs] != null_series)
887 output.add_series_transition(out_states[i],
893 template<typename A, typename AI>
897 BENCH_TASK_SCOPED(
"quotient");
900 AUTOMATON_TYPES(automaton_t);
901 automaton_t output(a.structure());
902 do_quotient(a.structure(), a.structure().series().semiring(),
903 SELECT(semiring_elt_value_t), output, a);
909 #endif // ! VCSN_ALGORITHMS_MINIMIZATION_HOPCROFT_HXX