Ok, I am now attempting to read in an individual using a text stream but I
seem to be having a tough issue. I think the problem is that I have a node
type, "predicate", which is a non-terminal ERC node. This predicate node can
have many different constraints. It always has 3 children but the 3 children
can be of three different types, say person, place, or thing, or the
emptyVariable (all terminals, and all ERC's except the empty variable). The
way I did this was create a whole lot of lines in the parameter file that
look like these:
//this is the first one in the file btw.
gp.nc.10 = ec.gp.GPNodeConstraints
gp.nc.10.name = P-predicateConstraints
gp.nc.10.returns = disjunction
gp.nc.10.size = 3
gp.nc.10.child.0 = person
gp.nc.10.child.1 = emptyVariable
gp.nc.10.child.2 = emptyVariable
gp.fs.0.func.10 = edu.jhuapl.PredicateERCNode
gp.fs.0.func.10.nc = P-predicateConstraints
gp.nc.14 = ec.gp.GPNodeConstraints
gp.nc.14.name = PL-predicateConstraints
gp.nc.14.returns = disjunction
gp.nc.14.size = 3
gp.nc.14.child.0 = person
gp.nc.14.child.1 = location
gp.nc.14.child.2 = emptyVariable
gp.fs.0.func.14 = edu.jhuapl.PredicateERCNode
gp.fs.0.func.14.nc = PL-predicateConstraints
Before you ask, the predicate and children are ERC's because the predicate
itself can vary, for example we might have "cute(person1, empty, empty)" or
"tall(person2, empty, empty)" as two concrete predicates that are
implemented by func.10 above.
When the readRootedTree method in GPNode gets executed on a predicate node,
I don't think it can determine which one of the constraints it is really
supposed to be using so it just picks the first one and always expects the
first child to be a "person" terminal. When it sees something else, it gives
me the "I came across a symbol which I could not match up with a type-valid
I believe the way to fix this may be to somehow modify the way my predicate
ERC reads itself in, but I could use some hints on how to do that. Is this
making any sense, or am I just way off base?
ECJ can load whole populations or create them from scratch, neither of which
you want in this case. This is most easily done with a new
subclass of Subpopulation, overriding Subpopulation.populate(...).
Probably the easiest approach would be:
- call super.populate(...) to fill the population with random individuals
- overwrite individuals with your custom individual, perhaps loaded from
a file (see the two Individual.readIndividual(...) methods), or by
constructing your individual programmatically and sticking it in.
ECJ's got several ways of reading and writing individuals, using
DataInput/DataOutput, or text streams.