Print

Print


>I don't know the details of your issue exactly, but from what you've 
described, I'm pretty certain it has nothing to do with ECJ's implementation.
>

Here's a copy of a message from March 30 with the details...
------------------------------
Hmmm...
Further to the type question, I got my answer but am having a few other 
issues. The trees seem to build ok with the types in place but I get warnings 
and crashes on larger populations. What can I do to fix these? I'd rather do the 
typing upfront, and with small populations it works great.

Should I just define the tS, cS, and oS types for the root as well? Is this part a 
major issue? In a previous try I over-rode all instances of nil for 
NodeConstraints.

WARNING:
In function set f0 for the GPTreeConstraints tc0, no *nonterminals* are given 
with the return type tS which is required by other functions in the function set 
or by the tree's return type.  This may or may not be a problem for you.
PARAMETER: gp.tc.0
WARNING:
In function set f0 for the GPTreeConstraints tc0, no *nonterminals* are given 
with the return type oS which is required by other functions in the function set 
or by the tree's return type.  This may or may not be a problem for you.
PARAMETER: gp.tc.0
WARNING:
In function set f0 for the GPTreeConstraints tc0, no *nonterminals* are given 
with the return type cS which is required by other functions in the function set 
or by the tree's return type.  This may or may not be a problem for you.
PARAMETER: gp.tc.0
WARNING:
In function set f0 for the GPTreeConstraints tc0, no terminals are given with 
the return type root which is required by other functions in the function set or 
by the tree's return type.  Nearly all tree-builders in ECJ require the ability to 
add a terminal of any type for which there is a nonterminal, and at any time.  
Without terminals, your code may not work.  One common indication that a 
tree-builder has failed due to this problem is if you get the MersenneTwister 
error 'n must be positive'.
PARAMETER: gp.tc.0
WARNING:
In function set f0 for the GPTreeConstraints tc0, no terminals are given with 
the return type nil which is required by other functions in the function set or by 
the tree's return type.  Nearly all tree-builders in ECJ require the ability to add 
a terminal of any type for which there is a nonterminal, and at any time.  
Without terminals, your code may not work.  One common indication that a 
tree-builder has failed due to this problem is if you get the MersenneTwister 
error 'n must be positive'.
PARAMETER: gp.tc.0

and...

Initializing Generation 0
ONCE-ONLY WARNING:
A GPNodeBuilder has been requested at least once to generate a one-node tree 
with a return value type-compatable with a certain type; but there is no 
TERMINAL which is type-compatable in this way.  As a result, the algorithm 
was forced to use a NON-TERMINAL, making the tree larger than requested, 
and exposing more child slots to fill, which if not carefully considered, could 
recursively repeat this problem and eventually fill all memory.
ONCE-ONLY WARNING:
class ec.gp.koza.HalfBuilder can't find a terminal type-compatable with nil
ONCE-ONLY WARNING:
A GPNodeBuilder has been requested at least once to generate a tree with a 
return value type-compatable with a certain type; but there is no NON-
TERMINAL which is type-compatable in this way.  As a result, the algorithm 
was forced to use a TERMINAL, making the tree smaller than requested.
ONCE-ONLY WARNING:
class ec.gp.koza.HalfBuilder can't find a non-terminal type-compatable with tS
ONCE-ONLY WARNING:
class ec.gp.koza.HalfBuilder can't find a non-terminal type-compatable with cS
ONCE-ONLY WARNING:
class ec.gp.koza.HalfBuilder can't find a non-terminal type-compatable with oS

And, indeed I crapped out memory with a 3000 population...

Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit 
exceeded at java.util.Arrays.copyOf(Arrays.java:2367)...

I noticed this warning in the noerc2.params file...

# The gotcha: many GP node builders require that for every
# reachable type used by nodes in the function set there
# must exist at least one terminal (and ideally one nonterminal)
# in the function set which returns that type.  This is
# because many GP node builder algorithms insist on being
# able to emit a terminal whenever they so desire, regardless
# of what the current type situation is where the terminal
# has to be hung.  The notable exception to this is Uniform.

# Ordinarily this would be a problem for us as we use
# Ramped Half-and-Half as our builder, and it has this 
# requirement.  However since we are telling Ramped Half-and-Half
# to generate only trees of sizes 2 and up (NOT 1 and up), 
# it will never attempt to select a terminal for the root
# and this gotcha will not occur.  The issue would also come
# up if we use tree mutation as an operator rather than solely
# crossover.  But we're not doing that.

