Most EO code is written using templates. This allows to write generic code, i.e. involving a class which doesn't have to be known when writing the code -- but only when compiling it. In some sense this is similar to naming variables in algebra: you can write a lot of equations involving some variable $x$ without knowing even it if will be an integer or a float (or a matrix or ...). The main basic type that is templatized in EO is the fitness: an EO object is some object which has a fitness of some type F that can be anything. The definition for that is (see EO.h)
template<F> class EO
The idea is that, later in your code, you can define a class as follows (see for instance eoBin.h
template<F> class eoBin : public EO<F>
{ ... code for eoBin };
and then use it in your application as
eoBin<double> myeoBin;
declares an object of type eoBin which has as fitness a double.
Whereas the advantages are obvious (writing generic reusable code instead of having to rewrite the same pieces of code for different types), there are some drawbacks: namely, it makes some of the compiler error messages hard to understand; and it forbids the compilation of most parts of EO into an object library file, as the actual types are not known in advance.
Though EO is a library, it contains almost no functions per se!
EO mainly contains functors, that are objects which have a method called
operator().
Such objects are used as if they were functions, but the big differences
are that
Functors: Example:
The following is a basic example of how to program and use a functor object: First code the class:
class MyFunctor
{ ...
void operator()(ArgType
arg)
{
// do what you have to do
}
}; // end of class declaration
Then use it later in the code :
ArgType myArgument;
MyFunctor myFunctorInstance;
// myFunctorInstance is an object of class MyFUnctor ...
myFunctorInstance(myArgument);
// calls operator() of myFunctorInstance acting on myArgument ...
Functors: The three basic classes:
Direct sub-classes of the root class , three classes
are defined to differentiate functors by the number of argument required
by their operator().
These classes are templatized by the types of its arguments, and by its
return type. Hence,
from the inheritance diagram of any functor class
in EO, you can immediately deduce the interface of their operator()
method.
Note: for obvious simplicity reasons, we very often omit the reference to the operator(), e.g. when we say above:
All EO heavily relies on STL, the Standard
Template Library.
But you don't have to know more than a few words
of STL to use EO (like with "hello", "please" and "goodbye" you
can survive in a foreign country :-) and even to contribute to new EO features.
Moreover, while browsing through EO code, you will gradually learn how
to use STL, especially if you check at the SGI
STL Web site from time to time, where you can not only download STL,
but also browse in the Programmer's guide for isntance from the Table
of Content.
Anyway, you will only find here, in EO tutorial, the basics of STL that you will need to understand most of EO code - and to guess what the parts you don't understand are actually doing. Don't worry, I don't understand everything :-)
STL provides the user with containers, iterators and algorithms. And you can access (almost) all containers content using (almost) all iterators, or apply (almost) all algorithms on (almost) all containers (of course the tricky part is to instanciate the "almost" in the previous sentence :-)
STL: Containers
Containers are high level data types used to hold simpler data - the
most widely used example of a container is the vector
construct.
The use of STL containers relieve the user from memory management.
STL: Iterators
Iterators are accessors to the containers contents that provide unified
access to different containers. They are very similar to pointers, i.e.
you can increment them, compare them with one another, etc
Some very useful iterators for vectors and lists are begin()
and end(), that refer to the first
and after-last items of a container. They allow loops to sweep all items
contained in a container as follows:
STLcontainer myContain;
STLcontainer::iterator it;
for (it=myContain.begin(); it!=myContain.end();
it++)
{
// do what you have to do to
(*it)
the current item in the container
}
STL: Algorithms
Algorithms are functions acting on containers - the most widely used
example of a STL algorithm are the different sorting
algorithms.
STL: Drawbacks
The main drawback I see in using STL is that it makes it almost
impossible
to use a debugger normally: whereas access to data is made simple
to the programmer, data structures are actually so complex, and debuggers
so willing to display everything that you get lines of template instantiation
when asking your debugger what is inside some container! For instance I
could never visualize some
v[i]
with gbd, v
being an STL vector!
Evolutionary Algorithms make intensive use of random numbers. Random numbers are simulated in computers by using pseudo-random number generators (RNGs for short), i.e. functions that return series of numbers who look random (w.r.t. some statistical criteria).
To make sure the random number generator is as good as possible, and to ensure reproducibility of the results across different platforms, EO has its own RNG, the ``Mersenne Twister'' random number generator MT19937 (thanks to Takuji Nishimura, see eoRNG.h comments).
Though you can define and use as many RNGs as you wish in EO, the library also provides you with a global RNG termed eo::rng. Using that single RNG in all calls to random numbers allows one to be able to reproduce a given run:
EO also provides random_generators that can be used in STL call to generate series of random numbers, as in eoPop initializers.
Note: the eo::
prefix indicates that it is in a separate C++ namespace, to avoid collision
with possible variables that would also be named rng in some other library.
As early versions of EO (<= 9.1) did not use a separate namespace
for rng, the compiler directive using eo::rng in eoRNG.h allows you to
use the name rng without the eo::
prefix. However, the notation eo::rng
should be preferred and might become mandatory some day.
A few naming conventions should help you to navigate more easily through EO:
class eoMyClass
{
public:
eoMyClass(unsigned _popSize):popSize(_popSize){...}
...
private:
unsigned popSize;
};