After going back and re-reading some of the documentation, I've got a much firmer grasp on ECJ parameter files now. My file is included below, in the unlikely event that anyone is interested. Some issues/bugs/questions: I was a bit disappointed to read that coevolution is not multithreaded, but I can see how this would be challenging. Perhaps I'll be able to help with that at a later date. Despite the claims in the documentation for ec.Subpopulation, ec.subpop does not appear to work as a default base. ec.Evaluator doesn't appear to have a default base, which makes for some redundancy in the parameter file. This file works on a stub problem I built; now I can get on to the real problem and start harnessing the mighty power of ECJ. Thanks for all the help, Peter Drake http://www.lclark.edu/~drake/ # Parent parameters file parent.0 = ../../ec/gp/koza/koza.params # ec.Evolve # ============================== # Simple generational evolution state = ec.simple.SimpleEvolutionState # ec.EvolutionState # (more precisely, its subclass ec.simple.SimpleEvolutionState) # ============================== # Standard GP initializer init = ec.gp.GPInitializer # Standard (empty) finalization method finish = ec.simple.SimpleFinisher # Standard (empty) exchange method exch = ec.simple.SimpleExchanger # Standard breeding -- no cross-population breeding breed = ec.simple.SimpleBreeder # Multipopulation coevolution eval = ec.coevolve.MultiPopCoevolutionaryEvaluator # Koza statistics stat = ec.gp.koza.KozaStatistics # Run for this many generations generations = 21 # Quit on finding an ideal individual? quit-on-run-complete = false # ec.Initializer # (more precisely, ec.gp.GPInitializer) # ============================== # Standard population pop = ec.Population # ec.Population # ============================== # Two subpopulations, for black and white strategies pop.subpops = 2 pop.subpop.0 = ec.Subpopulation pop.subpop.1 = ec.Subpopulation # ec.Subpopulation # ============================== # There is some redundancy because these must be specified for each subpopulation # I believe I SHOULD be able to say ec.subpop.* instead of pop.subpop. 0.*, but it doesn't work pop.subpop.0.size = 500 # Don't bother avoiding duplicates in initial population pop.subpop.0.duplicate-retries = 0 pop.subpop.0.species = ec.gp.GPSpecies # Now, the same information for the other subpopulation pop.subpop.1.size = 500 pop.subpop.1.duplicate-retries = 0 pop.subpop.1.species = ec.gp.GPSpecies # ec.simple.SimpleBreeder # ============================== # Elitism? # breed.elite.0 = 10 # breed.elite.1 = 10 # ec.SimpleStatistics # (more precisely, ec.gp.koza.KozaStatistics) # ============================== # output statistics to the file "out.stat" in the directory # the run was started in stat.file = $out.stat # ec.Evaluator # (more precisely, ec.coevolve.MultiPopCoevolutionaryEvaluator) # ============================== eval.problem = orego.gp.MostC3s # There is some redundancy because these must be specified for each subpopulation # Number of opponents for judging each individual, chosen from the other population randomly # (num-rand-ind), from the best (num-elites), or by selection (num-ind) eval.subpop.0.num-rand-ind = 6 eval.subpop.0.num-elites = 1 eval.subpop.0.num-ind = 0 # How to choose individuals from each population for evaluation # (A tournament of size 1 is equivalent to random selection) #eval.subpop.0.select = ec.select.TournamentSelection #eval.subpop.0.select.size = 1 # The same information for the other subpopulation eval.subpop.1.num-rand-ind = 6 eval.subpop.1.num-elites = 1 eval.subpop.1.num-ind = 0 eval.subpop.1.select = ec.select.TournamentSelection eval.subpop.1.select.size = 1 # ec.gp.GPSpecies # ============================== gp.species.fitness = ec.gp.koza.KozaFitness gp.species.ind = ec.gp.GPIndividual gp.species.pipe = ec.breed.MultiBreedingPipeline # ec.gp.GPIndividual # ============================== gp.individual.numtrees = 1 gp.individual.tree.0 = ec.gp.GPTree # ec.gp.GPTree # ============================== # The tree constraints are set to tc0, which is defined in koza.params gp.tree.tc = tc0 # ec.gp.GPTreeConstraints # ============================== # Return type gp.tc.0.returns = sequence # ec.gp.GPProblem # (more precisely, our specific problem) # ============================== eval.problem.data = orego.gp.DoubleData eval.problem.stack.context.data = orego.gp.DoubleData # ec.breed.MultiBreedingPipeline # ============================== # Either reproduce an existing individual or create a new one breed.multibreed.generate-max = false breed.multibreed.num-sources = 2 breed.multibreed.source.0 = ec.gp.koza.CrossoverPipeline breed.multibreed.source.1 = ec.breed.ReproductionPipeline breed.reproduce.prob = 0.1 gp.koza.xover.prob = 0.9 # The rest of this file has to do with the specific tree components for this problem # ============================== # Types gp.type.a.size = 2 gp.type.a.0.name = sequence gp.type.a.1.name = move gp.nc.size = 4 gp.nc.0 = ec.gp.GPNodeConstraints gp.nc.0.name = ncMove gp.nc.0.returns = move gp.nc.0.size = 0 gp.nc.1 = ec.gp.GPNodeConstraints gp.nc.1.name = ncIf gp.nc.1.returns = sequence gp.nc.1.size = 3 gp.nc.1.child.0 = move gp.nc.1.child.1 = sequence gp.nc.1.child.2 = sequence gp.nc.2 = ec.gp.GPNodeConstraints gp.nc.2.name = ncPlay gp.nc.2.returns = sequence gp.nc.2.size = 2 gp.nc.2.child.0 = move gp.nc.2.child.1 = sequence gp.nc.3 = ec.gp.GPNodeConstraints gp.nc.3.name = ncRandom gp.nc.3.returns = sequence gp.nc.3.size = 0 # We have four functions in the function set. They are: gp.fs.0.size = 4 gp.fs.0.func.0 = orego.gp.MoveNode gp.fs.0.func.0.nc = ncMove gp.fs.0.func.1 = orego.gp.IfNode gp.fs.0.func.1.nc = ncIf gp.fs.0.func.2 = orego.gp.PlayNode gp.fs.0.func.2.nc = ncPlay gp.fs.0.func.3 = orego.gp.RandomNode gp.fs.0.func.3.nc = ncRandom