Vaucanson  1.4.1
universal.hxx
1 // universal.hxx: this file is part of the Vaucanson project.
2 //
3 // Vaucanson, a generic library for finite state machines.
4 //
5 // Copyright (C) 2011 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_UNIVERSAL_HXX
18 # define VCSN_ALGORITHMS_UNIVERSAL_HXX
19 
20 
21 # include <map>
22 # include <set>
23 
24 # include <vaucanson/boolean_automaton.hh>
28 
29 # include <vaucanson/misc/usual_macros.hh>
30 
31 namespace vcsn {
32 
33  namespace universal_internal {
34 
35  // Returns the intersection of two sets.
36  template<typename Set>
37  Set intersection_structure(const Set& set1, const Set& set2)
38  {
39  Set tmp;
40  std::insert_iterator<Set> i(tmp, tmp.begin());
41  std::set_intersection(set1.begin(), set1.end(),
42  set2.begin(), set2.end(),
43  i);
44  return tmp;
45  }
46 
47  // A simple intersection closure.
48  template<typename Set>
49  std::set<Set> intersection_closure(const std::set<Set>& s)
50  {
51  std::set<Set> tmp = s;
52  std::set<Set> ret = s;
53 
54  do {
55  std::swap(ret, tmp);
56  for_all_const_(std::set<Set>, s1, tmp)
57  for_all_const_(std::set<Set>, s2, tmp)
58  ret.insert(intersection_structure(*s1, *s2));
59  } while (ret.size() != tmp.size());
60  return ret;
61  }
62 
63  // Return the image of a map.
64  template<typename K, typename V>
65  std::set<V> image(const std::map<K,V>& m)
66  {
67  std::set<V> ret;
68  for(typename std::map<K,V>::const_iterator a=m.begin(); a!= m.end(); ++a)
69  ret.insert(a->second);
70  return ret;
71  }
72 
73  // Return true if a set1 \subset set2.
74  template <class Container1, class Container2>
75  bool includes(const Container1& set1, const Container2& set2)
76  {
77  return std::includes(set2.begin(), set2.end(),
78  set1.begin(), set1.end());
79  }
80  } //univeral_internal
81 
82 
83 // And now, the algorithm:
84  template<typename A, typename AI>
85  void do_universal(const AutomataBase<A>&,
86  const Element<A,AI>& a,
87  Element<A,AI>& u)
88  {
89  typedef Element<A, AI> Auto;
90  AUTOMATON_TYPES(Auto);
91  AUTOMATON_FREEMONOID_TYPES(Auto);
92 
93  typedef std::set<std::set<hstate_t> > pstate_t;
94  typedef std::set<hstate_t> state_set_t;
95  typedef std::map<hstate_t, state_set_t> map_t;
96 
97  using namespace universal_internal;
98 
99  Auto automaton(a);
100 
101  if(!is_deterministic(automaton))
102  automaton = determinize(automaton);
103  if(!is_complete(automaton))
104  automaton = complete(automaton);
105 
106 
107  // let i, be the initial state of automaton.
108  hstate_t i = *automaton.initial().begin();
109 
110  // compute the co-determinized of the minimal automaton
111  // and retrieve the origin of each state.
112  map_t origin;
113  Auto transposed = transpose(automaton);
114  Auto co_det = determinize(transposed, origin);
115 
116  // the 'origin' is a map from co_det's hstate_t to
117  // minimal's std::set<hstate_t>.
118  // let 'transp_states' be the image of 'origin'.
119  pstate_t transp_states = image(origin);
120 
121  // the universal automaton's state set is its intersection closure.
122  pstate_t univers_states(intersection_closure(transp_states));
123 
124  // we have to save the state set associated to each automaton.
125  map_t subset_label;
126 
127  // X = univers_states \ {}.
128  for_all_const_(pstate_t, s, univers_states)
129  if (s->size() != 0)
130  {
131  hstate_t new_s = u.add_state();
132  subset_label[new_s] = *s;
133  // J = { X | i in X }
134  if (s->find(i) != s->end())
135  u.set_initial(new_s);
136  // U = { X | X \subset T }
137  if (includes(*s, automaton.final()))
138  u.set_final(new_s);
139  }
140 
141  // finally, the transition set.
142  for_all_states(x, u)
143  for_all_states(y, u)
144  for_all_letters(a, u.series().monoid().alphabet())
145  {
146  bool cont = false;
147  std::set<hstate_t> delta_ret;
148  for_all_const_(state_set_t, s, subset_label[*x])
149  {
150  bool empty = true;
151  // FIXME: bmig complains "Assertion failed: has_state(s)" for
152  // the line below.
153  for (typename automaton_t::delta_iterator dst(automaton.value(), *s);
154  ! dst.done(); dst.next())
155  {
156  monoid_elt_t w(automaton.series_of(*dst).structure().monoid(), *a);
157  if (automaton.series_of(*dst).get(w)
158  != automaton.series().semiring().wzero_)
159  {
160  empty = false;
161  delta_ret.insert(automaton.dst_of(*dst));
162  }
163  }
164  if (empty)
165  {
166  cont = true;
167  break;
168  }
169  }
170  // case 1: \exists p \in X, p.a = {}
171  if (cont)
172  continue;
173  // case 2: X.a \subset Y ?
174  if (includes(delta_ret, subset_label[*y]))
175  u.add_letter_transition(*x, *y, *a);
176  }
177  }
178 
179  template<typename A, typename AI>
180  Element<A, AI>
182  {
183  precondition(is_realtime(a));
184 
185  Element<A, AI> ret(a.structure());
186  do_universal(a.structure(), a, ret);
187  return ret;
188  }
189 
190 } // vcsn
191 #endif // !VCSN_ALGORITHMS_UNIVERSAL_HXX