Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/exchange/InterPopulationExchange.java @ 8614

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

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

File size: 19.0 KB
Line 
1/*
2  Copyright 2006 by Sean Luke and George Mason University
3  Licensed under the Academic Free License version 3.0
4  See the file "LICENSE" for more information
5*/
6
7
8package ec.exchange;
9import ec.*;
10import ec.util.*;
11import java.io.*;
12
13/*
14 * InterPopulationExchange.java
15 *
16 * Created Sat Feb 10 13:44:11 EST 2001
17 * By: Liviu Panait
18 */
19
20/**
21 * InterPopulationExchange is an Exchanger which implements a simple exchanger
22 * between subpopulations. IterPopulationExchange uses an arbitrary graph topology
23 * for migrating individuals from subpopulations. The assumption is that all
24 * subpopulations have the same representation and same task to solve, otherwise
25 * the exchange between subpopulations does not make much sense.
26
27 * <p>InterPopulationExchange has a topology which is similar to the one used by
28 * IslandExchange.  Every few generations, a subpopulation will send some number
29 * of individuals to other subpopulations.  Since all subpopulations evolve at
30 * the same generational speed, this is a synchronous procedure (IslandExchange
31 * instead is asynchronous by default, though you can change it to synchronous).
32 
33 * <p>Individuals are sent from a subpopulation prior to breeding.  They are stored
34 * in a waiting area until after all subpopulations have bred; thereafter they are
35 * added into the new subpopulation.  This means that the subpopulation order doesn't
36 * matter.  Also note that it means that some individuals will be created during breeding,
37 * and immediately killed to make way for the migrants.  A little wasteful, we know,
38 * but it's simpler that way.
39 
40 <p><b>Parameters</b><br>
41 <table>
42 <tr><td valign=top><tt><i>base</i>.chatty</tt><br>
43 <font size=-1>boolean, default = true</font></td>
44 <td valign=top> Should we be verbose or silent about our exchanges?
45 </td></tr>
46 </table>
47 <p><i>Note:</i> For each subpopulation in your population, there <b>must</b> be
48 one exch.subpop... declaration set.
49 <table>
50 <tr><td valign=top><tt><i>base</i>.subpop.<i>n</i>.select</tt><br>
51 <font size=-1>classname, inherits and != ec.SelectionMethod</font></td>
52 <td valign=top> The selection method used by subpopulation #n for picking
53 migrants to emigrate to other subpopulations.  If not set, uses the default parameter below.
54 </td></tr>
55 <tr><td valign=top><tt><i>base</i>.select</tt><br>
56 <font size=-1>classname, inherits and != ec.SelectionMethod</font></td>
57 <td valign=top>
58 <i>server</i>: Default parameter: the selection method used by a given subpopulation for picking
59 migrants to emigrate to other subpopulations.
60 </td></tr>
61 <tr><td valign=top><tt><i>base</i>.subpop.<i>n</i>.select-to-die</tt><br>
62 <font size=-1>classname, inherits and != ec.SelectionMethod (Default is random selection)</font></td>
63 <td valign=top> The selection method used by subpopulation #n for picking
64 individuals to be replaced by migrants.  If not set, uses the default parameter below.
65 </td></tr>
66 <tr><td valign=top><tt><i>base</i>.select-to-die</tt><br>
67 <font size=-1>classname, inherits and != ec.SelectionMethod (Default is random selection)</font></td>
68 <td valign=top>
69 <i>server</i>: Default parameter: the selection method used by a given subpopulation for picking
70 individuals to be replaced by migrants.
71 </td></tr>
72 <tr><td valign=top><tt><i>base</i>.subpop.<i>n</i>.mod</tt><br>
73 <font size=-1>int >= 1</font></td>
74 <td valign=top> The number of generations that subpopulation #n waits between
75 sending emigrants.  If not set, uses the default parameter below.
76 </td></tr>
77 <tr><td valign=top><tt><i>base</i>.mod</tt><br>
78 <font size=-1>int >= 1</font></td>
79 <td valign=top>
80 <i>server</i>: Default parameter: the number of generations that a given subpopulation waits between
81 sending emigrants.
82 </td></tr>
83 <tr><td valign=top><tt><i>base</i>.subpop.<i>n</i>.start</tt><br>
84 <font size=-1>int >= 0</font></td>
85 <td valign=top> The generation when subpopulation #n begins sending emigrants.  If not set, uses the default parameter below.
86 </td></tr>
87 <tr><td valign=top><tt><i>base</i>.start</tt><br>
88 <font size=-1>int >= 0</font></td>
89 <td valign=top>
90 <i>server</i>: Default parameter: the generation when a given subpopulation begins sending emigrants.
91 </td></tr>
92 <tr><td valign=top><tt><i>base</i>.subpop.<i>n</i>.size</tt><br>
93 <font size=-1>int >= 0</font></td>
94 <td valign=top> The number of emigrants sent at one time by generation #n.  If not set, uses the default parameter below.
95 </td></tr>
96 <tr><td valign=top><tt><i>base</i>.subpop.<i>n</i>.num-dest</tt><br>
97 <font size=-1>int >= 0</font></td>
98 <td valign=top> The number of destination subpopulations for this subpopulation.
99 </td></tr>
100 <tr><td valign=top><tt><i>base</i>.subpop.<i>n</i>.dest.<i>m</i></tt><br>
101 <font size=-1>int >= 0</font></td>
102 <td valign=top> Subpopulation #n's destination #m is this subpopulation.
103 </td></tr>
104 </table>
105 
106 <p><b>Parameter bases</b><br>
107 <table>
108 <tr><td valign=top><tt><i>base</i>.subpop.<i>n</i>.select</tt><br>
109 <td>selection method for subpopulation #n's migrants</td></tr>
110 </table>
111
112 * 
113 * @author Liviu Panait & Sean Luke
114 * @version 2.0
115 */
116
117
118public class InterPopulationExchange extends Exchanger
119    {
120    // static inner classes don't need SerialVersionUIDs
121    static class IPEInformation implements Serializable
122        {
123        // the selection method
124        SelectionMethod immigrantsSelectionMethod;
125
126        // the selection method
127        SelectionMethod indsToDieSelectionMethod;
128
129        // the number of destination subpopulations
130        int numDest;
131
132        // the subpopulations where individuals need to be sent
133        int[] destinations;
134
135        // the modulo
136        int modulo;
137
138        // the start (offset)
139        int offset;
140
141        // the size
142        int size;
143        }
144
145
146    /** The subpopulation delimiter */
147    public static final String P_SUBPOP = "subpop";
148
149    /** The parameter for the modulo (how many generations should pass between consecutive sendings of individuals */
150    public static final String P_MODULO = "mod";
151
152    /** The number of emigrants to be sent */
153    public static final String P_SIZE = "size";
154
155    /** How many generations to pass at the beginning of the evolution before the first
156        emigration from the current subpopulation */
157    public static final String P_OFFSET = "start";
158
159    /** The number of destinations from current island */
160    public static final String P_DEST_FOR_SUBPOP = "num-dest";
161
162    /** The prefix for destinations */
163    public static final String P_DEST = "dest";
164
165    /** The selection method for sending individuals to other islands */
166    public static final String P_SELECT_METHOD = "select";
167
168    /** The selection method for deciding individuals to be replaced by immigrants */
169    public static final String P_SELECT_TO_DIE_METHOD = "select-to-die";
170   
171    /** Whether or not we're chatty */
172    public static final String P_CHATTY = "chatty";
173
174    /** My parameter base -- I need to keep this in order to help the server
175        reinitialize contacts */
176    // SERIALIZE
177    public Parameter base;
178   
179    IPEInformation[] exchangeInformation;
180
181    //  storage for the incoming immigrants: 2 sizes:
182    //    the subpopulation and the index of the emigrant
183    // this is virtually the array of mailboxes
184    Individual[][] immigrants;
185
186    // the number of immigrants in the storage for each of the subpopulations
187    int[] nImmigrants;
188
189    int nrSources;
190   
191    public boolean chatty;
192
193    // sets up the Island Exchanger
194    public void setup( final EvolutionState state, final Parameter _base )
195        {
196        base = _base;
197
198        Parameter p_numsubpops = new Parameter( ec.Initializer.P_POP ).push( ec.Population.P_SIZE );
199        int numsubpops = state.parameters.getInt(p_numsubpops,null,1);
200        if ( numsubpops == 0 )
201            {
202            // later on, Population will complain with this fatally, so don't
203            // exit here, just deal with it and assume that you'll soon be shut
204            // down
205            }
206
207        // how many individuals (maximally) would each of the mailboxes have to hold
208        int[] incoming = new int[ numsubpops ];
209
210        // allocate some of the arrays
211        exchangeInformation = new IPEInformation[ numsubpops ];
212        for( int i = 0 ; i < numsubpops ; i++ )
213            exchangeInformation[i] = new IPEInformation();
214        nImmigrants = new int[ numsubpops ];
215
216        Parameter p;
217
218        Parameter localBase = base.push( P_SUBPOP );
219
220        chatty = state.parameters.getBoolean(base.push(P_CHATTY), null, true);
221
222        for( int i = 0 ; i < numsubpops ; i++ )
223            {
224
225            // update the parameter for the new context
226            p = localBase.push( "" + i );
227
228            // read the selection method
229            exchangeInformation[i].immigrantsSelectionMethod = (SelectionMethod)
230                state.parameters.getInstanceForParameter( p.push( P_SELECT_METHOD ), base.push(P_SELECT_METHOD), ec.SelectionMethod.class );
231            if( exchangeInformation[i].immigrantsSelectionMethod == null )
232                state.output.fatal( "Invalid parameter.",  p.push( P_SELECT_METHOD ), base.push(P_SELECT_METHOD) );
233            exchangeInformation[i].immigrantsSelectionMethod.setup( state, p.push(P_SELECT_METHOD) );
234
235            // read the selection method
236            if( state.parameters.exists( p.push( P_SELECT_TO_DIE_METHOD ), base.push(P_SELECT_TO_DIE_METHOD ) ) )
237                exchangeInformation[i].indsToDieSelectionMethod = (SelectionMethod)
238                    state.parameters.getInstanceForParameter( p.push( P_SELECT_TO_DIE_METHOD ), base.push( P_SELECT_TO_DIE_METHOD ), ec.SelectionMethod.class );
239            else // use RandomSelection
240                exchangeInformation[i].indsToDieSelectionMethod = new ec.select.RandomSelection();
241            exchangeInformation[i].indsToDieSelectionMethod.setup( state, p.push(P_SELECT_TO_DIE_METHOD));
242
243            // get the modulo
244            exchangeInformation[i].modulo = state.parameters.getInt( p.push( P_MODULO ), base.push(P_MODULO ), 1 );
245            if( exchangeInformation[i].modulo == 0 )
246                state.output.fatal( "Parameter not found, or it has an incorrect value.", p.push( P_MODULO ), base.push( P_MODULO ) );
247           
248            // get the offset
249            exchangeInformation[i].offset = state.parameters.getInt( p.push( P_OFFSET ), base.push( P_OFFSET ), 0 );
250            if( exchangeInformation[i].offset == -1 )
251                state.output.fatal( "Parameter not found, or it has an incorrect value.", p.push( P_OFFSET ), base.push( P_OFFSET ) );
252           
253            // get the size
254            exchangeInformation[i].size = state.parameters.getInt( p.push( P_SIZE ), base.push( P_SIZE ), 1 );
255            if( exchangeInformation[i].size == 0 )
256                state.output.fatal( "Parameter not found, or it has an incorrect value.", p.push( P_SIZE ), base.push( P_SIZE ) );
257
258            // get the number of destinations
259            exchangeInformation[i].numDest = state.parameters.getInt( p.push( P_DEST_FOR_SUBPOP ), null, 0 );
260            if( exchangeInformation[i].numDest == -1 )
261                state.output.fatal( "Parameter not found, or it has an incorrect value.", p.push( P_DEST_FOR_SUBPOP ) );
262
263            exchangeInformation[i].destinations = new int[ exchangeInformation[i].numDest ];
264            // read the destinations
265            for( int j = 0 ; j < exchangeInformation[i].numDest ; j++ )
266                {
267                exchangeInformation[i].destinations[j] =
268                    state.parameters.getInt( p.push( P_DEST ).push( "" + j ), null, 0 );
269                if( exchangeInformation[i].destinations[j] == -1 ||
270                    exchangeInformation[i].destinations[j] >= numsubpops )
271                    state.output.fatal( "Parameter not found, or it has an incorrect value.", p.push( P_DEST ).push( "" + j ) );
272                // update the maximum number of incoming individuals for the destination island
273                incoming[ exchangeInformation[i].destinations[j] ] += exchangeInformation[i].size;
274                }
275
276            }
277           
278        // calculate the maximum number of incoming individuals to be stored in the mailbox
279        int max = -1;
280
281        for( int i = 0 ; i < incoming.length ; i++ )
282            if( max == - 1 || max < incoming[i] )
283                max = incoming[i];
284
285        // set up the mailboxes
286        immigrants = new Individual[ numsubpops ][ max ];
287
288        }   
289
290
291    /**
292       Initializes contacts with other processes, if that's what you're doing.
293       Called at the beginning of an evolutionary run, before a population is set up.
294       It doesn't do anything, as this exchanger works on only 1 computer.
295    */
296    public void initializeContacts(EvolutionState state)
297        {
298        }
299
300    /**
301       Initializes contacts with other processes, if that's what you're doing.  Called after restarting from a checkpoint.
302       It doesn't do anything, as this exchanger works on only 1 computer.
303    */
304    public void reinitializeContacts(EvolutionState state)
305        {
306        }
307
308
309
310    public Population preBreedingExchangePopulation(EvolutionState state)
311        {
312        // exchange individuals between subpopulations
313        // BUT ONLY if the modulo and offset are appropriate for this
314        // generation (state.generation)
315        // I am responsible for returning a population.  This could
316        // be a new population that I created fresh, or I could modify
317        // the existing population and return that.
318
319        // for each of the islands that sends individuals
320        for( int i = 0 ; i < exchangeInformation.length ; i++ )
321            {
322
323            // else, check whether the emigrants need to be sent
324            if( ( state.generation >= exchangeInformation[i].offset ) &&
325                    ( ( exchangeInformation[i].modulo == 0 ) ||
326                    ( ( ( state.generation - exchangeInformation[i].offset ) % exchangeInformation[i].modulo ) == 0 ) ) )
327                {
328
329                // send the individuals!!!!
330
331                // for each of the islands where we have to send individuals
332                for( int x = 0 ; x < exchangeInformation[i].numDest ; x++ )
333                    {
334
335                    if (chatty) state.output.message( "Sending the emigrants from subpopulation " +
336                        i + " to subpopulation " +
337                        exchangeInformation[i].destinations[x] );
338
339                    // select "size" individuals and send then to the destination as emigrants
340                    exchangeInformation[i].immigrantsSelectionMethod.prepareToProduce( state, i, 0 );
341                    for( int y = 0 ; y < exchangeInformation[i].size ; y++ ) // send all necesary individuals
342                        {
343                        // get the index of the immigrant
344                        int index = exchangeInformation[i].immigrantsSelectionMethod.produce( i, state, 0 );
345                        // copy the individual to the mailbox of the destination subpopulation
346                        immigrants[ exchangeInformation[i].destinations[x] ]
347                            [ nImmigrants[ exchangeInformation[i].destinations[x] ] ] =
348                            state.population.subpops[ i ].individuals[ index ];
349                        // increment the counter with the number of individuals in the mailbox
350                        nImmigrants[ exchangeInformation[i].destinations[x] ]++;
351                        }
352                    exchangeInformation[i].immigrantsSelectionMethod.finishProducing( state, i, 0 ); // end the selection step
353                    }
354                }
355            }
356
357        return state.population;
358
359        }
360
361
362    public Population postBreedingExchangePopulation(EvolutionState state)
363        {
364        // receiving individuals from other islands
365        // same situation here of course.
366
367        for( int x = 0 ; x < nImmigrants.length ; x++ )
368            {
369
370            if( nImmigrants[x] > 0 && chatty )
371                {
372                state.output.message( "Immigrating " +  nImmigrants[x] +
373                    " individuals from mailbox for subpopulation " + x );
374                }
375               
376            int len = state.population.subpops[x].individuals.length;
377            // double check that we won't go into an infinite loop!
378            if ( nImmigrants[x] >= state.population.subpops[x].individuals.length )
379                state.output.fatal("Number of immigrants ("+nImmigrants[x] +
380                    ") is larger than subpopulation #" + x + "'s size (" +
381                    len +").  This would cause an infinite loop in the selection-to-die procedure.");
382
383            boolean[] selected = new boolean[ len ];
384            int[] indeces = new int[ nImmigrants[x] ];
385            for( int i = 0 ; i < selected.length ; i++ )
386                selected[i] = false;
387            exchangeInformation[x].indsToDieSelectionMethod.prepareToProduce( state, x, 0 );
388            for( int i = 0 ; i < nImmigrants[x] ; i++ )
389                {
390                do {
391                    indeces[i] = exchangeInformation[x].indsToDieSelectionMethod.produce( x, state, 0 );
392                    } while( selected[indeces[i]] );
393                selected[indeces[i]] = true;
394                }
395            exchangeInformation[x].indsToDieSelectionMethod.finishProducing( state, x, 0 );
396
397            for( int y = 0 ; y < nImmigrants[x] ; y++ )
398                {
399
400                // read the individual
401                state.population.subpops[x].individuals[ indeces[y] ] = immigrants[x][y];
402
403                // reset the evaluated flag (the individuals are not evaluated in the current island */
404                state.population.subpops[x].individuals[ indeces[y] ].evaluated = false;
405
406                }
407
408            // reset the number of immigrants in the mailbox for the current subpopulation
409            // this doesn't need another synchronization, because the thread is already synchronized
410            nImmigrants[x] = 0;
411            }
412
413        return state.population;
414
415        }
416
417    /** Called after preBreedingExchangePopulation(...) to evaluate whether or not
418        the exchanger wishes the run to shut down (with ec.EvolutionState.R_FAILURE).
419        This would happen for two reasons.  First, another process might have found
420        an ideal individual and the global run is now over.  Second, some network
421        or operating system error may have occurred and the system needs to be shut
422        down gracefully.
423        This function does not return a String as soon as it wants to exit (another island found
424        the perfect individual, or couldn't connect to the server). Instead, it sets a flag, called
425        message, to remember next time to exit. This is due to a need for a graceful
426        shutdown, where checkpoints are working properly and save all needed information. */
427    public String runComplete(EvolutionState state)
428        {
429        return null;
430        }
431
432    /** Closes contacts with other processes, if that's what you're doing.  Called at the end of an evolutionary run. result is either ec.EvolutionState.R_SUCCESS or ec.EvolutionState.R_FAILURE, indicating whether or not an ideal individual was found. */
433    public void closeContacts(EvolutionState state, int result)
434        {
435        }
436
437    }
Note: See TracBrowser for help on using the repository browser.