Okay, on further thought about this, I've decided not to override the
MasterProblem code. Here's why: there actually isn't any guarantee at
all that finishEvaluating will be called on a generation boundary.
That's just a happy coincidence in the current generational evaluator.
But it wasn't meant to be used that way and may change with other
evaluators (like the Slave). So in fact finishEvaluating (and
subsequent prepareToEvaluate calls) might be called multiple times
before a generation is over. You don't want to rely on finishEvaluating
thus to do fitness cleanup.
So where to do it? The answer is one of:
1. Overriding SimpleEvaluator.evaluatePopulation to call
super.evaluatePopulation() and then do your fitness updating. That's
probably the best "canonical" location.
2. Add a new Statistics object to the statistics chain. In that object,
override postEvaluationStatistics(). This is called right after
evaluatePopulation, so it'll work fine. If your object is the first
object in the chain, you can do your stuff, and THEN call
super.postEvaluationStatistics() to let the other statistics objects
have a whack at it.
Robert Baruch wrote:
> Hi Sean,
> Thanks for the advice and the explanation. In looking through the code,
> my first idea had been to extend MasterProblem and use that as
> eval.masterproblem, but my teeth did some grinding when I found out that
> the master code requires eval.masterproblem to be exactly equal to
> MasterProblem. I could not augment the standard evil overlord with more
> evil overlordness of my own. (Shouldn't MasterProblem be a final class,
> So my next idea had been to hack MasterProblem as you suggested, but I
> really hated doing that, because then when the next ECJ version came out
> (and they've been coming out relatively fast and furious), I'd have to
> remember the changes I made. I could always stick with the current ECJ
> version, but I'm one of those upgrade addicts.
> Finally, I settled on creating a custom Exchanger, that being the next
> stage after evaluation, and fix up the fitnesses in the prebreeding
> exchange phase. Not ideal, but it's the very next phase after
> evaluation, and at least it would work for future ECJ versions.
> IMHO, the best thing would be to fix up MasterProblem, but I also didn't
> look at it closely enough to determine whether that would work under
> both synchronous and asynchronous evaluation. I defer to your far
> greater knowledge of the code :)
> Thanks, and I look forward to hearing your verdict!