diff --git a/eo/NEWS b/eo/NEWS index 8fce0ae33..2c10c8c81 100644 --- a/eo/NEWS +++ b/eo/NEWS @@ -1,7 +1,8 @@ -* release 0.9.4 +* release 0.9.4 (not yet released) - Update introductory pages of documentation and webpage. - Remove support for pre-standard C++ compiler (i.e. gcc-2.x), which allows to clean up the code considerably. Assume availability of sstream and limits. + - Implement CMA-ES. * release 0.9.3z.1 (1. Oct. 2005) diff --git a/eo/doc/mainpage.html b/eo/doc/mainpage.html index f295f68a9..9567b294f 100644 --- a/eo/doc/mainpage.html +++ b/eo/doc/mainpage.html @@ -102,7 +102,7 @@ -

Tutorial

+

Documentation

@@ -120,9 +120,8 @@ The tutorial is also included in the released - sources. + sources.

-

The latest introduction to ParadisEO, the parallel version of EO.

+

+ The complete code is also well documented and you can look at the + generated interface + documentation. +

diff --git a/eo/src/utils/eoRNG.cpp b/eo/src/utils/eoRNG.cpp index ad347c6cc..17159bfca 100644 --- a/eo/src/utils/eoRNG.cpp +++ b/eo/src/utils/eoRNG.cpp @@ -1,14 +1,14 @@ #ifdef _MSC_VER // to avoid long name warnings #pragma warning(disable:4786) -#endif +#endif #include #include "eoRNG.h" namespace eo { -/// The Global random number generator. -eoRng rng(time(0)); + /// The Global random number generator. + eoRng rng(time(0)); } diff --git a/eo/src/utils/eoRNG.h b/eo/src/utils/eoRNG.h index 9c7d89a04..ae5797c16 100644 --- a/eo/src/utils/eoRNG.h +++ b/eo/src/utils/eoRNG.h @@ -1,24 +1,24 @@ /** Random number generator adapted from (see comments below) - The random number generator is modified into a class - by Maarten Keijzer (mak@dhi.dk). Also added the Box-Muller - transformation to generate normal deviates. +The random number generator is modified into a class +by Maarten Keijzer (mak@dhi.dk). Also added the Box-Muller +transformation to generate normal deviates. - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Contact: todos@geneura.ugr.es, http://geneura.ugr.es +Contact: todos@geneura.ugr.es, http://geneura.ugr.es */ #ifndef EO_RANDOM_NUMBER_GENERATOR @@ -51,6 +51,15 @@ number generator MT19937 for generating random numbers. The various member functions implement useful functions for evolutionary algorithms. Included are: rand(), random(), flip() and normal(). +EO provides a global random number generator rng that is seeded by the +current UNIX time at program start. Moreover some global convenience functions +are provided that use the global random number generator: random, +normal. + +@warning If you want to repeatedly generated the same sequence of pseudo-random +numbers, you should always reseed the generator at the beginning of your code. + +

Documentation in original file

@@ -77,19 +86,19 @@ depending on data type sizes, and the code is quite short as well). It generates random numbers in batches of 624 at a time, so the caching and pipelining of modern systems is exploited. It is also divide- and mod-free. -The code as Shawn received it included the following notice: -- Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. When you use this, - send an e-mail to with an appropriate reference to - your work. -- It would be nice to CC: when you write. +The code as Shawn received it included the following notice: Copyright (C) +1997 Makoto Matsumoto and Takuji Nishimura. When you use this, send an e-mail to + with an appropriate reference to your work. It +would be nice to Cc: and + when you write.

Portability

