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.start
int >= 0 (default = 1)
The first generation where the clock may be started.
base.restart-type
random (default) 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
{
public static final String P_RESTART_TYPE = "restart-type";
public static final String P_RESTART_UPPERBOUND = "restart-upper-bound";
public static final String P_START = "start";
public int countdown; // what we'll use for the "ticking" clock
public int upperbound; // highest possible value on the clock
public int start;
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);
if (restartType == null)
restartType = "random";
upperbound = state.parameters.getInt( base.push(P_RESTART_UPPERBOUND), null, 1);
if (state.parameters.exists(base.push(P_START), null))
{
start = state.parameters.getInt(base.push(P_START), null, 0);
if (start < 0)
state.output.fatal("Start value must be >= 0", base.push(P_START));
}
else start = 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));
}
/**
* 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);
if (state.generation == start) resetClock(state); // first time only
if (state.generation >= start) possiblyRestart(state);
}
void possiblyRestart(EvolutionState state)
{
countdown--;
Subpopulation currentSubp;
// time to restart!
if( countdown == 0 )
{
state.output.message( "Restarting the population prior to evaluating generation " + state.generation );
// for each subpopulation
for( int subp = 0; subp < state.population.subpops.length; subp++ )
{
currentSubp = state.population.subpops[subp];
boolean temp = currentSubp.loadInds;
// disable loadInds so we generate candidates randomly
currentSubp.loadInds = false;
currentSubp.populate( state, 0 );
currentSubp.loadInds = temp;
}
this.resetClock( state );
}
}
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;
}
}
Ads help maintain this website.