Here's my relevant setup...
# use one function set
gp.fs.size = 1
gp.fs.0 = ec.gp.GPFunctionSet

# call it "f0".
gp.fs.0.name = f0

# 2 functions and 3 ERC terminals in the simple function set
gp.fs.0.size = 5
gp.fs.0.func.0 = ec.csc495.gp.test.timeslot.Join
gp.fs.0.func.0.nc = nc2
gp.fs.0.func.1 = ec.csc495.gp.test.timeslot.JoinERC
gp.fs.0.func.1.nc = nc3
gp.fs.0.func.2 = ec.csc495.gp.test.timeslot.TsERC
gp.fs.0.func.2.nc = nc0
gp.fs.0.func.3 = ec.csc495.gp.test.timeslot.CsERC
gp.fs.0.func.3.nc = nc0
gp.fs.0.func.4 = ec.csc495.gp.test.timeslot.OsERC
gp.fs.0.func.4.nc = nc0

# set up types
gp.type.a.size = 5
gp.type.a.0.name = nil
gp.type.a.1.name = root
gp.type.a.2.name = cS
gp.type.a.3.name = oS
gp.type.a.4.name = tS
gp.type.s.size = 1
gp.type.s.0.name = nil-and-root
gp.type.s.0.size = 2
gp.type.s.0.member.0 = nil
gp.type.s.0.member.1 = root

# make new constraints forms
gp.nc.size = 12
gp.nc.7 = ec.gp.GPNodeConstraints
gp.nc.7.name = nc-returning-nil-and-root
gp.nc.7.returns = nil-and-root
gp.nc.7.size = 2
gp.nc.7.child.0 = nil
gp.nc.7.child.1 = nil

gp.nc.8 = ec.gp.GPNodeConstraints
gp.nc.8.name = nc-accepting-erc
gp.nc.8.returns = nil
gp.nc.8.size = 3
gp.nc.8.child.0 = tS
gp.nc.8.child.1 = cS
gp.nc.8.child.2 = oS

gp.nc.9 = ec.gp.GPNodeConstraints
gp.nc.9.name = nc-returns-tS
gp.nc.9.returns = tS
gp.nc.9.size = 0

gp.nc.10 = ec.gp.GPNodeConstraints
gp.nc.10.name = nc-returns-cS
gp.nc.10.returns = cS
gp.nc.10.size = 0

gp.nc.11 = ec.gp.GPNodeConstraints
gp.nc.11.name = nc-returns-oS
gp.nc.11.returns = oS
gp.nc.11.size = 0

# keep it this way so that this code may be easily commented out
# redefine Join, JoinERC, TsERC, CsERC, OsERC
gp.fs.0.func.0.nc = nc-returning-nil-and-root
gp.fs.0.func.1.nc = nc-accepting-erc
gp.fs.0.func.2.nc = nc-returning-tS
gp.fs.0.func.3.nc = nc-returning-cS
gp.fs.0.func.4.nc = nc-returning-oS

# define the tree so that it only accepts items that are compatible with 
# root -- Join is the only such item
gp.tc.0.returns = root

-- ray

------------------------------

There's a slight issue with the node-constraints in this listing since I copied it 
from a file in progress. It's fixed now, of course.

>The only thing left is tree generation.  Here strong typing can have a strong 
effect on the nature of the trees; but it's not an ECJ implementation thing, it's 
just a GP tree generation thing.  If you select types which are too constrained, 
ECJ will have a hard time finding trees which meet the constraints.  The GROW, 
FULL, and RAMPED HALF-AND-HALF algorithms are simple depth-first algorithms 
which grow and grow until a certain depth is reached.  These algorithms have 
no size constraints, only depth constraints, and if your typing is set up just so, 
it coult make big trees.  An alternative which I strongly suggest is to use PTC2 
and specify the tree sizes you want.  Note that to make sure that typing 
doesn't fail on you, you must have a leaf node for every kind of return type.
>
>Sean

The typing seeming to work fine except memory got out of control on 
populations much larger than 300. Interestingly, increasing tree depth at a 
given population threshold didn't affect the stability much.

Hmm... so go with PTC2? I would prefer going with larger populations than 
increasing tree depth.

What about?
# However since we are telling Ramped Half-and-Half
# to generate only trees of sizes 2 and up (NOT 1 and up), 
# it will never attempt to select a terminal for the root
# and this gotcha will not occur.

-- ray