rw_composition.hxx

00001 // rw_composition.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_RW_COMPOSITION_HXX
00019 # define VCSN_ALGORITHMS_RW_COMPOSITION_HXX
00020 
00021 # include <map>
00022 # include <queue>
00023 # include <set>
00024 
00025 # include <vaucanson/algorithms/rw_composition.hh>
00026 # include <vaucanson/automata/concept/transducer.hh>
00027 // FIXME: The code for geometry computation must be enabled statically.
00028 // (see product.hxx for some hints)
00029 # include <vaucanson/automata/implementation/geometry.hh>
00030 
00031 namespace vcsn {
00032 
00033   template<typename U, typename Trans_t>
00034   void
00035   do_rw_composition(const TransducerBase<U>&,
00036                     const Trans_t& R,
00037                     const Trans_t& S,
00038                     Trans_t& T)
00039   {
00040     TIMER_SCOPED("rw_composition");
00041 
00042     // type helpers
00043     AUTOMATON_TYPES(Trans_t);
00044     typedef series_set_elt_t exp_t;
00045     typedef typename series_set_elt_t::semiring_elt_t output_exp_t;
00046     typedef std::set<std::pair<hstate_t, output_exp_t> > state_exp_pair_set_t;
00047     typedef typename std::map<hstate_t, typename Trans_t::geometry_t::coords_t>::const_iterator geom_iter_t;
00048     typedef std::pair<hstate_t, hstate_t> state_pair_t;
00049     typedef std::queue<state_pair_t> state_pair_queue_t;
00050     typedef std::map<state_pair_t, hstate_t> state_pair_map_t;
00051     typedef std::set<htransition_t> set_of_transitions_t;
00052 
00053     // declare the main queue
00054     state_pair_queue_t queue;
00055 
00056     // We will reuse this structure many times:
00057     // each time we call partial_evaluation.
00058     // Do not forget to clear() it before the call.
00059     state_exp_pair_set_t sep_set;
00060 
00061     // Each time we create a new state in the output transducer
00062     // (say a pair (p, r)), we will add it to the following map
00063     // with the corresponding hstate_t, to speedup lookups.
00064     state_pair_map_t Tstates;
00065 
00066     // These variables help us create the new state geometry.
00067     double xgeom;
00068     double ygeom;
00069     geom_iter_t iter;
00070 
00071     //
00072     // Part 1 (refer to the algorithm description - see header).
00073     // Initial states creation.
00074     //
00075 
00076     for_all_const_initial_states (p, R)
00077     {
00078       // Hold the initial weight of the state p.
00079       exp_t E = R.get_initial(*p);
00080 
00081       for_all_const_initial_states (q, S)
00082       {
00083         // Hold the initial weight of the state q.
00084         exp_t F = S.get_initial(*q);
00085 
00086         // Partial evaluation.
00087         sep_set.clear();
00088         partial_evaluation(E, S, *q, sep_set);
00089 
00090         // Iterates throughout the partial_evaluation output.
00091         for_all_const_(state_exp_pair_set_t, ig, sep_set)
00092         {
00093           // Construct the state representation (p, r).
00094           state_pair_t sp;
00095           sp.first = *p;
00096           sp.second = (*ig).first;
00097 
00098           // FIXME: store the iterator for later reuse
00099           if (Tstates.find(sp) == Tstates.end())
00100           {
00101             // (p, r) does not exists yet in the output
00102             // transducer.
00103 
00104             // So we create it,
00105             hstate_t new_state = T.add_state();
00106 
00107             // add it the deduced geometry from p and r,
00108             iter = R.geometry().states().find(*p);
00109             if (iter != R.geometry().states().end())
00110               xgeom = (*iter).second.first;
00111             else
00112               xgeom = 0;
00113             iter = S.geometry().states().find(*q);
00114             if (iter != S.geometry().states().end())
00115               ygeom = (*iter).second.second;
00116             else
00117               ygeom = 0;
00118             T.geometry().states()[new_state] = std::make_pair(xgeom, ygeom);
00119 
00120             // store it in our lookup table,
00121             Tstates[sp] = new_state;
00122 
00123             // set the initial weight (we are only dealing with
00124             // initial states),
00125             T.set_initial(new_state, F * ((*ig).second));
00126 
00127             // and finally push it in the queue.
00128             queue.push(sp);
00129           }
00130           else
00131           {
00132             // (p, r) has already been created: we only
00133             // update its initial weight.
00134             T.set_initial(Tstates[sp],
00135                           T.get_initial(Tstates[sp]) + F * ((*ig).second));
00136           }
00137         } // ! for_all_const_state_exp_pair_set_t
00138       } // ! for_all_const_initial_states
00139     } // ! for_all_const_initial_states
00140 
00141     //
00142     // Part 2 (refer to the algorithm description - see header).
00143     // Main loop (runs until the queue is exhausted).
00144     //
00145 
00146     while (not queue.empty())
00147     {
00148       // Pop one state from the queue.
00149       const state_pair_t sp = queue.front();
00150       queue.pop();
00151 
00152       const hstate_t p = sp.first;
00153       const hstate_t q = sp.second;
00154 
00155       // Fill a transition set appropriately.
00156       // FIXME: we should better use the transitions iterators.
00157       set_of_transitions_t transitions;
00158       R.deltac(transitions, p, delta_kind::transitions());
00159 
00160       for_all_const_(set_of_transitions_t, e, transitions)
00161       {
00162         // set s
00163         hstate_t s = R.dst_of(*e);
00164         // set E
00165         exp_t E = R.series_of(*e);
00166         // set x
00167         // Input must be realtime.
00168         assertion(E.supp().size() == 1);
00169         monoid_elt_t x(E.structure().monoid(), *E.supp().begin());
00170 
00171         // Partial evaluation.
00172         sep_set.clear();
00173         partial_evaluation(E, S, q, sep_set);
00174 
00175         for_all_const_(state_exp_pair_set_t, ig, sep_set)
00176         {
00177           // Construct the state representation (s, r).
00178           state_pair_t sp1;
00179           sp1.first = s;
00180           sp1.second = (*ig).first;
00181 
00182           // FIXME: store the iterator for later reuse
00183           if (Tstates.find(sp1) == Tstates.end())
00184           {
00185             // (s, r) does not exists yet in the output
00186             // transducer.
00187 
00188             // So we create it,
00189             hstate_t new_state = T.add_state();
00190 
00191             // add it the deduced geometry from s and r,
00192             iter = R.geometry().states().find(sp1.first);
00193             if (iter != R.geometry().states().end())
00194               xgeom = (*iter).second.first;
00195             else
00196               xgeom = 0;
00197             iter = S.geometry().states().find(sp1.second);
00198             if (iter != S.geometry().states().end())
00199               ygeom = (*iter).second.second;
00200             else
00201               ygeom = 0;
00202             T.geometry().states()[new_state] = std::make_pair(xgeom, ygeom);
00203 
00204             // store it in our lookup table,
00205             Tstates[sp1] = new_state;
00206 
00207             // and finally push it in the queue.
00208             queue.push(sp1);
00209           }
00210 
00211           exp_t Gexp (R.structure().series());
00212           Gexp.assoc(x, (*ig).second);
00213           // FIXME: if new_state optim?
00214           T.add_series_transition(Tstates[sp], Tstates[sp1], Gexp);
00215         }
00216       } // ! for_all_const_set_of_transitions_t
00217 
00218       // Handle final states.
00219       if (R.is_final(p))
00220       {
00221         // Partial evaluation.
00222         sep_set.clear();
00223         partial_evaluation(R.get_final(p), S, q, sep_set);
00224 
00225         for_all_const_(state_exp_pair_set_t, ig, sep_set)
00226         {
00227           const hstate_t r = (*ig).first;
00228           if (S.is_final(r))
00229             T.set_final(Tstates[sp], (*ig).second * S.get_final(r));
00230         }
00231       }
00232     } // ! main loop
00233   }
00234 
00235   // Wrapper around do_rw_composition.
00236   template< typename S, typename T>
00237   void
00238   rw_composition(const Element<S, T>& lhs,
00239                  const Element<S, T>& rhs,
00240                  Element<S, T>& ret)
00241   {
00242     typedef Element<S, T> auto_t;
00243     AUTOMATON_TYPES(auto_t);
00244     // We need to make sure RET is empty before passing it
00245     // to do_rw_composition(), therefore it won't work if
00246     // RET refers to the same automaton as LHS or RHS.
00247     precondition(&ret != &lhs);
00248     precondition(&ret != &rhs);
00249     for_all_states (s, ret)
00250       ret.del_state (*s);
00251     do_rw_composition(lhs.structure(), lhs, rhs, ret);
00252   }
00253 
00254   // This wrapper creates a new automaton. No
00255   // special care needs be taken.
00256   template< typename S, typename T>
00257   Element<S, T>
00258   rw_composition(const Element<S, T>& lhs, const Element<S, T>& rhs)
00259   {
00260     Element<S, T> ret (lhs.structure());
00261     do_rw_composition(lhs.structure(), lhs, rhs, ret);
00262     return ret;
00263   }
00264 
00265 } // ! vcsn
00266 
00267 #endif // ! VCSN_ALGORITHMS_RW_COMPOSITION_HXX

Generated on Thu Oct 9 20:22:41 2008 for Vaucanson by  doxygen 1.5.1