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

Generated on Wed Jun 13 17:00:22 2007 for Vaucanson by  doxygen 1.5.1