Vaucanson 1.4
shortest.hxx
00001 // shortest.hh: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2008, 2009, 2010 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_SHORTEST_HXX
00018 # define VCSN_ALGORITHMS_SHORTEST_HXX
00019 
00020 #include <vaucanson/algorithms/shortest.hh>
00021 #include <vaucanson/automata/concept/automata_base.hh>
00022 #include <vaucanson/misc/usual_macros.hh>
00023 #include <queue>
00024 #include <map>
00025 #include <vaucanson/misc/military_order.hh>
00026 #include <vaucanson/algorithms/shortest.hh>
00027 
00028 namespace vcsn
00029 {
00030   template<typename Automaton, typename MonoidElt>
00031   bool
00032   do_shortest(const Automaton& autom, MonoidElt& word)
00033   {
00034     precondition(is_realtime(autom));
00035     AUTOMATON_TYPES(Automaton);
00036     AUTOMATON_FREEMONOID_TYPES (Automaton);
00037 
00038     monoid_t themonoid = autom.structure().series().monoid();
00039     // shortest word read at this state
00040     typedef std::map<hstate_t, monoid_elt_t> theword_t;
00041     theword_t theword;
00042     std::queue<hstate_t> thequeue;
00043 
00044     monoid_elt_t empty_word = themonoid.identity(SELECT(monoid_elt_value_t));
00045 
00046     for_all_initial_states(j, autom)
00047       {
00048         theword.insert(std::pair<hstate_t,monoid_elt_t>(*j, empty_word));
00049         if (autom.is_final(*j))
00050           {
00051             word = empty_word;
00052             return true;
00053           }
00054         thequeue.push(*j);
00055       }
00056 
00057     while (not thequeue.empty())
00058       {
00059         hstate_t i = thequeue.front();
00060         thequeue.pop();
00061         for_all_letters(a, themonoid.alphabet())
00062           {
00063             for (typename Automaton::delta_iterator t(autom.value(), i);
00064                  ! t.done();
00065                  t.next())
00066               {
00067                 // iterate over successors of i by *a
00068                 monoid_elt_t w(themonoid, *a);
00069                 if (autom.series_of(*t).get(w)
00070                     != autom.series().semiring()
00071                        .zero(SELECT(typename semiring_elt_t::value_t)))
00072                   {
00073                     hstate_t j = autom.dst_of(*t);
00074                     if (theword.find(j) == theword.end())
00075                       {
00076                         // j is in the map only if it has been seen
00077                         // before, otherwise:
00078 
00079                         typename theword_t::const_iterator k = theword.find(i);
00080                         assert(k != theword.end());
00081 
00082                         theword.insert(std::pair<hstate_t, monoid_elt_t>(j, k->second * (*a)));
00083                         if (autom.is_final(j))
00084                           {
00085                             typename theword_t::const_iterator k = theword.find(j);
00086                             assert(k != theword.end());
00087 
00088                             word = k->second;
00089                             return true;
00090                           }
00091                         thequeue.push(j);
00092                       }
00093                   }
00094               }
00095           }
00096       }
00097     return false;
00098   }
00099 
00100   template<typename Automaton, typename MonoidElt, typename Alloc>
00101   void
00102   do_enumerate(const Automaton& autom,
00103                unsigned max_length,
00104                std::list<MonoidElt, Alloc>& words)
00105   {
00106     precondition(is_realtime(autom));
00107 
00108     AUTOMATON_TYPES(Automaton);
00109     AUTOMATON_FREEMONOID_TYPES (Automaton);
00110     monoid_t themonoid = autom.structure().series().monoid();
00111     // a list of words that leads to this state
00112     std::map<hstate_t,std::list<monoid_elt_t> > theword;
00113     //std::list allows swap, contrary to std::queue
00114     std::list<std::pair<hstate_t,monoid_elt_t> > queue1;
00115     std::list<std::pair<hstate_t,monoid_elt_t> > queue2;
00116 
00117     monoid_elt_t empty_word = themonoid.identity(SELECT(monoid_elt_value_t));
00118 
00119     for_all_initial_states(j, autom)
00120       {
00121         theword[*j].push_back(empty_word);
00122         queue1.push_back(std::pair<hstate_t,monoid_elt_t>(*j, empty_word));
00123       }
00124 
00125     for(unsigned i = 0; i < max_length && not queue1.empty(); i++)
00126       {
00127         while (not queue1.empty())
00128           {
00129             std::pair<hstate_t,monoid_elt_t> thepair = queue1.front();
00130             queue1.pop_front();
00131             hstate_t s = thepair.first;
00132             monoid_elt_t oldword = thepair.second;
00133             for (typename Automaton::delta_iterator t(autom.value(), s);
00134                  ! t.done();
00135                  t.next())
00136               {
00137                 for_all_letters(a, themonoid.alphabet())
00138                   {
00139                     // iterate over successors of i by *a
00140                     monoid_elt_t w(themonoid, *a);
00141                     if (autom.series_of(*t).get(w) !=
00142                         autom.series().semiring().zero(SELECT(typename semiring_elt_t::value_t)))
00143                       {
00144                         monoid_elt_t newword = oldword *(*a);
00145                         theword[autom.dst_of(*t)].push_back(newword);
00146                         queue2.push_back(std::pair<hstate_t,monoid_elt_t>(autom.dst_of(*t),newword));
00147                       }
00148                   }
00149               }
00150           }
00151         queue1.swap(queue2);
00152       }
00153 
00154     std::vector<monoid_elt_t> v;
00155     for_all_final_states(j, autom)
00156       {
00157         std::list<monoid_elt_t> &l = theword[*j];
00158         v.insert(v.end(), l.begin(), l.end());
00159       }
00160     sort(v.begin(), v.end(), MilitaryOrder<monoid_elt_t>());
00161     typename std::vector<monoid_elt_t>::iterator v_last
00162       = std::unique(v.begin(), v.end());
00163     words.insert(words.begin(), v.begin(), v_last);
00164   }
00165 
00166   template<typename Automaton>
00167   typename Automaton::monoid_elt_t
00168   shortest(const Automaton& autom)
00169   {
00170     typename Automaton::monoid_elt_t word(autom.structure().series().monoid());
00171     do_shortest(autom, word);
00172     return word;
00173   }
00174 
00175   template<typename Automaton, typename MonoidElt>
00176   bool
00177   shortest(const Automaton& autom, MonoidElt& word)
00178   {
00179     return do_shortest(autom, word);
00180   }
00181 
00182   template<typename Automaton, typename MonoidElt, typename Alloc>
00183   void
00184   enumerate(const Automaton& autom, unsigned max_length,
00185             std::list<MonoidElt, Alloc>& word_list)
00186   {
00187     do_enumerate(autom, max_length, word_list);
00188   }
00189 } // ! vcsn
00190 
00191 #endif // ! VCSN_ALGORITHMS_SHORTEST_HXX