- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

# minimization_hopcroft.hxx

    00001 // minimization_hopcroft.hxx: this file is part of the Vaucanson project.
    00002 //
    00003 // Vaucanson, a generic library for finite state machines.
    00004 //
    00005 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The Vaucanson Group.
    00006 //
    00007 // This program is free software; you can redistribute it and/or
    00008 // modify it under the terms of the GNU General Public License
    00009 // as published by the Free Software Foundation; either version 2
    00010 // of the License, or (at your option) any later version.
    00011 //
    00012 // The complete GNU General Public Licence Notice can be found as the
    00013 // `COPYING' file in the root directory.
    00014 //
    00015 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
    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/automata/concept/automata_base.hh>
    00029 # include <vaucanson/misc/usual_macros.hh>
    00030 # include <vaucanson/misc/bitset.hh>
    00031
    00032 namespace vcsn
    00033 {
    00034
    00035   namespace internal
    00036   {
    00037     namespace hopcroft_minimization_det
    00038     {
    00039
    00040 # define HOPCROFT_TYPES()                                               \
    00041       typedef std::set<hstate_t> hstates_t;                             \
    00042       typedef std::vector<hstates_t> partition_t;                       \
    00043       typedef std::vector<unsigned> class_of_t;                         \
    00044       typedef std::queue<std::pair<hstates_t*, unsigned> > to_treat_t;
    00045
    00050       template <typename input_t>
    00051       struct splitter_functor
    00052       {
    00053         AUTOMATON_TYPES (input_t);
    00054         AUTOMATON_FREEMONOID_TYPES (input_t);
    00055         HOPCROFT_TYPES ();
    00056
    00057         const input_t& input_;
    00058         hstates_t going_in_;
    00059         class_of_t& class_of_;
    00060         std::list<unsigned> maybe_splittable_;
    00061         std::vector<unsigned> count_for_;
    00062
    00063         splitter_functor (const input_t& input, hstate_t max_state,
    00064                           class_of_t& class_of)
    00065           : input_ (input), going_in_ (), class_of_(class_of),
    00066             count_for_ (max_state)
    00067         {}
    00068
    00070         bool compute_states_going_in (const hstates_t& ss, letter_t l)
    00071         {
    00072           going_in_.clear ();
    00073           maybe_splittable_.clear ();
    00074           for_all_const (hstates_t, i, ss)
    00075             input_.letter_rdeltaf (*this, *i, l, delta_kind::states ());
    00076           return not going_in_.empty ();
    00077         }
    00078
    00080         void operator () (hstate_t state)
    00081         {
    00082           unsigned class_of_state = class_of_[state];
    00083
    00084           if (count_for_[class_of_state] == 0)
    00085             maybe_splittable_.push_back (class_of_state);
    00086           count_for_[class_of_state]++;
    00087           going_in_.insert (state);
    00088         }
    00089
    00091         void execute (partition_t& partition, to_treat_t& to_treat,
    00092                       unsigned& n_partition)
    00093         {
    00094           for_all (std::list<unsigned>, inpartition, maybe_splittable_)
    00095           {
    00096             hstates_t& states = partition[*inpartition];
    00097             if (states.size () == count_for_[*inpartition])
    00098             { // All elements in states are predecessors, no split.
    00099               count_for_[*inpartition] = 0;
    00100               continue;
    00101             }
    00102             count_for_[*inpartition] = 0;
    00103             hstates_t states_inter_going_in;
    00104             hstates_t& states_minus_going_in = partition[n_partition];
    00105             // Compute @a states \ @a going_in_.
    00106             set_difference
    00107               (states.begin (), states.end (),
    00108                going_in_.begin (), going_in_.end (),
    00109                std::insert_iterator<hstates_t> (states_minus_going_in,
    00110                                                 states_minus_going_in.begin ()));
    00111             // Compute @a states Inter @a going_in_.
    00112             set_intersection
    00113               (states.begin(), states.end (),
    00114                going_in_.begin (), going_in_.end (),
    00115                std::insert_iterator<hstates_t> (states_inter_going_in,
    00116                                                 states_inter_going_in.begin ()));
    00117             // A split MUST occur.
    00118             assertion (not (states_inter_going_in.empty ()
    00119                             or states_minus_going_in.empty ()));
    00120             // @a states must be the bigger one.
    00121             if (states_minus_going_in.size () > states_inter_going_in.size ())
    00122             {
    00123               states.swap (states_minus_going_in);
    00124               states_minus_going_in.swap (states_inter_going_in);
    00125             }
    00126             else
    00127               states.swap (states_inter_going_in);
    00128             for_all (hstates_t, istate, states_minus_going_in)
    00129               class_of_[*istate] = n_partition;
    00130             to_treat.push (std::make_pair (&states_minus_going_in,
    00131                                            n_partition++));
    00132           }
    00133         }
    00134       };
    00135
    00137       template <typename input_t, typename output_t>
    00138       struct transition_adder_functor
    00139       {
    00140         AUTOMATON_TYPES (input_t);
    00141         HOPCROFT_TYPES ();
    00142
    00143         const input_t& input_;
    00144         output_t& output_;
    00145         const class_of_t& class_of_;
    00146
    00147         hstate_t src_;
    00148
    00149         transition_adder_functor (const input_t& input, output_t& output,
    00150                                   const class_of_t& class_of)
    00151           : input_ (input), output_ (output), class_of_ (class_of)
    00152         {}
    00153
    00155         void execute (hstate_t representative)
    00156         {
    00157           src_ = class_of_[representative];
    00158           input_.deltaf (*this, representative, delta_kind::transitions ());
    00159         }
    00160
    00161         void operator () (htransition_t t)
    00162         {
    00163           output_.add_series_transition (src_, class_of_[input_.dst_of (t)],
    00164                                          input_.series_of (t));
    00165         }
    00166       };
    00167     }
    00168   }
    00169
    00170
    00171   template <typename A, typename input_t, typename output_t>
    00172   void
    00173   do_hopcroft_minimization_det(const AutomataBase<A>&   ,
    00174                                output_t&                output,
    00175                                const input_t&           input)
    00176   {
    00177     AUTOMATON_TYPES (input_t);
    00178     AUTOMATON_FREEMONOID_TYPES (input_t);
    00179     HOPCROFT_TYPES ();
    00180
    00181     using namespace internal::hopcroft_minimization_det;
    00182
    00183     unsigned max_state = input.states ().max () + 1;
    00184     partition_t partition (max_state);
    00185     class_of_t class_of (max_state);
    00186     to_treat_t to_treat;
    00187     unsigned n_partition = 0;
    00188     const alphabet_t& alphabet =
    00189       input.structure ().series ().monoid ().alphabet ();
    00190
    00191     {
    00192       // Initialize Partition = {Q \ F , F }
    00193       hstates_t* finals = 0, * others = 0;
    00194       int n_finals = -1, n_others = -1,
    00195         count_finals = 0, count_others = 0;
    00196
    00197 # define add_to_class(Name)                     \
    00198       do {                                      \
    00199         if (not Name)                           \
    00200         {                                       \
    00201           Name = &(partition[n_partition]);     \
    00202           n_ ## Name = n_partition++;           \
    00203         }                                       \
    00204         count_ ## Name ++;                      \
    00205         (*Name).insert (*state);                \
    00206         class_of[*state] = n_ ## Name;          \
    00207       } while (0)
    00208
    00209       for_all_states (state, input)
    00210         if (input.is_final (*state))
    00211           add_to_class (finals);
    00212         else
    00213           add_to_class (others);
    00214 # undef add_to_class
    00215
    00216       if (n_partition == 0)
    00217         return;
    00218       if (n_partition == 1)
    00219       {
    00220         output = input;
    00221         return;
    00222       }
    00223       // Put F or Q \ F in the "To treat" list T.
    00224       if (count_finals > count_others)
    00225         to_treat.push (std::make_pair (others, n_others));
    00226       else
    00227         to_treat.push (std::make_pair (finals, n_finals));
    00228     }
    00229
    00230     {
    00231       splitter_functor<input_t> splitter (input, max_state, class_of);
    00232
    00233       // While T is not empty,
    00234       while (not to_treat.empty () && n_partition < max_state)
    00235       {
    00236         // Remove a set S of T ,
    00237         hstates_t& states = *(to_treat.front ().first);
    00238         to_treat.pop ();
    00239
    00240         // For each letter l in Alphabet,
    00241         for_all_letters (letter, alphabet)
    00242           {
    00243             if (not splitter.compute_states_going_in (states, *letter))
    00244               continue;
    00245             splitter.execute (partition, to_treat, n_partition);
    00246             if (n_partition == max_state)
    00247               break;
    00248           }
    00249       }
    00250     }
    00251
    00252     // Build the automaton.
    00253     // Assume that states are numbers starting from 0.
    00254     for (unsigned i = 0; i < n_partition; ++i)
    00255       output.add_state ();
    00256
    00257     transition_adder_functor<input_t, output_t>
    00258       transition_adder (input, output, class_of);
    00259
    00260     partition_t::iterator istates = partition.begin ();
    00261     for (unsigned i = 0; i < n_partition; ++i, ++istates)
    00262     {
    00263       int representative = *(*istates).begin();
    00264
    00265       if (input.is_final (representative))
    00266         output.set_final (class_of[representative]);
    00267       transition_adder.execute (representative);
    00268     }
    00269
    00270     for_all_initial_states (state, input)
    00271       output.set_initial (class_of[*state]);
    00272   }
    00273
    00274 # undef HOPCROFT_TYPES
    00275
    00284   template<typename A, typename T>
    00285   Element<A, T>
    00286   minimization_hopcroft(const Element<A, T>& a)
    00287   {
    00288     TIMER_SCOPED ("minimization_hopcroft");
    00289     Element<A, T> output(a.structure());
    00290     do_hopcroft_minimization_det(a.structure(), output, a);
    00291     return output;
    00292   }
    00293
    00294
    00295   /*-------------------------------------.
    00296   | Quotient with Boolean multiplicities |
    00297   `-------------------------------------*/
    00298   namespace internal
    00299   {
    00300     namespace hopcroft_minimization_undet
    00301     {
    00302
    00303 # define QUOTIENT_TYPES()                                               \
    00304       typedef std::list<hstate_t> partition_t;                          \
    00305       typedef std::vector<partition_t> partition_set_t;                 \
    00306       typedef typename partition_t::iterator partition_iterator;        \
    00307       typedef std::vector<unsigned> class_of_t;                         \
    00308       typedef std::set<hstate_t> delta_ret_t;                           \
    00309       typedef std::pair<unsigned, letter_t> pair_t;                     \
    00310       typedef std::list<pair_t> to_treat_t;
    00311
    00312       template <typename input_t>
    00313       class quotient_splitter
    00314       {
    00315       public:
    00316         AUTOMATON_TYPES(input_t);
    00317         AUTOMATON_FREEMONOID_TYPES(input_t);
    00318         QUOTIENT_TYPES();
    00319
    00320         typedef std::vector<bool> going_in_t;
    00321
    00322         quotient_splitter (const automaton_t& input, class_of_t& class_of,
    00323                            unsigned max_states)
    00324           : input_(input),
    00325             alphabet_(input.series().monoid().alphabet()),
    00326             class_(class_of),
    00327             count_for_(max_states, 0),
    00328             twin_(max_states, 0),
    00329             going_in_(max_states, false)
    00330         { }
    00331
    00333         bool compute_going_in_states (partition_t& p, letter_t a)
    00334         {
    00335           for_all_(going_in_t, s, going_in_)
    00336             *s = false;
    00337
    00338           for_all_(partition_t, s, p)
    00339             input_.letter_rdeltaf(*this, *s, a, delta_kind::states());
    00340           return !met_class_.empty();
    00341         }
    00342
    00344         void operator() (hstate_t s)
    00345         {
    00346           if (!going_in_[s])
    00347           {
    00348             going_in_[s] = true;
    00349             const unsigned i = class_[s];
    00350             if (count_for_[i] == 0)
    00351               met_class_.push_back(i);
    00352             count_for_[i]++;
    00353           }
    00354         }
    00355
    00357         void split (partition_set_t& parts, unsigned& max_partitions)
    00358         {
    00359           for_all_(std::list<unsigned>, klass, met_class_)
    00360           {
    00361             // if all states are predecessors there is no needed split
    00362             if (count_for_[*klass] == parts[*klass].size())
    00363               continue;
    00364
    00365             if (twin_[*klass] == 0)
    00366               twin_[*klass] = max_partitions++;
    00367             unsigned new_klass = twin_[*klass];
    00368
    00369             partition_t::iterator q;
    00370             for (partition_t::iterator next = parts[*klass].begin();
    00371                  next != parts[*klass].end();)
    00372             {
    00373               q = next;
    00374               ++next;
    00375               if (going_in_[*q])
    00376               {
    00377                 parts[new_klass].insert(parts[new_klass].end(), *q);
    00378                 class_[*q] = new_klass;
    00379                 parts[*klass].erase(q);
    00380               }
    00381             }
    00382           }
    00383         }
    00384
    00385         void add_new_partitions(to_treat_t&             to_treat,
    00386                                 const partition_set_t&  part)
    00387         {
    00388           for_all_(std::list<unsigned>, klass, met_class_)
    00389           {
    00390             if (twin_[*klass] != 0)
    00391             {
    00392               for_all_letters(e, alphabet_)
    00393               {
    00394                 if (find(to_treat.begin(), to_treat.end(), pair_t(*klass, *e)) !=
    00395                     to_treat.end())
    00396                   to_treat.push_back(pair_t(twin_[*klass], *e));
    00397                 else
    00398                   if (part[*klass].size() < part[twin_[*klass]].size())
    00399                     to_treat.push_back(pair_t(*klass, *e));
    00400                   else
    00401                     to_treat.push_back(pair_t(twin_[*klass], *e));
    00402               }
    00403             }
    00404           }
    00405
    00406           for_all_(std::list<unsigned>, klass, met_class_)
    00407           {
    00408             count_for_[*klass] = 0;
    00409             twin_[*klass] = 0;
    00410           }
    00411           met_class_.clear();
    00412         }
    00413
    00414       private:
    00415         const automaton_t& input_;
    00416         const alphabet_t& alphabet_;
    00417         class_of_t& class_;
    00418         std::vector<unsigned> count_for_;
    00419         std::vector<unsigned> twin_;
    00420         going_in_t going_in_;
    00421         std::list<unsigned> met_class_;
    00422       };
    00423     }
    00424   }
    00425
    00426   template <typename A, typename input_t, typename output_t>
    00427   void
    00428   do_quotient(const AutomataBase<A>&,
    00429               const algebra::NumericalSemiring&,
    00430               SELECTOR(bool),
    00431               output_t&                 output,
    00432               const input_t&            input)
    00433   {
    00434     AUTOMATON_TYPES(input_t);
    00435     AUTOMATON_FREEMONOID_TYPES(input_t);
    00436     QUOTIENT_TYPES();
    00437
    00438     using namespace internal::hopcroft_minimization_undet;
    00439
    00440     const alphabet_t& alphabet_(input.series().monoid().alphabet());
    00441     unsigned max_states = 0;
    00442
    00443     for_all_states(i, input)
    00444       max_states = std::max(unsigned(*i), max_states);
    00445     ++max_states;
    00446
    00447     /*--------------------------.
    00448     | To label the subsets of Q |
    00449     `--------------------------*/
    00450     unsigned max_partitions = 0;
    00451
    00452     /*-----------------------------------------.
    00453     | To manage efficiently the partition of Q |
    00454     `-----------------------------------------*/
    00455     class_of_t          class_(max_states);
    00456     partition_set_t     part(max_states);
    00457
    00458     /*-------------------------.
    00459     | To have a list of (P, a) |
    00460     `-------------------------*/
    00461     to_treat_t          to_treat;
    00462
    00463     /*-------------------------.
    00464     | Initialize the partition |
    00465     `-------------------------*/
    00466
    00467     // In the general case, we have two sets, part[0] and part[1] One
    00468     // holds the final states, the other the non-final states.  In
    00469     // some cases we may have only one set, for instance if we have no
    00470     // final states, or if we have only final states.  Because we do
    00471     // not want to have an empty part[0], we will fill it with the
    00472     // first kind of state (final / non-final) we encounter.
    00473     unsigned final = 1;
    00474
    00475     for_all_states (p, input)
    00476     {
    00477       unsigned c;
    00478       if (max_partitions == 0)
    00479         {
    00480           c = 0;
    00481           final = !input.is_final(*p);
    00482         }
    00483       else
    00484         {
    00485           c = input.is_final(*p) ? final : (1 - final);
    00486         }
    00487       class_[*p] = c;
    00488       part[c].insert(part[c].end(), *p);
    00489       max_partitions = std::max(max_partitions, c + 1);
    00490     }
    00491
    00492     /*------------------------------.
    00493     | Initialize the list of (P, a) |
    00494     `------------------------------*/
    00495
    00496     if (max_partitions > 0)
    00497       for_all_letters (e, alphabet_)
    00498         to_treat.push_back(pair_t(0, *e));
    00499
    00500     if (max_partitions > 1)
    00501       for_all_letters (e, alphabet_)
    00502         to_treat.push_back(pair_t(1, *e));
    00503
    00504     /*----------.
    00505     | Main loop |
    00506     `----------*/
    00507     {
    00508       quotient_splitter<input_t> splitter(input, class_, max_states);
    00509       while (!to_treat.empty())
    00510       {
    00511         pair_t c = to_treat.front();
    00512         to_treat.pop_front();
    00513         unsigned p = c.first;
    00514         letter_t a = c.second;
    00515
    00516         if (!splitter.compute_going_in_states(part[p], a))
    00517           continue;
    00518         splitter.split(part, max_partitions);
    00519
    00520         splitter.add_new_partitions(to_treat, part);
    00521       }
    00522     }
    00523
    00524     /*------------------------------------.
    00525     | Construction of the ouput automaton |
    00526     `------------------------------------*/
    00527     // Create the states
    00528     for (unsigned i = 0; i < max_partitions; ++i)
    00529       output.add_state();
    00530
    00531     delta_ret_t delta_ret;
    00532     std::set<unsigned> already_linked;
    00533     for (unsigned i = 0; i < max_partitions; ++i)
    00534     {
    00535       // Get the first state of the partition => each state has the
    00536       // same behaviour
    00537       hstate_t s = part[i].front();
    00538
    00539       if (input.is_final(s))
    00540         output.set_final(i);
    00541
    00542       // Create the transitions
    00543       for_all_letters (e, alphabet_)
    00544       {
    00545         delta_ret.clear();
    00546         already_linked.clear();
    00547
    00548         input.letter_deltac(delta_ret, s, *e, delta_kind::states());
    00549         for_all_(delta_ret_t, out, delta_ret)
    00550         {
    00551           unsigned c = class_[*out];
    00552           if (already_linked.find(c) == already_linked.end())
    00553           {
    00554             already_linked.insert(c);
    00555             output.add_letter_transition(i, c, *e);
    00556           }
    00557         }
    00558       }
    00559     }
    00560
    00561     // Set initial states.
    00562     for_all_initial_states(i, input)
    00563       output.set_initial(class_[*i]);
    00564   }
    00565
    00566 # undef QUOTIENT_TYPES
    00567
    00568
    00569   /*----------------------------------------.
    00570   | Quotient with multiplicities (covering) |
    00571   `----------------------------------------*/
    00572
    00573   template <class S, class T,
    00574             typename A, typename input_t, typename output_t>
    00575   void
    00576   do_quotient(const AutomataBase<A>&    ,
    00577               const S&                  ,
    00578               const T&                  ,
    00579               output_t&                 output,
    00580               const input_t&            input)
    00581   {
    00582     AUTOMATON_TYPES(input_t);
    00583     AUTOMATON_FREEMONOID_TYPES(input_t);
    00584     using namespace std;
    00585
    00586     /*----------------------------------------.
    00587     | Declare data structures and variables.  |
    00588     `----------------------------------------*/
    00589
    00590     typedef set<htransition_t>                       set_transitions_t;
    00591     typedef set<hstate_t>                      set_states_t;
    00592     typedef set<semiring_elt_t>                set_semiring_elt_t;
    00593     typedef vector<semiring_elt_t>             vector_semiring_elt_t;
    00594     typedef pair<unsigned, letter_t>           pair_class_letter_t;
    00595     typedef pair<hstate_t, semiring_elt_t>     pair_state_semiring_elt_t;
    00596     typedef set<pair_state_semiring_elt_t>     set_pair_state_semiring_elt_t;
    00597     typedef map<semiring_elt_t, unsigned>      map_semiring_elt_t;
    00598
    00599     series_set_elt_t    null_series     = input.series().zero_;
    00600     semiring_elt_t      weight_zero     = input.series().semiring().wzero_;
    00601     monoid_elt_t        monoid_identity = input.series().monoid().vcsn_empty;
    00602     const alphabet_t&   alphabet (input.series().monoid().alphabet());
    00603
    00604     queue<pair_class_letter_t>                          the_queue;
    00605
    00606     set<unsigned>       met_classes;
    00607     set_transitions_t           transitions_leaving;
    00608
    00609     unsigned    max_partition   = 0;
    00610     //     unsigned     max_letters     = alphabet.size();
    00611     unsigned    max_states      = 0;
    00612
    00613     for_all_states(q, input)
    00614       max_states = std::max(unsigned (*q), max_states);
    00615     ++max_states;
    00616     // Avoid special case problem (one initial and final state...)
    00617     max_states = std::max(max_states, 2u);
    00618
    00619     vector< vector<set_pair_state_semiring_elt_t> > inverse (max_states);
    00620
    00621     map<letter_t, unsigned> pos_of_letter;
    00622     {
    00623       unsigned pos (0);
    00624
    00625       for_all_letters(a, alphabet)
    00626         pos_of_letter[*a] = pos++;
    00627     }
    00628
    00629     set_states_t                states_visited;
    00630     set_semiring_elt_t          semiring_had_class;
    00631     vector<set_states_t>        classes (max_states);
    00632     vector<unsigned>            class_of_state (max_states);
    00633     vector_semiring_elt_t       old_weight (max_states);
    00634     map_semiring_elt_t          class_of_weight;
    00635
    00636     for(unsigned i = 0; i < max_states; ++i)
    00637       inverse[i].resize(max_states);
    00638
    00639     for_all_states(q, input)
    00640       for_all_letters(a, alphabet)
    00641       {
    00642
    00643         for_all_const_(set_states_t, r, states_visited)
    00644           old_weight[*r] = weight_zero;
    00645         states_visited.clear();
    00646
    00647         set_transitions_t transitions_comming;
    00648         input.letter_rdeltac(transitions_comming, *q, *a,
    00649                              delta_kind::transitions());
    00650
    00651         for_all_const_(set_transitions_t, e, transitions_comming)
    00652           {
    00653             hstate_t            p = input.src_of(*e);
    00654             if (states_visited.find(p) != states_visited.end())
    00655               inverse[*q][pos_of_letter[*a]].
    00656                 erase(pair_state_semiring_elt_t (p, old_weight[p]));
    00657             else
    00658               states_visited.insert(p);
    00659             series_set_elt_t    sd = input.series_of(*e);
    00660             monoid_elt_t        md (input.structure().series().monoid(), *a);
    00661             semiring_elt_t      wsd = sd.get(md);
    00662             old_weight[p] += wsd;
    00663             inverse[*q][pos_of_letter[*a]].
    00664               insert(pair_state_semiring_elt_t (p, old_weight[p]));
    00665           }
    00666       }
    00667
    00668     /*-----------------------------------------------------------.
    00669     | Initialize the partition with as many classes as there are |
    00670     | final values.                                              |
    00671     `-----------------------------------------------------------*/
    00672
    00673     bool         empty = true;
    00674     unsigned     class_non_final (0);
    00675
    00676     for_all_states(q, input)
    00677       {
    00678         if (not input.is_final(*q))
    00679         {
    00680           if (empty == true)
    00681           {
    00682             empty = false;
    00683             class_non_final = max_partition;
    00684             max_partition++;
    00685           }
    00686           classes[class_non_final].insert(*q);
    00687           class_of_state[*q] = class_non_final;
    00688         }
    00689         else
    00690         {
    00691           semiring_elt_t w = input.get_final(*q).get(monoid_identity);
    00692           if (semiring_had_class.find(w) == semiring_had_class.end())
    00693           {
    00694             semiring_had_class.insert(w);
    00695             classes[max_partition].insert(*q);
    00696             class_of_weight[w] = max_partition;
    00697             class_of_state[*q] = max_partition;
    00698             max_partition++;
    00699           }
    00700           else
    00701           {
    00702             classes[class_of_weight[w]].insert(*q);
    00703             class_of_state[*q] = class_of_weight[w];
    00704           }
    00705         }
    00706       }
    00707
    00708     /*-----------------------------------------------------.
    00709     | Initialize the queue with pairs <class_id, letter>.  |
    00710     `-----------------------------------------------------*/
    00711
    00712     for (unsigned i = 0; i < max_partition; i++)
    00713       for_all_letters(a, alphabet)
    00714         the_queue.push(pair_class_letter_t (i, *a));
    00715
    00716     /*----------------.
    00717     | The main loop.  |
    00718     `----------------*/
    00719
    00720     unsigned old_max_partition = max_partition;
    00721
    00722     while(not the_queue.empty())
    00723     {
    00724       pair_class_letter_t pair = the_queue.front();
    00725       the_queue.pop();
    00726       //val.clear(); // FIXME: Is this line necessary?
    00727       met_classes.clear();
    00728       vector_semiring_elt_t val (max_states);
    00729
    00730       for_all_states(q, input)
    00731         val[*q] = 0;
    00732
    00733       // First, calculcate val[state] and note met_classes.
    00734       for_all_const_(set_states_t, q, classes[pair.first])
    00735         for_all_const_(set_pair_state_semiring_elt_t, pair_,
    00736                        inverse[*q][pos_of_letter[pair.second]])
    00737         {
    00738           unsigned  state = pair_->first;
    00739           if (met_classes.find(class_of_state[state]) ==
    00740               met_classes.end())
    00741             met_classes.insert(class_of_state[state]);
    00742           val[state] += pair_->second;
    00743         }
    00744
    00745       // Next, for each met class, do the partition.
    00746       for_all_const_(set<unsigned>, class_id, met_classes)
    00747       {
    00748         if (classes[*class_id].size() == 1)
    00749           continue ;
    00750
    00751         queue<hstate_t> to_erase;
    00752         semiring_elt_t  next_val;
    00753         semiring_elt_t  first_val = val[*(classes[*class_id].begin())];
    00754         class_of_weight.clear();
    00755         semiring_had_class.clear();
    00756
    00757         for_all_const_(set_states_t, p, classes[*class_id])
    00758         {
    00759           next_val = val[*p];
    00760           // This state must be moved to another class!
    00761           if (next_val != first_val)
    00762           {
    00763             if (semiring_had_class.find(next_val) ==
    00764                 semiring_had_class.end()) // Must create a new class
    00765             {
    00766               classes[max_partition].insert(*p);
    00767               class_of_state[*p] = max_partition;
    00768               semiring_had_class.insert(next_val);
    00769               class_of_weight[next_val] = max_partition;
    00770               max_partition++;
    00771             }
    00772             else
    00773             {
    00774               classes[class_of_weight[next_val]].insert(*p);
    00775               class_of_state[*p] = class_of_weight[next_val];
    00776             }
    00777             to_erase.push(*p);
    00778           }
    00779         }
    00780
    00781         while(not to_erase.empty())
    00782         {
    00783           hstate_t s = to_erase.front();
    00784           to_erase.pop();
    00785           classes[*class_id].erase(s);
    00786         }
    00787
    00788         // Push pairs <new_class_id, letter> into the queue.
    00789         for (unsigned i = old_max_partition; i < max_partition; i++)
    00790           for_all_letters(b, alphabet)
    00791             the_queue.push(pair_class_letter_t(i, *b));
    00792         old_max_partition = max_partition;
    00793       }
    00794     }
    00795
    00796     /*------------------.
    00797     | Form the output.  |
    00798     `------------------*/
    00799
    00800     typedef vector<series_set_elt_t> vector_series_set_elt_t;
    00801
    00802     std::vector<hstate_t>       out_states (max_partition);
    00803
    00804     // typedef map<unsigned, series_set_elt_t> map_class_series_elt_t;
    00805     // map_class_series_elt_t   seriesof;
    00806
    00807     // Add states.
    00808     for(unsigned i = 0; i < max_partition; i++)
    00809     {
    00810       out_states[i]  = output.add_state();
    00811       hstate_t a_state = *classes[i].begin();
    00812       series_set_elt_t a_serie = null_series;
    00813
    00814       for_all_const_(set_states_t, state, classes[i])
    00815         if(input.is_initial(*state))
    00816           a_serie += input.get_initial(*state);
    00817
    00818       output.set_initial(out_states[i] , a_serie);
    00819
    00820       if (input.is_final(a_state))
    00821         output.set_final(out_states[i] , input.get_final(a_state));
    00822     }
    00823
    00824     // Add transitions.
    00825     vector_series_set_elt_t seriesof (max_partition, null_series);
    00826
    00827     for(unsigned i = 0; i < max_partition; i++)
    00828     {
    00829       met_classes.clear();
    00830
    00831       transitions_leaving.clear();
    00832       input.deltac(transitions_leaving, *classes[i].begin(),
    00833                    delta_kind::transitions());
    00834
    00835       for_all_const_(set_transitions_t, e, transitions_leaving)
    00836         {
    00837           series_set_elt_t      se = input.series_of(*e);
    00838           unsigned              cs = class_of_state[input.dst_of(*e)];
    00839
    00840           if (met_classes.find(cs) == met_classes.end())
    00841           {
    00842             met_classes.insert(cs);
    00843             seriesof[cs] = se;
    00844           }
    00845           else
    00846             seriesof[cs] += se;
    00847         }
    00848
    00849       for_all_const_(set<unsigned>, cs, met_classes)
    00850         output.add_series_transition(out_states[i],
    00851                                      out_states[*cs],
    00852                                      seriesof[*cs]);
    00853     }
    00854   }
    00855
    00856   template<typename A, typename T>
    00857   Element<A, T>
    00858   quotient(const Element<A, T>& a)
    00859   {
    00860     TIMER_SCOPED ("quotient");
    00861     typedef Element<A, T> auto_t;
    00862     AUTOMATON_TYPES(auto_t);
    00863     Element<A, T> output(a.structure());
    00864     do_quotient(a.structure(), a.structure().series().semiring(),
    00865                 SELECT(semiring_elt_value_t), output, a);
    00866     return output;
    00867   }
    00868
    00869 } // vcsn
    00870
    00871 #endif // ! VCSN_ALGORITHMS_MINIMIZATION_HOPCROFT_HXX