Lesson 2 - Lesson 4 - Main page - Algorithm-Based - Component-Based - Hints - EO documentation

# Tutorial Lesson 3: input/output

In this lesson, you will still use the same Evolutionary Algorithm, BUT in a much more user-friendly way. You will discover how to

- input parameters on the command-line or from a text file
- save the population to disk, together with every part of the algorithm you could think of - so you can decide to reload everything later to continue the same run, eventually with different parameters.
- generate statistics on the populations, and output them to the screen, text or graphic, or to a file (or to any other device you might want to use).

First, but you should now have done it without being told, go into the Lesson3 sub-dir of the tutorial dir and type `make`. This will compile the `SecondBitEA` and `SecondRealEA` programs.

You can then either

- browse the corresponding code (SecondBitEA and SecondRealEA),
- look at the summary of changes,
- or find out directly explanations about the new features: the eoParser, eoState and eoCheckpoint classes.

Changes
As already said, the behavior of the algorithm will be exactly the same as the previous one as far as optimization is concerned. Only the input (of algorithm parameters) and output (of program results) will be very different.
Hence, the sections corresponding to the fitness function, the initialization, the variation operators, the evolution engine and the algorithm itself are almost identical (apart from variable name changes).

- Fitness function: there is an additional line after the encapsulation of our binary_function into an `eoEvalFunc` object, which again encapsulate the `eoEvalFunc` into an `eoEvalFuncCounter`. As its name says, this object will, in addition to computing the fitness, count the actual number of evaluations: the fitness of non-modified individuals is of course not recomputed - and this is taken care of by this object. Moreover, it can be later used for displays in eoMonitor objects, as done in the checkpoint section.
- The initialization section has been extended to account for the possibility to re-load a previously saved population. This is achieved through an eoState object, if the corresponding program parameter is set.
- The variation operators and the evolution engine sections are similar to the ones in Lesson2
- The parameter section is completely different from the previous one. All variables corresponding to program parameters are now read at run-time using an object of class eoParser.
- The stopping criterion section, has in fact now become the checkpoint section, as it involves much more than just stopping criteria. See all details in the eoCheckpoint paragraph below.

eoParser: parameter input
The first two examples of Lessons 1 and 2 had a very crude way to set parameter values: they were hard-coded, and you had to recompile the whole program to change a single value. We shall now see now to set parameter values in a flexible way (though we're still looking for volunteers to create a Graphical User Interface :-)
Two base classes are used for that purpose:

- The `eoValueParam` class, templatized by the type of the variable you want to handle (i.e. i `integer, double, yourPrivateClass`, ...). In this lesson, we will not go into details: e.g. we will not tell you that the eoValueParam is actually a templatized sub-class of abstract class eoParam (oops, I said it!), nor will we deal with parameters outside their use from an eoParser. See the parameter section of the Component-Based tutorial, or wait until lesson 4).
- The `eoParser` class, whose only purpose is the input of parameters. Read its description if you are interested.

eoParser: Modifying parameter values at run-time:
Using an eoParser object, the parameter values are read, by order of priority

1. from the command-line
2. from a text file
3. from the environment (forthcoming, if somebody insists)
4. from default values

The syntax of parameter reading is a keyword-based syntax, now traditional in the Unix world:

- in EO, each parameter is designated by a (long) keyword, and optionally by a short (1 character) keyword.
- the general syntax to modify parameter value at run-time is (either from the command-line or in a text file)
`--longKeyword=value` or `-cvalue` if 'c' is the short keyword (though `-c=value` also works)
- so, after compiling the executable for Lesson 3 (`make lesson3` at system prompt in Unix), you can try to type in
`SecondBitEA`
and see the algorithm run as before (OneMax optimized on 8-bits bitstrings). But you can now type in
`SecondBitEA --vecSize=100`
and see the output of the optimization of OneMax on 100-bit bitstrings.
- Take a look at all available parameters by typing in
`SecondBitEA --help`
or by going into the code: all parameter inputs have been grouped in the read_param function.
- After running the algorithm, a new file has been created, named `SecondBitEA.status`: it contains the list of all actual parameters used, and can directly be used as parameter input file: change the file name (e.g. to `SecondBitEA.param`), edit it, change whichever parameter you want, and type in
`SecondBitEA @SecondBitEA.param`
and you will see all values that you defined into the file taken into account.
- The priority remains to the command-line, so you can still override the values in the parameter file by giving a new value directly on the command-line.

