Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/steadystate/SteadyStateEvolutionState.java @ 6703

Last change on this file since 6703 was 6152, checked in by bfarka, 14 years ago

added ecj and custom statistics to communicate with the okb services #1441

File size: 13.5 KB
Line 
1/*
2  Copyright 2006 by Sean Luke
3  Licensed under the Academic Free License version 3.0
4  See the file "LICENSE" for more information
5*/
6
7
8package ec.steadystate;
9import ec.*;
10import ec.util.Parameter;
11import ec.util.Checkpoint;
12import ec.util.Output;
13import ec.simple.*;
14//import ec.eval.MasterProblem;
15import java.util.*;
16
17/*
18 * SteadyStateEvolutionState.java
19 *
20 */
21
22/**
23 * This subclass of EvolutionState implements basic Steady-State Evolution and (in distributed form)
24 * Asynchronous Evolution. The procedure is as follows.  We begin with an empty Population and one by
25 * one create new Indivdiuals and send them off to be evaluated.  In basic Steady-State Evolution the
26 * individuals are immediately evaluated and we wait for them; but in Asynchronous Evolution the individuals are evaluated
27 * for however long it takes and we don't wait for them to finish.  When individuals return they are
28 * added to the Population until it is full.  No duplicate individuals are allowed.
29 *
30 * <p>At this point the system switches to its "steady state": individuals are bred from the population
31 * one by one, and sent off to be evaluated.  Once again, in basic Steady-State Evolution the
32 * individuals are immediately evaluated and we wait for them; but in Asynchronous Evolution the individuals are evaluated
33 * for however long it takes and we don't wait for them to finish.  When an individual returns, we
34 * mark an individual in the Population for death, then replace it with the new returning individual.
35 * Note that during the steady-state, Asynchronous Evolution could be still sending back some "new" individuals
36 * created during the initialization phase, not "bred" individuals.
37 *
38 * <p>The determination of how an individual is marked for death is done by the SteadyStateBreeder.
39 *
40 * <p>SteadyStateEvolutionState will run either for some N "generations" or for some M evaluations of
41 * individuals.   A "generation" is defined as a Population's worth of evaluations.   If you do not
42 * specify the number of evaluations (the M), then SteadyStateEvolutionState will use the standard
43 * generations parameter defined in EvolutionState.
44 *
45 
46 <p><b>Parameters</b><br>
47 <table>
48 <tr><td valign=top><tt>evaluations</tt><br>
49 <font size=-1>int &gt;= 1</font></td>
50 <td valign=top>(maximal number of evaluations to run.)</td></tr>
51 </table>
52 
53 *
54 * @author Sean Luke
55 * @version 1.0
56 */
57
58
59public class SteadyStateEvolutionState extends EvolutionState
60    {
61    /** base parameter for steady-state */
62    public static final String P_NUMEVALUATIONS = "evaluations";
63       
64    /** Did we just start a new generation? */
65    public boolean generationBoundary;
66    /** How many evaluations should we run for?  If set to UNDEFINED (0), we run for the number of generations instead. */
67    public long numEvaluations;
68    public static long UNDEFINED = 0;
69    /** how big is a generation? Set to the size of subpopulation 0 of the initial population. */
70    public int generationSize;
71    /** How many evaluations have we run so far? */
72    public long evaluations;
73       
74    /** How many individuals have we added to the initial population? */
75    int[] individualCount;
76       
77    /** Hash table to check for duplicate individuals */
78    HashMap[] individualHash;
79       
80    /** Holds which subpopulation we are currently operating on */
81    int whichSubpop;
82   
83    /** First time calling evolve */
84    protected boolean firstTime;
85       
86    public void setup(final EvolutionState state, final Parameter base)
87        {
88        super.setup(state,base);
89               
90        // double check that we have valid evaluators and breeders and exchangers
91        if (!(breeder instanceof SteadyStateBreeder))
92            state.output.error("You've chosen to use Steady-State Evolution, but your breeder is not of the class SteadyStateBreeder.",base);
93        if (!(evaluator instanceof SteadyStateEvaluator))
94            state.output.error("You've chosen to use Steady-State Evolution, but your evaluator is not of the class SteadyStateEvaluator.",base);
95        if (!(exchanger instanceof SteadyStateExchangerForm))
96            state.output.error("You've chosen to use Steady-State Evolution, but your exchanger does not implement the SteadyStateExchangerForm.",base);
97       
98        checkStatistics(state, statistics, base);
99       
100        numEvaluations = parameters.getLong(new Parameter(P_NUMEVALUATIONS),null,1);
101        if (numEvaluations == 0)
102            output.message("Number of evaluations not defined; using number of generations");
103        }
104   
105    // recursively prints out warnings for all statistics that are not
106    // of steadystate statistics form
107    void checkStatistics(final EvolutionState state, Statistics stat, final Parameter base)
108        {
109        if (!(stat instanceof SteadyStateStatisticsForm))
110            state.output.warning("You've chosen to use Steady-State Evolution, but your statistics does not implement the SteadyStateStatisticsForm.",base);
111        for(int x=0;x<stat.children.length;x++)
112            if (stat.children[x]!=null)
113                checkStatistics(state, stat.children[x], base.push("child").push(""+x));
114        }
115   
116   
117    /**
118     *
119     */
120    public void startFresh()
121        {
122        output.message("Setting up");
123        setup(this,null);  // a garbage Parameter
124
125        // POPULATION INITIALIZATION
126        output.message("Initializing Generation 0");
127        statistics.preInitializationStatistics(this);
128        population = initializer.setupPopulation(this, 0);  // unthreaded.  We're NOT initializing here, just setting up.
129
130        // INITIALIZE VARIABLES
131        if (numEvaluations > 0 && numEvaluations < population.subpops[0].individuals.length)
132            output.fatal("Number of evaluations desired is smaller than the initial population of individuals");
133        generationSize = 0;
134        generationBoundary = false;
135        firstTime = true;
136        evaluations=0;
137        whichSubpop=-1;
138               
139        individualHash = new HashMap[population.subpops.length];
140        for(int i=0;i<population.subpops.length; i++) individualHash[i] = new HashMap();
141               
142        individualCount = new int[population.subpops.length];
143        for (int sub=0; sub < population.subpops.length; sub++) 
144            {
145            individualCount[sub]=0;
146            generationSize += population.subpops[sub].individuals.length;  // so our sum total 'generationSize' will be the initial total number of individuals
147            }
148
149        // INITIALIZE CONTACTS -- done after initialization to allow
150        // a hook for the user to do things in Initializer before
151        // an attempt is made to connect to island models etc.
152        exchanger.initializeContacts(this);
153        evaluator.initializeContacts(this);
154        }
155
156
157 
158    public int evolve()
159        {
160        if (generationBoundary && generation > 0)
161            {
162            output.message("Generation " + generation +"\tEvaluations " + evaluations);
163            statistics.generationBoundaryStatistics(this);
164            statistics.postEvaluationStatistics(this);
165            }
166               
167        if (firstTime)
168            {
169            if (statistics instanceof SteadyStateStatisticsForm)
170                ((SteadyStateStatisticsForm)statistics).enteringInitialPopulationStatistics(this);
171            statistics.postInitializationStatistics(this);
172            ((SteadyStateBreeder)breeder).prepareToBreed(this, 0); // unthreaded
173            ((SteadyStateEvaluator)evaluator).prepareToEvaluate(this, 0); // unthreaded
174            firstTime=false;
175            }
176               
177        whichSubpop = (whichSubpop+1)%population.subpops.length;  // round robin selection
178               
179        // is the current subpop full?
180        boolean partiallyFullSubpop = (individualCount[whichSubpop] < population.subpops[whichSubpop].individuals.length); 
181               
182        // MAIN EVOLVE LOOP
183        if (((SteadyStateEvaluator) evaluator).canEvaluate())   // are we ready to evaluate?
184            {
185            Individual ind=null;
186            int numDuplicateRetries = population.subpops[whichSubpop].numDuplicateRetries;
187
188            for (int tries=0; tries <= numDuplicateRetries; tries++)  // see Subpopulation
189                {
190                if ( partiallyFullSubpop )   // is population full?
191                    {
192                    ind = population.subpops[whichSubpop].species.newIndividual(this, 0);  // unthreaded
193                    }
194                else 
195                    {
196                    ind = ((SteadyStateBreeder)breeder).breedIndividual(this, whichSubpop,0);
197                    statistics.individualsBredStatistics(this, new Individual[]{ind});
198                    }
199                               
200                if (numDuplicateRetries >= 1) 
201                    {
202                    Object o = individualHash[whichSubpop].get(ind);
203                    if (o == null)
204                        {
205                        individualHash[whichSubpop].put(ind, ind);
206                        break;
207                        }
208                    }
209                } // tried to cut down the duplicates
210                       
211            // evaluate the new individual
212            ((SteadyStateEvaluator)evaluator).evaluateIndividual(this, ind, whichSubpop);
213            }
214       
215        Individual ind = ((SteadyStateEvaluator)evaluator).getNextEvaluatedIndividual();
216        if (ind != null)   // do we have an evaluated individual?
217            {
218            int subpop = ((SteadyStateEvaluator)evaluator).getSubpopulationOfEvaluatedIndividual();
219                                               
220            if ( partiallyFullSubpop ) // is subpopulation full?
221                { 
222                population.subpops[subpop].individuals[individualCount[subpop]++]=ind;
223                               
224                // STATISTICS FOR GENERATION ZERO
225                if ( individualCount[subpop] == population.subpops[subpop].individuals.length )
226                    if (statistics instanceof SteadyStateStatisticsForm)
227                        ((SteadyStateStatisticsForm)statistics).enteringSteadyStateStatistics(subpop, this);
228                }
229            else
230                {
231                // mark individual for death
232                int deadIndividual = ((SteadyStateBreeder)breeder).deselectors[subpop].produce(subpop,this,0);
233                Individual deadInd = population.subpops[subpop].individuals[deadIndividual];
234                               
235                // replace dead individual with new individual
236                population.subpops[subpop].individuals[deadIndividual] = ind;
237                               
238                // update duplicate hash table
239                individualHash[subpop].remove(deadInd);
240                               
241                if (statistics instanceof SteadyStateStatisticsForm)
242                    ((SteadyStateStatisticsForm)statistics).individualsEvaluatedStatistics(this,
243                        new Individual[]{ind}, new Individual[]{deadInd}, new int[]{subpop}, new int[]{deadIndividual});
244                }
245                                               
246            // INCREMENT NUMBER OF COMPLETED EVALUATIONS
247            evaluations++;
248           
249            // COMPUTE GENERATION BOUNDARY
250            generationBoundary = (evaluations % generationSize == 0);
251            }
252        else
253            {
254            generationBoundary = false;
255            }
256
257        // SHOULD WE QUIT?
258        if (!partiallyFullSubpop && evaluator.runComplete(this) && quitOnRunComplete)
259            {
260            output.message("Found Ideal Individual");
261            return R_SUCCESS;
262            }
263               
264        if ((numEvaluations > 0 && evaluations >= numEvaluations) ||  // using numEvaluations
265            (numEvaluations <= 0 && generationBoundary && generation == numGenerations -1))  // not using numEvaluations
266            {
267            return R_FAILURE;
268            }
269               
270               
271        // EXCHANGING
272        if (generationBoundary)
273            {
274            // PRE-BREED EXCHANGE
275            statistics.prePreBreedingExchangeStatistics(this);
276            population = exchanger.preBreedingExchangePopulation(this);
277            statistics.postPreBreedingExchangeStatistics(this);
278            String exchangerWantsToShutdown = exchanger.runComplete(this);
279            if (exchangerWantsToShutdown!=null)
280                {
281                output.message(exchangerWantsToShutdown);
282                return R_SUCCESS;
283                }
284                       
285            // POST BREED EXCHANGE
286            statistics.prePostBreedingExchangeStatistics(this);
287            population = exchanger.postBreedingExchangePopulation(this);
288            statistics.postPostBreedingExchangeStatistics(this);
289                       
290            // INCREMENT GENERATION AND CHECKPOINT
291            generation++;
292            if (checkpoint && generation%checkpointModulo == 0)
293                {
294                output.message("Checkpointing");
295                statistics.preCheckpointStatistics(this);
296                Checkpoint.setCheckpoint(this);
297                statistics.postCheckpointStatistics(this);
298                }
299            }
300        return R_NOTDONE;
301        }
302       
303    /**
304     * @param result
305     */
306    public void finish(int result)
307        {
308        /* finish up -- we completed. */
309        ((SteadyStateBreeder)breeder).finishPipelines(this);
310        statistics.finalStatistics(this,result);
311        finisher.finishPopulation(this,result);
312        exchanger.closeContacts(this,result);
313        evaluator.closeContacts(this,result);
314        }
315    }
Note: See TracBrowser for help on using the repository browser.