Strange exception related to random-number-generation

46 views
Skip to first unread message

Ian Clarke

unread,
Jun 13, 2011, 6:34:47 AM6/13/11
to epo...@googlegroups.com

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)

Ian Clarke

unread,
Jun 13, 2011, 7:06:32 AM6/13/11
to epo...@googlegroups.com
Hmm, perhaps not so rare - it just happened again, also on the 4th generation.  Now I'm a bit worried as its preventing me from proceeding, and the exception doesn't give much of a clue as to how I might be able to workaround the problem :-/

Ian.
--
Ian Clarke

Ian Clarke

unread,
Jun 13, 2011, 7:09:23 AM6/13/11
to epo...@googlegroups.com
My guess is that its happening on line 271 of GrowInitialiser.java:

final int randomIndex = rng.nextInt(validNodes.size());

Could validNodes.size() be 0?  Would this / should this cause this problem?

Ian.

Tom Castle

unread,
Jun 13, 2011, 7:47:20 AM6/13/11
to EpochX
The exception is not very intuitive. Clearly this could be improved!

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.

Ideally, SubtreeMutation would have an option to use a maxSubtreeDepth
that was equal to the remaining depth at the node being replaced. But,
this hasn't been implemented as yet.

Tom

On Jun 13, 12:09 pm, Ian Clarke <ian.cla...@gmail.com> wrote:
> My guess is that its happening on line 271 of GrowInitialiser.java:
>
> final int randomIndex = rng.nextInt(validNodes.size());
>
> Could validNodes.size() be 0?  Would this / should this cause this problem?
>
> Ian.
>
>
>
>
>
>
>
>
>
> On Mon, Jun 13, 2011 at 6:06 AM, Ian Clarke <ian.cla...@gmail.com> wrote:
> > Hmm, perhaps not so rare - it just happened again, also on the 4th
> > generation.  Now I'm a bit worried as its preventing me from proceeding, and
> > the exception doesn't give much of a clue as to how I might be able to
> > workaround the problem :-/
>
> > Ian.
>

Ian Clarke

unread,
Jun 13, 2011, 8:10:30 AM6/13/11
to epo...@googlegroups.com
On Mon, Jun 13, 2011 at 6:47 AM, Tom Castle <tc...@kent.ac.uk> wrote:
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.

Hmm, I'm a little confused.  All of the node types I've added (so far as I know) can have Literals or Variables as their immediate children.  Given this, how could this problem occur?

Weirdly, this is the first time I've seen this problem, but now it occurs repeatedly.  Note that I am injecting previous winners into the first generation, so perhaps one of those is "poisoning" the well somehow?

I deleted the last winner so that it is no-longer injected into the first generation, and I haven't yet seen the problem reoccur.

Nonetheless, it would be good to have a more robust workaround...

Ian.

Ian Clarke

unread,
Jun 13, 2011, 6:59:43 PM6/13/11
to epo...@googlegroups.com
Oh dear, this problem isn't going away, I'm afraid.

Can you give me any more detailed recommendations about how to avoid this issue?  I'm not really sure what might be wrong with my Node implementations given that all of them can have Literals of one form or another as children.

Ian.

Ian Clarke

unread,
Jun 13, 2011, 8:51:57 PM6/13/11
to epo...@googlegroups.com
Ok, this is weird, I tried:

model.setMaxDepth(-1);


Yet I'm *still* getting the same error:

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)


Help! :-/

Ian.

Tom Castle

unread,
Jun 13, 2011, 9:47:33 PM6/13/11
to epo...@googlegroups.com
I'm not too sure what is going on here either. Setting the max depth to -1 is unlikely to help though because I don't think that is interpreted as no limit.

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.

Tom

Ian Clarke

unread,
Jun 13, 2011, 10:06:59 PM6/13/11
to epo...@googlegroups.com
On Mon, Jun 13, 2011 at 8:47 PM, Tom Castle <tc...@kent.ac.uk> wrote:
Are you making any configuration changes between the two runs that you are transferring individuals between?

Nope.
 
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?

Is there any chance you could produce a version of the .jar with debugging enabled?  This way I could trap the exception and walk backwards.

My own attempts to compile the .jar have been unfruitful :-/
 
If this doesn't give you any clues then you might want to do the same thing for the GrowInitialiser operator too.

Hmm, I'm worried that debugging this could be rather difficult for me given my unfamiliarity with EpochX's internals.  I have a hard enough time debugging my own code :-)

While my code is proprietary, I would be willing to give you a .jar file that triggers the error.  The problem is that its very intermittent, each of my generations takes a few minutes (each has a population of 1000), yet it seems to occur consistently after the third generation (ie. generation #2).

Another possibility would be if you could patch the code to catch this error so that it isn't fatal...

Tom Castle

unread,
Jun 13, 2011, 10:19:11 PM6/13/11
to EpochX
Since this is now just a case of debugging code, and I don't think it
will be of much value to others, I'm going to move this off of the
discussion group and I'll e-mail you directly.

Tom

On Jun 14, 3:06 am, Ian Clarke <ian.cla...@gmail.com> wrote:
Reply all
Reply to author
Forward
0 new messages