package ec.evolve; import ec.*; import ec.steadystate.*; import ec.util.*; import java.io.*; /** * A special Statistics class which performs random restarts on the population, * effectively reininitializing the population and starting over again. * RandomRestarts has two ways of determining when to perform a restart. If * the restart type is "fixed", then the restart will occur precisely when * the generation is a multiple of restart-upper-bound, minus one. (That's * hardly random, of course). If the restart type is "random", then at the * beginning of the run, and after every restart, a new restart is chosen * randomly from one to restart-upper-bound. * *

This class is compatible with populations which load from files -- it * temporarily disables the load-from-file feature when telling the population * to populate itself again, forcing the population to do so by creating random * individuals. * * @author James O'Beirne

Parameters
base.restart-type
random or fixed
Either initiates clock at a random value or a fixed one.
base.restart-upper-bound
1 < int < \inf
Maximum time clock can initiate with.
*/ public class RandomRestarts extends Statistics implements SteadyStateStatisticsForm { /** Two options available here: "fixed" and "random"; "fixed" * will initate the restart timer at the value specified for * restart-upper-bound, "random" will initiate the restart * timer somewhere below the value specified for * restart-upper-bound */ public static final String P_RESTART_TYPE = "restart-type"; /** This is the highest value at which the "ticking" * restart clock can initiate at. */ public static final String P_RESTART_UPPERBOUND = "restart-upper-bound"; public int countdown; // what we'll use for the "ticking" clock public int upperbound; // highest possible value on the clock String restartType; // are we doing random or fixed? /** Gets the clock ticking. */ public void setup( final EvolutionState state, final Parameter base ) { super.setup( state, base ); restartType = state.parameters.getString(base.push(P_RESTART_TYPE), null); upperbound = state.parameters.getInt( base.push(P_RESTART_UPPERBOUND), null, 1); if( upperbound < 1 ) state.output.fatal("Parameter either not found or invalid (<1).", base.push(P_RESTART_UPPERBOUND)); if( !restartType.equals( "random" ) && !restartType.equals( "fixed" ) ) state.output.fatal("Parameter must be either 'fixed' or 'random'.", base.push(P_RESTART_TYPE)); // start counting down this.resetClock( state ); } /** * Checks the clock; if it's time to restart, we repopulate the population. * Afterwards, we reset the clock. * * If it's not time yet, the clock goes tick. */ public void preEvaluationStatistics( final EvolutionState state ) { super.preEvaluationStatistics(state); possiblyRestart(state); } public void generationBoundaryStatistics(final EvolutionState state) { super.generationBoundaryStatistics(state); possiblyRestart(state); } void possiblyRestart(EvolutionState state) { Subpopulation currentSubp; File tempFile; // time to restart! if( countdown == 0 ) { System.out.println( "Restarting the population!" ); // for each subpopulation for( int subp = 0; subp < state.population.subpops.length; subp++ ) { currentSubp = state.population.subpops[subp]; tempFile = currentSubp.loadInds; // disable loadInds so we generate candidates randomly currentSubp.loadInds = null; currentSubp.populate( state, 0 ); currentSubp.loadInds = tempFile; } this.resetClock( state ); } else countdown--; } void resetClock( final EvolutionState state ) { if(restartType.equals( "fixed" )) countdown = upperbound; else // might need to fix random index to support multithreading countdown = state.random[0].nextInt( upperbound + 1 ); } }