Note for people porting EO to other platforms: please make sure that the type -uint32_t in the file eoRng.h is exactly 32 bits long. It may be longer, but not -shorter. If it is longer, file compatibility between EO on different platforms -may be broken. +uint32_t in the file eoRng.h is exactly 32 bits long. It may in principle be +longer, but not shorter. If it is longer, file compatibility between EO on +different platforms may be broken. */ class eoRng : public eoObject, public eoPersistent { @@ -130,85 +139,87 @@ public : /** Re-initializes the Random Number Generator - This is the traditional seeding procedure. + This is the traditional seeding procedure. This version is deprecated and + only provided for compatibility with old code. In new projects you should + use reseed. @see reseed for details on usage of the seeding value. - @version old version + @version old version (deprecated) */ void oldReseed(uint32_t s) { initialize(s); } - /** + /** uniform(m = 1.0) returns a random double in the range [0, m) - */ - double uniform(double m = 1.0) - { // random number between [0, m] - return m * double(rand()) / double(1.0 + rand_max()); - } - - /** - random() returns a random integer in the range [0, m) - */ - uint32_t random(uint32_t m) - { - return uint32_t(uniform() * double(m)); - } - - /** - flip() tosses a biased coin such that flip(x/100.0) will - returns true x% of the time - */ - bool flip(float bias=0.5) - { - return uniform() < bias; - } - - /** - normal() zero mean gaussian deviate with standard deviation of 1 - */ - double normal(void); // gaussian mutation, stdev 1 - - /** - normal(stdev) zero mean gaussian deviate with user defined standard deviation - */ - double normal(double stdev) - { - return stdev * normal(); - } - - /** - normal(mean, stdev) user defined mean gaussian deviate with user defined standard deviation - */ - double normal(double mean, double stdev) - { - return mean + normal(stdev); - } - - /** - Generates random numbers using a negative exponential distribution - */ - double negexp(double mean) - { - return ( -mean*log((double)rand() / rand_max())); - } - - /** - rand() returns a random number in the range [0, rand_max) - */ - uint32_t rand(); + */ + double uniform(double m = 1.0) + { // random number between [0, m] + return m * double(rand()) / double(1.0 + rand_max()); + } /** - rand_max() the maximum returned by rand() + random() returns a random integer in the range [0, m) + */ + uint32_t random(uint32_t m) + { + return uint32_t(uniform() * double(m)); + } + + /** + flip() tosses a biased coin such that flip(x/100.0) will + returns true x% of the time + */ + bool flip(float bias=0.5) + { + return uniform() < bias; + } + + /** + normal() zero mean gaussian deviate with standard deviation of 1 + */ + double normal(void); // gaussian mutation, stdev 1 + + /** + normal(stdev) zero mean gaussian deviate with user defined standard deviation + */ + double normal(double stdev) + { + return stdev * normal(); + } + + /** + normal(mean, stdev) user defined mean gaussian deviate with user defined standard deviation + */ + double normal(double mean, double stdev) + { + return mean + normal(stdev); + } + + /** + Generates random numbers using a negative exponential distribution + */ + double negexp(double mean) + { + return ( -mean*log((double)rand() / rand_max())); + } + + /** + rand() returns a random number in the range [0, rand_max) + */ + uint32_t rand(); + + /** + rand_max() the maximum returned by rand() */ uint32_t rand_max(void) const { return uint32_t(0xffffffff); } /** - roulette_wheel(vec, total = 0) does a roulette wheel selection - on the input std::vector vec. If the total is not supplied, it is - calculated. It returns an integer denoting the selected argument. + roulette_wheel(vec, total = 0) does a roulette wheel selection + on the input std::vector vec. If the total is not supplied, it is + calculated. It returns an integer denoting the selected argument. */ template int roulette_wheel(const std::vector& vec, TYPE total = 0) @@ -241,79 +252,149 @@ public : @overload + Provide a version returning a non-const element reference. + @return Uniformly chosen element from the vector. + + @warning Changing the return value does alter the vector. */ template TYPE& choice(std::vector& vec) { return vec[random(vec.size())]; } - /// - void printOn(std::ostream& _os) const - { - for (int i = 0; i < N; ++i) - { - _os << state[i] << ' '; - } - _os << int(next - state) << ' '; - _os << left << ' ' << cached << ' ' << cacheValue; - } + /// + void printOn(std::ostream& _os) const + { + for (int i = 0; i < N; ++i) + { + _os << state[i] << ' '; + } + _os << int(next - state) << ' '; + _os << left << ' ' << cached << ' ' << cacheValue; + } - /// - void readFrom(std::istream& _is) - { - for (int i = 0; i < N; ++i) - { - _is >> state[i]; - } + /// + void readFrom(std::istream& _is) + { + for (int i = 0; i < N; ++i) + { + _is >> state[i]; + } - int n; - _is >> n; - next = state + n; + int n; + _is >> n; + next = state + n; - _is >> left; - _is >> cached; - _is >> cacheValue; - } + _is >> left; + _is >> cached; + _is >> cacheValue; + } - std::string className(void) const { return "Mersenne-Twister"; } + std::string className(void) const { return "Mersenne-Twister"; } -private : - uint32_t restart(void); - void initialize(uint32_t seed); +private: - uint32_t* state; // the array for the state - uint32_t* next; - int left; - - // for normal distribution - bool cached; - float cacheValue; - - const int N; - const int M; - const uint32_t K; // a magic constant + uint32_t restart(void); - /** - Private copy ctor and assignment operator to make sure that - nobody accidentally copies the random number generator. - If you want similar RNG's, make two RNG's and initialize - them with the same seed. - */ - eoRng (const eoRng&); // no implementation - eoRng& operator=(const eoRng&); // dito + /* @brief Initialize state + + We initialize state[0..(N-1)] via the generator + + x_new = (69069 * x_old) mod 2^32 + + from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's _The Art of Computer + Programming_, Volume 2, 3rd ed. + + Notes (SJC): I do not know what the initial state requirements of the + Mersenne Twister are, but it seems this seeding generator could be better. + It achieves the maximum period for its modulus (2^30) iff x_initial is odd + (p. 20-21, Sec. 3.2.1.2, Knuth); if x_initial can be even, you have + sequences like 0, 0, 0, ...; 2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...; + 2^29, 2^29 + 2^31, 2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd + below. + + Even if x_initial is odd, if x_initial is 1 mod 4 then + + the lowest bit of x is always 1, + the next-to-lowest bit of x is always 0, + the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... , + the 3rd-from-lowest bit of x 4-cycles ... 0 1 1 0 0 1 1 0 ... , + the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... , + ... + + and if x_initial is 3 mod 4 then + + the lowest bit of x is always 1, + the next-to-lowest bit of x is always 1, + the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... , + the 3rd-from-lowest bit of x 4-cycles ... 0 0 1 1 0 0 1 1 ... , + the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... , + ... + + The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is 16, + which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It also does well + in the dimension 2..5 spectral tests, but it could be better in dimension 6 + (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth). + + Note that the random number user does not see the values generated here + directly since restart() will always munge them first, so maybe none of all + of this matters. In fact, the seed values made here could even be + extra-special desirable if the Mersenne Twister theory says so-- that's why + the only change I made is to restrict to odd seeds. + */ + void initialize(uint32_t seed); + + /** @brief Array for the state */ + uint32_t* state; + + uint32_t* next; + + int left; + + // for normal distribution + bool cached; + + float cacheValue; + + const int N; + + const int M; + + /** @brief Magic constant */ + const uint32_t K; + + + /** @brief Copy constructor + + Private copy ctor and assignment operator to make sure that nobody + accidentally copies the random number generator. If you want similar RNG's, + make two RNG's and initialize them with the same seed. + + As it cannot be called, we do not provide an implementation. + */ + eoRng(const eoRng&); + + /** @brief Assignmant operator + + @see Copy constructor eoRng(const eoRng&). + */ + eoRng& operator=(const eoRng&); }; -/** - The one and only global eoRng object -*/ + + namespace eo { -extern eoRng rng; + /** The one and only global eoRng object */ + extern eoRng rng; } - using eo::rng; + + + + // Implementation of some eoRng members.... Don't mind the mess, it does work. @@ -323,139 +404,118 @@ using eo::rng; #define mixBits(u, v) (hiBit(u)|loBits(v)) // move hi bit of u to hi bit of v inline void eoRng::initialize(uint32_t seed) - { - // - // We initialize state[0..(N-1)] via the generator - // - // x_new = (69069 * x_old) mod 2^32 - // - // from Line 15 of Table 1, p. 106, Sec. 3.3.4 of Knuth's - // _The Art of Computer Programming_, Volume 2, 3rd ed. - // - // Notes (SJC): I do not know what the initial state requirements - // of the Mersenne Twister are, but it seems this seeding generator - // could be better. It achieves the maximum period for its modulus - // (2^30) iff x_initial is odd (p. 20-21, Sec. 3.2.1.2, Knuth); if - // x_initial can be even, you have sequences like 0, 0, 0, ...; - // 2^31, 2^31, 2^31, ...; 2^30, 2^30, 2^30, ...; 2^29, 2^29 + 2^31, - // 2^29, 2^29 + 2^31, ..., etc. so I force seed to be odd below. - // - // Even if x_initial is odd, if x_initial is 1 mod 4 then - // - // the lowest bit of x is always 1, - // the next-to-lowest bit of x is always 0, - // the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... , - // the 3rd-from-lowest bit of x 4-cycles ... 0 1 1 0 0 1 1 0 ... , - // the 4th-from-lowest bit of x has the 8-cycle ... 0 0 0 1 1 1 1 0 ... , - // ... - // - // and if x_initial is 3 mod 4 then - // - // the lowest bit of x is always 1, - // the next-to-lowest bit of x is always 1, - // the 2nd-from-lowest bit of x alternates ... 0 1 0 1 0 1 0 1 ... , - // the 3rd-from-lowest bit of x 4-cycles ... 0 0 1 1 0 0 1 1 ... , - // the 4th-from-lowest bit of x has the 8-cycle ... 0 0 1 1 1 1 0 0 ... , - // ... - // - // The generator's potency (min. s>=0 with (69069-1)^s = 0 mod 2^32) is - // 16, which seems to be alright by p. 25, Sec. 3.2.1.3 of Knuth. It - // also does well in the dimension 2..5 spectral tests, but it could be - // better in dimension 6 (Line 15, Table 1, p. 106, Sec. 3.3.4, Knuth). - // - // Note that the random number user does not see the values generated - // here directly since restart() will always munge them first, so maybe - // none of all of this matters. In fact, the seed values made here could - // even be extra-special desirable if the Mersenne Twister theory says - // so-- that's why the only change I made is to restrict to odd seeds. - // +{ + left = -1; - left = -1; + register uint32_t x = (seed | 1U) & 0xFFFFFFFFU, *s = state; + register int j; - register uint32_t x = (seed | 1U) & 0xFFFFFFFFU, *s = state; - register int j; + for(left=0, *s++=x, j=N; --j; + *s++ = (x*=69069U) & 0xFFFFFFFFU); +} - for(left=0, *s++=x, j=N; --j; - *s++ = (x*=69069U) & 0xFFFFFFFFU); - } inline uint32_t eoRng::restart(void) { - register uint32_t *p0=state, *p2=state+2, *pM=state+M, s0, s1; - register int j; + register uint32_t *p0=state, *p2=state+2, *pM=state+M, s0, s1; + register int j; - left=N-1, next=state+1; + left=N-1, next=state+1; - for(s0=state[0], s1=state[1], j=N-M+1; --j; s0=s1, s1=*p2++) - *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); + for(s0=state[0], s1=state[1], j=N-M+1; --j; s0=s1, s1=*p2++) + *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); - for(pM=state, j=M; --j; s0=s1, s1=*p2++) - *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); + for(pM=state, j=M; --j; s0=s1, s1=*p2++) + *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); - s1=state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); - s1 ^= (s1 >> 11); - s1 ^= (s1 << 7) & 0x9D2C5680U; - s1 ^= (s1 << 15) & 0xEFC60000U; - return(s1 ^ (s1 >> 18)); + s1=state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U); + s1 ^= (s1 >> 11); + s1 ^= (s1 << 7) & 0x9D2C5680U; + s1 ^= (s1 << 15) & 0xEFC60000U; + return(s1 ^ (s1 >> 18)); } + + inline uint32_t eoRng::rand(void) - { +{ - uint32_t y; + uint32_t y; + + if(--left < 0) + return(restart()); + + y = *next++; + y ^= (y >> 11); + y ^= (y << 7) & 0x9D2C5680U; + y ^= (y << 15) & 0xEFC60000U; + return(y ^ (y >> 18)); +} - if(--left < 0) - return(restart()); - y = *next++; - y ^= (y >> 11); - y ^= (y << 7) & 0x9D2C5680U; - y ^= (y << 15) & 0xEFC60000U; - return(y ^ (y >> 18)); - } inline double eoRng::normal(void) { - if (cached) + if (cached) { - cached = false; - return cacheValue; + cached = false; + return cacheValue; } - float rSquare, factor, var1, var2; + float rSquare, factor, var1, var2; - do - { - var1 = 2.0 * uniform() - 1.0; - var2 = 2.0 * uniform() - 1.0; + do + { + var1 = 2.0 * uniform() - 1.0; + var2 = 2.0 * uniform() - 1.0; - rSquare = var1 * var1 + var2 * var2; - } - while (rSquare >= 1.0 || rSquare == 0.0); + rSquare = var1 * var1 + var2 * var2; + } + while (rSquare >= 1.0 || rSquare == 0.0); - factor = sqrt(-2.0 * log(rSquare) / rSquare); + factor = sqrt(-2.0 * log(rSquare) / rSquare); - cacheValue = var1 * factor; - cached = true; + cacheValue = var1 * factor; + cached = true; - return (var2 * factor); + return (var2 * factor); } -namespace eo { -// a few convenience functions for generating numbers - /** - * Templatized random function, works with most basic types such as: - * char - * int - * unsigned - * float - * double - */ + +namespace eo { + // a few convenience functions for generating numbers + + /** @brief Random function + + Templatized random function, returns a random double in the range [0, max). + + @param max Maximum for distribution + + It works with most basic types such as: + - char + - int + - unsigned + - float + - double + */ template - inline - T random(const T& mx) { return static_cast(rng.uniform() * mx); } + inline T random(const T& max) { + return static_cast(rng.uniform() * max); } + + /** @brief Random function + + Templatized random function, returns a random double in the range [min, max). + + @param min Minimum for distribution + @param max Maximum for distribution + + @see random(const T& max) + */ + template + inline T random(const T& min, const T& max) { + return static_cast(rng.uniform() * (max-min)) + min; } /** Normal distribution */ inline double normal() { return rng.normal(); }