/*
Copyright 2006 by Sean Luke
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package ec.simple;
import ec.Initializer;
import ec.Individual;
import ec.BreedingPipeline;
import ec.Breeder;
import ec.EvolutionState;
import ec.Population;
import ec.util.Parameter;
import ec.util.*;
/*
* SimpleBreeder.java
*
* Created: Tue Aug 10 21:00:11 1999
* By: Sean Luke
*/
/**
* Breeds each subpopulation separately, with no inter-population exchange,
* and using a generational approach. A SimpleBreeder may have multiple
* threads; it divvys up a subpopulation into chunks and hands one chunk
* to each thread to populate. One array of BreedingPipelines is obtained
* from a population's Species for each operating breeding thread.
*
* Prior to breeding a subpopulation, a SimpleBreeder may first fill part of the new
* subpopulation up with the best n individuals from the old subpopulation.
* By default, n is 0 for each subpopulation (that is, this "elitism"
* is not done). The elitist step is performed by a single thread.
*
Parameters
base.elite.i
int >= 0 (default=0) |
(the number of elitist individuals for subpopulation i) |
base.reevalate-elites.i
boolean (default = false) |
(should we reevaluate the elites of subpopulation i each generation?) |
*
*
* @author Sean Luke
* @version 1.0
*/
public class SimpleBreeder extends Breeder
{
public static final String P_ELITE = "elite";
public static final String P_REEVALUATE_ELITES = "reevalate-elites";
/** An array[subpop] of the number of elites to keep for that subpopulation */
public int[] elite;
public boolean[] reevaluateElites;
public void setup(final EvolutionState state, final Parameter base)
{
Parameter p = new Parameter(Initializer.P_POP).push(Population.P_SIZE);
int size = state.parameters.getInt(p,null,1); // if size is wrong, we'll let Population complain about it -- for us, we'll just make 0-sized arrays and drop out.
elite = new int[size];
reevaluateElites = new boolean[size];
for(int x=0;x= 0",base.push(P_ELITE).push(""+x));
reevaluateElites[x] = state.parameters.getBoolean(base.push(P_REEVALUATE_ELITES).push(""+x),null,false);
}
state.output.exitIfErrors();
}
/** Elites are often stored in the top part of the subpopulation; this function returns what
part of the subpopulation contains individuals to replace with newly-bred ones
(up to but not including the elites). */
public int computeSubpopulationLength(Population newpop, int subpopulation)
{
return newpop.subpops[subpopulation].individuals.length - elite[subpopulation];
}
/** A simple breeder that doesn't attempt to do any cross-
population breeding. Basically it applies pipelines,
one per thread, to various subchunks of a new population. */
public Population breedPopulation(EvolutionState state)
{
int numinds[][] =
new int[state.breedthreads][state.population.subpops.length];
int from[][] =
new int[state.breedthreads][state.population.subpops.length];
Population newpop = (Population) state.population.emptyClone();
// load elites into top of newpop
loadElites(state, newpop);
for(int y=0;yupperbound) // uh oh! Someone blew it!
state.output.fatal("Whoa! A breeding pipeline overwrote the space of another pipeline in subpopulation " + subpop + ". You need to check your breeding pipeline code (in produce() ).");
bp.finishProducing(state,subpop,threadnum);
}
}
class EliteComparator implements SortComparatorL
{
Individual[] inds;
public EliteComparator(Individual[] inds) {super(); this.inds = inds;}
public boolean lt(long a, long b)
{ return inds[(int)b].fitness.betterThan(inds[(int)a].fitness); }
public boolean gt(long a, long b)
{ return inds[(int)a].fitness.betterThan(inds[(int)b].fitness); }
}
protected void unmarkElitesEvaluated(Population newpop)
{
for(int sub=0;substate.population.subpops[x].individuals.length)
state.output.error("The number of elites for subpopulation " + x + " exceeds the actual size of the subpopulation", new Parameter(EvolutionState.P_BREEDER).push(P_ELITE).push(""+x));
state.output.exitIfErrors();
// we assume that we're only grabbing a small number (say <10%), so
// it's not being done multithreaded
for(int sub=0;sub0) // we'll need to sort
{
int[] orderedPop = new int[state.population.subpops[sub].individuals.length];
for(int x=0;x