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

Generated on Thu Oct 9 20:22:40 2008 for Vaucanson by  doxygen 1.5.1