-
Notifications
You must be signed in to change notification settings - Fork 1
3. Charting , Visualization and result listener
Darwin offers two type of charts to better understand what is going on during calculation. Visual aid often is of tremendous aid when fine tuning algorithm settings, both for numerical and categorical data.
Be aware that charting is still a rough spot of the library and does not perform stable if to many updates occuring within a short period of time!
The fundamental idea is simple. The genetic algorithm provides an interface to register result listeners which are notified when ever a new generation is created. We can then look at the returned individuals and plot the data. You could go right ahead and implement your own gui, luckily two basic JavaFX implementations are available via the com.github.kilianB.geneticAlgorithm.charting.ChartHelper
class to dive into charting without doing much coding on your own.
var geneticAlgorithm;
geneticAlgorithm.addResultListener(new ResultListener() {
@Override
public void intermediateResult(Result r) {}
@Override
public void finalResult(Result r) {}
});
geneticAlgorithm.calculate(0);
The result object contains information about the current state of the algorithm, the individuals created during each generation, the runtime, the abort reason if applicable, as well as summary statistics for each generation. Be aware that the result object is mutable and the same object will be returned by all subsequent calls. Similar to JavaFX the result handler is a blocking method and calculation of the ga will be paused as long as work is done in the listener. Long lasting actions should be performed on a new thread. Since the result object will be altered concurrently it's good practice to take note of the generation before returning from the method and access the desired information at a later time.
public void intermediateResult(Result r) {
//If expensive task remember generation and spawn a thread*
int generation = r.getGenerationCount();
new Thread(()->{
r.getSummary(generation);
..... do expensive operation
}).start();
}
A result adapter also exists in case you are only interested in the final or intermediate result.
- If repeated calculates are performed cached thread pool executors might be the way to go.
//Spawn a chart window
String title = "Rastrigin";
boolean displayAverage = false;
boolean logScale = true;
ChartHelper.displayProgressPane(title,geneticAlgorithm,false,true);
The overall progress panes strong suit is to visualize the development of the fitness values as well as population diversity and overall progress. It's really suited to see how choosing different algorithm settings influence the behavior of the calculation.
Here we have chose an non optimized algorithm similar to the one used in the very first example to get a few more data points. With displayAverage
set to false every single individual will be drawn. You can see that the majority of the individuals accumulate close to the currently best value. This is desired as more fit individuals are more likely to be kept in a population. The individuals higher up usually are created by mutation and are exploring the search space further.
Be aware that while displaying all individuals might be appealing this heavily strains the cpu. For the above examples we have 20 points for each series for each generation already piling up to over 200.000 points drawn. Much more scaleable charts can be generated by setting displayAverage=true
.
This will only display the best and average value of each sub population.
A click on the legends lets you toggle the series visibility.
The overall progress pane is straight forward. All you have to do is
Be aware that
Right clicking on the graph allows you to export it as an ..
The variable inspection pane displays the relationship between two variables and the resulting fitness value.
The color key visualizes the average normalized fitness of all solutions in this square. A red square does not necessarily mean the best solution will be found in this location but that solutions present on average are pretty good. Be aware that average values are also depended on sample sizes which usually vary widely on these charts. Moving your mouse cursor over a square will display additional information.
Plotting 2 variables over each other gives you the landscape .. It can be useful to see how variables affect each other and if some
The variable in
Right click on the chart lets you save it to a file
The following example displays the chart created in the bootstrap algorithm example. As you can see categorical data can be displayed
Categories are assigned by utilizing the equals()
and hashCode()
contract
A logaritmic scaling of the fitness puts more weight on the high end of the
How to read the chart The Y-Axis mirrors it values!. Opposed to ordinary graphs high values are plotted at the bottom and low values are plotted at the top of the graph. Originally this design was implemented due to only finesses being plotted on the axis and a low fitness indicating a high .
The best found solution will always be at 100% fitness while the worst will be at 0%. Due to it's nature, genetic algorithm, the overall individual fitness is not normally distributed but skewed towards a low value when taking every generation and individual into consideration. Logarithmic scaling the color key allows to offset the heavy density found at the bottom and lets you differentiate the areas of interest more closely.
This might be changed in the future but the user should be aware of the axis when reading the charts