-
Notifications
You must be signed in to change notification settings - Fork 77
If you can’t find an answer to your problem here, try posting on the Watchmaker Framework discussion group.
Why does the fittest candidate sometimes get worse in subsequent generations even though I am using elitism?
Are you using a custom EvolutionaryOperator? Check that your implementation obeys the rule about not modifying the selected candidates passed to the operator:
An implementation of this class must not modify any of the selected candidate objects passed in. Doing so will affect the correct operation of the EvolutionEngine. Instead the operator should create and return new candidate objects. The operator is not required to create copies of unmodified individuals (for efficiency these may be returned directly).
The justification for this rule is as follows:
The candidates that are preserved via elitism are still eligible for selection as parents for the next generation. This means that a good candidate may survive unchanged and may also spawn one or more offspring (via mutation/cross-over). If this weren’t the case then none of the offspring would be descended from the best candidates, which would be sub-optimal.
Because an individual may be passed to the evolutionary operator more than once (depending on the selection strategy for parents), and because any individual passed to an operator may also be preserved via elitism, the operator is not permitted to modify the objects passed in. If it decides to mutate an individual, it must return a new candidate object incorporating the mutation and leave the original untouched.
Even if your operator obeys the above rule, it is possible for the same unmodified individual to have a different fitness score in a subsequent generation – unless the fitness function is both isolated and repeatable. If the function is non-deterministic or depends on the other members of the population then the output will vary even if the individual remains the same.
This functionality is currently not explicitly supported by the framework but it is possible.
Probably the best approach is to sub-class the specific EvolutionEngine that you are using and over-ride the nextEvolutionStep method. This protected method, declared in AbstractEvolutionEngine, is invoked for each iteration of the algorithm. If you over-ride it you can do whatever you need to do before or after you delegate to the super class version of the method.