00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef VCSN_ALGORITHMS_MINIMIZATION_HOPCROFT_HXX
00018 # define VCSN_ALGORITHMS_MINIMIZATION_HOPCROFT_HXX
00019
00020 # include <algorithm>
00021 # include <list>
00022 # include <queue>
00023 # include <set>
00024 # include <vector>
00025
00026 # include <vaucanson/algebra/implementation/semiring/numerical_semiring.hh>
00027 # include <vaucanson/algorithms/minimization_hopcroft.hh>
00028 # include <vaucanson/algorithms/is_deterministic.hh>
00029 # include <vaucanson/algorithms/complete.hh>
00030 # include <vaucanson/automata/concept/automata_base.hh>
00031 # include <vaucanson/misc/usual_macros.hh>
00032
00033 # ifndef VCSN_NDEBUG
00034 # include <vaucanson/algorithms/is_deterministic.hh>
00035 # endif // ! VCSN_NDEBUG
00036
00037 namespace vcsn
00038 {
00039
00040 namespace internal
00041 {
00042 namespace hopcroft_minimization_det
00043 {
00044
00045 # define HOPCROFT_TYPES() \
00046 typedef std::set<hstate_t> hstates_t; \
00047 typedef std::vector<hstates_t> partition_t; \
00048 typedef std::vector<unsigned> class_of_t; \
00049 typedef std::queue<std::pair<hstates_t*, unsigned> > to_treat_t;
00050
00054 template <typename input_t>
00055 struct splitter_functor
00056 {
00057 AUTOMATON_TYPES (input_t);
00058 AUTOMATON_FREEMONOID_TYPES (input_t);
00059 HOPCROFT_TYPES ();
00060
00061 const input_t& input_;
00062 hstates_t going_in_;
00063 class_of_t& class_of_;
00064 std::list<unsigned> maybe_splittable_;
00065 std::vector<unsigned> count_for_;
00066
00067 splitter_functor (const input_t& input, unsigned int max_state,
00068 class_of_t& class_of)
00069 : input_ (input), going_in_ (), class_of_(class_of),
00070 count_for_ (max_state)
00071 {}
00072
00074 bool compute_states_going_in (const hstates_t& ss, letter_t l)
00075 {
00076 going_in_.clear ();
00077 maybe_splittable_.clear ();
00078 for_all_const_ (hstates_t, i, ss)
00079 {
00080 for (rdelta_iterator t(input_.value(), *i); ! t.done(); t.next())
00081 {
00082 monoid_elt_t w(input_.series_of(*t).structure().monoid(), l);
00083 if (input_.series_of(*t).get(w) != input_.series().semiring().wzero_)
00084 {
00085 hstate_t s = input_.src_of(*t);
00086 unsigned class_of_state = class_of_[s];
00087
00088 if (count_for_[class_of_state] == 0)
00089 maybe_splittable_.push_back (class_of_state);
00090 count_for_[class_of_state]++;
00091 going_in_.insert (s);
00092 }
00093 }
00094 }
00095 return not going_in_.empty ();
00096 }
00097
00099 void execute (partition_t& partition, to_treat_t& to_treat,
00100 unsigned& n_partition)
00101 {
00102 for_all (std::list<unsigned>, inpartition, maybe_splittable_)
00103 {
00104 hstates_t& states = partition[*inpartition];
00105 if (states.size () == count_for_[*inpartition])
00106 {
00107 count_for_[*inpartition] = 0;
00108 continue;
00109 }
00110 count_for_[*inpartition] = 0;
00111 hstates_t states_inter_going_in;
00112 hstates_t& states_minus_going_in = partition[n_partition];
00113
00114 set_difference
00115 (states.begin (), states.end (),
00116 going_in_.begin (), going_in_.end (),
00117 std::insert_iterator<hstates_t> (states_minus_going_in,
00118 states_minus_going_in.begin ()));
00119
00120 set_intersection
00121 (states.begin(), states.end (),
00122 going_in_.begin (), going_in_.end (),
00123 std::insert_iterator<hstates_t> (states_inter_going_in,
00124 states_inter_going_in.begin ()));
00125
00126 assertion (not (states_inter_going_in.empty ()
00127 or states_minus_going_in.empty ()));
00128
00129 if (states_minus_going_in.size () > states_inter_going_in.size ())
00130 {
00131 states.swap (states_minus_going_in);
00132 states_minus_going_in.swap (states_inter_going_in);
00133 }
00134 else
00135 states.swap (states_inter_going_in);
00136 for_all_const_ (hstates_t, istate, states_minus_going_in)
00137 class_of_[*istate] = n_partition;
00138 to_treat.push (std::make_pair (&states_minus_going_in,
00139 n_partition++));
00140 }
00141 }
00142 };
00143
00145 template <typename input_t, typename output_t>
00146 struct transition_adder_functor
00147 {
00148 AUTOMATON_TYPES (input_t);
00149 HOPCROFT_TYPES ();
00150
00151 const input_t& input_;
00152 output_t& output_;
00153 const class_of_t& class_of_;
00154
00155 unsigned src_;
00156
00157 transition_adder_functor (const input_t& input, output_t& output,
00158 const class_of_t& class_of)
00159 : input_ (input), output_ (output), class_of_ (class_of)
00160 {}
00161
00163 void execute (hstate_t representative)
00164 {
00165 src_ = class_of_[representative];
00166 for (delta_iterator t(input_.value(), representative); ! t.done(); t.next())
00167 {
00168 output_.add_series_transition (src_, class_of_[input_.dst_of (*t)],
00169 input_.series_of (*t));
00170 }
00171 }
00172 };
00173 }
00174 }
00175
00176
00177 template <typename A, typename AI1, typename AI2>
00178 void
00179 do_hopcroft_minimization_det(const AutomataBase<A>&,
00180 Element<A, AI2>& output,
00181 const Element<A, AI1>& input)
00182 {
00183 typedef Element<A, AI1> input_t;
00184 typedef Element<A, AI2> output_t;
00185 AUTOMATON_TYPES (input_t);
00186 AUTOMATON_FREEMONOID_TYPES (input_t);
00187 HOPCROFT_TYPES ();
00188
00189 using namespace internal::hopcroft_minimization_det;
00190
00191 precondition(is_deterministic(input));
00192
00193 unsigned max_state = input.states ().back () + 1;
00194 partition_t partition (max_state);
00195 class_of_t class_of (max_state);
00196 to_treat_t to_treat;
00197 unsigned n_partition = 0;
00198 const alphabet_t& alphabet =
00199 input.structure ().series ().monoid ().alphabet ();
00200
00201 {
00202
00203 hstates_t* finals = 0, * others = 0;
00204 int n_finals = -1, n_others = -1,
00205 count_finals = 0, count_others = 0;
00206
00207 # define add_to_class(Name) \
00208 do { \
00209 if (not Name) \
00210 { \
00211 Name = &(partition[n_partition]); \
00212 n_ ## Name = n_partition++; \
00213 } \
00214 count_ ## Name ++; \
00215 (*Name).insert (*state); \
00216 class_of[*state] = n_ ## Name; \
00217 } while (0)
00218
00219 for_all_const_states (state, input)
00220 if (input.is_final (*state))
00221 add_to_class (finals);
00222 else
00223 add_to_class (others);
00224 # undef add_to_class
00225
00226 if (n_partition == 0)
00227 return;
00228 if (n_partition == 1)
00229 {
00230 output = input;
00231 return;
00232 }
00233
00234 if (count_finals > count_others)
00235 to_treat.push (std::make_pair (others, n_others));
00236 else
00237 to_treat.push (std::make_pair (finals, n_finals));
00238 }
00239
00240 {
00241 splitter_functor<input_t> splitter (input, max_state, class_of);
00242
00243
00244 while (not to_treat.empty () && n_partition < max_state)
00245 {
00246
00247 hstates_t& states = *(to_treat.front ().first);
00248 to_treat.pop ();
00249
00250
00251 for_all_const_letters (letter, alphabet)
00252 {
00253 if (not splitter.compute_states_going_in (states, *letter))
00254 continue;
00255 splitter.execute (partition, to_treat, n_partition);
00256 if (n_partition == max_state)
00257 break;
00258 }
00259 }
00260 }
00261
00262
00263
00264 for (unsigned i = 0; i < n_partition; ++i)
00265 output.add_state ();
00266
00267 transition_adder_functor<input_t, output_t>
00268 transition_adder (input, output, class_of);
00269
00270 typename partition_t::iterator istates = partition.begin ();
00271 for (unsigned i = 0; i < n_partition; ++i, ++istates)
00272 {
00273 hstate_t representative = *(*istates).begin();
00274
00275 if (input.is_final (representative))
00276 output.set_final (class_of[representative]);
00277 transition_adder.execute (representative);
00278 }
00279
00280 for_all_const_initial_states (state, input)
00281 output.set_initial (class_of[*state]);
00282 }
00283
00284 # undef HOPCROFT_TYPES
00285
00295 template<typename A, typename AI>
00296 Element<A, AI>
00297 minimization_hopcroft(const Element<A, AI>& a)
00298 {
00299 BENCH_TASK_SCOPED("minimization_hopcroft");
00300 precondition(is_deterministic(a));
00301 precondition(is_complete(a));
00302 Element<A, AI> output(a.structure());
00303 do_hopcroft_minimization_det(a.structure(), output, a);
00304 return output;
00305 }
00306
00307
00308
00309
00310
00311 namespace internal
00312 {
00313 namespace hopcroft_minimization_undet
00314 {
00315
00316 # define QUOTIENT_TYPES() \
00317 typedef std::list<hstate_t> partition_t; \
00318 typedef std::vector<partition_t> partition_set_t; \
00319 typedef typename partition_t::iterator partition_iterator; \
00320 typedef std::vector<unsigned> class_of_t; \
00321 typedef std::pair<unsigned, letter_t> pair_t; \
00322 typedef std::list<pair_t> to_treat_t;
00323
00324 template <typename input_t>
00325 class quotient_splitter
00326 {
00327 public:
00328 AUTOMATON_TYPES(input_t);
00329 AUTOMATON_FREEMONOID_TYPES(input_t);
00330 QUOTIENT_TYPES();
00331
00332 typedef std::vector<bool> going_in_t;
00333
00334 quotient_splitter (const automaton_t& input, class_of_t& class_of,
00335 unsigned max_states)
00336 : input_(input),
00337 alphabet_(input.series().monoid().alphabet()),
00338 class_(class_of),
00339 count_for_(max_states, 0),
00340 twin_(max_states, 0),
00341 going_in_(max_states, false)
00342 { }
00343
00345 bool compute_going_in_states (partition_t& p, letter_t a)
00346 {
00347 for_all_(going_in_t, s, going_in_)
00348 *s = false;
00349
00350
00351 semiring_elt_t weight_zero = input_.series().semiring().wzero_;
00352 monoid_elt_t w(input_.series().monoid(), a);
00353
00354 for_all_(partition_t, s, p)
00355 {
00356 for (rdelta_iterator t(input_.value(), *s); ! t.done(); t.next())
00357 {
00358 series_set_elt_t st = input_.series_of(*t);
00359 if (st.get(w) != weight_zero)
00360 {
00361 hstate_t s = input_.src_of(*t);
00362 if (!going_in_[s])
00363 {
00365 going_in_[s] = true;
00366 const unsigned i = class_[s];
00367 if (count_for_[i] == 0)
00368 met_class_.push_back(i);
00369 count_for_[i]++;
00370 }
00371 }
00372 }
00373 }
00374 return !met_class_.empty();
00375 }
00376
00378 void split (partition_set_t& parts, unsigned& max_partitions)
00379 {
00380 for_all_(std::list<unsigned>, klass, met_class_)
00381 {
00382
00383 if (count_for_[*klass] == parts[*klass].size())
00384 continue;
00385
00386 if (twin_[*klass] == 0)
00387 twin_[*klass] = max_partitions++;
00388 unsigned new_klass = twin_[*klass];
00389
00390 typename partition_t::iterator q;
00391 for (typename partition_t::iterator next = parts[*klass].begin();
00392 next != parts[*klass].end();)
00393 {
00394 q = next;
00395 ++next;
00396 if (going_in_[*q])
00397 {
00398 parts[new_klass].insert(parts[new_klass].end(), *q);
00399 class_[*q] = new_klass;
00400 parts[*klass].erase(q);
00401 }
00402 }
00403 }
00404 }
00405
00406 void add_new_partitions(to_treat_t& to_treat,
00407 const partition_set_t& part)
00408 {
00409 for_all_(std::list<unsigned>, klass, met_class_)
00410 {
00411 if (twin_[*klass] != 0)
00412 {
00413 for_all_const_letters(e, alphabet_)
00414 {
00415 if (find(to_treat.begin(), to_treat.end(), pair_t(*klass, *e)) !=
00416 to_treat.end())
00417 to_treat.push_back(pair_t(twin_[*klass], *e));
00418 else
00419 if (part[*klass].size() < part[twin_[*klass]].size())
00420 to_treat.push_back(pair_t(*klass, *e));
00421 else
00422 to_treat.push_back(pair_t(twin_[*klass], *e));
00423 }
00424 }
00425 }
00426
00427 for_all_(std::list<unsigned>, klass, met_class_)
00428 {
00429 count_for_[*klass] = 0;
00430 twin_[*klass] = 0;
00431 }
00432 met_class_.clear();
00433 }
00434
00435 private:
00436 const automaton_t& input_;
00437 const alphabet_t& alphabet_;
00438 class_of_t& class_;
00439 std::vector<unsigned> count_for_;
00440 std::vector<unsigned> twin_;
00441 going_in_t going_in_;
00442 std::list<unsigned> met_class_;
00443 };
00444 }
00445 }
00446
00447 template <typename A, typename AI1, typename AI2>
00448 void
00449 do_quotient(const AutomataBase<A>&,
00450 const algebra::NumericalSemiring&,
00451 SELECTOR(bool),
00452 Element<A, AI2>& output,
00453 const Element<A, AI1>& input)
00454 {
00455 BENCH_TASK_SCOPED("do_quotient");
00456
00457 typedef Element<A, AI1> input_t;
00458 typedef Element<A, AI2> output_t;
00459 AUTOMATON_TYPES(input_t);
00460 AUTOMATON_FREEMONOID_TYPES(input_t);
00461 QUOTIENT_TYPES();
00462
00463 using namespace internal::hopcroft_minimization_undet;
00464
00465 const alphabet_t& alphabet_(input.series().monoid().alphabet());
00466 unsigned max_states = 0;
00467
00468 for_all_const_states(i, input)
00469 max_states = std::max(unsigned(*i), max_states);
00470 ++max_states;
00471
00472
00473
00474
00475 unsigned max_partitions = 0;
00476
00477
00478
00479
00480 class_of_t class_(max_states);
00481 partition_set_t part(max_states);
00482
00483
00484
00485
00486 to_treat_t to_treat;
00487
00488
00489
00490
00491 BENCH_TASK_START("initialize partition");
00492
00493
00494
00495
00496
00497
00498
00499 unsigned final = 1;
00500
00501 for_all_const_states (p, input)
00502 {
00503 unsigned c;
00504 if (max_partitions == 0)
00505 {
00506 c = 0;
00507 final = !input.is_final(*p);
00508 }
00509 else
00510 {
00511 c = input.is_final(*p) ? final : (1 - final);
00512 }
00513 class_[*p] = c;
00514 part[c].insert(part[c].end(), *p);
00515 max_partitions = std::max(max_partitions, c + 1);
00516 }
00517
00518 BENCH_TASK_STOP();
00519
00520
00521
00522
00523 BENCH_TASK_START("initialize partition");
00524
00525 if (max_partitions > 0)
00526 for_all_const_letters (e, alphabet_)
00527 to_treat.push_back(pair_t(0, *e));
00528
00529 if (max_partitions > 1)
00530 for_all_const_letters (e, alphabet_)
00531 to_treat.push_back(pair_t(1, *e));
00532
00533 BENCH_TASK_STOP();
00534
00535
00536
00537
00538 BENCH_TASK_START("main loop");
00539 {
00540 quotient_splitter<input_t> splitter(input, class_, max_states);
00541 while (!to_treat.empty())
00542 {
00543 BENCH_TASK_SCOPED("inner loop");
00544 pair_t c = to_treat.front();
00545 to_treat.pop_front();
00546 unsigned p = c.first;
00547 letter_t a = c.second;
00548
00549 if (!splitter.compute_going_in_states(part[p], a))
00550 continue;
00551 {
00552 BENCH_TASK_SCOPED("splitter.split");
00553 splitter.split(part, max_partitions);
00554 }
00555 {
00556 BENCH_TASK_SCOPED("splitter.add_new_partitions");
00557 splitter.add_new_partitions(to_treat, part);
00558 }
00559 }
00560 }
00561
00562 BENCH_TASK_STOP();
00563
00564
00565
00566
00567 BENCH_TASK_START("construct output automaton");
00568
00569
00570 for (unsigned i = 0; i < max_partitions; ++i)
00571 output.add_state();
00572
00573 std::set<unsigned> already_linked;
00574 for (unsigned i = 0; i < max_partitions; ++i)
00575 {
00576
00577
00578 hstate_t s = part[i].front();
00579
00580 if (input.is_final(s))
00581 output.set_final(i);
00582
00583
00584 for_all_const_letters (e, alphabet_)
00585 {
00586 already_linked.clear();
00587
00588 for (delta_iterator t(input.value(), s); ! t.done(); t.next())
00589 {
00590 monoid_elt_t w(input.series_of(*t).structure().monoid(), *e);
00591 if (input.series_of(*t).get(w) != input.series().semiring().wzero_)
00592 {
00593 hstate_t out = input.dst_of(*t);
00594 unsigned c = class_[out];
00595 if (already_linked.find(c) == already_linked.end())
00596 {
00597 already_linked.insert(c);
00598 output.add_letter_transition(i, c, *e);
00599 }
00600 }
00601 }
00602 }
00603 }
00604
00605
00606 for_all_const_initial_states(i, input)
00607 output.set_initial(class_[*i]);
00608
00609 BENCH_TASK_STOP();
00610 }
00611
00612 # undef QUOTIENT_TYPES
00613
00614
00615
00616
00617
00618
00619 template <class S, class T,
00620 typename A, typename input_t, typename output_t>
00621 void
00622 do_quotient(const AutomataBase<A>& ,
00623 const S& ,
00624 const T& ,
00625 output_t& output,
00626 const input_t& input)
00627 {
00628 AUTOMATON_TYPES(input_t);
00629 AUTOMATON_FREEMONOID_TYPES(input_t);
00630 using namespace std;
00631
00632
00633
00634
00635
00636 typedef set<htransition_t> set_transitions_t;
00637 typedef set<hstate_t> set_states_t;
00638 typedef set<semiring_elt_t> set_semiring_elt_t;
00639 typedef vector<semiring_elt_t> vector_semiring_elt_t;
00640 typedef pair<unsigned, letter_t> pair_class_letter_t;
00641 typedef pair<hstate_t, semiring_elt_t> pair_state_semiring_elt_t;
00642 typedef set<pair_state_semiring_elt_t> set_pair_state_semiring_elt_t;
00643 typedef map<semiring_elt_t, unsigned> map_semiring_elt_t;
00644
00645 series_set_elt_t null_series = input.series().zero_;
00646 semiring_elt_t weight_zero = input.series().semiring().wzero_;
00647 monoid_elt_t monoid_identity = input.series().monoid().VCSN_EMPTY_;
00648 const alphabet_t& alphabet (input.series().monoid().alphabet());
00649
00650 queue<pair_class_letter_t> the_queue;
00651
00652 set<unsigned> met_classes;
00653
00654 unsigned max_partition = 0;
00655 unsigned max_states = 0;
00656
00657 for_all_const_states(q, input)
00658 max_states = std::max(unsigned (*q), max_states);
00659 ++max_states;
00660
00661 max_states = std::max(max_states, 2u);
00662
00663 vector< vector<set_pair_state_semiring_elt_t> > inverse (max_states);
00664
00665 map<letter_t, unsigned> pos_of_letter;
00666
00667 unsigned max_pos = 0;
00668
00669 for_all_const_letters(a, alphabet)
00670 pos_of_letter[*a] = max_pos++;
00671
00672 set_states_t states_visited;
00673 set_semiring_elt_t semiring_had_class;
00674 vector<set_states_t> classes (max_states);
00675 vector<unsigned> class_of_state (max_states);
00676 vector_semiring_elt_t old_weight (max_states);
00677 map_semiring_elt_t class_of_weight;
00678
00679 for (unsigned i = 0; i < max_states; ++i)
00680 inverse[i].resize(max_pos);
00681
00682 for_all_const_states(q, input)
00683 for_all_const_letters(a, alphabet)
00684 {
00685
00686 for_all_const_(set_states_t, r, states_visited)
00687 old_weight[*r] = weight_zero;
00688 states_visited.clear();
00689
00690 for (rdelta_iterator e(input.value(), *q); ! e.done(); e.next())
00691 {
00692 monoid_elt_t w(input.series_of(*e).structure().monoid(), *a);
00693 if (input.series_of(*e).get(w) != input.series().semiring().wzero_)
00694 {
00695 hstate_t p = input.src_of(*e);
00696 if (states_visited.find(p) != states_visited.end())
00697 inverse[*q][pos_of_letter[*a]].
00698 erase(pair_state_semiring_elt_t (p, old_weight[p]));
00699 else
00700 states_visited.insert(p);
00701 series_set_elt_t sd = input.series_of(*e);
00702 monoid_elt_t md (input.structure().series().monoid(), *a);
00703 semiring_elt_t wsd = sd.get(md);
00704 old_weight[p] += wsd;
00705 inverse[*q][pos_of_letter[*a]].
00706 insert(pair_state_semiring_elt_t (p, old_weight[p]));
00707 }
00708 }
00709 }
00710
00711
00712
00713
00714
00715
00716 bool empty = true;
00717 unsigned class_non_final (0);
00718
00719 for_all_const_states(q, input)
00720 {
00721 if (not input.is_final(*q))
00722 {
00723 if (empty == true)
00724 {
00725 empty = false;
00726 class_non_final = max_partition;
00727 max_partition++;
00728 }
00729 classes[class_non_final].insert(*q);
00730 class_of_state[*q] = class_non_final;
00731 }
00732 else
00733 {
00734 semiring_elt_t w = input.get_final(*q).get(monoid_identity);
00735 if (semiring_had_class.find(w) == semiring_had_class.end())
00736 {
00737 semiring_had_class.insert(w);
00738 classes[max_partition].insert(*q);
00739 class_of_weight[w] = max_partition;
00740 class_of_state[*q] = max_partition;
00741 max_partition++;
00742 }
00743 else
00744 {
00745 classes[class_of_weight[w]].insert(*q);
00746 class_of_state[*q] = class_of_weight[w];
00747 }
00748 }
00749 }
00750
00751
00752
00753
00754
00755 for (unsigned i = 0; i < max_partition; i++)
00756 for_all_const_letters(a, alphabet)
00757 the_queue.push(pair_class_letter_t (i, *a));
00758
00759
00760
00761
00762
00763 unsigned old_max_partition = max_partition;
00764
00765 while(not the_queue.empty())
00766 {
00767 pair_class_letter_t pair = the_queue.front();
00768 the_queue.pop();
00769 met_classes.clear();
00770 vector_semiring_elt_t val (max_states);
00771
00772
00773 for_all_const_states(q, input)
00774 val[*q] = 0;
00775
00776
00777 for_all_const_(set_states_t, q, classes[pair.first])
00778 for_all_const_(set_pair_state_semiring_elt_t, pair_,
00779 inverse[*q][pos_of_letter[pair.second]])
00780 {
00781 unsigned state = pair_->first;
00782 if (met_classes.find(class_of_state[state]) ==
00783 met_classes.end())
00784 met_classes.insert(class_of_state[state]);
00785 val[state] += pair_->second;
00786 }
00787
00788
00789 for_all_const_(set<unsigned>, class_id, met_classes)
00790 {
00791 if (classes[*class_id].size() == 1)
00792 continue ;
00793
00794 queue<hstate_t> to_erase;
00795 semiring_elt_t next_val;
00796 semiring_elt_t first_val = val[*(classes[*class_id].begin())];
00797 class_of_weight.clear();
00798 semiring_had_class.clear();
00799
00800 for_all_const_(set_states_t, p, classes[*class_id])
00801 {
00802 next_val = val[*p];
00803
00804 if (next_val != first_val)
00805 {
00806 if (semiring_had_class.find(next_val) ==
00807 semiring_had_class.end())
00808 {
00809 classes[max_partition].insert(*p);
00810 class_of_state[*p] = max_partition;
00811 semiring_had_class.insert(next_val);
00812 class_of_weight[next_val] = max_partition;
00813 max_partition++;
00814 }
00815 else
00816 {
00817 classes[class_of_weight[next_val]].insert(*p);
00818 class_of_state[*p] = class_of_weight[next_val];
00819 }
00820 to_erase.push(*p);
00821 }
00822 }
00823
00824 while(not to_erase.empty())
00825 {
00826 hstate_t s = to_erase.front();
00827 to_erase.pop();
00828 classes[*class_id].erase(s);
00829 }
00830
00831
00832 for (unsigned i = old_max_partition; i < max_partition; i++)
00833 for_all_const_letters(b, alphabet)
00834 the_queue.push(pair_class_letter_t(i, *b));
00835 old_max_partition = max_partition;
00836 }
00837 }
00838
00839
00840
00841
00842
00843 typedef vector<series_set_elt_t> vector_series_set_elt_t;
00844
00845 std::vector<hstate_t> out_states (max_partition);
00846
00847
00848 for(unsigned i = 0; i < max_partition; i++)
00849 {
00850 out_states[i] = output.add_state();
00851 hstate_t a_state = *classes[i].begin();
00852 series_set_elt_t a_serie = null_series;
00853
00854 for_all_const_(set_states_t, state, classes[i])
00855 if(input.is_initial(*state))
00856 a_serie += input.get_initial(*state);
00857
00858 output.set_initial(out_states[i] , a_serie);
00859
00860 if (input.is_final(a_state))
00861 output.set_final(out_states[i] , input.get_final(a_state));
00862 }
00863
00864
00865 vector_series_set_elt_t seriesof (max_partition, null_series);
00866
00867 for(unsigned i = 0; i < max_partition; i++)
00868 {
00869 met_classes.clear();
00870
00871 for (delta_iterator e(input.value(), *classes[i].begin()); ! e.done(); e.next())
00872 {
00873 series_set_elt_t se = input.series_of(*e);
00874 unsigned cs = class_of_state[input.dst_of(*e)];
00875
00876 if (met_classes.find(cs) == met_classes.end())
00877 {
00878 met_classes.insert(cs);
00879 seriesof[cs] = se;
00880 }
00881 else
00882 seriesof[cs] += se;
00883 }
00884
00885 for_all_const_(set<unsigned>, cs, met_classes)
00886 if (seriesof[*cs] != null_series)
00887 output.add_series_transition(out_states[i],
00888 out_states[*cs],
00889 seriesof[*cs]);
00890 }
00891 }
00892
00893 template<typename A, typename AI>
00894 Element<A, AI>
00895 quotient(const Element<A, AI>& a)
00896 {
00897 BENCH_TASK_SCOPED("quotient");
00898 precondition(is_realtime(a));
00899 typedef Element<A, AI> automaton_t;
00900 AUTOMATON_TYPES(automaton_t);
00901 automaton_t output(a.structure());
00902 do_quotient(a.structure(), a.structure().series().semiring(),
00903 SELECT(semiring_elt_value_t), output, a);
00904 return output;
00905 }
00906
00907 }
00908
00909 #endif // ! VCSN_ALGORITHMS_MINIMIZATION_HOPCROFT_HXX