Vaucanson  1.4.1
shortest.hxx
1 // shortest.hh: this file is part of the Vaucanson project.
2 //
3 // Vaucanson, a generic library for finite state machines.
4 //
5 // Copyright (C) 2008, 2009, 2010 The Vaucanson Group.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11 //
12 // The complete GNU General Public Licence Notice can be found as the
13 // `COPYING' file in the root directory.
14 //
15 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
16 //
17 #ifndef VCSN_ALGORITHMS_SHORTEST_HXX
18 # define VCSN_ALGORITHMS_SHORTEST_HXX
19 
21 #include <vaucanson/automata/concept/automata_base.hh>
22 #include <vaucanson/misc/usual_macros.hh>
23 #include <queue>
24 #include <map>
25 #include <vaucanson/misc/military_order.hh>
27 
28 namespace vcsn
29 {
30  template<typename Automaton, typename MonoidElt>
31  bool
32  do_shortest(const Automaton& autom, MonoidElt& word)
33  {
34  precondition(is_realtime(autom));
35  AUTOMATON_TYPES(Automaton);
36  AUTOMATON_FREEMONOID_TYPES (Automaton);
37 
38  monoid_t themonoid = autom.structure().series().monoid();
39  // shortest word read at this state
40  typedef std::map<hstate_t, monoid_elt_t> theword_t;
41  theword_t theword;
42  std::queue<hstate_t> thequeue;
43 
44  monoid_elt_t empty_word = themonoid.identity(SELECT(monoid_elt_value_t));
45 
46  for_all_initial_states(j, autom)
47  {
48  theword.insert(std::pair<hstate_t,monoid_elt_t>(*j, empty_word));
49  if (autom.is_final(*j))
50  {
51  word = empty_word;
52  return true;
53  }
54  thequeue.push(*j);
55  }
56 
57  while (not thequeue.empty())
58  {
59  hstate_t i = thequeue.front();
60  thequeue.pop();
61  for_all_letters(a, themonoid.alphabet())
62  {
63  for (typename Automaton::delta_iterator t(autom.value(), i);
64  ! t.done();
65  t.next())
66  {
67  // iterate over successors of i by *a
68  monoid_elt_t w(themonoid, *a);
69  if (autom.series_of(*t).get(w)
70  != autom.series().semiring()
71  .zero(SELECT(typename semiring_elt_t::value_t)))
72  {
73  hstate_t j = autom.dst_of(*t);
74  if (theword.find(j) == theword.end())
75  {
76  // j is in the map only if it has been seen
77  // before, otherwise:
78 
79  typename theword_t::const_iterator k = theword.find(i);
80  assert(k != theword.end());
81 
82  theword.insert(std::pair<hstate_t, monoid_elt_t>(j, k->second * (*a)));
83  if (autom.is_final(j))
84  {
85  typename theword_t::const_iterator k = theword.find(j);
86  assert(k != theword.end());
87 
88  word = k->second;
89  return true;
90  }
91  thequeue.push(j);
92  }
93  }
94  }
95  }
96  }
97  return false;
98  }
99 
100  template<typename Automaton, typename MonoidElt, typename Alloc>
101  void
102  do_enumerate(const Automaton& autom,
103  unsigned max_length,
104  std::list<MonoidElt, Alloc>& words)
105  {
106  precondition(is_realtime(autom));
107 
108  AUTOMATON_TYPES(Automaton);
109  AUTOMATON_FREEMONOID_TYPES (Automaton);
110  monoid_t themonoid = autom.structure().series().monoid();
111  // a list of words that leads to this state
112  std::map<hstate_t,std::list<monoid_elt_t> > theword;
113  //std::list allows swap, contrary to std::queue
114  std::list<std::pair<hstate_t,monoid_elt_t> > queue1;
115  std::list<std::pair<hstate_t,monoid_elt_t> > queue2;
116 
117  monoid_elt_t empty_word = themonoid.identity(SELECT(monoid_elt_value_t));
118 
119  for_all_initial_states(j, autom)
120  {
121  theword[*j].push_back(empty_word);
122  queue1.push_back(std::pair<hstate_t,monoid_elt_t>(*j, empty_word));
123  }
124 
125  for(unsigned i = 0; i < max_length && not queue1.empty(); i++)
126  {
127  while (not queue1.empty())
128  {
129  std::pair<hstate_t,monoid_elt_t> thepair = queue1.front();
130  queue1.pop_front();
131  hstate_t s = thepair.first;
132  monoid_elt_t oldword = thepair.second;
133  for (typename Automaton::delta_iterator t(autom.value(), s);
134  ! t.done();
135  t.next())
136  {
137  for_all_letters(a, themonoid.alphabet())
138  {
139  // iterate over successors of i by *a
140  monoid_elt_t w(themonoid, *a);
141  if (autom.series_of(*t).get(w) !=
142  autom.series().semiring().zero(SELECT(typename semiring_elt_t::value_t)))
143  {
144  monoid_elt_t newword = oldword *(*a);
145  theword[autom.dst_of(*t)].push_back(newword);
146  queue2.push_back(std::pair<hstate_t,monoid_elt_t>(autom.dst_of(*t),newword));
147  }
148  }
149  }
150  }
151  queue1.swap(queue2);
152  }
153 
154  std::vector<monoid_elt_t> v;
155  for_all_final_states(j, autom)
156  {
157  std::list<monoid_elt_t> &l = theword[*j];
158  v.insert(v.end(), l.begin(), l.end());
159  }
160  sort(v.begin(), v.end(), MilitaryOrder<monoid_elt_t>());
161  typename std::vector<monoid_elt_t>::iterator v_last
162  = std::unique(v.begin(), v.end());
163  words.insert(words.begin(), v.begin(), v_last);
164  }
165 
166  template<typename Automaton>
167  typename Automaton::monoid_elt_t
168  shortest(const Automaton& autom)
169  {
170  typename Automaton::monoid_elt_t word(autom.structure().series().monoid());
171  do_shortest(autom, word);
172  return word;
173  }
174 
175  template<typename Automaton, typename MonoidElt>
176  bool
177  shortest(const Automaton& autom, MonoidElt& word)
178  {
179  return do_shortest(autom, word);
180  }
181 
182  template<typename Automaton, typename MonoidElt, typename Alloc>
183  void
184  enumerate(const Automaton& autom, unsigned max_length,
185  std::list<MonoidElt, Alloc>& word_list)
186  {
187  do_enumerate(autom, max_length, word_list);
188  }
189 } // ! vcsn
190 
191 #endif // ! VCSN_ALGORITHMS_SHORTEST_HXX