random.h

00001 /*
00002  * ASTL - the Automaton Standard Template Library.
00003  * C++ generic components for Finite State Automata handling.
00004  * Copyright (C) 2000-2003 Vincent Le Maout (vincent.lemaout@chello.fr).
00005  * 
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  * 
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #ifndef ASTL_RANDOM_H
00023 #define ASTL_RANDOM_H
00024 
00025 #include <astl.h>
00026 #include <cmath>       // modf
00027 #include <ctime>       // time
00028 
00029 namespace astl {
00030 
00031 // TODO:
00032 // 1. Les méthodes find et exists ne sont pas implémentées (tournent en temps linéaire de
00033 //    toute façon, beurk).
00034 // 2. On ne peut pas itérer deux fois de suite sur les transitions d'un état.
00035 
00036 // Generates double floating point numbers in the range [0,1].
00037 // Based on Lary Hudson's public domain function frandom
00038 class randomizer
00039 {
00040 protected:
00041   double seed_, state;
00042   static const double TEN_PI;
00043   static const double E;
00044 
00045 public:
00046   randomizer(unsigned int i = time(0)) {
00047     seed(i);
00048   }
00049 
00050   unsigned int seed() const {
00051     return (unsigned int) seed_;
00052   }
00053 
00054   void seed(unsigned int i) {
00055     seed_ = i;
00056     state = seed_ * E; 
00057   }
00058 
00059   double operator()() {
00060     static double bogus;
00061     state = modf(state * TEN_PI + E, &bogus);
00062     return state;
00063   }
00064 };
00065 
00066 const double randomizer::TEN_PI = 31.41592653589793;
00067 const double randomizer::E = 2.718281828459045;
00068 
00069 template <typename EnumerableCharTraits>
00070 class generator_base : public forward_cursor_concept
00071 {
00072 public:
00073   typedef generator_base self;
00074   typedef unsigned int   state_type;
00075   typedef empty_tag      tag_type;
00076   typedef typename EnumerableCharTraits::char_type char_type;
00077   typedef EnumerableCharTraits char_traits;
00078 
00079 protected:
00080   mutable randomizer gen1, gen2;    // 1 for transitions, 2 for final states
00081   int graine;
00082   state_type q;
00083   pair<typename EnumerableCharTraits::const_iterator, state_type> t;
00084   unsigned int depth;
00085   double t_prob, f_prob;
00086         
00087 public:
00088   generator_base(unsigned int height, double t_probability, 
00089                  double f_probability, int seed = time(0))
00090     : graine(seed), depth(height), t_prob(t_probability), 
00091       f_prob(f_probability) 
00092   { }
00093                 
00094   bool src_final() const {
00095     gen2.seed(graine + q);
00096     return gen2() < f_prob;
00097   }
00098 
00099   bool aim_final() const {
00100     gen2.seed(graine + t.second);
00101     return gen2() < f_prob;
00102   }
00103 
00104   self& operator=(state_type p) {
00105     q = p;
00106   }
00107 
00108   state_type src() const {
00109     return q;
00110   }
00111 
00112   state_type aim() const {
00113     return t.second;
00114   }
00115 
00116   tag_type src_tag() const {
00117     return empty_tag();
00118   }
00119 
00120   tag_type aim_tag() const {
00121     return empty_tag();
00122   }
00123 
00124   char_type letter() const {
00125     return *t.first;
00126   }
00127 
00128   state_type sink_state() const {
00129     return state_type(0);
00130   }
00131 
00132   bool sink() const {
00133     return q == sink_state();
00134   }
00135 
00136   void forward() {
00137     q = t.second;
00138     --depth;
00139   }
00140 
00141   bool operator==(const self& x) const {
00142     return q == x.q && t == x.t;
00143   }
00144 };
00145 
00146 template <typename EnumerableCharTraits>
00147 class dag_generator : public generator_base<EnumerableCharTraits>
00148 {
00149 public:
00150   typedef dag_generator self;
00151   typedef generator_base<EnumerableCharTraits> super;
00152   typedef typename super::state_type state_type;
00153   typedef typename super::tag_type   tag_type;
00154   typedef typename super::char_type  char_type;
00155   typedef typename super::char_traits char_traits;
00156 
00157 public:
00158   dag_generator(unsigned int height, double t_probability, 
00159                 double f_probability, int seed = time(0))
00160     : super(height, t_probability, f_probability, seed) {
00161     q = t.second = 1;
00162   }
00163                 
00164   bool first() {
00165     if (depth == 0) return false;
00166     gen1.seed(graine + q);
00167     for(t.first = EnumerableCharTraits::begin(); 
00168         t.first != EnumerableCharTraits::end() && gen1() >= t_prob; ++t.first);
00169     if (t.first != EnumerableCharTraits::end()) {
00170       ++t.second;
00171       return true;
00172     }
00173     return false;
00174   }
00175                         
00176   bool next() {
00177     for(++t.first; t.first != EnumerableCharTraits::end() 
00178           && gen1() >= t_prob; ++t.first);
00179     if (t.first != EnumerableCharTraits::end()) {
00180       ++t.second;
00181       return true;
00182     }
00183     return false;
00184   }
00185 
00186 protected:
00187   using super::q;
00188   using super::t;
00189   using super::depth;
00190   using super::gen1;
00191   using super::graine;
00192   using super::t_prob;
00193 };
00194 
00195 template <typename EnumerableCharTraits>
00196 class tree_generator : public generator_base<EnumerableCharTraits>
00197 {
00198 public:
00199   typedef tree_generator self;
00200   typedef generator_base<EnumerableCharTraits> super;
00201   typedef typename super::state_type state_type;
00202   typedef typename super::tag_type   tag_type;
00203   typedef typename super::char_type  char_type;
00204   typedef typename super::char_traits char_traits;
00205 
00206 protected:
00207   static state_type count;
00208         
00209 public:
00210   tree_generator(unsigned int height, float t_probability, 
00211                  float f_probability, int seed = time(0))
00212     : super(height, t_probability, f_probability, seed) {
00213     q = ++count;
00214   }
00215                 
00216   bool first() {
00217     if (depth == 0) return false;
00218     gen1.seed(graine + q);
00219     for(t.first = EnumerableCharTraits::begin(); 
00220         t.first != EnumerableCharTraits::end() && gen1() >= t_prob; ++t.first);
00221     if (t.first != EnumerableCharTraits::end()) {
00222       t.second = ++count;
00223       return true;
00224     }
00225     return false;
00226   }
00227                         
00228   bool next() {
00229     if (depth == 0) return false;
00230     for(++t.first; t.first != EnumerableCharTraits::end() 
00231           && gen1() >= t_prob; ++t.first);
00232     if (t.first != EnumerableCharTraits::end()) {
00233       t.second = ++count;
00234       return true;
00235     }
00236     return false;
00237   }
00238 
00239 protected:
00240   using super::q;
00241   using super::t;
00242   using super::depth;
00243   using super::gen1;
00244   using super::graine;
00245   using super::t_prob;
00246 };
00247 
00248 template <typename EnumerableCharTraits>
00249 typename tree_generator<EnumerableCharTraits>::state_type 
00250 tree_generator<EnumerableCharTraits>::count = 0;
00251 
00252 template <typename EnumerableCharTraits>
00253 class cyclic_generator : public generator_base<EnumerableCharTraits>
00254 {
00255 public:
00256   typedef cyclic_generator self;
00257   typedef generator_base<EnumerableCharTraits> super;
00258   typedef typename super::state_type state_type;
00259   typedef typename super::tag_type   tag_type;
00260   typedef typename super::char_type  char_type;
00261   typedef typename super::char_traits char_traits;
00262 
00263   cyclic_generator(unsigned int height, float t_probability, 
00264                    float f_probability, int seed = time(0))
00265     : super(height, t_probability, f_probability, seed) {
00266     q = t.second = 1;
00267   }
00268                 
00269   bool first() 
00270   {
00271     if (depth == 0) return false;
00272     gen1.seed(graine + q);
00273     for(t.first = EnumerableCharTraits::begin(); 
00274         t.first != EnumerableCharTraits::end() && gen1() >= t_prob; ++t.first);
00275     if (t.first != EnumerableCharTraits::end()) {
00276       t.second = ((state_type) (gen1() * (++t.second * 2))) + 1;
00277       return true;
00278     }
00279     return false;
00280   }
00281                         
00282   bool next() 
00283   {
00284     if (depth == 0) return false;
00285     for(++t.first; t.first != EnumerableCharTraits::end() 
00286           && gen1() >= t_prob; ++t.first);
00287     if (t.first != EnumerableCharTraits::end()) {
00288       t.second = ((state_type) (gen1() * (++t.second * 2))) + 1;
00289       return true;
00290     }
00291     return false;
00292   }
00293 
00294 protected:
00295   using super::q;
00296   using super::t;
00297   using super::depth;
00298   using super::gen1;
00299   using super::graine;
00300   using super::t_prob;
00301 };
00302 
00303 } // namespace astl
00304 
00305 
00306 #endif // GENERATOR_CURSOR_H

Generated on Sun Mar 8 02:41:34 2009 for ASTL by  doxygen 1.5.7.1