Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

is_synchronisable.hxx

00001 // is_synchronisable.hxx: this file is part of the Vaucanson project.
00002 //
00003 // Vaucanson, a generic library for finite state machines.
00004 //
00005 // Copyright (C) 2006, 2007 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_IS_SYNCHRONISABLE_HXX
00018 # define VCSN_ALGORITHMS_IS_SYNCHRONISABLE_HXX
00019 
00020 # include <vaucanson/algorithms/is_synchronisable.hh>
00021 
00022 # include <vaucanson/automata/concept/automata_base.hh>
00023 # include <vaucanson/algebra/concept/freemonoid_product.hh>
00024 # include <vaucanson/misc/usual_macros.hh>
00025 
00026 # include <vaucanson/tools/dot_display.hh>
00027 # include <vaucanson/tools/dot_dump.hh>
00028 
00029 # include <map>
00030 # include <set>
00031 # include <list>
00032 # include <utility>
00033 # include <queue>
00034 # include <iostream>
00035 # include <stdlib.h>
00036 
00037 namespace vcsn
00038 {
00039 
00040   template <typename Trans>
00041   int
00042   length_discrepancy (const htransition_t& l, const Trans& trans)
00043   {
00044     AUTOMATON_TYPES(Trans);
00045 
00046     monoid_elt_t label = trans.word_of (l);
00047     int res = label.value ().first.length () - label.value ().second.length ();
00048     return res;
00049   }
00050 
00051 
00052   template <typename Trans>
00053   class IsBoundedLag
00054   {
00055       AUTOMATON_TYPES(Trans);
00056       typedef enum { WHITE, GRAY, BLACK } color_t;
00057       typedef std::map<hstate_t, color_t> visited_t;
00058       typedef std::map<hstate_t, std::pair<hstate_t, htransition_t> > father_t;
00059 
00060     private:
00061       const automaton_t& trans_;
00062 
00067       visited_t visited_;
00068 
00070       father_t father_of_;
00071 
00072     public:
00073 
00074       IsBoundedLag(const automaton_t& t)
00075         : trans_(t)
00076       {
00077         for_all_states(s, trans_)
00078           visited_[*s] = WHITE;
00079       }
00080 
00081       bool operator() ()
00082       {
00083         bool is_synch = true;
00084 
00085         for_all_states(s, trans_)
00086           if (visited_[*s] == WHITE &&
00087               !(is_synch = dispatch_bounded_lag (*s)))
00088             break;
00089         return is_synch;
00090       }
00091 
00092       bool
00093       dispatch_bounded_lag (const hstate_t s)
00094       {
00095         std::list<htransition_t> delta_ret;
00096 
00097         visited_[s] = GRAY;
00098         trans_.deltac (delta_ret, s, delta_kind::transitions());
00099         for_all_const(std::list<htransition_t>, e, delta_ret)
00100         {
00101           hstate_t r = trans_.dst_of (*e);
00102           if (visited_[r] == WHITE)
00103           {
00104             father_of_[r] = std::make_pair (s, *e);
00105             if (!dispatch_bounded_lag (r))
00106               return false;
00107           }
00108           else if (visited_[r] == GRAY) // Circuit detected !!
00109           {
00110             // Compute the length discrepancy
00111             // Should be zero to be bounded_lag
00112             int res = length_discrepancy (*e, trans_);
00113             if (s != r)
00114             {
00115               hstate_t p = father_of_[s].first;
00116               hstate_t f = s;
00117               htransition_t l = father_of_[s].second;
00118               while (p != r)
00119               {
00120                 res += length_discrepancy (l, trans_);
00121                 f = p;
00122                 p = father_of_[p].first;
00123                 l = father_of_[p].second;
00124               }
00125               res += length_discrepancy (l, trans_);
00126             }
00127             std::cerr << "bounded_lag: circuit detected" << std::endl;
00128             if (res != 0)
00129               return false;
00130           }
00131         }
00132         visited_[s] = BLACK;
00133         return true;
00134       }
00135   };
00136 
00137   template <typename T_, typename M1, typename M2, typename Trans>
00138   bool
00139   do_is_bounded_lag(const AutomataBase<T_>&,
00140                     const algebra::FreeMonoidProduct<M1, M2>&,
00141                     const Trans& t)
00142   {
00143     IsBoundedLag<Trans> is_bounded(t);
00144 
00145     return is_bounded();
00146   }
00147 
00148   template <typename S, typename T>
00149   bool
00150   is_bounded_lag (const Element<S, T>& t)
00151   {
00152     return do_is_bounded_lag (t.structure(), t.structure().series().monoid(), t);
00153   }
00154 
00155   typedef std::pair<hstate_t, int> valued_state_t;
00156   typedef std::map<valued_state_t, hstate_t> conv_t;
00157 
00158 
00159   // Synchronisation
00160 
00161 
00162   template <typename Trans>
00163   class Ranker
00164   {
00165     public:
00166       AUTOMATON_TYPES(Trans);
00167       typedef std::map<hstate_t, int> rank_t;
00168 
00169       void
00170       operator() (const automaton_t& t, rank_t& rank, automaton_t& B)
00171       {
00172         std::stack<valued_state_t> to_treat;
00173         conv_t conv;
00174 
00175         // Init: set rank of initial states to zero
00176         // Add a corresponding initial state in B
00177 
00178         for_all_initial_states(s, t)
00179         {
00180           hstate_t p;
00181           valued_state_t vp;
00182           p = B.add_state ();
00183           B.set_initial (p);
00184           if (t.is_final (*s))
00185             B.set_final (p, t.get_final (*s));
00186           vp = std::make_pair (*s, 0);
00187           rank[p] = 0;
00188           to_treat.push (vp);
00189           conv[vp] = p;
00190         }
00191 
00192         valued_state_t s;
00193         std::list<htransition_t> delta_ret;
00194         while (!to_treat.empty ())
00195         {
00196           s = to_treat.top ();
00197           to_treat.pop ();
00198           delta_ret.clear ();
00199 
00200           // for each transition (s, (w,v), d)
00201           // we compute rank[d] = rank[s] + (w - v)
00202           t.deltac (delta_ret, s.first, delta_kind::transitions());
00203           for (std::list<htransition_t>::iterator e = delta_ret.begin ();
00204                e != delta_ret.end (); ++e)
00205           {
00206             hstate_t r = t.dst_of (*e);
00207             int lag = s.second + length_discrepancy (*e, t);
00208             valued_state_t vr = std::make_pair (r, lag);
00209             conv_t::iterator b;
00210             b = conv.find (vr);
00211 
00212             // State (r, rank) doesn't exist
00213             if (b == conv.end ())
00214             {
00215               hstate_t p = B.add_state ();
00216               if (t.is_final (vr.first))
00217                 B.set_final (p, t.get_final (vr.first));
00218               conv[vr] = p;
00219               rank[p] = lag;
00220               B.add_transition(conv[s], p, t.label_of (*e));
00221               to_treat.push (vr);
00222             }
00223             else
00224               B.add_transition (conv[s], b->second, t.label_of (*e));
00225           }
00226         }
00227       }
00228   };
00229 
00230   namespace synchronise_internal
00231   {
00232     // Add the transition (src, (left,right), dst)
00233     template <typename Trans>
00234     void split_transition (Trans& t,
00235                            hstate_t src,
00236                            hstate_t dst,
00237                            const typename Trans::monoid_elt_t::first_monoid_elt_t::value_t& left,
00238                            const typename Trans::monoid_elt_t::second_monoid_elt_t::value_t& right)
00239     {
00240       AUTOMATON_TYPES(Trans);
00241 
00242       monoid_elt_t mon (t.structure().series().monoid());
00243       semiring_elt_t weight (t.structure().series().semiring());
00244       weight = true;
00245 
00246       monoid_elt_value_t v1(left, right);
00247       mon = v1;
00248 
00249       series_set_elt_t s1 (t.structure().series());
00250       s1.assoc(mon, weight);
00251       t.add_series_transition (src, dst, s1);
00252     }
00253   }
00254 
00255   // Split transition between positive ranked state and negative ranked state
00256   template <typename Trans>
00257   void
00258   split_transitions (Trans& t, typename Ranker<Trans>::rank_t& rank)
00259   {
00260     AUTOMATON_TYPES(Trans);
00261 
00262     AUTOMATON_FREEMONOIDPRODUCT_TYPES(Trans);
00263 
00264     first_monoid_elt_t fm_empty =
00265       algebra::identity_as<first_monoid_elt_value_t>::of
00266       (t.structure().series().monoid().first_monoid());
00267 
00268     second_monoid_elt_t sm_empty =
00269       algebra::identity_as<second_monoid_elt_value_t>::of
00270       (t.structure().series().monoid().second_monoid());
00271     for_all_transitions(e, t)
00272     {
00273       hstate_t src = t.src_of (*e);
00274       hstate_t dst = t.dst_of (*e);
00275 
00276       if ((rank[src] > 0 && rank[dst] < 0) ||
00277           (rank[src] < 0 && rank[dst] > 0))
00278       {
00279         hstate_t zero_state = t.add_state ();
00280         rank[zero_state] = 0;
00281         monoid_elt_t m(t.structure().series().monoid());
00282         m = t.word_of (*e);
00283         int delta = abs (rank[src] - rank[dst]);
00284 
00285         if (rank[src] > 0 && rank[dst] < 0)
00286         {
00287           synchronise_internal::split_transition
00288             (t,
00289              src,
00290              zero_state,
00291              m.value().first,
00292              second_monoid_elt_value_t(m.value().second.c_str(), delta));
00293 
00294           synchronise_internal::split_transition
00295             (t,
00296              zero_state,
00297              dst,
00298              fm_empty.value(),
00299              second_monoid_elt_value_t(m.value().second, delta,
00300                                        m.value().second.length() - delta));
00301         }
00302         else
00303         {
00304           synchronise_internal::split_transition
00305             (t,
00306              src,
00307              zero_state,
00308              first_monoid_elt_value_t(m.value().first.c_str(), delta),
00309              m.value().second);
00310 
00311           synchronise_internal::split_transition
00312             (t,
00313              zero_state,
00314              dst,
00315              first_monoid_elt_value_t(m.value().first, delta,
00316                                       m.value().first.length() - delta),
00317              sm_empty.value());
00318         }
00319         t.del_transition (*e);
00320       }
00321     }
00322   }
00323 
00324 
00325   template <typename Trans>
00326   class Synchroniser
00327   {
00328     public:
00329       AUTOMATON_TYPES(Trans);
00330       AUTOMATON_FREEMONOIDPRODUCT_TYPES(automaton_t);
00331 
00332       typedef typename Ranker<Trans>::rank_t rank_t;
00333       typedef std::map<std::string, hstate_t> prefix_map_t;
00334 
00335       Synchroniser(automaton_t& t, rank_t& rank)
00336         : t_(t), rank_(rank)
00337       {}
00338 
00339       void operator() ()
00340       {
00341         AUTOMATON_TYPES(Trans);
00342 
00343         hstate_t s;
00344         std::set<hstate_t> done;
00345 
00346         while (choose_state(s))
00347         {
00348           std::cerr << s << std::endl;
00349 
00350           make_circulation (s);
00351 
00352           rank_.erase (s);
00353           t_.del_state (s);
00354         }
00355       }
00356 
00357     private:
00358 
00359       void
00360       remove_pref_from_transition (const htransition_t& e,
00361                                    const std::string&   pref,
00362                                    prefix_map_t&                p2s)
00363       {
00364         monoid_elt_t mon(t_.structure().series().monoid());
00365         semiring_elt_t weight (t_.structure().series().semiring());
00366 
00367         std::string output;
00368         if (rank_[t_.src_of (e)] > 0)
00369         {
00370           output = t_.word_of (e).value().second;
00371           monoid_elt_value_t v1(t_.word_of (e).value ().first,
00372                                 std::string(output, pref.length (), output.length () - pref.length ()));
00373           mon = v1;
00374         }
00375         else
00376         {
00377           output = t_.word_of (e).value().first;
00378           monoid_elt_value_t v1(std::string(output, pref.length (), output.length () - pref.length ()),
00379                                 t_.word_of (e).value ().second);
00380           mon = v1;
00381         }
00382 
00383         weight = true;
00384         series_set_elt_t s (t_.structure().series());
00385         s.assoc(mon, weight);
00386         t_.add_series_transition(p2s[pref], t_.dst_of (e), s);
00387       }
00388 
00389       void
00390       append_pref_to_transition (const htransition_t&   e,
00391                                  const std::string&     pref,
00392                                  hstate_t                       src,
00393                                  hstate_t                       dst,
00394                                  std::string            rpref = std::string(""))
00395       {
00396         monoid_elt_t mon(t_.structure().series().monoid());
00397         semiring_elt_t weight (t_.structure().series().semiring());
00398 
00399         monoid_elt_value_t v1;
00400 
00401         if (rank_[t_.dst_of (e)] > 0)
00402           v1.first = t_.word_of (e).value().first;
00403         else
00404           v1.second = t_.word_of (e).value().second;
00405 
00406         if (t_.src_of (e) != t_.dst_of (e))
00407         {
00408           if (rank_[t_.dst_of (e)] > 0)
00409             v1.second = t_.word_of (e).value().second + pref;
00410           else
00411             v1.first = t_.word_of (e).value().first + pref;
00412         }
00413         else
00414         {
00415           // Special case for loop.
00416           if (rank_[t_.dst_of (e)] > 0)
00417           {
00418             std::string output = t_.word_of (e).value().second;
00419             v1.second = std::string (output, rpref.length(), output.length() - rpref.length()) + pref;
00420           }
00421           else
00422           {
00423             std::string output = t_.word_of (e).value().first;
00424             v1.first = std::string (output, rpref.length(), output.length() - rpref.length()) + pref;
00425           }
00426         }
00427         mon = v1;
00428         weight = true;
00429         series_set_elt_t s (t_.structure().series());
00430         s.assoc(mon, weight);
00431         t_.add_series_transition(src, dst, s);
00432       }
00433 
00434 
00435       void
00436       remove_pref_from_final(hstate_t           s,
00437                              prefix_map_t&      p2s,
00438                              std::set<hstate_t>&        done)
00439       {
00440         typename series_set_elt_t::support_t::iterator i =
00441           t_.get_final(s).supp().begin();
00442         monoid_elt_t m(t_.structure().series().monoid());
00443         m = *i;
00444 
00445         std::string pref;
00446         if (rank_[s] > 0)
00447           pref = std::string(m.value().second.c_str(), rank_[s]);
00448         else
00449           pref = std::string(m.value().first.c_str(), rank_[s]);
00450 
00451         p2s[pref] = t_.add_state ();
00452         rank_[p2s[pref]] = rank_[s];
00453 
00454         monoid_elt_t mon(t_.structure().series().monoid());
00455         semiring_elt_t weight (t_.structure().series().semiring());
00456 
00457         if (rank_[s] > 0)
00458         {
00459           second_monoid_elt_value_t output = m.value().second;
00460           monoid_elt_value_t v1
00461             (m.value().first,
00462              std::string(output, pref.length (), output.length () - pref.length ()));
00463           mon = v1;
00464         }
00465         else
00466         {
00467           first_monoid_elt_value_t output = m.value().first;
00468           monoid_elt_value_t v1(
00469             first_monoid_elt_value_t(output, pref.length (),
00470                                      output.length () - pref.length ()),
00471             m.value().second);
00472           mon = v1;
00473         }
00474 
00475         weight = true;
00476         series_set_elt_t s1(t_.structure().series());
00477         s1.assoc(mon, weight);
00478         t_.set_final(p2s[pref], s1);
00479         done.insert(p2s[pref]);
00480       }
00481 
00482       void
00483       make_circulation (hstate_t s)
00484       {
00485         // prefix to state map...
00486         prefix_map_t p2s;
00487 
00488         std::set<hstate_t> done;
00489         std::list<htransition_t> delta_ret;
00490 
00491         // Special case for the final transition
00492         if (t_.is_final(s))
00493           remove_pref_from_final(s, p2s, done);
00494         delta_ret.clear();
00495 
00496         // Suppress prefix from outgoing transition
00497         t_.deltac (delta_ret, s, delta_kind::transitions());
00498         for_all_const(std::list<htransition_t>, e, delta_ret)
00499         {
00500           std::string proj;
00501           if (rank_[s] > 0)
00502             proj = t_.word_of(*e).value().second;
00503           else
00504             proj = t_.word_of(*e).value().first;
00505           std::string pref(proj.c_str(), abs(rank_[s]));
00506           if (p2s.find (pref) == p2s.end ())
00507           {
00508             p2s[pref] = t_.add_state ();
00509             rank_[p2s[pref]] = rank_[s];
00510           }
00511           if (t_.dst_of (*e) != t_.src_of (*e))
00512             remove_pref_from_transition(*e, pref, p2s);
00513         }
00514         delta_ret.clear ();
00515 
00516         //vcsn::tools::dot_display (t, "AS", true);
00517 
00518         // Add prefix to incoming transition
00519         t_.rdeltac (delta_ret, s, delta_kind::transitions());
00520         for_all_const(std::list<htransition_t>, e, delta_ret)
00521         {
00522           hstate_t src = t_.src_of (*e);
00523           if (src != s)
00524           {
00525             for (prefix_map_t::iterator s1 = p2s.begin ();
00526                  s1 != p2s.end (); ++s1)
00527               append_pref_to_transition(*e, s1->first, src, s1->second);
00528           }
00529           else
00530           {
00531             // Special case if transition is a loop
00532             std::string pref(t_.word_of (*e).value().second.c_str(), rank_[s]);
00533             for (prefix_map_t::iterator s1 = p2s.begin ();
00534                  s1 != p2s.end (); ++s1)
00535               append_pref_to_transition(*e, s1->first, p2s[pref], s1->second, pref);
00536           }
00537         }
00538 
00539         //vcsn::tools::dot_display (t, "AP", true);
00540       }
00541 
00542       bool
00543       choose_state (hstate_t& selected)
00544       {
00545         typedef std::vector<htransition_t> delta_ret_t;
00546 
00547         delta_ret_t delta_ret;
00548         bool find = true;
00549 
00550         for_all_states(s, t_)
00551         {
00552           if (rank_[*s] == 0)
00553             continue;
00554 
00555           // Check if all transitions have the same number of character
00556           // on each component.
00557           bool all_equal = true;
00558           delta_ret.clear ();
00559           t_.deltac (delta_ret, *s, delta_kind::transitions());
00560           for (delta_ret_t::iterator e = delta_ret.begin();
00561                e != delta_ret.end() && all_equal; ++e)
00562           {
00563             monoid_elt_t m(t_.structure().series().monoid());
00564             m = t_.word_of (*e);
00565             if (m.value().first.length() != m.value().second.length())
00566               all_equal = false;
00567           }
00568 
00569           // Check next state, outgoing transitions of this state are all
00570           // well balanced.
00571           if (all_equal)
00572             continue;
00573 
00574           // Special case for final
00575           if (t_.is_final (*s))
00576           {
00577             typename series_set_elt_t::support_t::iterator i = t_.get_final(*s).supp().begin();
00578             monoid_elt_t m(t_.structure().series().monoid());
00579             m = *i;
00580             if (rank_[*s] > 0)
00581             {
00582               if ((int)m.value().second.length() < rank_[*s])
00583                 continue;
00584             }
00585             else
00586             {
00587               if ((int)m.value().first.length() < -rank_[*s])
00588                 continue;
00589             }
00590           }
00591 
00592           t_.deltac (delta_ret, *s, delta_kind::transitions());
00593 
00594           // State s is selectable if enough letter on all transition's labels
00595           if (rank_[*s] > 0)
00596           {
00597             for_all_(delta_ret_t, e, delta_ret)
00598             {
00599               monoid_elt_t m(t_.structure().series().monoid());
00600               m = t_.word_of (*e);
00601               if ((int)m.value().second.length() < rank_[*s])
00602               {
00603                 find = false;
00604                 break;
00605               }
00606             }
00607           }
00608           else
00609           {
00610             for_all_(delta_ret_t, e, delta_ret)
00611             {
00612               monoid_elt_t m(t_.structure().series().monoid());
00613               m = t_.word_of (*e);
00614               if ((int)m.value().first.length() < -rank_[*s])
00615               {
00616                 find = false;
00617                 break;
00618               }
00619             }
00620           }
00621 
00622           if (!find)
00623           {
00624             find = true;
00625             continue;
00626           }
00627           selected = *s;
00628           return true;
00629         }
00630         return false;
00631       }
00632 
00633       automaton_t& t_;
00634       rank_t rank_;
00635   };
00636 
00637   template <typename S, typename T, typename M1, typename M2>
00638   void
00639   do_synchronise (SELECTOR(AutomataBase<S>),
00640                   SELECTOR2(algebra::FreeMonoidProduct<M1, M2>),
00641                   const Element<S, T>& t,
00642                   Element<S, T>& B)
00643   {
00644     typedef Element<S, T> trans_t;
00645     AUTOMATON_TYPES(trans_t);
00646 
00647     typename Ranker<trans_t>::rank_t rank;
00648     Ranker<trans_t> compute_rank;
00649 
00650     compute_rank (t, rank, B);
00651 
00652     // Split transition between state of positive rank and negative rank
00653     split_transitions (B, rank);
00654 
00655     // vcsn::tools::dot_display (B, "A1", true);
00656     // for (typename Ranker<trans_t>::rank_t::iterator e = rank.begin (); e != rank.end (); ++e)
00657     // std::cerr << e->first << " -> " << e->second << std::endl;
00658 
00659     // Synchronise
00660     Synchroniser<trans_t> sync(B, rank);
00661     sync();
00662   }
00663 
00664   template <typename S, typename T>
00665   Element<S, T>
00666   synchronise (const Element<S, T>& t)
00667   {
00668     typedef Element<S, T> trans_t;
00669 
00670     typedef typename trans_t::set_t trans_set_t;
00671     typedef typename trans_set_t::series_set_t series_set_t;
00672 
00673     trans_set_t aset(series_set_t(t.structure().series().semiring(),
00674                                   t.structure().series().monoid()));
00675     trans_t res(aset);
00676 
00677     do_synchronise(t.structure(), t.structure().series().monoid(),
00678                    t, res);
00679     return res;
00680   }
00681 
00682 }
00683 
00684 #endif // ! VCSN_ALGORITHMS_IS_SYNCHRONISABLE_HXX

Generated on Fri Oct 12 21:22:47 2007 for Vaucanson by  doxygen 1.4.4