Vaucanson 1.4
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