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