Vaucanson 1.4
|
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