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

- File List
- File Members

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