All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ec.steadystate.SteadyStateEvolutionState Maven / Gradle / Ivy

Go to download

ECJ, A Java-based Evolutionary Computation Research System. ECJ is a research EC system written in Java. It was designed to be highly flexible, with nearly all classes (and all of their settings) dynamically determined at runtime by a user-provided parameter file. All structures in the system are arranged to be easily modifiable. Even so, the system was designed with an eye toward efficiency. ECJ is developed at George Mason University's ECLab Evolutionary Computation Laboratory. The software has nothing to do with its initials' namesake, Evolutionary Computation Journal. ECJ's sister project is MASON, a multi-agent simulation system which dovetails with ECJ nicely.

The newest version!
/*
  Copyright 2006 by Sean Luke
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/


package ec.steadystate;
import ec.*;
import ec.util.Parameter;
import ec.util.Checkpoint;
import ec.util.Output;
import ec.simple.*;
//import ec.eval.MasterProblem;
import java.util.*; 

/* 
 * SteadyStateEvolutionState.java
 * 
 */

/**
 * This subclass of EvolutionState implements basic Steady-State Evolution and (in distributed form)
 * Asynchronous Evolution. The procedure is as follows.  We begin with an empty Population and one by
 * one create new Indivdiuals and send them off to be evaluated.  In basic Steady-State Evolution the
 * individuals are immediately evaluated and we wait for them; but in Asynchronous Evolution the individuals are evaluated
 * for however long it takes and we don't wait for them to finish.  When individuals return they are
 * added to the Population until it is full.  No duplicate individuals are allowed.
 *
 * 

At this point the system switches to its "steady state": individuals are bred from the population * one by one, and sent off to be evaluated. Once again, in basic Steady-State Evolution the * individuals are immediately evaluated and we wait for them; but in Asynchronous Evolution the individuals are evaluated * for however long it takes and we don't wait for them to finish. When an individual returns, we * mark an individual in the Population for death, then replace it with the new returning individual. * Note that during the steady-state, Asynchronous Evolution could be still sending back some "new" individuals * created during the initialization phase, not "bred" individuals. * *

The determination of how an individual is marked for death is done by the SteadyStateBreeder. * *

SteadyStateEvolutionState will run either for some N "generations" or for some M evaluations of * individuals. A "generation" is defined as a Population's worth of evaluations. If you do not * specify the number of evaluations (the M), then SteadyStateEvolutionState will use the standard * generations parameter defined in EvolutionState. *

Parameters

evaluations
int >= 1
(maximal number of evaluations to run.)
steady.replacement-probability
0.0 <= double <= 1.0 (default is 1.0)
(probability that an incoming individual will unilaterally replace the individual marked for death, as opposed to replacing it only if the incoming individual is superior in fitness)
* * @author Sean Luke * @version 1.0 */ public class SteadyStateEvolutionState extends EvolutionState { public static final String P_REPLACEMENT_PROBABILITY = "replacement-probability"; /** Did we just start a new generation? */ public boolean generationBoundary; /** how big is a generation? Set to the size of subpopulation 0 of the initial population. */ public int generationSize; /** How many evaluations have we run so far? */ public long evaluations; /** When a new individual arrives, with what probability should it directly replace the existing "marked for death" individual, as opposed to only replacing it if it's superior? */ public double replacementProbability; /** How many individuals have we added to the initial population? */ int[] individualCount; /** Hash table to check for duplicate individuals */ HashMap[] individualHash; /** Holds which subpopulation we are currently operating on */ int whichSubpop; /** First time calling evolve */ protected boolean firstTime; public void setup(final EvolutionState state, final Parameter base) { super.setup(state,base); // double check that we have valid evaluators and breeders and exchangers if (!(breeder instanceof SteadyStateBreeder)) state.output.error("You've chosen to use Steady-State Evolution, but your breeder is not of the class SteadyStateBreeder.",base); if (!(evaluator instanceof SteadyStateEvaluator)) state.output.error("You've chosen to use Steady-State Evolution, but your evaluator is not of the class SteadyStateEvaluator.",base); if (!(exchanger instanceof SteadyStateExchangerForm)) state.output.error("You've chosen to use Steady-State Evolution, but your exchanger does not implement the SteadyStateExchangerForm.",base); checkStatistics(state, statistics, new Parameter(P_STATISTICS)); if (parameters.exists(SteadyStateDefaults.base().push(P_REPLACEMENT_PROBABILITY),null)) { replacementProbability = parameters.getDoubleWithMax(SteadyStateDefaults.base().push(P_REPLACEMENT_PROBABILITY),null,0.0, 1.0); if (replacementProbability < 0.0) // uh oh state.output.error("Replacement probability must be between 0.0 and 1.0 inclusive.", SteadyStateDefaults.base().push(P_REPLACEMENT_PROBABILITY), null); } else { replacementProbability = 1.0; // always replace state.output.message("Replacement probability not defined: using 1.0 (always replace)"); } } // recursively prints out warnings for all statistics that are not // of steadystate statistics form void checkStatistics(final EvolutionState state, Statistics stat, final Parameter base) { if (!(stat instanceof SteadyStateStatisticsForm)) state.output.warning("You've chosen to use Steady-State Evolution, but your statistics does not implement the SteadyStateStatisticsForm.",base); for(int x=0;x UNDEFINED && numEvaluations < generationSize) output.fatal("Number of evaluations desired is smaller than the initial population of individuals"); // INITIALIZE CONTACTS -- done after initialization to allow // a hook for the user to do things in Initializer before // an attempt is made to connect to island models etc. exchanger.initializeContacts(this); evaluator.initializeContacts(this); } boolean justCalledPostEvaluationStatistics = false; public int evolve() { if (generationBoundary && generation > 0) { output.message("Generation " + generation +"\tEvaluations " + evaluations); statistics.generationBoundaryStatistics(this); statistics.postEvaluationStatistics(this); justCalledPostEvaluationStatistics = true; } else { justCalledPostEvaluationStatistics = false; } if (firstTime) { if (statistics instanceof SteadyStateStatisticsForm) ((SteadyStateStatisticsForm)statistics).enteringInitialPopulationStatistics(this); statistics.postInitializationStatistics(this); ((SteadyStateBreeder)breeder).prepareToBreed(this, 0); // unthreaded ((SteadyStateEvaluator)evaluator).prepareToEvaluate(this, 0); // unthreaded firstTime=false; } whichSubpop = (whichSubpop+1)%population.subpops.length; // round robin selection // is the current subpop full? boolean partiallyFullSubpop = (individualCount[whichSubpop] < population.subpops[whichSubpop].individuals.length); // MAIN EVOLVE LOOP if (((SteadyStateEvaluator) evaluator).canEvaluate()) // are we ready to evaluate? { Individual ind=null; int numDuplicateRetries = population.subpops[whichSubpop].numDuplicateRetries; for (int tries=0; tries <= numDuplicateRetries; tries++) // see Subpopulation { if ( partiallyFullSubpop ) // is population full? { ind = population.subpops[whichSubpop].species.newIndividual(this, 0); // unthreaded } else { ind = ((SteadyStateBreeder)breeder).breedIndividual(this, whichSubpop,0); statistics.individualsBredStatistics(this, new Individual[]{ind}); } if (numDuplicateRetries >= 1) { Object o = individualHash[whichSubpop].get(ind); if (o == null) { individualHash[whichSubpop].put(ind, ind); break; } } } // tried to cut down the duplicates // evaluate the new individual ((SteadyStateEvaluator)evaluator).evaluateIndividual(this, ind, whichSubpop); } Individual ind = ((SteadyStateEvaluator)evaluator).getNextEvaluatedIndividual(); if (ind != null) // do we have an evaluated individual? { int subpop = ((SteadyStateEvaluator)evaluator).getSubpopulationOfEvaluatedIndividual(); if ( partiallyFullSubpop ) // is subpopulation full? { population.subpops[subpop].individuals[individualCount[subpop]++]=ind; // STATISTICS FOR GENERATION ZERO if ( individualCount[subpop] == population.subpops[subpop].individuals.length ) if (statistics instanceof SteadyStateStatisticsForm) ((SteadyStateStatisticsForm)statistics).enteringSteadyStateStatistics(subpop, this); } else { // mark individual for death int deadIndividual = ((SteadyStateBreeder)breeder).deselectors[subpop].produce(subpop,this,0); Individual deadInd = population.subpops[subpop].individuals[deadIndividual]; // maybe replace dead individual with new individual if (ind.fitness.betterThan(deadInd.fitness) || // it's better, we want it random[0].nextDouble() < replacementProbability) // it's not better but maybe we replace it directly anyway population.subpops[subpop].individuals[deadIndividual] = ind; // update duplicate hash table individualHash[subpop].remove(deadInd); if (statistics instanceof SteadyStateStatisticsForm) ((SteadyStateStatisticsForm)statistics).individualsEvaluatedStatistics(this, new Individual[]{ind}, new Individual[]{deadInd}, new int[]{subpop}, new int[]{deadIndividual}); } // INCREMENT NUMBER OF COMPLETED EVALUATIONS evaluations++; // COMPUTE GENERATION BOUNDARY generationBoundary = (evaluations % generationSize == 0); } else { generationBoundary = false; } // SHOULD WE QUIT? if (!partiallyFullSubpop && evaluator.runComplete(this) && quitOnRunComplete) { output.message("Found Ideal Individual"); return R_SUCCESS; } if ((numEvaluations > UNDEFINED && evaluations >= numEvaluations) || // using numEvaluations (numEvaluations <= UNDEFINED && generationBoundary && generation == numGenerations -1)) // not using numEvaluations { // we are not exchanging again, but we might wish to increment the generation // one last time if we hit a generation boundary if (generationBoundary) generation++; return R_FAILURE; } // EXCHANGING if (generationBoundary) { // PRE-BREED EXCHANGE statistics.prePreBreedingExchangeStatistics(this); population = exchanger.preBreedingExchangePopulation(this); statistics.postPreBreedingExchangeStatistics(this); String exchangerWantsToShutdown = exchanger.runComplete(this); if (exchangerWantsToShutdown!=null) { output.message(exchangerWantsToShutdown); return R_SUCCESS; } // POST BREED EXCHANGE statistics.prePostBreedingExchangeStatistics(this); population = exchanger.postBreedingExchangePopulation(this); statistics.postPostBreedingExchangeStatistics(this); // INCREMENT GENERATION AND CHECKPOINT generation++; if (checkpoint && generation%checkpointModulo == 0) { output.message("Checkpointing"); statistics.preCheckpointStatistics(this); Checkpoint.setCheckpoint(this); statistics.postCheckpointStatistics(this); } } return R_NOTDONE; } /** * @param result */ public void finish(int result) { /* finish up -- we completed. */ ((SteadyStateBreeder)breeder).finishPipelines(this); if (!justCalledPostEvaluationStatistics) { output.message("Generation " + generation +"\tEvaluations " + evaluations); statistics.postEvaluationStatistics(this); } statistics.finalStatistics(this,result); finisher.finishPopulation(this,result); exchanger.closeContacts(this,result); evaluator.closeContacts(this,result); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy