minimization_moore.hxx

00001 // minimization_moore.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 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_MOORE_HXX
00018 # define VCSN_ALGORITHMS_MINIMIZATION_MOORE_HXX
00019 
00020 # include <vaucanson/algorithms/minimization_moore.hh>
00021 
00022 # include <vaucanson/automata/concept/handlers.hh>
00023 # include <vaucanson/automata/concept/delta_kind.hh>
00024 # include <vaucanson/misc/usual_macros.hh>
00025 # include <vaucanson/misc/contract.hh>
00026 
00027 # include <map>
00028 # include <set>
00029 # include <vector>
00030 
00031 // Useful macros for Moore's minimization.
00032 
00033 // Iterator on a list of groups.
00034 # define for_all_groups(I, P)                                           \
00035   for (groupid_to_group_t::iterator I = ((P).begin()); I != (P).end(); ++I)
00036 
00037 // Iterator on state in a group. We don't iterate on the first not
00038 // processed state.
00039 # define for_all_state_in_groups(I, P)                                  \
00040   for (group_t::iterator I = ++((P).begin()); I != (P).end(); ++I)
00041 
00042 namespace vcsn {
00043 
00044   /*-------------------.
00045   | minimization_moore |
00046   `-------------------*/
00047   // preconditions :
00048   // - the input automaton is deterministic or co-deterministic
00049   //   according to Transposed;
00050   // - the output automaton is well initialized with good sets ;
00051   //
00052 
00053   template<typename A, typename T, bool Transposed>
00054   void
00055   do_minimization_moore(const Element<A, T>& input, Element<A, T>& output)
00056   {
00057     typedef Element<A, T> automata_type;
00058     AUTOMATON_TYPES(automata_type);
00059     AUTOMATON_FREEMONOID_TYPES(automata_type);
00060     using std::map;
00061     using std::vector;
00062     using std::set;
00063 
00064     // Consts.
00065 
00066     const hstate_t      NullState = -1;
00067     const hstate_t      NullGroup = -1;
00068     const alphabet_t&   alphabet (input.series().monoid().alphabet());
00069 
00070     // Typedefs.
00071 
00072     typedef int                                 letterid_t;
00073     typedef int                                 groupid_t;
00074 
00075     typedef set<hstate_t>                       group_t;
00076     typedef vector<group_t>                     groupid_to_group_t;
00077 
00078     typedef vector<hstate_t>                    letterid_to_state_t;
00079 
00080     typedef map<hstate_t, letterid_to_state_t>  state_to_letterid_to_state_t;
00081 
00082     typedef map<hstate_t, groupid_t>            state_to_groupid_t;
00083     typedef map<letter_t,  letterid_t>          letter_to_letterid_t;
00084 
00085     // Variables.
00086 
00087     letter_to_letterid_t                        letter_to_letterid;
00088     state_to_groupid_t                          state_to_groupid;
00089     group_t                                     delta_ret;
00090 
00091     // Store successors if non-inverted, predecessors otherwise.
00092     state_to_letterid_to_state_t                aut_view;
00093 
00094     groupid_to_group_t  groupid_to_group(input.states().size());
00095 
00096     int                                         letter_count = 0;
00097     int                                         i;
00098 
00099     /*---------------.
00100     | Initialization |
00101     `---------------*/
00102 
00103     precondition(input.exists());
00104 
00105     state_to_groupid[NullState] = NullGroup;
00106 
00107     for_all_letters(iletter, alphabet)
00108       letter_to_letterid[*iletter] = letter_count++;
00109 
00110     for_all_states(istate, input)
00111     {
00112       aut_view[*istate] = letterid_to_state_t(letter_count, NullState);
00113       if ((not Transposed and input.is_final(*istate)) or
00114           (Transposed and input.is_initial(*istate)))
00115       {
00116         groupid_to_group[0].insert(*istate);
00117         state_to_groupid[*istate] = 0;
00118       }
00119       else
00120       {
00121         groupid_to_group[1].insert(*istate);
00122         state_to_groupid[*istate] = 1;
00123       }
00124     }
00125 
00126     for_all_states(istate, input)
00127     {
00128       for_all_const_(letter_to_letterid_t, iletter, letter_to_letterid)
00129       {
00130         delta_ret.clear();
00131         if (not Transposed)
00132           input.letter_deltac(delta_ret, *istate, iletter->first,
00133                               delta_kind::states());
00134         else
00135           input.letter_rdeltac(delta_ret, *istate, iletter->first,
00136                                delta_kind::states());
00137         if (not delta_ret.empty())
00138           aut_view[*istate][iletter->second] = *delta_ret.begin();
00139       }
00140     }
00141 
00142 
00143     /*-----.
00144     | Loop |
00145     `-----*/
00146 
00147     int  last_group = 1;
00148     bool group_modified;
00149 
00150     do
00151     {
00152       group_modified = false;
00153 
00154       for_all_groups(igroup, groupid_to_group)
00155       {
00156         if (igroup->empty())
00157           break;
00158 
00159         hstate_t first_state = *(igroup->begin());
00160         bool     group_created = false;
00161 
00162         for_all_state_in_groups(istate, *igroup)
00163         {
00164           for (i = 0; i < letter_count; ++i)
00165             if (state_to_groupid[aut_view[first_state][i]] !=
00166                 state_to_groupid[aut_view[*istate][i]])
00167               break;
00168           if (i != letter_count)
00169           {
00170             group_t::iterator istate_save = istate;
00171 
00172             istate_save--;
00173             if (group_created == false)
00174             {
00175               last_group++;
00176               group_created = true;
00177               group_modified = true;
00178             }
00179             groupid_to_group[last_group].insert(*istate);
00180             state_to_groupid[*istate] = last_group;
00181             igroup->erase(*istate);
00182             istate = istate_save;
00183           }
00184         }
00185       }
00186     }
00187     while (group_modified);
00188 
00189 
00190     /*-----------------------.
00191     | Automaton construction |
00192     `-----------------------*/
00193 
00194     std::vector<hstate_t> new_states(last_group + 1);
00195 
00196     // Create all states.
00197     for (i = 0; i <= last_group; ++i)
00198       new_states[i] = output.add_state();
00199 
00200     // Create all transitions.
00201     for (i = 0; i <= last_group; ++i)
00202     {
00203       hstate_t repres = *(groupid_to_group[i].begin());
00204 
00205       for_all_const_(letter_to_letterid_t, iletter, letter_to_letterid)
00206         if (aut_view[repres][iletter->second] != NullState)
00207         {
00208           if (not Transposed)
00209             output.add_letter_transition(new_states[i],
00210                                          new_states[state_to_groupid
00211                                                     [aut_view[repres]
00212                                                      [iletter->second]]],
00213                                          iletter->first);
00214           else
00215             output.add_letter_transition(new_states[state_to_groupid
00216                                                     [aut_view[repres]
00217                                                      [iletter->second]]],
00218                                          new_states[i],
00219                                          iletter->first);
00220         }
00221     }
00222 
00223     // Setting initial and final states.
00224     if (not Transposed)
00225     {
00226       output.set_final(new_states[0]);
00227       output.set_initial(new_states[state_to_groupid[*input.initial().begin()]]);
00228     }
00229     else
00230     {
00231       output.set_initial(new_states[0]);
00232       output.set_final(new_states[state_to_groupid[*input.final().begin()]]);
00233     }
00234 
00235   }
00236 
00237 
00238   template<typename A, typename T>
00239   void
00240   minimization_moore_here(Element<A, T>& a)
00241   {
00242     Element<A, T> output(a.structure());
00243     do_minimization_moore<A, T, false>(a, output);
00244     a = output;
00245   }
00246 
00247 
00248   template<typename A, typename T>
00249   Element<A, T>
00250   minimization_moore(const Element<A, T>& a)
00251   {
00252     Element<A, T> output(a.structure());
00253     do_minimization_moore<A, T, false>(a, output);
00254     return output;
00255   }
00256 
00257   template<typename A, typename T>
00258   void
00259   co_minimization_moore_here(Element<A, T>& a)
00260   {
00261     Element<A, T> output(a.structure());
00262     do_minimization_moore<A, T, true>(a, output);
00263     a = output;
00264   }
00265 
00266 
00267   template<typename A, typename T>
00268   Element<A, T>
00269   co_minimization_moore(const Element<A, T>& a)
00270   {
00271     Element<A, T> output(a.structure());
00272     do_minimization_moore<A, T, true>(a, output);
00273     return output;
00274   }
00275 
00276 } // vcsn
00277 
00278 // Prevent potential conflicts.
00279 # undef for_all_groups
00280 # undef for_all_state_in_groups
00281 
00282 
00283 #endif // ! VCSN_ALGORITHMS_MINIMIZATION_MOORE_HXX

Generated on Sat Jul 29 17:13:09 2006 for Vaucanson by  doxygen 1.4.6