- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

# infiltration.hxx

    00001 // infiltration.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, 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_INFILTRATION_HXX
    00018 # define VCSN_ALGORITHMS_INFILTRATION_HXX
    00019
    00020 # include <set>
    00021 # include <map>
    00022 # include <queue>
    00023 # include <stack>
    00024
    00025 # include <vaucanson/algorithms/infiltration.hh>
    00026
    00027 # ifndef VCSN_NDEBUG
    00028 #  include <vaucanson/algorithms/realtime.hh>
    00029 # endif // ! VCSN_NDEBUG
    00030
    00031 # include <vaucanson/automata/concept/automata_base.hh>
    00032 # include <vaucanson/misc/usual_macros.hh>
    00033 # include <vaucanson/automata/implementation/geometry.hh>
    00034 # include <vaucanson/misc/static.hh>
    00035
    00036 namespace vcsn
    00037 {
    00038
    00039 /*--------------------------------.
    00040 | Functor for infiltration algorithm.  |
    00041 `--------------------------------*/
    00042 template<typename A, typename T, typename U>
    00043 class Infiltration
    00044 {
    00045   public:
    00046     typedef AutomataBase<A> structure_t;
    00047     typedef Element<A, T> lhs_t;
    00048     typedef Element<A, U> rhs_t;
    00049     typedef lhs_t           output_t;
    00050     typedef std::map<typename output_t::hstate_t,
    00051               std::pair<typename lhs_t::hstate_t, typename rhs_t::hstate_t> >
    00052                           pair_map_t;
    00053
    00054     Infiltration (const structure_t& structure,
    00055              const bool use_geometry)
    00056       : use_geometry_(use_geometry),
    00057         series_(structure.series()),
    00058         monoid_(series_.monoid()),
    00059         semiring_zero_(series_.semiring().zero(SELECT(semiring_elt_value_t)))
    00060     {
    00061     }
    00062
    00063     // returns the infiltration of @c lhs and @c rhs (and put it also in @c output)
    00064     output_t&
    00065     operator() (output_t& output,
    00066                 const lhs_t& lhs,
    00067                 const rhs_t& rhs,
    00068                 pair_map_t& m)
    00069     {
    00070       BENCH_TASK_SCOPED("infiltration");
    00071       visited_.clear();
    00072
    00073       precondition(is_realtime(lhs));
    00074       precondition(is_realtime(rhs));
    00075
    00076       this->initialize_queue(output, lhs, rhs, m);
    00077
    00078       while (not to_process_.empty())
    00079       {
    00080         const pair_hstate_t current_pair = to_process_.front();
    00081         to_process_.pop();
    00082
    00083         const hstate_t lhs_s         = current_pair.first;
    00084         const hstate_t rhs_s         = current_pair.second;
    00085         const hstate_t current_state = visited_[current_pair];
    00086
    00087         output.set_initial(current_state,
    00088                            lhs.get_initial(lhs_s) * rhs.get_initial(rhs_s));
    00089         output.set_final(current_state,
    00090                          lhs.get_final(lhs_s) * rhs.get_final(rhs_s));
    00091
    00092         for (typename lhs_t::delta_iterator l(lhs.value(), lhs_s);
    00093              ! l.done();
    00094              l.next())
    00095           for (typename rhs_t::delta_iterator r(rhs.value(), rhs_s);
    00096                ! r.done();
    00097                r.next())
    00098           {
    00099             series_set_elt_t    prod_series(series_);
    00100
    00101             if (is_product_not_null(lhs, rhs, l, r, prod_series))
    00102             {
    00103               const pair_hstate_t new_pair(lhs.dst_of(*l), rhs.dst_of(*r));
    00104               typename visited_t::const_iterator found = visited_.find(new_pair);
    00105
    00106               hstate_t dst;
    00107               if (found == visited_.end())
    00108               {
    00109                 dst = output.add_state();
    00110
    00111                 this->add_state_to_process(output, lhs, rhs, m, dst, new_pair);
    00112               }
    00113               else
    00114                 dst = found->second;
    00115               output.add_series_transition(current_state, dst, prod_series);
    00116             }
    00117           }
    00118         for (typename lhs_t::delta_iterator l(lhs.value(), lhs_s);
    00119              ! l.done();
    00120              l.next())
    00121         {
    00122               const pair_hstate_t new_pair(lhs.dst_of(*l), rhs_s);
    00123               typename visited_t::const_iterator found = visited_.find(new_pair);
    00124
    00125               hstate_t dst;
    00126               if (found == visited_.end())
    00127               {
    00128                 dst = output.add_state();
    00129
    00130                 this->add_state_to_process(output, lhs, rhs, m, dst, new_pair);
    00131               }
    00132               else
    00133                 dst = found->second;
    00134               output.add_series_transition(current_state, dst, lhs.series_of(*l));
    00135         }
    00136         for (typename rhs_t::delta_iterator r(rhs.value(), rhs_s);
    00137              ! r.done();
    00138              r.next())
    00139         {
    00140               const pair_hstate_t new_pair(lhs_s, rhs.dst_of(*r));
    00141               typename visited_t::const_iterator found = visited_.find(new_pair);
    00142
    00143               hstate_t dst;
    00144               if (found == visited_.end())
    00145               {
    00146                 dst = output.add_state();
    00147
    00148                 this->add_state_to_process(output, lhs, rhs, m, dst, new_pair);
    00149               }
    00150               else
    00151                 dst = found->second;
    00152               output.add_series_transition(current_state, dst, rhs.series_of(*r));
    00153         }
    00154
    00155       }
    00156       merge_transitions(output);
    00157       return output;
    00158     }
    00159
    00160   private:
    00161      //merge transitions with the same ends
    00162     void merge_transitions(output_t& a)
    00163     {
    00164       typedef std::map<hstate_t, series_set_elt_t> map_t;
    00165       for_all_states(s, a)
    00166         {
    00167           map_t map;
    00168           std::list<htransition_t> transitions;
    00169           for (delta_iterator e(a.value(), *s); ! e.done(); e.next())
    00170             {
    00171               hstate_t target = a.dst_of(*e);
    00172               transitions.push_back(*e);
    00173               typename map_t::iterator it = map.find(target);
    00174               if (it == map.end())
    00175                 map.insert(std::pair<hstate_t, series_set_elt_t>(target,
    00176                                                                  a.series_of(*e)));
    00177               else
    00178                 it->second += a.series_of(*e);
    00179             }
    00180           for_all_(std::list<htransition_t>, e, transitions)
    00181             a.del_transition(*e);
    00182           for_all_(map_t, it, map)
    00183             a.add_series_transition(*s, it->first, it->second);
    00184         }
    00185     }
    00186
    00187     // Some little graphic tools
    00188     class grphx
    00189     {
    00190       public:
    00191         template <typename Output, typename Lhs, typename Rhs>
    00192         static void
    00193         setcoordfrom (Output& a,
    00194                       const Lhs& lhs,
    00195                       const Rhs& rhs,
    00196                       const typename Output::hstate_t state,
    00197                       const typename Lhs::hstate_t x_state,
    00198                       const typename Rhs::hstate_t y_state)
    00199         {
    00200           typename std::map<typename Lhs::hstate_t,
    00201             typename Lhs::geometry_t::coords_t>::const_iterator iter;
    00202           typename std::map<typename Rhs::hstate_t,
    00203             typename Rhs::geometry_t::coords_t>::const_iterator iter2;
    00204           double x = 0, y = 0;
    00205
    00206           iter = lhs.geometry().states().find(x_state);
    00207           if (iter != lhs.geometry().states().end())
    00208             x = iter->second.first;
    00209
    00210           iter2 = rhs.geometry().states().find(y_state);
    00211           if (iter2 != rhs.geometry().states().end())
    00212             y = iter2->second.second;
    00213
    00214           a.geometry().states()[state] = std::make_pair(x, y);
    00215         }
    00216       private:
    00217         // Diagonal alignement with a depth-first traversal
    00218         template<typename I>
    00219         void
    00220         align (const I& a)
    00221         {
    00222           AUTOMATON_TYPES(I);
    00223           std::map<hstate_t,bool> visited;
    00224           std::stack<hstate_t> stack;
    00225
    00226           for_all_const_states(i, a)
    00227             {
    00228               visited[*i] = false;
    00229               // ensure inaccessible states will be visited
    00230               stack.push(*i);
    00231             }
    00232
    00233           for_all_const_initial_states(i, a)
    00234             stack.push(*i);
    00235
    00236           int x = 0;
    00237           while (!stack.empty())
    00238           {
    00239             hstate_t i = stack.top();
    00240             stack.pop();
    00241
    00242             if (!visited[i])
    00243             {
    00244               visited[i] = true;
    00245
    00246               a.geometry()[i] = std::make_pair(x, x);
    00247               x++;
    00248
    00249               for (delta_iterator j(a.value(), i);
    00250                    ! j.done();
    00251                    j.next())
    00252                 stack.push(a.dst_of(*j));
    00253             }
    00254           }
    00255         }
    00256
    00257     };
    00258     class no_grphx
    00259     {
    00260       public:
    00261         template <typename Output, typename Lhs, typename Rhs>
    00262         static void
    00263         setcoordfrom (Output& a,
    00264                       const Lhs& lhs,
    00265                       const Rhs& rhs,
    00266                       const typename Output::hstate_t state,
    00267                       const typename Lhs::hstate_t x_state,
    00268                       const typename Rhs::hstate_t y_state) {};
    00269     };
    00270
    00271     // useful typedefs
    00272     AUTOMATON_TYPES(output_t);
    00273
    00274     typedef std::pair<typename lhs_t::hstate_t, typename rhs_t::hstate_t>
    00275                                                       pair_hstate_t;
    00276     typedef std::list<htransition_t>                    delta_ret_t;
    00277     typedef std::map<pair_hstate_t, hstate_t>           visited_t;
    00278     typedef typename series_set_elt_t::support_t        support_t;
    00279
    00280     // add a @c new_state in the queue
    00281     inline void
    00282     add_state_to_process (output_t& output,
    00283                           const lhs_t& lhs,
    00284                           const rhs_t& rhs,
    00285                           pair_map_t& m,
    00286                           const hstate_t& new_state,
    00287                           const pair_hstate_t& new_pair)
    00288     {
    00289       m[new_state] = new_pair;
    00290       visited_[new_pair] = new_state;
    00291       to_process_.push(new_pair);
    00292
    00293 # define if_(Cond, ThenClause, ElseClause)                      \
    00294 misc::static_if_simple<Cond, ThenClause, ElseClause>::t
    00295 # define eq_(Type1, Type2)                      \
    00296 misc::static_eq<Type1, Type2>::value
    00297 # define DECLARE_GEOMETRY(Type) \
    00298   typedef geometry<typename Type::hstate_t, typename Type::htransition_t, typename Type::geometry_coords_t> geometry_ ## Type ;
    00299
    00300       DECLARE_GEOMETRY(output_t)
    00301       DECLARE_GEOMETRY(lhs_t)
    00302       DECLARE_GEOMETRY(rhs_t)
    00303       if (use_geometry_)
    00304         if_(eq_(typename output_t::geometry_t, geometry_output_t)  and \
    00305             eq_(typename rhs_t::geometry_t, geometry_rhs_t) and \
    00306             eq_(typename lhs_t::geometry_t, geometry_lhs_t),    \
    00307             grphx, no_grphx)
    00308           ::setcoordfrom(output, lhs, rhs,
    00309                          new_state, new_pair.first, new_pair.second);
    00310 # undef if_
    00311 # undef eq_
    00312     }
    00313
    00314     // initialize queue with all pairs of intials states from @c lhs and @c rhs
    00315     inline void
    00316     initialize_queue (output_t& output,
    00317                       const lhs_t& lhs,
    00318                       const rhs_t& rhs,
    00319                       pair_map_t& m)
    00320     {
    00321       for_all_const_initial_states(lhs_s, lhs)
    00322         for_all_const_initial_states(rhs_s, rhs)
    00323         {
    00324           const pair_hstate_t   new_pair(*lhs_s, *rhs_s);
    00325           const hstate_t        new_state = output.add_state();
    00326
    00327           this->add_state_to_process(output, lhs, rhs, m, new_state, new_pair);
    00328         }
    00329     }
    00330
    00331     inline bool
    00332     is_product_not_null (const lhs_t& lhs,
    00333                          const rhs_t& rhs,
    00334                          const typename lhs_t::delta_iterator& l,
    00335                          const typename rhs_t::delta_iterator& r,
    00336                          series_set_elt_t&  prod_series) const
    00337     {
    00338       const series_set_elt_t    left_series  = lhs.series_of(*l);
    00339       const series_set_elt_t    right_series = rhs.series_of(*r);
    00340
    00341       bool                      prod_is_not_null = false;
    00342       for_all_(support_t, supp, left_series.supp())
    00343         {
    00344           const monoid_elt_t     supp_elt (monoid_, *supp);
    00345           const semiring_elt_t l = left_series.get(supp_elt);
    00346           const semiring_elt_t r = right_series.get(supp_elt);
    00347           const semiring_elt_t p = l * r;
    00348           if (p != semiring_zero_)
    00349           {
    00350             prod_series.assoc(*supp, p.value());
    00351             prod_is_not_null = true;
    00352           }
    00353         }
    00354       return (prod_is_not_null);
    00355     }
    00356
    00357     // If set to true, <geometry> tags of the result automaton should be filled
    00358     const bool  use_geometry_;
    00359
    00360     // keep traces of new states created
    00361     visited_t                   visited_;
    00362     // @c to_process_ stores all states of output that needs are not
    00363     std::queue<pair_hstate_t>   to_process_;
    00364
    00365     // frequently used objects in computation
    00366     const series_set_t& series_;
    00367     const monoid_t&             monoid_;
    00368     // This variable's type must not be set to a reference.
    00369     const semiring_elt_t        semiring_zero_;
    00370 };
    00371
    00372 /*-----------.
    00373 | Wrappers.  |
    00374 `-----------*/
    00375
    00376 template<typename A, typename T, typename U>
    00377 Element<A, T>
    00378 infiltration (const Element<A, T>& lhs, const Element<A, U>& rhs,
    00379          std::map<typename T::hstate_t,
    00380          std::pair<typename T::hstate_t, typename U::hstate_t> >& m,
    00381          const bool use_geometry)
    00382 {
    00383   Element<A, T> ret(rhs.structure());
    00384   Infiltration<A, T, U> do_infiltration(ret.structure(), use_geometry);
    00385   return do_infiltration (ret, lhs, rhs, m);
    00386 }
    00387
    00388 template<typename A, typename T, typename U>
    00389 Element<A, T>
    00390 infiltration (const Element<A, T>& lhs, const Element<A, U>& rhs,
    00391          const bool use_geometry)
    00392 {
    00393   std::map<typename T::hstate_t,
    00394     std::pair<typename T::hstate_t, typename U::hstate_t> > m;
    00395   return infiltration (lhs, rhs, m, use_geometry);
    00396 }
    00397
    00398 } // End of namespace vcsn.
    00399
    00400 #endif // ! VCSN_ALGORITHMS_INFILTRATION_HXX