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

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