eoParser: Programming parameter input:
The code of SeconBitEA provides examples of parameters reading. Lets take the example of the random number generator `seed`. Of course, you first need to declare an eoParser object (it needs the standard argc and argv in its constructor).

- You must first declare a parameter of type `uint32` (32-bits integer). The arguments are: default value, long keyword, comment (that will appear in the help message and in the output "status" file if any) and optional character keyword.
- Then you must pass it to the parser using the processParam method. The optional argument is a section name, that will be used to make the output of the parser look clean and ordered.
- Finally, you need to assign the value to the variable `seed`. Note that the `value()` method of eoParam returns a reference, so you can eventually modify its value somewhere else later (though of course this is not any useful for variable `seed`!).

There is however another way to achieve the same result in less lines of code - with a different memory management. This is what is done in the code for eoRealEA. The same parameter for the random number generator `seed` is read, but in one single line of code. The only difference is that now you cannot access the eoValueParam object itself - but this is not often necessary.
Be careful to ensure that the type of the default value in the call to eoParameterLoader::createParam method as this is the only way the compiler can desambiguate the template (remember that eoParameterLoader is a base class for eoParser.

eoState: saving and loading You might have noticed in the `read_param` described above a new parameter named `load_name.` Now if you go to the init section of the code, you will see an alternative way of initializing the population: if load_name is an empty string, then we do as in the preceding example and use an eoInitFixedLength object. However, if a load_name name was entered, the population is read through the `inState.load(load_name)` instruction. Moreover, the comment says "Loading pop and rng".

This is made possible using the `eoState` class. `eoState` objects maintain references to `eoObjects` that have both an input method (`readFrom`) and an output method (`printOn`), i.e. that derive from the base class eoPersistent . You must first `register` object into a state, and can then save them to a (text) file, and later read them from that file using the `load` method, as done here.
Of course, you can call the `save` method for an `eoState` object anywhere in the code. But the checkpointing mechanism offers you better ways to do that - and it's so easy ....

Note that an eoState alos has another use in EO whan it comes to memory management: it can be a repository of pointers that are not allocated within obects - allowing to delete them by simply deleting the eoState (see Lesson 4).

eoCheckpoint: every generation I'd like to ...
The checkpointing mechanism is a very powerful construct to perform some systematic actions every generation - like saving things (using eoState objects described above), computing statistics on the population, updating dynamical parameters or displaying information.

`eoCheckpoint` objects are `eoContinue` objects that contain pointers to different types of objects. When their `operator()` method is called (i.e. every generation in the examples up to now), they first call the `operator()` methods of all object they contain, and then return their result as an `eoContinue` object (i.e. should we continue or stop).
Programming: To do something every generation, you simply need to `add` an object whose `operator()` does what you want to the eoState that you will use as continuator in the algorithm.

eoCheckpoint: Stopping
The `eoContinue` part of an `eoCheckpoint` is a single object, passed to the constructor. If you want more that one stopping criterion, use an eoCombinedContinue object as described in Lesson2.

eoCheckpoint: Computing statistics
Statistics are computed using `eoStat` objects, i.e. functor objects whose `operator()` receives as argument a reference to a population as argument, and can hence compute whatever is needed over that population. `eoStat` objects are templatized over the type of what they compute (e.g. `double`, or `pair<double>`, or ...). But looking at the inheritance diagram of the `eoStat` class, you find that `eoStat` objects are also `eoValueParam` objects. And this allows `eoStat` to be used within `eoMonitor` object, and hence displayed to the user!

Statistics: Available instances
Some widely used statistics are already available (and of course you can build you own!).

- `eoBestFitnessStat` returns the fitness value of the best individual in the population (of type `FitnessType`, whatever this is).
- `eoAverageStat` and `eoSecondMomentStat` respectively return the average (type double, assumes that `FitnessType` is castable to a double) and a pair made of the average and the standard deviation (type `pair<double>`) of the fitnesses in the populations.
- `eoDiversityStat` returns the diversity in the population: assuming that there is a distance function defined among individuals, it returns the average inter-individuals distance. See also Exercise 2.

Statistics: Adding to the checkpoint
To compute more statistics when your algorithm is running, simply declare the corresponding eoStat objects, and add them to the `eoCheckpoint` you use in the algorithm. But it hardly makes any sense if you don't monitor those statistics (i.e. either displaying them on the screen, or storing them into a file): see next section!

Note: actually, there are 2 distinct classes that compute and give access to statistics: `eoStat`and `eoSortedStat`. As its name indicate, the latter is used whenever computing the statistics require a sorted population: not only this avoids to sort the population many times, but also it avoids changing the order of the population at all as `eoSortedStat` objects work on a temporary vector of fitnesses . But as far as their usage is concerned, its makes no difference.

eoCheckpoint: Monitoring eoParameters
The `eoMonitor` objects are used to display or store to a file a set of `eoValueParam` objects.

Monitors: Available instances
A few monitors are available in the EO distribution:

- `eoStdoutMonitor` displays its parameters in text format on the screen. The (optional) boolean value in the constructor modifies the output: when true (the default), verbose output is used, with one line per parameter. When false, parsimonious output displays one line for all parameters.
- `eoFileMonitor` writes its parameters in text format in a file. A file name is required in the constructor, and an optional separator character can be added (default is ' '). Note that the file is by default overwritten by next call to the same program, unless you pass "true" as third (optional) boolean parameter, which will result in appending to the file if it ever exists.
- `eoGnuplot1DMonitor` displays its parameters in graphical format on the screen by calling the `gnuplot` program, and as of today, only works in the Unix version of EO (as always, volunteers are welcome to port that to MS Windows). It takes an optional filename as input, as communication of data with `gnuplot` is done through a file. If no filename is provided, the file will be erased at the end of the run, while it is otherwise kept (though it will be overwritten by next call to the same program).

Monitors: Adding to the checkpoint
To display something while the algorithm is running, you need to declare an `eoMonitor` object, add some objects (that must be `eoValueParam` objects) to that monitor, and of course add the monitor to the `eoCheckpoint` you use in the algorithm.

eoCheckpoint: Updating things
The last type of objects that `eoCheckpoint` can handle are `eoUpdater` objects. You should simply encapsulate in an `eoUpdater` anything you wish to do which does not fit into one of the above category. Note that their `operator() method` does not receive any argument.

Updater: Available instances: A few updaters are available in the EO distribution:

- `eoIncrementor` A simple updater which maintains a counter (an `eoValueParam` that needs to be created beforehand, and passed in the constructor). It is incremented every time the `operator()` method is called (every generation at the moment). You can of course also give an increment in the constructor (1 by default).
- `eoCountedStateSaver` and `eoTimedStateSaver` can be used to save some existing `eoState` (see above) to a file regularly, either based on the generation count (e.g. every 4 generations) or based on the clock (e.g. every 5 seconds).

Updater: Adding to the checkpoint
A very simple example of using an `eoUpdater` is given in the code for SecondBitEA: First declare an `eoValueParam` object, then use it to construct an `eoIncrementor` that you must add to the `eoCheckpoint` in order to activate its update. You can then use the parameter for your purpose, for instance as a first coordinate for a monitor.
Note also how to use the statesavers: first declare a state, then register whatever you think necessary to that state, then pass the state to some state-saver - and don't forget to add the statesavers to the current `eoCheckpoint`.

Exercise 1:

- The code of `SecondBitEA` display things in the current window in text format. Replace the `eoFileMonitor` by an `eoGnuplot1DMonitor` and watch the graphical output (Unix systems with gnuplot installed only, sorry).
- Note that you must also replace the `eoSecondMomentStat` by an `eoAverageStat`, otherwise the standard deviations won't make any sense here.
- Please try to understand why the average is always 0 before taking a look at the solution (file exercise1.cpp).
- Then run
`exercise1 --vecSize=1000 --maxGen=1000`
to get a chance to see something happening before the program ends!

Exercise 2:
Write the `eoDiversityStat` stat computation and test it. Thanks to send us the code!

Exercise 3:
Write the code for an `eoGnuplotSecondStatMonitor` that would display the `eoSecondMomentStat` (i.e. take into account the standard deviations and display them as error-bars.
Again, send us the code afterwards, thanks :-)

Lessons learned:

- Value of program parameters can be set at run-time using the `eoParser` class.
- Snapshots of the algorithms can easily be saved (and restored) thanks to the `eoState` class.
- The `eoCheckpoint` mechanism let you do things every generation without modifying existing algorithms, by simply writing the necessary code and encapsulating it into an object that `eoCheckpoint` is aware of, that are at the moment the following:
- computing statistics, displaying parameters (e.g. statistics), saving the `(eo)State` of the program.

In next lesson you will find out that many adaptive techniques (the state-of-the-art in Evolutionary Computation) can easily be programmed through the `eoUpdater` construct.

Lesson 2 - Lesson 4 - Main page - Algorithm-Based - Component-Based - Hints - EO documentation

Last modified: None of your business!