Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/simple/SimpleBreeder.java @ 10187

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

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

File size: 11.3 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.simple;
9import ec.Initializer;
10import ec.Individual;
11import ec.BreedingPipeline;
12import ec.Breeder;
13import ec.EvolutionState;
14import ec.Population;
15import ec.util.Parameter;
16import ec.util.*;
17
18/*
19 * SimpleBreeder.java
20 *
21 * Created: Tue Aug 10 21:00:11 1999
22 * By: Sean Luke
23 */
24
25/**
26 * Breeds each subpopulation separately, with no inter-population exchange,
27 * and using a generational approach.  A SimpleBreeder may have multiple
28 * threads; it divvys up a subpopulation into chunks and hands one chunk
29 * to each thread to populate.  One array of BreedingPipelines is obtained
30 * from a population's Species for each operating breeding thread.
31 *
32 * Prior to breeding a subpopulation, a SimpleBreeder may first fill part of the new
33 * subpopulation up with the best <i>n</i> individuals from the old subpopulation.
34 * By default, <i>n</i> is 0 for each subpopulation (that is, this "elitism"
35 * is not done).  The elitist step is performed by a single thread.
36 *
37 <p><b>Parameters</b><br>
38 <table>
39 <tr><td valign=top><tt><i>base</i>.elite.<i>i</i></tt><br>
40 <font size=-1>int >= 0 (default=0)</font></td>
41 <td valign=top>(the number of elitist individuals for subpopulation <i>i</i>)</td></tr>
42 <tr><td valign=top><tt><i>base</i>.reevalate-elites.<i>i</i></tt><br>
43 <font size=-1>boolean (default = false)</font></td>
44 <td valign=top>(should we reevaluate the elites of subpopulation <i>i</i> each generation?)</td></tr>
45 </table>
46 *
47 *
48 * @author Sean Luke
49 * @version 1.0
50 */
51
52public class SimpleBreeder extends Breeder
53    {
54    public static final String P_ELITE = "elite";
55    public static final String P_REEVALUATE_ELITES = "reevalate-elites";
56    /** An array[subpop] of the number of elites to keep for that subpopulation */
57    public int[] elite;
58    public boolean[] reevaluateElites;
59
60    public void setup(final EvolutionState state, final Parameter base)
61        {
62        Parameter p = new Parameter(Initializer.P_POP).push(Population.P_SIZE);
63        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.
64
65        elite = new int[size];
66        reevaluateElites = new boolean[size];
67               
68        for(int x=0;x<size;x++)
69            {
70            elite[x] = state.parameters.getIntWithDefault(base.push(P_ELITE).push(""+x),null,0);
71            if (elite[x]<0) state.output.error("The number of elites for subpopulation " + x + " must be >= 0",base.push(P_ELITE).push(""+x));
72            reevaluateElites[x] = state.parameters.getBoolean(base.push(P_REEVALUATE_ELITES).push(""+x),null,false);
73            }
74
75        state.output.exitIfErrors();
76        }
77
78    /** Elites are often stored in the top part of the subpopulation; this function returns what
79        part of the subpopulation contains individuals to replace with newly-bred ones
80        (up to but not including the elites). */
81    public int computeSubpopulationLength(Population newpop, int subpopulation)
82        {
83        return newpop.subpops[subpopulation].individuals.length - elite[subpopulation];
84        }
85
86    /** A simple breeder that doesn't attempt to do any cross-
87        population breeding.  Basically it applies pipelines,
88        one per thread, to various subchunks of a new population. */
89    public Population breedPopulation(EvolutionState state)
90        {
91        int numinds[][] =
92            new int[state.breedthreads][state.population.subpops.length];
93        int from[][] =
94            new int[state.breedthreads][state.population.subpops.length];
95
96        Population newpop = (Population) state.population.emptyClone();
97       
98        // load elites into top of newpop
99        loadElites(state, newpop);
100
101        for(int y=0;y<state.breedthreads;y++)
102            for(int x=0;x<state.population.subpops.length;x++)
103                {
104                // the number of individuals we need to breed
105                int length = computeSubpopulationLength(newpop, x);
106                // the size of each breeding chunk except the last one
107                int firstBreedChunkSizes = length/state.breedthreads;
108                // the size of the last breeding chunk
109                int lastBreedChunkSize =
110                    firstBreedChunkSizes + length - firstBreedChunkSizes * (state.breedthreads);
111               
112                // figure numinds
113                if (y < state.breedthreads-1) // not the last one
114                    numinds[y][x] = firstBreedChunkSizes;
115                else // the last one
116                    numinds[y][x] = lastBreedChunkSize;
117               
118                // figure from
119                from[y][x] = (firstBreedChunkSizes * y);
120                }
121           
122        if (state.breedthreads==1)
123            {
124            breedPopChunk(newpop,state,numinds[0],from[0],0);
125            }
126        else
127            {
128            Thread[] t = new Thread[state.breedthreads];
129               
130            // start up the threads
131            for(int y=0;y<state.breedthreads;y++)
132                {
133                SimpleBreederThread r = new SimpleBreederThread();
134                r.threadnum = y;
135                r.newpop = newpop;
136                r.numinds = numinds[y];
137                r.from = from[y];
138                r.me = this;
139                r.state = state;
140                t[y] = new Thread(r);
141                t[y].start();
142                }
143               
144            // gather the threads
145            for(int y=0;y<state.breedthreads;y++) try
146                                                      {
147                                                      t[y].join();
148                                                      }
149                catch(InterruptedException e)
150                    {
151                    state.output.fatal("Whoa! The main breeding thread got interrupted!  Dying...");
152                    }
153            }
154        return newpop;
155        }
156
157
158    /** A private helper function for breedPopulation which breeds a chunk
159        of individuals in a subpopulation for a given thread.
160        Although this method is declared
161        public (for the benefit of a private helper class in this file),
162        you should not call it. */
163
164    protected void breedPopChunk(Population newpop, EvolutionState state,
165        int[] numinds, int[] from, int threadnum)
166        {
167        //System.out.println("Breeding: " + numinds[0] + " Starting at: " + from[0]);
168        for(int subpop=0;subpop<newpop.subpops.length;subpop++)
169            {
170            BreedingPipeline bp = (BreedingPipeline)newpop.subpops[subpop].
171                species.pipe_prototype.clone();
172               
173            // check to make sure that the breeding pipeline produces
174            // the right kind of individuals.  Don't want a mistake there! :-)
175            int x;
176            if (!bp.produces(state,newpop,subpop,threadnum))
177                state.output.fatal("The Breeding Pipeline of subpopulation " + subpop + " does not produce individuals of the expected species " + newpop.subpops[subpop].species.getClass().getName() + " or fitness " + newpop.subpops[subpop].species.f_prototype );
178            bp.prepareToProduce(state,subpop,threadnum);
179               
180            // start breedin'!
181               
182            x=from[subpop];
183            int upperbound = from[subpop]+numinds[subpop];
184            while(x<upperbound)
185                x += bp.produce(1,upperbound-x,x,subpop,
186                    newpop.subpops[subpop].individuals,
187                    state,threadnum);
188            if (x>upperbound) // uh oh!  Someone blew it!
189                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() ).");
190
191            bp.finishProducing(state,subpop,threadnum);
192            }
193        }
194   
195    class EliteComparator implements SortComparatorL
196        {
197        Individual[] inds;
198        public EliteComparator(Individual[] inds) {super(); this.inds = inds;}
199        public boolean lt(long a, long b)
200            { return inds[(int)b].fitness.betterThan(inds[(int)a].fitness); }
201        public boolean gt(long a, long b)
202            { return inds[(int)a].fitness.betterThan(inds[(int)b].fitness); }
203        }
204
205    protected void unmarkElitesEvaluated(Population newpop)
206        {
207        for(int sub=0;sub<newpop.subpops.length;sub++)
208            for(int e=0; e < elite[sub]; e++)
209                {
210                int len = newpop.subpops[sub].individuals.length;
211                if (reevaluateElites[sub])
212                    newpop.subpops[sub].individuals[len - elite[sub]].evaluated = false;
213                }
214        }
215
216    /** A private helper function for breedPopulation which loads elites into
217        a subpopulation. */
218
219    protected void loadElites(EvolutionState state, Population newpop)
220        {
221        // are our elites small enough?
222        for(int x=0;x<state.population.subpops.length;x++)
223            if (elite[x]>state.population.subpops[x].individuals.length)
224                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));
225        state.output.exitIfErrors();
226
227        // we assume that we're only grabbing a small number (say <10%), so
228        // it's not being done multithreaded
229        for(int sub=0;sub<state.population.subpops.length;sub++)
230            // if the number of elites is 1, then we handle this by just finding the best one.
231            if (elite[sub]==1)
232                {
233                int best = 0;
234                Individual[] oldinds = state.population.subpops[sub].individuals;
235                for(int x=1;x<oldinds.length;x++)
236                    if (oldinds[x].fitness.betterThan(oldinds[best].fitness))
237                        best = x;
238                Individual[] inds = newpop.subpops[sub].individuals;
239                inds[inds.length-1] = (Individual)(oldinds[best].clone());
240                }
241            else if (elite[sub]>0)  // we'll need to sort
242                {
243                int[] orderedPop = new int[state.population.subpops[sub].individuals.length];
244                for(int x=0;x<state.population.subpops[sub].individuals.length;x++) orderedPop[x] = x;
245
246                // sort the best so far where "<" means "not as fit as"
247                QuickSort.qsort(orderedPop, new EliteComparator(state.population.subpops[sub].individuals));
248                // load the top N individuals
249
250                Individual[] inds = newpop.subpops[sub].individuals;
251                Individual[] oldinds = state.population.subpops[sub].individuals;
252                for(int x=inds.length-elite[sub];x<inds.length;x++)
253                    inds[x] = (Individual)(oldinds[orderedPop[x]].clone());
254                }
255               
256        // optionally force reevaluation
257        unmarkElitesEvaluated(newpop);
258        }
259    }
260
261
262/** A private helper class for implementing multithreaded breeding */
263class SimpleBreederThread implements Runnable
264    {
265    Population newpop;
266    public int[] numinds;
267    public int[] from;
268    public SimpleBreeder me;
269    public EvolutionState state;
270    public int threadnum;
271    public void run()
272        {
273        me.breedPopChunk(newpop,state,numinds,from,threadnum);
274        }
275    }
Note: See TracBrowser for help on using the repository browser.