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

- File List
- File Members

# 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