Vaucanson 1.4
determinize.hxx
00001 // determinize.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The
00006 // Vaucanson Group.
00007 //
00008 // This program is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU General Public License
00010 // as published by the Free Software Foundation; either version 2
00011 // of the License, or (at your option) any later version.
00012 //
00013 // The complete GNU General Public Licence Notice can be found as the
00014 // `COPYING' file in the root directory.
00015 //
00016 // The Vaucanson Group consists of people listed in the `AUTHORS' file.
00017 //
00018 #ifndef VCSN_ALGORITHMS_DETERMINIZE_HXX
00019 # define VCSN_ALGORITHMS_DETERMINIZE_HXX
00020 
00021 # include <map>
00022 # include <set>
00023 # include <queue>
00024 # include <vaucanson/misc/usual_macros.hh>
00025 # include <vaucanson/automata/concept/automata_base.hh>
00026 
00027 # ifndef VCSN_NDEBUG
00028 #  include <vaucanson/algorithms/realtime.hh>
00029 # endif // ! VCSN_NDEBUG
00030 
00031 namespace vcsn {
00032 
00033   /*--------------------.
00034   | subset_construction |
00035   `--------------------*/
00036   // preconditions :
00037   //    - output has been initialized with good series set
00038   //      (alphabet is well initialized) ;
00039   //    - this algorithm is intended to work with realtime automaton
00040   //      over |B<A*> => add concept checking.
00041   //
00042 
00043   template <typename A, typename input_t, typename output_t>
00044   void
00045   do_subset_construction(const AutomataBase<A>& ,
00046                          output_t&              output,
00047                          const input_t&         input,
00048                          std::map<typename output_t::hstate_t,
00049                           std::set<typename input_t::hstate_t> >& m =
00050                          std::map<typename output_t::hstate_t,
00051                           std::set<typename input_t::hstate_t> >())
00052   {
00053 
00054     /*--------.
00055     | Typedef |
00056     `--------*/
00057 
00058     AUTOMATON_TYPES(input_t);
00059     AUTOMATON_FREEMONOID_TYPES(input_t);
00060     typedef typename std::set<typename input_t::hstate_t>    subset_t;
00061     typedef typename std::map<subset_t, typename output_t::hstate_t>
00062                                                              subset_set_t;
00063     typedef std::pair<subset_t, typename output_t::hstate_t> subset_set_pair_t;
00064     typedef std::vector<typename input_t::hstate_t>          delta_ret_t;
00065 
00066 
00067     /*-----------------.
00068     | Initialization.  |
00069     `-----------------*/
00070 
00071     typename output_t::hstate_t qi_hstate = output.add_state();
00072     subset_t qi;
00073     bool is_final = false;
00074     for_all_const_initial_states(i, input)
00075     {
00076       qi.insert(*i);
00077       is_final |= input.is_final(*i);
00078     }
00079     output.set_initial(qi_hstate);
00080 
00081     if (is_final)
00082       output.set_final(qi_hstate);
00083 
00084     subset_set_t subset_set;
00085     subset_set[qi] = qi_hstate;
00086     m[qi_hstate] = qi;
00087 
00088 
00089     /*------------.
00090     | Main loop.  |
00091     `------------*/
00092 
00093     subset_t q;
00094     const alphabet_t& alphabet(input.structure().series().monoid().alphabet());
00095     delta_ret_t dst;
00096     dst.reserve(input.states().size());
00097     std::queue<subset_t> path;
00098     path.push(qi);
00099     while (!path.empty())
00100     {
00101       subset_t s = path.front();
00102       typename input_t::hstate_t s_hstate = subset_set[s];
00103       path.pop();
00104 
00105       for_all_const_letters(e, alphabet)
00106       {
00107         q.clear ();
00108         bool is_final = false;
00109         for_all_const_ (subset_t, j, s)
00110         {
00111           for (delta_iterator t(input.value(), *j); ! t.done(); t.next())
00112           {
00113             monoid_elt_t w(input.series_of(*t).structure().monoid(), *e);
00114             if (input.series_of(*t).get(w) != input.series().semiring().wzero_)
00115             {
00116               hstate_t s = input.dst_of(*t);
00117               q.insert(s);
00118               is_final |= input.is_final(s);
00119             }
00120           }
00121         }
00122         typename subset_set_t::const_iterator current = subset_set.find(q);
00123         if (current == subset_set.end())
00124         {
00125           typename output_t::hstate_t qs = output.add_state();
00126           current = (subset_set.insert(subset_set_pair_t(q, qs))).first;
00127           m[qs] = q;
00128 
00129           if (is_final)
00130             output.set_final(current->second);
00131           path.push(q);
00132         }
00133         output.add_letter_transition(s_hstate, (*current).second, *e);
00134       }
00135     }
00136   }
00137 
00138   template<typename A, typename AI>
00139   Element<A, AI>
00140   subset_construction(const Element<A, AI>& a)
00141   {
00142     Element<A, AI> res(a.structure());
00143     do_subset_construction(res.structure(), res, a);
00144     return res;
00145   }
00146 
00147   /*--------------.
00148   | determinize.  |
00149   `--------------*/
00150   template <typename A, typename AI>
00151   void
00152   do_determinize(const AutomataBase<A>& a_set,
00153                  Element<A, AI>&        output,
00154                  const Element<A, AI>&  input,
00155                  std::map<typename Element<A, AI>::hstate_t,
00156                           std::set<typename Element<A, AI>::hstate_t> >& m)
00157   {
00158     BENCH_TASK_SCOPED("determinize");
00159     precondition(is_realtime(input));
00160     do_subset_construction(a_set, output, input, m);
00161   }
00162 
00163   template<typename A, typename AI>
00164   Element<A, AI>
00165   determinize(const Element<A, AI>& a,
00166               std::map<typename Element<A, AI>::hstate_t,
00167                 std::set<typename Element<A, AI>::hstate_t> >& m)
00168   {
00169     Element<A, AI> ret(a.structure());
00170     do_determinize(ret.structure(), ret, a, m);
00171     return ret;
00172   }
00173 
00174   template<typename A, typename AI>
00175   Element<A, AI>
00176   determinize(const Element<A, AI>& a)
00177   {
00178     std::map<typename Element<A, AI>::hstate_t,
00179              std::set<typename Element<A, AI>::hstate_t> > m;
00180     return determinize(a, m);
00181   }
00182 
00183 } // vcsn
00184 
00185 #endif // ! VCSN_ALGORITHMS_DETERMINIZE_HXX