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 ...etc. 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 node..." error. 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? Thanks, Chris Sean wrote: 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.