/*
Copyright 2006 by Sean Luke
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package ec.gp;
import ec.*;
import ec.util.*;
import java.io.*;
/*
* GPIndividual.java
*
* Created: Fri Aug 27 17:07:45 1999
* By: Sean Luke
*/
/**
* GPIndividual is an Individual used for GP evolution runs.
* GPIndividuals contain, at the very least, a nonempty array of GPTrees.
* You can use GPIndividual directly, or subclass it to extend it as
* you see fit.
*
GPIndividuals have two clone methods: clone() and lightClone(). clone() is
* a deep clone method as usual. lightClone() is a light clone which does not copy
* the trees.
*
*
In addition to serialization for checkpointing, Individuals may read and write themselves to streams in three ways.
*
*
* - writeIndividual(...,DataOutput)/readIndividual(...,DataInput) This method
* transmits or receives an individual in binary. It is the most efficient approach to sending
* individuals over networks, etc. These methods write the evaluated flag and the fitness, then
* call readGenotype/writeGenotype, which you must implement to write those parts of your
* Individual special to your functions-- the default versions of readGenotype/writeGenotype throw errors.
* You don't need to implement them if you don't plan on using read/writeIndividual.
*
*
- printIndividual(...,PrintWriter)/readIndividual(...,LineNumberReader) This
* approach transmits or receives an indivdual in text encoded such that the individual is largely readable
* by humans but can be read back in 100% by ECJ as well. Because GPIndividuals are often very large,
* GPIndividual has overridden these methods -- they work differently than in Individual (the superclass). In specific:
* readIndividual by default reads in the fitness and the evaluation flag, then calls parseGenotype
* to read in the trees (via GPTree.readTree(...)).
* However printIndividual by default prints the fitness and evaluation flag, and prints all the trees
* by calling GPTree.printTree(...). It does not call genotypeToString at all. This
* is because it's very wasteful to build up a large string holding the printed form of the GPIndividual
* just to pump it out a stream once.
*
*
- printIndividualForHumans(...,PrintWriter) This
* approach prints an individual in a fashion intended for human consumption only. Because GPIndividuals are often very large,
* GPIndividual has overridden this methods -- it works differently than in Individual (the superclass). In specific:
* printIndividual by default prints the fitness and evaluation flag, and prints all the trees
* by calling GPTree.printTreeForHumans(...). It does not call genotypeToStringForHumans at all. This
* is because it's very wasteful to build up a large string holding the printed form of the GPIndividual
* just to pump it out a stream once.
*
*
In general, the various readers and writers do three things: they tell the Fitness to read/write itself,
* they read/write the evaluated flag, and they read/write the GPTree array (by having each GPTree read/write
* itself). If you add instance variables to GPIndividual, you'll need to read/write those variables as well.
Parameters
base.numtrees
int >= 1 |
(number of trees in the GPIndividual) |
base.tree.n
classname, inherits or = ec.gp.GPTree |
(class of tree n in the individual) |
Default Base
gp.individual
Parameter bases
base.tree.n |
tree n in the individual |
*
* @author Sean Luke
* @version 1.0
*/
public class GPIndividual extends Individual
{
public static final String P_NUMTREES = "numtrees";
public static final String P_TREE = "tree";
public GPTree[] trees;
public Parameter defaultBase()
{
return GPDefaults.base().push(P_INDIVIDUAL);
}
public boolean equals(Object ind)
{
if (!(this.getClass().equals(ind.getClass()))) return false; // GPIndividuals are special.
GPIndividual i = (GPIndividual)ind;
if (trees.length != i.trees.length) return false;
// this default version works fine for most GPIndividuals.
for(int x=0;x>> 31 ) ^
trees[x].treeHashCode();
return hash;
}
/** Sets up a prototypical GPIndividual with those features which it
shares with other GPIndividuals in its species, and nothing more. */
public void setup(final EvolutionState state, final Parameter base)
{
super.setup(state,base); // actually unnecessary (Individual.setup() is empty)
Parameter def = defaultBase();
// set my evaluation to false
evaluated = false;
// how many trees?
int t = state.parameters.getInt(base.push(P_NUMTREES),def.push(P_NUMTREES),1); // at least 1 tree for GP!
if (t <= 0)
state.output.fatal("A GPIndividual must have at least one tree.",
base.push(P_NUMTREES),def.push(P_NUMTREES));
// load the trees
trees = new GPTree[t];
for (int x=0;x