An Individual is an item in the EC population stew which is evaluated and assigned a fitness which determines its likelihood of selection. Individuals are created most commonly by the newIndividual(...) method of the ec.Species class.
In general Individuals are immutable. That is, once they are created their genetic material should not be modified. This protocol helps insure that they are safe to read under multithreaded conditions. You can violate this protocol, but try to do so when you know you have only have a single thread.
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. To do this, these methods will encode numbers using the ec.util.Code class. These methods are mostly used to write out populations to files for inspection, slight modification, then reading back in later on. readIndividualreads in the fitness and the evaluation flag, then calls parseGenotype to read in the remaining individual. You are responsible for implementing parseGenotype: the Code class is there to help you. printIndividual writes out the fitness and evaluation flag, then calls genotypeToString and printlns the resultant string. You are responsible for implementing the genotypeToString method in such a way that parseGenotype can read back in the individual println'd with genotypeToString. The default form of genotypeToString simply calls toString, which you may override instead if you like. The default form of parseGenotype throws an error. You are not required to implement these methods, but without them you will not be able to write individuals to files in a simultaneously computer- and human-readable fashion.
- printIndividualForHumans(...,PrintWriter) This approach prints an individual in a fashion intended for human consumption only. printIndividualForHumans writes out the fitness and evaluation flag, then calls genotypeToStringForHumans and printlns the resultant string. You are responsible for implementing the genotypeToStringForHumans method. The default form of genotypeToStringForHumans simply calls toString, which you may override instead if you like (though note that genotypeToString's default also calls toString). You should handle one of these methods properly to ensure individuals can be printed by ECJ.
Since individuals should be largely immutable, why is there a readIndividual method? after all this method doesn't create a new individual -- it just erases the existing one. This is largely historical; but the method is used underneath by the various newIndividual methods in Species, which do create new individuals read from files. If you're trying to create a brand new individual read from a file, look in Species.
Individuals are Comparable: if you sort Individuals, the FITTER individuals will appear EARLIER in a list or array.
@author Sean Luke
@version 1.0