Vaucanson 1.4
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     BENCH_TASK_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     for_all_const_states(istate, input)
00122     {
00123       for_all_const_(letter_to_letterid_t, iletter, letter_to_letterid)
00124       {
00125         bool empty = true;
00126         hstate_t first;
00127         if (not Transposed)
00128         {
00129           for (delta_iterator t(input.value(), *istate);
00130                ! t.done() && empty;
00131                t.next())
00132           {
00133             monoid_elt_t w(input.series_of(*t).structure().monoid(), iletter->first);
00134             if (input.series_of(*t).get(w) != input.series().semiring().wzero_)
00135             {
00136               empty = false;
00137               first = input.dst_of(*t);
00138               break;
00139             }
00140           }
00141         }
00142         else
00143         {
00144           for (rdelta_iterator t(input.value(), *istate);
00145                ! t.done() && empty;
00146                t.next())
00147           {
00148             monoid_elt_t w(input.series_of(*t).structure().monoid(), iletter->first);
00149             if (input.series_of(*t).get(w) != input.series().semiring().wzero_)
00150             {
00151               empty = false;
00152               first = input.src_of(*t);
00153               break;
00154             }
00155           }
00156         }
00157         if (not empty)
00158           aut_view[*istate][iletter->second] = first;
00159       }
00160     }
00161 
00162 
00163     /*-----.
00164     | Loop |
00165     `-----*/
00166 
00167     int  last_group = 1;
00168     for (bool group_modified = true; group_modified;)
00169     {
00170       group_modified = false;
00171       for_all_groups(igroup, groupid_to_group)
00172       {
00173         if (igroup->empty())
00174           break;
00175 
00176         hstate_t first_state = *(igroup->begin());
00177         bool     group_created = false;
00178 
00179         for_all_state_in_groups(istate, *igroup)
00180         {
00181           int i;
00182           for (i = 0; i < letter_count; ++i)
00183             if (state_to_groupid[aut_view[first_state][i]] !=
00184                 state_to_groupid[aut_view[*istate][i]])
00185               break;
00186           if (i != letter_count)
00187           {
00188             typename group_t::iterator istate_save = istate;
00189 
00190             istate_save--;
00191             if (group_created == false)
00192             {
00193               last_group++;
00194               group_created = true;
00195               group_modified = true;
00196             }
00197             groupid_to_group[last_group].insert(*istate);
00198             state_to_groupid[*istate] = last_group;
00199             igroup->erase(*istate);
00200             istate = istate_save;
00201           }
00202         }
00203       }
00204     }
00205 
00206 
00207     /*-----------------------.
00208     | Automaton construction |
00209     `-----------------------*/
00210 
00211     std::vector<hstate_t> new_states(last_group + 1);
00212 
00213     // Create all states.
00214     for (int i = 0; i <= last_group; ++i)
00215       new_states[i] = output.add_state();
00216 
00217     // Create all transitions.
00218     for (int i = 0; i <= last_group; ++i)
00219     {
00220       hstate_t repres = *(groupid_to_group[i].begin());
00221 
00222       for_all_const_(letter_to_letterid_t, iletter, letter_to_letterid)
00223         if (aut_view[repres][iletter->second] != NullState)
00224         {
00225           if (not Transposed)
00226             output.add_letter_transition(new_states[i],
00227                                          new_states[state_to_groupid
00228                                                     [aut_view[repres]
00229                                                      [iletter->second]]],
00230                                          iletter->first);
00231           else
00232             output.add_letter_transition(new_states[state_to_groupid
00233                                                     [aut_view[repres]
00234                                                      [iletter->second]]],
00235                                          new_states[i],
00236                                          iletter->first);
00237         }
00238     }
00239 
00240     // Setting initial and final states.
00241     if (not Transposed)
00242     {
00243       output.set_final(new_states[0]);
00244       output.set_initial(new_states[state_to_groupid[*input.initial().begin()]]);
00245     }
00246     else
00247     {
00248       output.set_initial(new_states[0]);
00249       output.set_final(new_states[state_to_groupid[*input.final().begin()]]);
00250     }
00251 
00252   }
00253 
00254 
00255   template<typename A, typename AI>
00256   void
00257   minimization_moore_here(Element<A, AI>& a)
00258   {
00259     precondition(is_deterministic(a));
00260     precondition(is_complete(a));
00261     Element<A, AI> output(a.structure());
00262     do_minimization_moore<A, AI, false>(a, output);
00263     a = output;
00264   }
00265 
00266 
00267   template<typename A, typename AI>
00268   Element<A, AI>
00269   minimization_moore(const Element<A, AI>& a)
00270   {
00271     precondition(is_deterministic(a));
00272     precondition(is_complete(a));
00273     Element<A, AI> output(a.structure());
00274     do_minimization_moore<A, AI, false>(a, output);
00275     return output;
00276   }
00277 
00278   template<typename A, typename AI>
00279   void
00280   co_minimization_moore_here(Element<A, AI>& a)
00281   {
00282     precondition(is_deterministic(transpose(a)));
00283     precondition(is_complete(transpose(a)));
00284     Element<A, AI> output(a.structure());
00285     do_minimization_moore<A, AI, true>(a, output);
00286     a = output;
00287   }
00288 
00289 
00290   template<typename A, typename AI>
00291   Element<A, AI>
00292   co_minimization_moore(const Element<A, AI>& a)
00293   {
00294     precondition(is_deterministic(transpose(a)));
00295     precondition(is_complete(transpose(a)));
00296     Element<A, AI> output(a.structure());
00297     do_minimization_moore<A, AI, true>(a, output);
00298     return output;
00299   }
00300 
00301 } // vcsn
00302 
00303 // Prevent potential conflicts.
00304 # undef for_all_groups
00305 # undef for_all_state_in_groups
00306 
00307 
00308 #endif // ! VCSN_ALGORITHMS_MINIMIZATION_MOORE_HXX