I haven't seen this before, it appears to be a very intermittent bug:
Exception in thread "main" java.lang.IllegalArgumentException: n must be positive
at org.epochx.tools.random.MersenneTwisterFast.nextInt(Unknown Source)
at org.epochx.gp.op.init.GrowInitialiser.getNodeTree(Unknown Source)
at org.epochx.gp.op.init.GrowInitialiser.getGrownNodeTree(Unknown Source)
at org.epochx.gp.op.mutation.SubtreeMutation.mutate(Unknown Source)
at org.epochx.gp.op.mutation.SubtreeMutation.mutate(Unknown Source)
at org.epochx.core.MutationManager.mutate(Unknown Source)
at org.epochx.core.GenerationManager.generation(Unknown Source)
at org.epochx.core.RunManager.run(Unknown Source)
at org.epochx.core.Model.run(Unknown Source)
at org.epochx.gp.model.GPModel.run(Unknown Source)
I suspect you're right about the source of the problem though. Calling
nextInt with an argument of zero will throw an exception because that
is an exclusive upper bound. So there are no valid return values. If
this is a count of the number of valid nodes, this implies that there
is a situation occurring where a valid tree cannot be constructed from
the available syntax in the given depth. This is happening as part of
a subtree mutation, so you need to ensure that all types of node you
are using can have a complete subtree constructed within the depth
given to the constructor's maxSubtreeDepth parameter (this is 4 by
default). Otherwise, whenever a mutation occurs at a node that cannot
be replaced with a subtree of that depth, it will fail.
model.setMaxDepth(-1);
Exception in thread "main" java.lang.IllegalArgumentException: n must be positive
at org.epochx.tools.random.MersenneTwisterFast.nextInt(Unknown Source)
at org.epochx.gp.op.init.GrowInitialiser.getNodeTree(Unknown Source)
at org.epochx.gp.op.init.GrowInitialiser.getGrownNodeTree(Unknown Source)
at org.epochx.gp.op.mutation.SubtreeMutation.mutate(Unknown Source)
at org.epochx.gp.op.mutation.SubtreeMutation.mutate(Unknown Source)
at org.epochx.core.MutationManager.mutate(Unknown Source)
at org.epochx.core.GenerationManager.generation(Unknown Source)
at org.epochx.core.RunManager.run(Unknown Source)
at org.epochx.core.Model.run(Unknown Source)
at org.epochx.gp.model.GPModel.run(Unknown Source)
Are you making any configuration changes between the two runs that you are transferring individuals between?
Perhaps you should debug this a bit further. If you create your own mutation operator that is just a copy/paste of the source for the SubtreeMutation, then you can use that as mutation operator to look into what is going on during a mutation. The first thing to check is probably what the data-type of the Node the 'originalSubtree' variable holds is before everything blows up. Because this is the data-type that the grow initialiser is trying to build a subtree for. Is this always the same data-type when the exception is thrown?
If this doesn't give you any clues then you might want to do the same thing for the GrowInitialiser operator too.