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

- File List
- File Members

# 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           letter_t e = set.series().monoid().alphabet().choose();
    00177           bool empty = true;
    00178           for (delta_iterator t(work.value(), *prev);
    00179                ! t.done() && empty;
    00180                t.next())
    00181           {
    00182             monoid_elt_t w(work.series_of(*t).structure().monoid(), e);
    00183             if (work.series_of(*t).get(w) != work.series().semiring().wzero_)
    00184             {
    00185               empty = false;
    00186               break;
    00187             }
    00188           }
    00189
    00190           if (empty &&
    00191               algebra::letter_traits<letter_t>::letter_to_literal(e) != work.structure().series().monoid().representation()->empty)
    00192             work.add_letter_transition(*prev, *i, e);
    00193           prev = i;
    00194         }
    00195
    00196         for (int i = 0; i < nb_transition; i++)
    00197         {
    00198           std::set<hstate_t> dst;
    00199           letter_t e = set.series().monoid().alphabet().choose();
    00200           hstate_t s = work.choose_state();
    00201           hstate_t a = work.choose_state();
    00202           for (delta_iterator t(work.value(), s);
    00203                ! t.done();
    00204                t.next())
    00205           {
    00206             monoid_elt_t w(work.series_of(*t).structure().monoid(), e);
    00207             if (work.series_of(*t).get(w) != work.series().semiring().wzero_)
    00208               dst.insert(work.dst_of(*t));
    00209           }
    00210           if (dst.find(a) == dst.end() &&
    00211               algebra::letter_traits<letter_t>::letter_to_literal(e) != work.structure().series().monoid().representation()->empty)
    00212             work.add_letter_transition(s, a, e);
    00213         }
    00214
    00215         work.set_initial(*work.states().begin());
    00216         // set initial states
    00217         for (unsigned i = 1; i < istate; i++)
    00218         {
    00219           hstate_t tmp = work.choose_state();
    00220           while (work.is_initial(tmp))
    00221             tmp = work.choose_state();
    00222           work.set_initial(tmp);
    00223         }
    00224
    00225         work.set_final(*--work.states().end());
    00226         // set final states
    00227         for (unsigned i = 1; i < fstate; i++)
    00228         {
    00229           hstate_t tmp = work.choose_state();
    00230           while (work.is_final(tmp))
    00231             tmp = work.choose_state();
    00232           work.set_final(tmp);
    00233         }
    00234
    00235         return work;
    00236       }
    00237
    00238     /*---------------.
    00239     | useful methods |
    00240     `---------------*/
    00241
    00242     template <class TAutomata, class AutomataSetGenerator>
    00243       unsigned GenRandomAutomata<TAutomata, AutomataSetGenerator>::
    00244       nb_transition_circle(TAutomata work, hstate_t state)
    00245       {
    00246         AUTOMATON_TYPES(TAutomata);
    00247         unsigned res = 0;
    00248
    00249         for_all_transitions(i, work)
    00250           if ((work.src_of(*i) == state) && (work.dst_of(*i) == state))
    00251             res++;
    00252
    00253         return res;
    00254       }
    00255
    00256     template <class TAutomata, class AutomataSetGenerator>
    00257       void GenRandomAutomata<TAutomata, AutomataSetGenerator>::
    00258       del_transition_circle(TAutomata& work, hstate_t state)
    00259       {
    00260         AUTOMATON_TYPES(TAutomata);
    00261
    00262         std::list<htransition_t> to_remove;
    00263         for_all_transitions(i, work)
    00264         {
    00265           if ((work.src_of(*i) == state) && (work.dst_of(*i) == state))
    00266             to_remove.push_back(*i);
    00267         }
    00268         for_all_const_(std::list<htransition_t>, e, to_remove)
    00269           work.del_transition(*e);
    00270       }
    00271
    00272
    00273     /*----------------------.
    00274     | generate with epsilon |
    00275     `----------------------*/
    00276
    00277     template <class TAutomata, class AutomataSetGenerator>
    00278       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
    00279       generate_with_epsilon(unsigned nb_state,
    00280           unsigned nb_transition,
    00281           unsigned nb_epsilon_min,
    00282           unsigned nb_epsilon_max)
    00283       {
    00284         automata_set_t aset =
    00285           GenRandomAutomataSet::generate(SELECT(automata_set_t));
    00286         TAutomata a = generate_with_epsilon(aset, nb_state, nb_transition,
    00287             nb_epsilon_min, nb_epsilon_max);
    00288         return a;
    00289       }
    00290
    00291
    00292
    00293     template <class TAutomata, class AutomataSetGenerator>
    00294       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
    00295       generate_with_epsilon(const automata_set_t& set,
    00296           unsigned nb_state,
    00297           unsigned nb_transition,
    00298           unsigned nb_epsilon_min,
    00299           unsigned nb_epsilon_max)
    00300       {
    00301         TAutomata a = generate(set, nb_state, nb_transition);
    00302         unsigned nb_eps = nb_epsilon_min + alea(nb_epsilon_max - nb_epsilon_min);
    00303
    00304         for (unsigned i = 0; i < nb_eps; ++i)
    00305         {
    00306           hstate_t f = a.choose_state();
    00307           hstate_t t = a.choose_state();
    00308           a.add_spontaneous(f, t);
    00309         }
    00310         return a;
    00311       }
    00312
    00313
    00314     /*-------------.
    00315     | generate dfa |
    00316     `-------------*/
    00317
    00318     template <class TAutomata, class AutomataSetGenerator>
    00319       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
    00320       generate_dfa(unsigned nb_state,
    00321           unsigned size_alphabet,
    00322           unsigned fstate)
    00323       {
    00324         automata_set_t aset =
    00325           GenRandomAutomataSet::generate(SELECT(automata_set_t), size_alphabet);
    00326         TAutomata a = generate_dfa(aset, nb_state, fstate);
    00327         return a;
    00328       }
    00329
    00330
    00331
    00332     template <class TAutomata, class AutomataSetGenerator>
    00333       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
    00334       generate_dfa(const automata_set_t& set,
    00335           unsigned nb_state,
    00336           unsigned fstate)
    00337       {
    00338         AUTOMATON_TYPES(TAutomata);
    00339         AUTOMATON_FREEMONOID_TYPES(TAutomata);
    00340         automaton_t work(set);
    00341
    00342         for (unsigned i = 0; i < nb_state; i++)
    00343           work.add_state();
    00344
    00345         for_all_states(i, work)
    00346         {
    00347           for_all_letters(j, set.series().monoid().alphabet())
    00348             work.add_letter_transition(*i,work.choose_state(),*j);
    00349           while (nb_transition_circle(work, *i) == set.series().monoid().alphabet().size())
    00350           {
    00351             del_transition_circle(work, *i);
    00352             for_all_letters(j, set.series().monoid().alphabet())
    00353             {
    00354               bool empty = true;
    00355               for (delta_iterator t(work.value(), *i);
    00356                    ! t.done() && empty;
    00357                    t.next())
    00358               {
    00359                 monoid_elt_t w(work.series_of(*t).structure().monoid(), *j);
    00360                 if (work.series_of(*t).get(w) != work.series().semiring().wzero_)
    00361                 {
    00362                   empty = false;
    00363                   break;
    00364                 }
    00365               }
    00366               if (empty)
    00367               {
    00368                 hstate_t s;
    00369                 while ((s = work.choose_state()) == *i) ;
    00370                 work.add_letter_transition(*i, s, *j);
    00371               }
    00372             }
    00373           }
    00374         }
    00375
    00376         // set initial states
    00377         work.set_initial(work.choose_state());
    00378
    00379         // set final states
    00380         for (unsigned i = 0; i < fstate; i++)
    00381         {
    00382           hstate_t tmp = work.choose_state();
    00383           while (work.is_final(tmp))
    00384             tmp = work.choose_state();
    00385           work.set_final(tmp);
    00386         }
    00387         return work;
    00388       }
    00389
    00390
    00391     /*--------------------.
    00392     | generate normalized |
    00393     `--------------------*/
    00394
    00395     template <class TAutomata, class AutomataSetGenerator>
    00396       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
    00397       generate_normalized(unsigned nb_state, unsigned density)
    00398       {
    00399         automata_set_t aset =
    00400           AutomataSetGenerator::generate(SELECT(automata_set_t));
    00401         TAutomata a = generate_normalized(aset, nb_state, density);
    00402         return a;
    00403       }
    00404
    00405     template <class TAutomata, class AutomataSetGenerator>
    00406       TAutomata GenRandomAutomata<TAutomata, AutomataSetGenerator>::
    00407       generate_normalized(const automata_set_t& set,
    00408           unsigned nb_state,
    00409           unsigned density)
    00410       {
    00411         typedef typename TAutomata::state_iterator state_iterator;
    00412         typedef typename TAutomata::monoid_t::alphabets_elt_t alphabets_elt_t;
    00413
    00414         if (density == 0)
    00415           density = 1;
    00416
    00417         TAutomata work = generate(set, nb_state,
    00418             nb_state + alea(nb_state * density));
    00419
    00420         for (state_iterator i = work.states().begin(); i != work.states().end();
    00421             i++)
    00422         {
    00423           if (work.is_initial(*i))
    00424             work.unset_initial(*i);
    00425           if (work.is_final(*i))
    00426             work.unset_final(*i);
    00427         }
    00428
    00429         hstate_t init = work.add_state();
    00430         hstate_t final = work.add_state();
    00431
    00432         work.set_initial(init);
    00433         work.set_final(final);
    00434
    00435         const alphabets_elt_t&
    00436           alpha = work.structure().series().monoid().alphabet();
    00437
    00438         hstate_t tmp;
    00439
    00440         for (unsigned i = 0; i < density; i++)
    00441           if ((tmp = work.choose_state()) != init)
    00442             work.add_letter_transition(init, tmp,
    00443                                        alpha.choose());
    00444
    00445         for (unsigned i =0; i < density; i++)
    00446           if ((tmp = work.choose_state()) != final)
    00447             work.add_letter_transition(tmp, final,
    00448                 alpha.choose());
    00449
    00450         return work;
    00451       }
    00452
    00453   } // ! tools
    00454
    00455 } // ! vcsn
    00456
    00457 #endif // ! VCSN_TOOLS_GEN_RANDOM_HXX