Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

#32 sortByFitness broken by unhandled NaN

JGAP 3.1
closed-fixed
Klaus
7
2006-11-21
2006-11-08
Oswaldo Dantas
No

Adding the following piece of code between the calls to
gp.evolve and gp.outputSolution (lines 97 and 98) on
the example class MathProblem, you can see that the
presence of NaNs with the current comparator
implementation breaks the Arrays.sort:

(...)
GPPopulation pop = gp.getGPPopulation();
pop.sortByFitness();
IGPProgram[] programs = pop.getGPPrograms();
for (int i = 0; i < programs.length; i++) {
System.out.println(programs[i].getFitnessValue());
}
(...)

The console shows lines as the following:

(...)
2615.9530421048403
2602.550199523568
2558.993910089135
2519.7835219053086
2517.326104655862
2167.5602150410414
NaN
NaN
2149.6663913726807
2149.6663913726807
2070.5095789581537
2019.594516173005
NaN
NaN
3110.4262635558844
NaN
2650.885959379375
NaN
2661.181804791093
2647.056322351098
2641.892960086465
1961.5068318545818
NaN
2603.6024593263865
2590.584208384156
(...)

In the Arrays.sort javadoc it says "(...)NaN value
compares neither less than, greater than, nor equal to
any floating-point value, even itself."

In GPProgramFitnessComparator, the compare method
doesn't treat the NaNs.

Because it uses the interface IGPFitnessEvaluator I did
the following change to the isFitter in
DefaultGPFitnessEvaluator and the console showed the
population sorted as I was expecting:

public boolean isFitter(final double
a_fitness_value1, final double a_fitness_value2) {
if (!Double.isNaN(a_fitness_value1) &&
!Double.isNaN(a_fitness_value2)) {
return a_fitness_value1 > a_fitness_value2;
} else if (Double.isNaN(a_fitness_value1)) {
return true;
}
return false;
}

console:
(...)
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
NaN
Infinity
Infinity
Infinity
Infinity
Infinity
Infinity
Infinity
Infinity
3.738367993405087E26
3.145758618761281E26
3.145728063043205E26
1.7614289442266205E21
2.099303006994994E15
2.1016545871856912E12
2.1341104795381653E10
2.430443262374036E9
2.195302605344229E9
1.5327009848193336E9
1.4592348866245925E9
1.455640339174735E9
(...)

Discussion

  • Oswaldo Dantas
    Oswaldo Dantas
    2006-11-08

    modified DefaultGPFitnessEvaluator

     
  • Klaus
    Klaus
    2006-11-09

    Logged In: YES
    user_id=722855

    Great bug report!
    I could immediately follow the problem and added some tests for the class.
    The only thing I changed was that a NaN is non fitter than a not-NaN. IMO this is correct because a NaN cannot be
    evaluated and cannot be better than a valid number. Do you agree with that?
    I checked in the new test class and the changes to CVS.

     
  • Klaus
    Klaus
    2006-11-09

    • labels: --> logic error (semantics)
    • milestone: --> JGAP 3.1
    • assigned_to: nobody --> klausikm
    • status: open --> open-fixed
     
  • Oswaldo Dantas
    Oswaldo Dantas
    2006-11-11

    Logged In: YES
    user_id=1358314

    I am not sure about where the NaNs should be placed inside
    the ordered array.
    In the MathProblem example, if I got it right, lower fitness
    values means lower error, thus a better, mode fitted individual.
    Calling Arrays.sort(a) when double a[] = {5d, 1d,
    Double.NaN, 2d, Double.INFINITY, 8d} would print [1, 2, 5,
    8, infinity, NaN], ordering from lowest to greatest value
    and putting NaNs at the end.
    The evaluations on the original DefaultGPFitnessEvaluator
    used by the comparator, result in a inverse ordering, so, I
    was expecting to see the NaNs first, then the rest of the
    values from the greatest to the lowest. Then the last
    position of the array would have the most fitted individual

     
  • Klaus
    Klaus
    2006-11-12

    • priority: 5 --> 7
     
  • Klaus
    Klaus
    2006-11-12

    Logged In: YES
    user_id=722855

    You are right that with the MathProblem lower fitness values are better. The problem I now fixed was that the wrong
    fitness evaluator was used. I created a DeltaGPFitnessEvaluator and configured it for usage with the MathProblem.
    Now the output first shows lower values, then higher ones, and at the end of the list "Infinity" entries and then
    NaN's, which is as I expect it.
    So there were multiple errors contributing to the problem (one I didn't mention yet was the wrong usage of setters
    for fitness evaluators in GPConfiguration).

     
  • Klaus
    Klaus
    2006-11-21

    Logged In: YES
    user_id=722855
    Originator: NO

    I herewith close this bug. If there is something to add please tell me and I may open the bug again if necessary.

     
  • Klaus
    Klaus
    2006-11-21

    • status: open-fixed --> closed-fixed