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