Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | 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     // to avoid special case problem (one state initial and final ...)
00447     max_states = std::max(max_states, 2u);
00448 
00449     /*--------------------------.
00450     | To label the subsets of Q |
00451     `--------------------------*/
00452     unsigned max_partitions = 2;
00453 
00454     /*-----------------------------------------.
00455     | To manage efficiently the partition of Q |
00456     `-----------------------------------------*/
00457     class_of_t          class_(max_states);
00458     partition_set_t     part(max_states);
00459 
00460     /*-------------------------.
00461     | To have a list of (P, a) |
00462     `-------------------------*/
00463     to_treat_t          to_treat;
00464 
00465     /*-------------------------.
00466     | Initialize the partition |
00467     `-------------------------*/
00468 
00469     for_all_states (p, input)
00470     {
00471       unsigned c = input.is_final(*p) ? 1 : 0;
00472       class_[*p] = c;
00473       part[c].insert(part[c].end(), *p);
00474     }
00475 
00476     /*------------------------------.
00477     | Initialize the list of (P, a) |
00478     `------------------------------*/
00479 
00480     for_all_letters (e, alphabet_)
00481       to_treat.push_back(pair_t(0, *e));
00482 
00483     for_all_letters (e, alphabet_)
00484       to_treat.push_back(pair_t(1, *e));
00485 
00486     /*----------.
00487     | Main loop |
00488     `----------*/
00489     {
00490       quotient_splitter<input_t> splitter(input, class_, max_states);
00491       while (!to_treat.empty())
00492       {
00493         pair_t c = to_treat.front();
00494         to_treat.pop_front();
00495         unsigned p = c.first;
00496         letter_t a = c.second;
00497 
00498         if (!splitter.compute_going_in_states(part[p], a))
00499           continue;
00500         splitter.split(part, max_partitions);
00501 
00502         splitter.add_new_partitions(to_treat, part);
00503       }
00504     }
00505 
00506     /*------------------------------------.
00507     | Construction of the ouput automaton |
00508     `------------------------------------*/
00509     // Create the states
00510     for (unsigned i = 0; i < max_partitions; ++i)
00511       output.add_state();
00512 
00513     delta_ret_t delta_ret;
00514     std::set<unsigned> already_linked;
00515     for (unsigned i = 0; i < max_partitions; ++i)
00516     {
00517       // Get the first state of the partition => each state has the
00518       // same behaviour
00519       hstate_t s = part[i].front();
00520 
00521       if (input.is_final(s))
00522         output.set_final(i);
00523 
00524       // Create the transitions
00525       for_all_letters (e, alphabet_)
00526       {
00527         delta_ret.clear();
00528         already_linked.clear();
00529 
00530         input.letter_deltac(delta_ret, s, *e, delta_kind::states());
00531         for_all_(delta_ret_t, out, delta_ret)
00532         {
00533           unsigned c = class_[*out];
00534           if (already_linked.find(c) == already_linked.end())
00535           {
00536             already_linked.insert(c);
00537             output.add_letter_transition(i, c, *e);
00538           }
00539         }
00540       }
00541     }
00542 
00543     // Set initial states.
00544     for_all_initial_states(i, input)
00545       output.set_initial(class_[*i]);
00546   }
00547 
00548 # undef QUOTIENT_TYPES
00549 
00550 
00551   /*----------------------------------------.
00552   | Quotient with multiplicities (covering) |
00553   `----------------------------------------*/
00554 
00555   template <class S, class T,
00556             typename A, typename input_t, typename output_t>
00557   void
00558   do_quotient(const AutomataBase<A>&    ,
00559               const S&                  ,
00560               const T&                  ,
00561               output_t&                 output,
00562               const input_t&            input)
00563   {
00564     AUTOMATON_TYPES(input_t);
00565     AUTOMATON_FREEMONOID_TYPES(input_t);
00566     using namespace std;
00567 
00568     /*----------------------------------------.
00569     | Declare data structures and variables.  |
00570     `----------------------------------------*/
00571 
00572     typedef set<htransition_t>                       set_transitions_t;
00573     typedef set<hstate_t>                      set_states_t;
00574     typedef set<semiring_elt_t>                set_semiring_elt_t;
00575     typedef vector<semiring_elt_t>             vector_semiring_elt_t;
00576     typedef pair<unsigned, letter_t>           pair_class_letter_t;
00577     typedef pair<hstate_t, semiring_elt_t>     pair_state_semiring_elt_t;
00578     typedef set<pair_state_semiring_elt_t>     set_pair_state_semiring_elt_t;
00579     typedef map<semiring_elt_t, unsigned>      map_semiring_elt_t;
00580 
00581     series_set_elt_t    null_series     = input.series().zero_;
00582     semiring_elt_t      weight_zero     = input.series().semiring().wzero_;
00583     monoid_elt_t        monoid_identity = input.series().monoid().vcsn_empty;
00584     const alphabet_t&   alphabet (input.series().monoid().alphabet());
00585 
00586     queue<pair_class_letter_t>                          the_queue;
00587 
00588     set<unsigned>       met_classes;
00589     set_transitions_t           transitions_leaving;
00590 
00591     unsigned    max_partition   = 0;
00592     //     unsigned     max_letters     = alphabet.size();
00593     unsigned    max_states      = 0;
00594 
00595     for_all_states(q, input)
00596       max_states = std::max(unsigned (*q), max_states);
00597     ++max_states;
00598     // Avoid special case problem (one initial and final state...)
00599     max_states = std::max(max_states, 2u);
00600 
00601     vector< vector<set_pair_state_semiring_elt_t> > inverse (max_states);
00602 
00603     map<letter_t, unsigned> pos_of_letter;
00604     {
00605       unsigned pos (0);
00606 
00607       for_all_letters(a, alphabet)
00608         pos_of_letter[*a] = pos++;
00609     }
00610 
00611     set_states_t                states_visited;
00612     set_semiring_elt_t          semiring_had_class;
00613     vector<set_states_t>        classes (max_states);
00614     vector<unsigned>            class_of_state (max_states);
00615     vector_semiring_elt_t       old_weight (max_states);
00616     map_semiring_elt_t          class_of_weight;
00617 
00618     for(unsigned i = 0; i < max_states; ++i)
00619       inverse[i].resize(max_states);
00620 
00621     for_all_states(q, input)
00622       for_all_letters(a, alphabet)
00623       {
00624 
00625         for_all_const_(set_states_t, r, states_visited)
00626           old_weight[*r] = weight_zero;
00627         states_visited.clear();
00628 
00629         set_transitions_t transitions_comming;
00630         input.letter_rdeltac(transitions_comming, *q, *a,
00631                              delta_kind::transitions());
00632 
00633         for_all_const_(set_transitions_t, e, transitions_comming)
00634           {
00635             hstate_t            p = input.src_of(*e);
00636             if (states_visited.find(p) != states_visited.end())
00637               inverse[*q][pos_of_letter[*a]].
00638                 erase(pair_state_semiring_elt_t (p, old_weight[p]));
00639             else
00640               states_visited.insert(p);
00641             series_set_elt_t    sd = input.series_of(*e);
00642             monoid_elt_t        md (input.structure().series().monoid(), *a);
00643             semiring_elt_t      wsd = sd.get(md);
00644             old_weight[p] += wsd;
00645             inverse[*q][pos_of_letter[*a]].
00646               insert(pair_state_semiring_elt_t (p, old_weight[p]));
00647           }
00648       }
00649 
00650     /*-----------------------------------------------------------.
00651     | Initialize the partition with as many classes as there are |
00652     | final values.                                              |
00653     `-----------------------------------------------------------*/
00654 
00655     bool         empty = true;
00656     unsigned     class_non_final (0);
00657 
00658     for_all_states(q, input)
00659       {
00660         if (not input.is_final(*q))
00661         {
00662           if (empty == true)
00663           {
00664             empty = false;
00665             class_non_final = max_partition;
00666             max_partition++;
00667           }
00668           classes[class_non_final].insert(*q);
00669           class_of_state[*q] = class_non_final;
00670         }
00671         else
00672         {
00673           semiring_elt_t w = input.get_final(*q).get(monoid_identity);
00674           if (semiring_had_class.find(w) == semiring_had_class.end())
00675           {
00676             semiring_had_class.insert(w);
00677             classes[max_partition].insert(*q);
00678             class_of_weight[w] = max_partition;
00679             class_of_state[*q] = max_partition;
00680             max_partition++;
00681           }
00682           else
00683           {
00684             classes[class_of_weight[w]].insert(*q);
00685             class_of_state[*q] = class_of_weight[w];
00686           }
00687         }
00688       }
00689 
00690     /*-----------------------------------------------------.
00691     | Initialize the queue with pairs <class_id, letter>.  |
00692     `-----------------------------------------------------*/
00693 
00694     for (unsigned i = 0; i < max_partition; i++)
00695       for_all_letters(a, alphabet)
00696         the_queue.push(pair_class_letter_t (i, *a));
00697 
00698     /*----------------.
00699     | The main loop.  |
00700     `----------------*/
00701 
00702     unsigned old_max_partition = max_partition;
00703 
00704     while(not the_queue.empty())
00705     {
00706       pair_class_letter_t pair = the_queue.front();
00707       the_queue.pop();
00708       //val.clear(); // FIXME: Is this line necessary?
00709       met_classes.clear();
00710       vector_semiring_elt_t val (max_states);
00711 
00712       for_all_states(q, input)
00713         val[*q] = 0;
00714 
00715       // First, calculcate val[state] and note met_classes.
00716       for_all_const_(set_states_t, q, classes[pair.first])
00717         for_all_const_(set_pair_state_semiring_elt_t, pair_,
00718                        inverse[*q][pos_of_letter[pair.second]])
00719         {
00720           unsigned  state = pair_->first;
00721           if (met_classes.find(class_of_state[state]) ==
00722               met_classes.end())
00723             met_classes.insert(class_of_state[state]);
00724           val[state] += pair_->second;
00725         }
00726 
00727       // Next, for each met class, do the partition.
00728       for_all_const_(set<unsigned>, class_id, met_classes)
00729       {
00730         if (classes[*class_id].size() == 1)
00731           continue ;
00732 
00733         queue<hstate_t> to_erase;
00734         semiring_elt_t  next_val;
00735         semiring_elt_t  first_val = val[*(classes[*class_id].begin())];
00736         class_of_weight.clear();
00737         semiring_had_class.clear();
00738 
00739         for_all_const_(set_states_t, p, classes[*class_id])
00740         {
00741           next_val = val[*p];
00742           // This state must be moved to another class!
00743           if (next_val != first_val)
00744           {
00745             if (semiring_had_class.find(next_val) ==
00746                 semiring_had_class.end()) // Must create a new class
00747             {
00748               classes[max_partition].insert(*p);
00749               class_of_state[*p] = max_partition;
00750               semiring_had_class.insert(next_val);
00751               class_of_weight[next_val] = max_partition;
00752               max_partition++;
00753             }
00754             else
00755             {
00756               classes[class_of_weight[next_val]].insert(*p);
00757               class_of_state[*p] = class_of_weight[next_val];
00758             }
00759             to_erase.push(*p);
00760           }
00761         }
00762 
00763         while(not to_erase.empty())
00764         {
00765           hstate_t s = to_erase.front();
00766           to_erase.pop();
00767           classes[*class_id].erase(s);
00768         }
00769 
00770         // Push pairs <new_class_id, letter> into the queue.
00771         for (unsigned i = old_max_partition; i < max_partition; i++)
00772           for_all_letters(b, alphabet)
00773             the_queue.push(pair_class_letter_t(i, *b));
00774         old_max_partition = max_partition;
00775       }
00776     }
00777 
00778     /*------------------.
00779     | Form the output.  |
00780     `------------------*/
00781 
00782     typedef vector<series_set_elt_t> vector_series_set_elt_t;
00783 
00784     std::vector<hstate_t>       out_states (max_partition);
00785 
00786     // typedef map<unsigned, series_set_elt_t> map_class_series_elt_t;
00787     // map_class_series_elt_t   seriesof;
00788 
00789     // Add states.
00790     for(unsigned i = 0; i < max_partition; i++)
00791     {
00792       out_states[i]  = output.add_state();
00793       hstate_t a_state = *classes[i].begin();
00794       series_set_elt_t a_serie = null_series;
00795 
00796       for_all_const_(set_states_t, state, classes[i])
00797         if(input.is_initial(*state))
00798           a_serie += input.get_initial(*state);
00799 
00800       output.set_initial(out_states[i] , a_serie);
00801 
00802       if (input.is_final(a_state))
00803         output.set_final(out_states[i] , input.get_final(a_state));
00804     }
00805 
00806     // Add transitions.
00807     vector_series_set_elt_t seriesof (max_partition, null_series);
00808 
00809     for(unsigned i = 0; i < max_partition; i++)
00810     {
00811       met_classes.clear();
00812 
00813       transitions_leaving.clear();
00814       input.deltac(transitions_leaving, *classes[i].begin(),
00815                    delta_kind::transitions());
00816 
00817       for_all_const_(set_transitions_t, e, transitions_leaving)
00818         {
00819           series_set_elt_t      se = input.series_of(*e);
00820           unsigned              cs = class_of_state[input.dst_of(*e)];
00821 
00822           if (met_classes.find(cs) == met_classes.end())
00823           {
00824             met_classes.insert(cs);
00825             seriesof[cs] = se;
00826           }
00827           else
00828             seriesof[cs] += se;
00829         }
00830 
00831       for_all_const_(set<unsigned>, cs, met_classes)
00832         output.add_series_transition(out_states[i],
00833                                      out_states[*cs],
00834                                      seriesof[*cs]);
00835     }
00836   }
00837 
00838   template<typename A, typename T>
00839   Element<A, T>
00840   quotient(const Element<A, T>& a)
00841   {
00842     TIMER_SCOPED ("quotient");
00843     typedef Element<A, T> auto_t;
00844     AUTOMATON_TYPES(auto_t);
00845     Element<A, T> output(a.structure());
00846     do_quotient(a.structure(), a.structure().series().semiring(),
00847                 SELECT(semiring_elt_value_t), output, a);
00848     return output;
00849   }
00850 
00851 } // vcsn
00852 
00853 #endif // ! VCSN_ALGORITHMS_MINIMIZATION_HOPCROFT_HXX

Generated on Fri Oct 12 21:22:48 2007 for Vaucanson by  doxygen 1.4.4