/*
Copyright 2006 by Sean Luke
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package ec;
import ec.util.*;
import java.io.*;
/*
* Species.java
*
* Created: Tue Aug 10 20:31:50 1999
* By: Sean Luke
*/
/**
* Species is a prototype which defines the features for a set of individuals
* in the population. Typically, individuals may breed if they belong to the
* same species (but it's not a hard-and-fast rule). Each Subpopulation has
* one Species object which defines the species for individuals in that
* Subpopulation.
*
*
Species are generally responsible for creating individuals, through
* their newIndividual(...) method. This method usually clones its prototypical
* individual and makes some additional modifications to the clone, then returns it.
* Note that the prototypical individual does not need to be a complete individual --
* for example, GPSpecies holds a GPIndividual which doesn't have any trees (the tree
* roots are null).
*
*
Species also holds a prototypical breeding pipeline meant to breed
* this individual. To breed individuals of this species, clone the pipeline
* and use the clone.
Parameters
base.ind
classname, inherits and != ec.Individual |
(the class for the prototypical individual for the species) |
base.fitness
classname, inherits and != ec.Fitness |
(the class for the prototypical fitness for the species) |
base.numpipes
int >= 1 |
(total number of breeding pipelines for the species) |
base.pipe
classname, inherits and != ec.BreedingPipeline |
(the class for the prototypical Breeding Pipeline) |
Parameter bases
base.ind |
i_prototype (the prototypical individual) |
base.pipe |
pipe_prototype (breeding pipeline prototype) |
base.fitness |
f_prototype (the prototypical fitness) |
* @author Sean Luke
* @version 1.0
*/
public abstract class Species implements Prototype
{
public static final String P_INDIVIDUAL = "ind";
public static final String P_PIPE = "pipe";
public static final String P_FITNESS = "fitness";
/** The prototypical individual for this species. */
public Individual i_prototype;
/** The prototypical breeding pipeline for this species. */
public BreedingPipeline pipe_prototype;
/** The prototypical fitness for individuals of this species. */
public Fitness f_prototype;
public Object clone()
{
try
{
Species myobj = (Species) (super.clone());
myobj.i_prototype = (Individual) i_prototype.clone();
myobj.f_prototype = (Fitness) f_prototype.clone();
myobj.pipe_prototype = (BreedingPipeline) pipe_prototype.clone();
return myobj;
}
catch (CloneNotSupportedException e)
{ throw new InternalError(); } // never happens
}
// deprecate the old ones
final private Individual newIndividual(final EvolutionState state,
final Subpopulation _population,
final Fitness _fitness) throws IOException { return null; }
final private Individual newIndividual(final EvolutionState state,
final Subpopulation _population,
final Fitness _fitness,
final LineNumberReader reader) throws IOException { return null; }
final private Individual newIndividual(final EvolutionState state,
final Subpopulation _population,
final Fitness _fitness,
final DataInput input) throws IOException { return null; }
/** Provides a brand-new individual to fill in a population. The default form
simply calls clone(), creates a fitness, sets evaluated to false, and sets
the species. If you need to make a more custom genotype (as is the case
for GPSpecies, which requires a light rather than deep clone),
you will need to override this method as you see fit.
*/
public Individual newIndividual(final EvolutionState state, int thread)
{
Individual newind = (Individual)(i_prototype.clone());
// Set the fitness
newind.fitness = (Fitness)(f_prototype.clone());
newind.evaluated = false;
// Set the species to me
newind.species = this;
// ...and we're ready!
return newind;
}
/**
Provides an individual read from a stream, including
the fitness; the individual will
appear as it was written by printIndividual(...). Doesn't
close the stream. Sets evaluated to false and sets the species.
If you need to make a more custom mechanism (as is the case
for GPSpecies, which requires a light rather than deep clone),
you will need to override this method as you see fit.
*/
public Individual newIndividual(final EvolutionState state,
final LineNumberReader reader)
throws IOException
{
Individual newind = (Individual)(i_prototype.clone());
// Set the fitness
newind.fitness = (Fitness)(f_prototype.clone());
newind.evaluated = false; // for sanity's sake, though it's a useless line
// load that sucker
newind.readIndividual(state,reader);
// Set the species to me
newind.species = this;
// and we're ready!
return newind;
}
/**
Provides an individual read from a DataInput source, including
the fitness. Doesn't
close the DataInput. Sets evaluated to false and sets the species.
If you need to make a more custom mechanism (as is the case
for GPSpecies, which requires a light rather than deep clone),
you will need to override this method as you see fit.
*/
public Individual newIndividual(final EvolutionState state,
final DataInput dataInput)
throws IOException
{
Individual newind = (Individual)(i_prototype.clone());
// Set the fitness
newind.fitness = (Fitness)(f_prototype.clone());
newind.evaluated = false; // for sanity's sake, though it's a useless line
// Set the species to me
newind.species = this;
// load that sucker
newind.readIndividual(state,dataInput);
// and we're ready!
return newind;
}
/** The default version of setup(...) loads requested pipelines and calls setup(...) on them and normalizes their probabilities.
If your individual prototype might need to know special things about the species (like parameters stored in it),
then when you override this setup method, you'll need to set those parameters BEFORE you call super.setup(...),
because the setup(...) code in Species sets up the prototype.
@see Prototype#setup(EvolutionState,Parameter)
*/
public void setup(final EvolutionState state, final Parameter base)
{
Parameter def = defaultBase();
// load the breeding pipeline
pipe_prototype = (BreedingPipeline)(
state.parameters.getInstanceForParameter(
base.push(P_PIPE),def.push(P_PIPE),BreedingPipeline.class));
pipe_prototype.setup(state,base.push(P_PIPE));
// I promised over in BreedingSource.java that this method would get called.
state.output.exitIfErrors();
// load our individual prototype
i_prototype = (Individual)(state.parameters.getInstanceForParameter(
base.push(P_INDIVIDUAL),def.push(P_INDIVIDUAL),
Individual. class));
// set the species to me before setting up the individual, so they know who I am
i_prototype.species = this;
i_prototype.setup(state,base.push(P_INDIVIDUAL));
// load our fitness
f_prototype = (Fitness) state.parameters.getInstanceForParameter(
base.push(P_FITNESS),def.push(P_FITNESS),
Fitness.class);
f_prototype.setup(state,base.push(P_FITNESS));
}
}