gen_random.hxx

00001 // gen_random.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, 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_TOOLS_GEN_RANDOM_HXX
00019 # define VCSN_TOOLS_GEN_RANDOM_HXX
00020 
00021 # include <vaucanson/tools/gen_random.hh>
00022 # include <vaucanson/misc/usual_macros.hh>
00023 
00024 # include <cstdlib>
00025 
00026 namespace vcsn {
00027 
00028   namespace tools {
00029 
00030     using namespace algebra;
00031 
00032     /*---------------------.
00033     | GenRandomAutomataSet |
00034     `---------------------*/
00035 
00036     template <class AutoSet>
00037       AutoSet
00038       GenRandomAutomataSet::generate(SELECTOR(AutomataBase<AutoSet>),
00039           unsigned nb_letter)
00040       {
00041 
00042         AUTOMATA_SET_TYPES(AutoSet);
00043 
00044         alphabet_t              alpha;
00045         unsigned                max = (alpha.max_size() > ALPHABET_MAX_SIZE ?
00046                                        ALPHABET_MAX_SIZE :
00047                                        alpha.max_size());
00048         unsigned                nb = alea(nb_letter ? nb_letter : max);
00049         for (unsigned i = 0; i < nb; ++i)
00050           alpha.insert(alpha.random_letter());
00051 
00052         monoid_t                monoid(alpha);
00053         semiring_t              semi;
00054         series_set_t    series(semi, monoid);
00055         automata_set_t  autoset(series);
00056         return autoset;
00057       }
00058 
00059     template <class AutoSet>
00060       AutoSet
00061       GenRandomAutomataSet::generate(SELECTOR(TransducerBase<AutoSet>),
00062           unsigned input_nb_letter,
00063           unsigned output_nb_letter)
00064       {
00065         AUTOMATA_SET_TYPES(AutoSet);
00066 
00067         alphabet_t      input_alpha;
00068         alphabet_t      output_alpha;
00069 
00070         unsigned        max = (input_alpha.max_size() > ALPHABET_MAX_SIZE ?
00071                                ALPHABET_MAX_SIZE :
00072                                input_alpha.max_size());
00073         unsigned        nb = alea(input_nb_letter ? input_nb_letter : max);
00074         for (unsigned i = 0; i < nb; ++i)
00075           input_alpha.insert(input_alpha.random_letter());
00076 
00077         max = (output_alpha.max_size() > ALPHABET_MAX_SIZE ?
00078                ALPHABET_MAX_SIZE :
00079                output_alpha.max_size());
00080         nb = alea(output_nb_letter ? output_nb_letter : max);
00081         for (unsigned i = 0; i < nb; ++i)
00082           output_alpha.insert(output_alpha.random_letter());
00083 
00084         monoid_t                        input_monoid(input_alpha);
00085         monoid_t                        output_monoid(output_alpha);
00086 
00087         typename semiring_t::semiring_t semi;
00088         semiring_t                      output_series(semi, output_monoid);
00089 
00090         series_set_t            series(output_series, input_monoid);
00091 
00092         automata_set_t          auto_set(series);
00093         return auto_set;
00094       }
00095 
00096     unsigned alea(unsigned max)
00097     {
00098       return int (1 + float (max) * rand() / (RAND_MAX + 1.0));
00099     }
00100 
00101     /*------------------.
00102     | GenRandomAutomata |
00103     `------------------*/
00104 
00105     template <class TAutomata, class AutomataSetGenerator>
00106       GenRandomAutomata<TAutomata, AutomataSetGenerator>::GenRandomAutomata()
00107       {}
00108 
00109 
00110     /*------.
00111     | empty |
00112     `------*/
00113 
00114     template <class TAutomata, class AutomataSetGenerator>
00115       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
00116       empty(unsigned nb_letter)
00117       {
00118         automata_set_t aset =
00119           GenRandomAutomataSet::generate(SELECT(automata_set_t), nb_letter);
00120         TAutomata work(aset);
00121         return work;
00122       }
00123 
00124     template <class TAutomata, class AutomataSetGenerator>
00125       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
00126       empty(const automata_set_t& set)
00127       {
00128         TAutomata work(set);
00129         return work;
00130       }
00131 
00132     /*---------.
00133     | generate |
00134     `---------*/
00135 
00136     template <class TAutomata, class AutomataSetGenerator>
00137       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
00138       generate(unsigned nb_state, unsigned nb_transition_,
00139           unsigned istate, unsigned fstate,
00140           unsigned nb_letter)
00141       {
00142         automata_set_t aset =
00143           GenRandomAutomataSet::generate(SELECT(automata_set_t), nb_letter);
00144         return generate(aset, nb_state, nb_transition_, istate, fstate);
00145       }
00146 
00147     template <class TAutomata, class AutomataSetGenerator>
00148       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
00149       generate(const automata_set_t& set,
00150           unsigned nb_state, unsigned nb_transition_,
00151           unsigned istate, unsigned fstate)
00152       {
00153         AUTOMATON_TYPES(TAutomata);
00154         AUTOMATON_FREEMONOID_TYPES(TAutomata);
00155         int nb_transition = nb_transition_;
00156         // check consistency of automaton
00157         if (nb_transition_ < nb_state - 1)
00158           nb_transition = nb_state - 1;
00159         if (fstate > nb_state) fstate = nb_state;
00160         if (fstate <= 0) fstate = 1;
00161         if (istate > nb_state) istate = nb_state;
00162         if (istate <= 0) istate = 1;
00163 
00164         TAutomata work(set);
00165 
00166         for (unsigned i = 0; i < nb_state; i++)
00167           work.add_state();
00168 
00169         // minimal construction
00170         state_iterator prev = work.states().begin();
00171         state_iterator i = prev;
00172         ++i;
00173         for (; i != work.states().end(); ++i)
00174         {
00175           nb_transition--;
00176           std::set<htransition_t> dst;
00177           letter_t e = set.series().monoid().alphabet().choose();
00178           work.letter_deltac(dst, *prev, e, delta_kind::transitions());
00179           if (dst.size() == 0)
00180             work.add_letter_transition(*prev, *i, e);
00181           prev = i;
00182         }
00183 
00184         for (int i = 0; i < nb_transition; i++)
00185         {
00186           std::set<hstate_t> dst;
00187           letter_t e = set.series().monoid().alphabet().choose();
00188           hstate_t s = work.choose_state();
00189           hstate_t a = work.choose_state();
00190           work.letter_deltac(dst, s, e, delta_kind::states());
00191           if (dst.find(a) == dst.end())
00192             work.add_letter_transition(s, a, e);
00193         }
00194 
00195         work.set_initial(*work.states().begin());
00196         // set initial states
00197         for (unsigned i = 1; i < istate; i++)
00198         {
00199           hstate_t tmp = work.choose_state();
00200           while (work.is_initial(tmp))
00201             tmp = work.choose_state();
00202           work.set_initial(tmp);
00203         }
00204 
00205         work.set_final(*--work.states().end());
00206         // set final states
00207         for (unsigned i = 1; i < fstate; i++)
00208         {
00209           hstate_t tmp = work.choose_state();
00210           while (work.is_final(tmp))
00211             tmp = work.choose_state();
00212           work.set_final(tmp);
00213         }
00214 
00215         return work;
00216       }
00217 
00218     /*---------------.
00219     | useful methods |
00220     `---------------*/
00221 
00222     template <class TAutomata, class AutomataSetGenerator>
00223       unsigned GenRandomAutomata<TAutomata, AutomataSetGenerator>::
00224       nb_transition_circle(TAutomata work, hstate_t state)
00225       {
00226         AUTOMATON_TYPES(TAutomata);
00227         unsigned res = 0;
00228 
00229         for_all_transitions(i, work)
00230           if ((work.src_of(*i) == state) && (work.dst_of(*i) == state))
00231             res++;
00232 
00233         return res;
00234       }
00235 
00236     template <class TAutomata, class AutomataSetGenerator>
00237       void GenRandomAutomata<TAutomata, AutomataSetGenerator>::
00238       del_transition_circle(TAutomata& work, hstate_t state)
00239       {
00240         AUTOMATON_TYPES(TAutomata);
00241 
00242         std::list<htransition_t> to_remove;
00243         for_all_transitions(i, work)
00244         {
00245           if ((work.src_of(*i) == state) && (work.dst_of(*i) == state))
00246             to_remove.push_back(*i);
00247         }
00248         for_all_const_(std::list<htransition_t>, e, to_remove)
00249           work.del_transition(*e);
00250       }
00251 
00252 
00253     /*----------------------.
00254     | generate with epsilon |
00255     `----------------------*/
00256 
00257     template <class TAutomata, class AutomataSetGenerator>
00258       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
00259       generate_with_epsilon(unsigned nb_state,
00260           unsigned nb_transition,
00261           unsigned nb_epsilon_min,
00262           unsigned nb_epsilon_max)
00263       {
00264         automata_set_t aset =
00265           GenRandomAutomataSet::generate(SELECT(automata_set_t));
00266         TAutomata a = generate_with_epsilon(aset, nb_state, nb_transition,
00267             nb_epsilon_min, nb_epsilon_max);
00268         return a;
00269       }
00270 
00271 
00272 
00273     template <class TAutomata, class AutomataSetGenerator>
00274       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
00275       generate_with_epsilon(const automata_set_t& set,
00276           unsigned nb_state,
00277           unsigned nb_transition,
00278           unsigned nb_epsilon_min,
00279           unsigned nb_epsilon_max)
00280       {
00281         TAutomata a = generate(set, nb_state, nb_transition);
00282         unsigned nb_eps = nb_epsilon_min + alea(nb_epsilon_max - nb_epsilon_min);
00283 
00284         for (unsigned i = 0; i < nb_eps; ++i)
00285         {
00286           hstate_t f = a.choose_state();
00287           hstate_t t = a.choose_state();
00288           a.add_spontaneous(f, t);
00289         }
00290         return a;
00291       }
00292 
00293 
00294     /*-------------.
00295     | generate dfa |
00296     `-------------*/
00297 
00298     template <class TAutomata, class AutomataSetGenerator>
00299       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
00300       generate_dfa(unsigned nb_state,
00301           unsigned size_alphabet,
00302           unsigned fstate)
00303       {
00304         automata_set_t aset =
00305           GenRandomAutomataSet::generate(SELECT(automata_set_t), size_alphabet);
00306         TAutomata a = generate_dfa(aset, nb_state, fstate);
00307         return a;
00308       }
00309 
00310 
00311 
00312     template <class TAutomata, class AutomataSetGenerator>
00313       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
00314       generate_dfa(const automata_set_t& set,
00315           unsigned nb_state,
00316           unsigned fstate)
00317       {
00318         AUTOMATON_TYPES(TAutomata);
00319         AUTOMATON_FREEMONOID_TYPES(TAutomata);
00320         automaton_t work(set);
00321 
00322         for (unsigned i = 0; i < nb_state; i++)
00323           work.add_state();
00324 
00325         for_all_states(i, work)
00326         {
00327           for_all_letters(j, set.series().monoid().alphabet())
00328             work.add_letter_transition(*i,work.choose_state(),*j);
00329           while (nb_transition_circle(work, *i) == set.series().monoid().alphabet().size())
00330           {
00331             del_transition_circle(work, *i);
00332             for_all_letters(j, set.series().monoid().alphabet())
00333             {
00334               std::set<hstate_t> ret;
00335               work.letter_deltac(ret, *i, *j, delta_kind::states());
00336               if (ret.size() == 0)
00337               {
00338                 hstate_t s;
00339                 while ((s = work.choose_state()) == *i) ;
00340                 work.add_letter_transition(*i, s, *j);
00341               }
00342             }
00343           }
00344         }
00345 
00346         // set initial states
00347         work.set_initial(work.choose_state());
00348 
00349         // set final states
00350         for (unsigned i = 0; i < fstate; i++)
00351         {
00352           hstate_t tmp = work.choose_state();
00353           while (work.is_final(tmp))
00354             tmp = work.choose_state();
00355           work.set_final(tmp);
00356         }
00357         return work;
00358       }
00359 
00360 
00361     /*--------------------.
00362     | generate normalized |
00363     `--------------------*/
00364 
00365     template <class TAutomata, class AutomataSetGenerator>
00366       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
00367       generate_normalized(unsigned nb_state, unsigned density)
00368       {
00369         automata_set_t aset =
00370           AutomataSetGenerator::generate(SELECT(automata_set_t));
00371         TAutomata a = generate_normalized(aset, nb_state, density);
00372         return a;
00373       }
00374 
00375     template <class TAutomata, class AutomataSetGenerator>
00376       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
00377       generate_normalized(const automata_set_t& set,
00378           unsigned nb_state,
00379           unsigned density)
00380       {
00381         typedef typename TAutomata::state_iterator state_iterator;
00382         typedef typename TAutomata::monoid_t::alphabets_elt_t alphabets_elt_t;
00383 
00384         if (density == 0)
00385           density = 1;
00386 
00387         TAutomata work = generate(set, nb_state,
00388             nb_state + alea(nb_state * density));
00389 
00390         for (state_iterator i = work.states().begin(); i != work.states().end();
00391             i++)
00392         {
00393           if (work.is_initial(*i))
00394             work.unset_initial(*i);
00395           if (work.is_final(*i))
00396             work.unset_final(*i);
00397         }
00398 
00399         hstate_t init = work.add_state();
00400         hstate_t final = work.add_state();
00401 
00402         work.set_initial(init);
00403         work.set_final(final);
00404 
00405         const alphabets_elt_t&
00406           alpha = work.structure().series().monoid().alphabet();
00407 
00408         hstate_t tmp;
00409 
00410         for (unsigned i = 0; i < density; i++)
00411           if ((tmp = work.choose_state()) != init)
00412             work.add_letter_transition(init, tmp,
00413                                        alpha.choose());
00414 
00415         for (unsigned i =0; i < density; i++)
00416           if ((tmp = work.choose_state()) != final)
00417             work.add_letter_transition(tmp, final,
00418                 alpha.choose());
00419 
00420         return work;
00421       }
00422 
00423   } // ! tools
00424 
00425 } // ! vcsn
00426 
00427 #endif // ! VCSN_TOOLS_GEN_RANDOM_HXX

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