Vaucanson 1.4
|
00001 // universal.hxx: this file is part of the Vaucanson project. 00002 // 00003 // Vaucanson, a generic library for finite state machines. 00004 // 00005 // Copyright (C) 2011 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_UNIVERSAL_HXX 00018 # define VCSN_ALGORITHMS_UNIVERSAL_HXX 00019 00020 00021 # include <map> 00022 # include <set> 00023 00024 # include <vaucanson/boolean_automaton.hh> 00025 # include <vaucanson/algorithms/determinize.hh> 00026 # include <vaucanson/algorithms/transpose.hh> 00027 # include <vaucanson/algorithms/complete.hh> 00028 00029 # include <vaucanson/misc/usual_macros.hh> 00030 00031 namespace vcsn { 00032 00033 namespace universal_internal { 00034 00035 // Returns the intersection of two sets. 00036 template<typename Set> 00037 Set intersection_structure(const Set& set1, const Set& set2) 00038 { 00039 Set tmp; 00040 std::insert_iterator<Set> i(tmp, tmp.begin()); 00041 std::set_intersection(set1.begin(), set1.end(), 00042 set2.begin(), set2.end(), 00043 i); 00044 return tmp; 00045 } 00046 00047 // A simple intersection closure. 00048 template<typename Set> 00049 std::set<Set> intersection_closure(const std::set<Set>& s) 00050 { 00051 std::set<Set> tmp = s; 00052 std::set<Set> ret = s; 00053 00054 do { 00055 std::swap(ret, tmp); 00056 for_all_const_(std::set<Set>, s1, tmp) 00057 for_all_const_(std::set<Set>, s2, tmp) 00058 ret.insert(intersection_structure(*s1, *s2)); 00059 } while (ret.size() != tmp.size()); 00060 return ret; 00061 } 00062 00063 // Return the image of a map. 00064 template<typename K, typename V> 00065 std::set<V> image(const std::map<K,V>& m) 00066 { 00067 std::set<V> ret; 00068 for(typename std::map<K,V>::const_iterator a=m.begin(); a!= m.end(); ++a) 00069 ret.insert(a->second); 00070 return ret; 00071 } 00072 00073 // Return true if a set1 \subset set2. 00074 template <class Container1, class Container2> 00075 bool includes(const Container1& set1, const Container2& set2) 00076 { 00077 return std::includes(set2.begin(), set2.end(), 00078 set1.begin(), set1.end()); 00079 } 00080 } //univeral_internal 00081 00082 00083 // And now, the algorithm: 00084 template<typename A, typename AI> 00085 void do_universal(const AutomataBase<A>&, 00086 const Element<A,AI>& a, 00087 Element<A,AI>& u) 00088 { 00089 typedef Element<A, AI> Auto; 00090 AUTOMATON_TYPES(Auto); 00091 AUTOMATON_FREEMONOID_TYPES(Auto); 00092 00093 typedef std::set<std::set<hstate_t> > pstate_t; 00094 typedef std::set<hstate_t> state_set_t; 00095 typedef std::map<hstate_t, state_set_t> map_t; 00096 00097 using namespace universal_internal; 00098 00099 Auto automaton(a); 00100 00101 if(!is_deterministic(automaton)) 00102 automaton = determinize(automaton); 00103 if(!is_complete(automaton)) 00104 automaton = complete(automaton); 00105 00106 00107 // let i, be the initial state of automaton. 00108 hstate_t i = *automaton.initial().begin(); 00109 00110 // compute the co-determinized of the minimal automaton 00111 // and retrieve the origin of each state. 00112 map_t origin; 00113 Auto transposed = transpose(automaton); 00114 Auto co_det = determinize(transposed, origin); 00115 00116 // the 'origin' is a map from co_det's hstate_t to 00117 // minimal's std::set<hstate_t>. 00118 // let 'transp_states' be the image of 'origin'. 00119 pstate_t transp_states = image(origin); 00120 00121 // the universal automaton's state set is its intersection closure. 00122 pstate_t univers_states(intersection_closure(transp_states)); 00123 00124 // we have to save the state set associated to each automaton. 00125 map_t subset_label; 00126 00127 // X = univers_states \ {}. 00128 for_all_const_(pstate_t, s, univers_states) 00129 if (s->size() != 0) 00130 { 00131 hstate_t new_s = u.add_state(); 00132 subset_label[new_s] = *s; 00133 // J = { X | i in X } 00134 if (s->find(i) != s->end()) 00135 u.set_initial(new_s); 00136 // U = { X | X \subset T } 00137 if (includes(*s, automaton.final())) 00138 u.set_final(new_s); 00139 } 00140 00141 // finally, the transition set. 00142 for_all_states(x, u) 00143 for_all_states(y, u) 00144 for_all_letters(a, u.series().monoid().alphabet()) 00145 { 00146 bool cont = false; 00147 std::set<hstate_t> delta_ret; 00148 for_all_const_(state_set_t, s, subset_label[*x]) 00149 { 00150 bool empty = true; 00151 // FIXME: bmig complains "Assertion failed: has_state(s)" for 00152 // the line below. 00153 for (typename automaton_t::delta_iterator dst(automaton.value(), *s); 00154 ! dst.done(); dst.next()) 00155 { 00156 monoid_elt_t w(automaton.series_of(*dst).structure().monoid(), *a); 00157 if (automaton.series_of(*dst).get(w) 00158 != automaton.series().semiring().wzero_) 00159 { 00160 empty = false; 00161 delta_ret.insert(automaton.dst_of(*dst)); 00162 } 00163 } 00164 if (empty) 00165 { 00166 cont = true; 00167 break; 00168 } 00169 } 00170 // case 1: \exists p \in X, p.a = {} 00171 if (cont) 00172 continue; 00173 // case 2: X.a \subset Y ? 00174 if (includes(delta_ret, subset_label[*y])) 00175 u.add_letter_transition(*x, *y, *a); 00176 } 00177 } 00178 00179 template<typename A, typename AI> 00180 Element<A, AI> 00181 universal(const Element<A, AI>& a) 00182 { 00183 precondition(is_realtime(a)); 00184 00185 Element<A, AI> ret(a.structure()); 00186 do_universal(a.structure(), a, ret); 00187 return ret; 00188 } 00189 00190 } // vcsn 00191 #endif // !VCSN_ALGORITHMS_UNIVERSAL_HXX