Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OKBJavaConnector/ECJClient/src/ec/eval/Slave.java @ 12147

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

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

File size: 29.1 KB
RevLine 
[6152]1/*
2  Copyright 2006 by Sean Paus, 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
8/*
9 * Created on Oct 8, 2004
10 */
11package ec.eval;
12
13import java.io.DataInputStream;
14import java.io.DataOutputStream;
15import java.io.File;
16import java.io.FileNotFoundException;
17import java.io.IOException;
18import java.io.InputStream;
19import java.io.OutputStream;
20import java.net.ConnectException;
21import java.net.Socket;
22import java.net.UnknownHostException;
23
24import ec.*;
25import ec.coevolve.GroupedProblemForm;
26import ec.simple.SimpleProblemForm;
27import ec.simple.SimpleEvolutionState;
28import ec.util.*;
29
30/**
31 * Slave.java
32 *
33 
34 <p>Slave is the main entry point for a slave evaluation process.  The slave works with a master process,
35 receiving individuals from the master, evaluating them, and reporting the results back to the master, thus
36 enabling distributed evolution. 
37 
38 <p>Slave replicates most of the functionality of
39 the ec.Evolve class, for example in terms of parameters and checkpointing.  This is mostly because it needs
40 to bootstrap and set up the EvolutionState in much the same way that ec.Evolve does.  Additionally, depending
41 on settings below, the Slave may act like a mini-evolver on the individuals it receives from the master.
42 
43 <p>Like ec.Evolve, Slave is run with like this:
44 
45 <p><tt>java ec.eval.Slave -file </tt><i>parameter_file [</i><tt>-p </tt><i>parameter=value]*</i>
46 
47 <p>This starts a new slave, using the parameter file <i>parameter_file</i>.
48 The user can provide optional overriding parameters on the command-line with the <tt>-p</tt> option.
49 
50 <p>Slaves need to know some things in order to run: the master's IP address and socket port number,
51 whether to do compression, and whether or not to return individuals or just fitnesses.  Unfortunately,
52 Sun's CompressedInputStream/CompressedOutputStream is broken (it doesn't allow partial flushes, which
53 is critical for doing compressed network streams).  In order to do compression, you need to download the
54 JZLIB library from the ECJ website or from http://www.jcraft.com/jzlib/  .  ECJ will detect and use it
55 automatically.
56 
57 <p>Slaves presently always run in single-threaded mode and receive their random number generator seed
58 from the master.  Thus they ignore any seed parameters given to them.
59 
60 <p>Slaves run in one of three modes:
61 
62 <ul>
63 <p><li>"Regular" mode, which does a loop where it receives N individuals, evaluates them, and
64 returns either the individuals or their new fitnesses.
65 <p><li>"Regular Coevolutionary" mode, which does a loop where it receives N individuals to assess together in
66 a single coevolutionary evaluation, evaluates them, and returns either the individuals or their new fitnesses
67 (or only some fitnesses if only some are requested).
68 <p><li>"Evolve" mode, which does a loop where it receives
69 N individuals, evaluates them, and if there's some more time left, does a little evolution on those individuals as
70 if they were a population, then when the time is up, the current individuals in the population are returned in lieu
71 of the original individuals.  In this second form, individuals MUST be returned, not fitnesses.  This mode is not
72 available if you're doing coevolution.
73 </ul>
74 
75 <p><b>Parameters</b><br>
76 <table>
77 
78 <tr><td valign=top><tt>eval.slave-name</tt><br>
79 <font size=-1> String </font></td>
80 <td valign=top>(the slave's name, only for debugging purposes.  If not specified, the slave makes one up.)</td></tr>
81
82 <tr><td valign=top><tt>eval.master.host</tt><br>
83 <font size=-1> String </font></td>
84 <td valign=top>(the IP Address of the master.)</td></tr>
85
86 <tr><td valign=top><tt>eval.master.port</tt><br>
87 <font size=-1> integer &gt;= 1024 </font></td>
88 <td valign=top>(the socket port number of the master.)</td></tr>
89
90 <tr><td valign=top><tt>eval.compression</tt><br>
91 <font size=-1> bool = <tt>true</tt> or <tt>false</tt> (default) </font></td>
92 <td valign=top>(should we use compressed streams in communicating with the master?)</td></tr>
93
94 <tr><td valign=top><tt>eval.run-evolve</tt><br>
95 <font size=-1> bool = <tt>true</tt> or <tt>false</tt> (default) </font></td>
96 <td valign=top>(should we immediately evaluate the individuals and return them (or their fitnesses), or if we have extra time (defined by eval.runtime),
97 should we do a little evolution on our individuals first?)</td></tr>
98
99 <tr><td valign=top><tt>eval.runtime</tt><br>
100 <font size=-1> integer &gt; 0 </font></td>
101 <td valign=top>(if eval.run-evolve is true, how long (in milliseconds wall-clock time) should we allow the individuals to evolve?)</td></tr>
102
103 <tr><td valign=top><tt>eval.return-inds</tt><br>
104 <font size=-1> bool = <tt>true</tt> or <tt>false</tt> (default) </font></td>
105 <td valign=top>(should we return whole individuals or (if false) just the fitnesses of the individuals?  This must be TRUE if eval.run-evolve is true.)</td></tr>
106
107 <!--
108 <tr><td valign=top><tt>nostore</tt><br>
109 <font size=-1> bool = <tt>true</tt> or <tt>false</tt> (default)</font></td>
110 <td valign=top>(should the ec.util.Output facility <i>not</i> store announcements in memory?)</td></tr>
111
112 <tr><td valign=top><tt>flush</tt><br>
113 <font size=-1> bool = <tt>true</tt> or <tt>false</tt> (default)</font></td>
114 <td valign=top>(should I flush all output as soon as it's printed (useful for debugging when an exception occurs))</td></tr>
115 -->
116
117 <tr><td valign=top><tt>state</tt><br>
118 <font size=-1>classname, inherits and != ec.EvolutionState</font></td>
119 <td valign=top>(the EvolutionState object class)</td></tr>
120
121 <tr><td valign=top><tt>print-accessed-params</tt><br>
122 <font size=-1>bool = <tt>true</tt> or <tt>false</tt> (default)</td>
123 <td valign=top>(at the end of a run, do we print out a list of all the parameters requested during the run?)</td></tr>
124
125 <tr><td valign=top><tt>print-used-params</tt><br>
126 <font size=-1>bool = <tt>true</tt> or <tt>false</tt> (default)</td>
127 <td valign=top>(at the end of a run, do we print out a list of all the parameters actually <i>used</i> during the run?)</td></tr>
128
129 <tr><td valign=top><tt>print-unaccessed-params</tt><br>
130 <font size=-1>bool = <tt>true</tt> or <tt>false</tt> (default)</td>
131 <td valign=top>(at the end of a run, do we print out a list of all the parameters NOT requested during the run?)</td></tr>
132
133 <tr><td valign=top><tt>print-unused-params</tt><br>
134 <font size=-1>bool = <tt>true</tt> or <tt>false</tt> (default)</td>
135 <td valign=top>(at the end of a run, do we print out a list of all the parameters NOT actually used during the run?)</td></tr>
136
137 <tr><td valign=top><tt>print-all-params</tt><br>
138 <font size=-1>bool = <tt>true</tt> or <tt>false</tt> (default)</td>
139 <td valign=top>(at the end of a run, do we print out a list of all the parameters stored in the parameter database?)</td></tr>
140
141 </table>
142 
143 *
144 * @author Liviu Panait, Sean Paus, Keith Sullivan, and Sean Luke
145 */
146 
147 
148 
149public class Slave
150    {
151    public final static String P_PRINTACCESSEDPARAMETERS = "print-accessed-params";
152       
153    public final static String P_PRINTUSEDPARAMETERS = "print-used-params";
154       
155    public final static String P_PRINTALLPARAMETERS = "print-all-params";
156       
157    public final static String P_PRINTUNUSEDPARAMETERS = "print-unused-params";
158       
159    public final static String P_PRINTUNACCESSEDPARAMETERS = "print-unaccessed-params";
160       
161    public final static String P_EVALSLAVENAME = "eval.slave-name";
162       
163    public final static String P_EVALMASTERHOST = "eval.master.host";
164       
165    public final static String P_EVALMASTERPORT = "eval.master.port";
166       
167    public final static String P_EVALCOMPRESSION = "eval.compression";
168   
169    public final static String P_RETURNINDIVIDUALS = "eval.return-inds";
170       
171    public static final String P_SUBPOP = "pop.subpop";
172   
173    public static final byte V_NOTHING = 0;
174    public static final byte V_INDIVIDUAL = 1;
175    public static final byte V_FITNESS = 2;
176       
177    public static final byte V_SHUTDOWN = 0;
178    public static final byte V_EVALUATESIMPLE = 1;
179    public static final byte V_EVALUATEGROUPED = 2;
180//    public static final byte V_CHECKPOINT = 3;
181       
182    /* The argument indicating that we're starting up from a checkpoint file. */
183//    public static final String A_CHECKPOINT = "-checkpoint";
184       
185    /** The argument indicating that we're starting fresh from a new parameter file. */
186    public static final String A_FILE = "-file";
187       
188    /* flush announcements parameter */
189    // public static final String P_FLUSH = "flush";
190       
191    /* nostore parameter */
192    // public static final String P_STORE = "store";
193       
194    /** state parameter */
195    public static final String P_STATE = "state";
196       
197    /** Time to run evolution on the slaves in seconds */
198    public static final String P_RUNTIME = "eval.runtime";
199    public static int runTime=0;
200       
201    /** Should slave run its own evolutionary process? */
202    public static final String P_RUNEVOLVE = "eval.run-evolve";
203    public static boolean runEvolve=false;
204       
205    /** How long we sleep in between attempts to connect to the master (in milliseconds). */
206    public static final int SLEEP_TIME = 100;
207       
208    public static void main(String[] args)
209        {
210        EvolutionState state = null;
211        ParameterDatabase parameters = null;
212        Output output = null;
213
214        boolean store;
215        int x;
216               
217        // 0. find the parameter database
218        for (x = 0; x < args.length - 1; x++)
219            if (args[x].equals(A_FILE))
220                {
221                try
222                    {
223                    parameters = new ParameterDatabase(
224                        // not available in jdk1.1: new File(args[x+1]).getAbsoluteFile(),
225                        new File(new File(args[x + 1]).getAbsolutePath()),
226                        args);
227                                               
228                    // add the fact that I am a slave:      eval.i-am-slave = true
229                    // this is used only by the Evaluator to determine whether to use the MasterProblem
230                    parameters.set(new Parameter(ec.EvolutionState.P_EVALUATOR).push(ec.Evaluator.P_IAMSLAVE), "true");
231                    break;
232                    }
233                catch(FileNotFoundException e)
234                    {
235                    Output.initialError(
236                        "A File Not Found Exception was generated upon" +
237                        "reading the parameter file \"" + args[x+1] +
238                        "\".\nHere it is:\n" + e); }
239                catch(IOException e)
240                    {
241                    Output.initialError(
242                        "An IO Exception was generated upon reading the" +
243                        "parameter file \"" + args[x+1] +
244                        "\".\nHere it is:\n" + e); }
245                }
246        if (parameters == null)
247            Output.initialError("No parameter file was specified." );
248               
249        // 5. Determine whether or not to return entire Individuals or just Fitnesses
250        //    (plus whether or not the Individual has been evaluated).
251       
252        boolean returnIndividuals = parameters.getBoolean(new Parameter(P_RETURNINDIVIDUALS),null,false);
253               
254               
255        // 6. Open a server socket and listen for requests
256        String slaveName = parameters.getString(
257            new Parameter(P_EVALSLAVENAME),null);
258               
259        String masterHost = parameters.getString(
260            new Parameter(P_EVALMASTERHOST),null );
261        int masterPort = parameters.getInt(
262            new Parameter(P_EVALMASTERPORT),null);
263        boolean useCompression = parameters.getBoolean(new Parameter(P_EVALCOMPRESSION),null,false);
264               
265        runTime = parameters.getInt(new Parameter(P_RUNTIME), null, 0);
266               
267        runEvolve = parameters.getBoolean(new Parameter(P_RUNEVOLVE),null,false);
268       
269        if (runEvolve && !returnIndividuals)
270            {
271            Output.initialError("You have the slave running in 'evolve' mode, but it's only returning fitnesses to the master, not whole individuals.  This is almost certainly wrong.",
272                new Parameter(P_RUNEVOLVE), new Parameter(P_RETURNINDIVIDUALS));
273            }
274       
275        Output.initialMessage("ECJ Slave");
276        if (runEvolve) Output.initialMessage("Running in Evolve mode, evolve time is " + runTime + " milliseconds");
277        if (returnIndividuals) Output.initialMessage("Whole individuals will be returned");
278        else Output.initialMessage("Only fitnesses will be returned");
279       
280       
281        // Continue to serve new masters until killed.
282        while (true)
283            {
284            try
285                {
286                Socket socket;
287                long connectAttemptCount = 0;
288                Output.initialMessage("Connecting to master at "+masterHost+":"+masterPort);
289                while (true)
290                    {
291                    try
292                        {
293                        socket = new Socket(masterHost, masterPort);
294                        break;
295                        }
296                    catch (ConnectException e)   // it's not up yet...
297                        {
298                        connectAttemptCount++;
299                        try
300                            {
301                            Thread.sleep(SLEEP_TIME);
302                            }
303                        catch( InterruptedException f )
304                            {
305                            }
306                        }
307                    }
308                Output.initialMessage("Connected to master after " + (connectAttemptCount * SLEEP_TIME) + " ms");
309                               
310                DataInputStream dataIn = null;
311                DataOutputStream dataOut = null;
312
313                try
314                    {
315                    InputStream tmpIn = socket.getInputStream();
316                    OutputStream tmpOut = socket.getOutputStream();
317                    if (useCompression)
318                        {
319                        //Output.initialError("JDK 1.5 has broken compression.  For now, you must set eval.compression=false");
320                        /*
321                          tmpIn = new CompressingInputStream(tmpIn);
322                          tmpOut = new CompressingOutputStream(tmpOut);
323                        */
324                        tmpIn = Output.makeCompressingInputStream(tmpIn);
325                        tmpOut = Output.makeCompressingOutputStream(tmpOut);
326                        if (tmpIn == null || tmpOut == null)
327                            Output.initialError("You do not appear to have JZLib installed on your system, and so must set eval.compression=false.  " +
328                                "To get JZLib, download from the ECJ website or from http://www.jcraft.com/jzlib/");
329                        }
330                                               
331                    dataIn = new DataInputStream(tmpIn);
332                    dataOut = new DataOutputStream(tmpOut);
333                    }
334                catch (IOException e)
335                    {
336                    Output.initialError("Unable to open input stream from socket:\n"+e);
337                    }
338                               
339                // specify the slaveName
340                if (slaveName==null)
341                    {
342                    slaveName = socket.getLocalAddress().toString() + "/" + System.currentTimeMillis();
343                    Output.initialMessage("No slave name specified.  Using: " + slaveName);
344                    }
345                               
346                dataOut.writeUTF(slaveName);
347                dataOut.flush();
348
349                // 1. create the output
350                // store = parameters.getBoolean(new Parameter(P_STORE), null, false);
351               
352                if (output != null) output.close();
353                output = new Output(true);
354                //output.setFlush(
355                //    parameters.getBoolean(new Parameter(P_FLUSH),null,false));
356               
357                // stdout is always log #0. stderr is always log #1.
358                // stderr accepts announcements, and both are fully verbose
359                // by default.
360                output.addLog(ec.util.Log.D_STDOUT, false);
361                output.addLog(ec.util.Log.D_STDERR, true);
362
363                output.systemMessage(Version.message());
364
365
366                // 2. set up thread values
367
368/*
369  int breedthreads = parameters.getInt(
370  new Parameter(Evolve.P_BREEDTHREADS),null,1);
371
372  if (breedthreads < 1)
373  output.fatal("Number of breeding threads should be an integer >0.",
374  new Parameter(Evolve.P_BREEDTHREADS),null);
375
376
377  int evalthreads = parameters.getInt(
378  new Parameter(Evolve.P_EVALTHREADS),null,1);
379
380  if (evalthreads < 1)
381  output.fatal("Number of eval threads should be an integer >0.",
382  new Parameter(Evolve.P_EVALTHREADS),null);
383*/
384
385                int breedthreads = Evolve.determineThreads(output, parameters, new Parameter(Evolve.P_BREEDTHREADS));
386                int evalthreads = Evolve.determineThreads(output, parameters, new Parameter(Evolve.P_EVALTHREADS));
387
388                // Note that either breedthreads or evalthreads (or both) may be 'auto'.  We don't warn about this because
389                // the user isn't providing the thread seeds.
390               
391
392                // 3. create the Mersenne Twister random number generators,
393                // one per thread
394
395                MersenneTwisterFast[] random = new MersenneTwisterFast[breedthreads > evalthreads ?
396                    breedthreads : evalthreads];
397       
398                int seed = dataIn.readInt();
399                for(int i = 0; i < random.length; i++)
400                    random[i] = Evolve.primeGenerator(new MersenneTwisterFast(seed++));  // we prime the generator to be more sure of randomness.
401
402                // 4. Set up the evolution state
403               
404                // what evolution state to use?
405                state = (EvolutionState)
406                    parameters.getInstanceForParameter(new Parameter(P_STATE),null,
407                        EvolutionState.class);
408                state.parameters = new ParameterDatabase();
409                state.parameters.addParent(parameters);
410                state.random = random;
411                state.output = output;
412                state.evalthreads = evalthreads;
413                state.breedthreads = breedthreads;
414       
415                state.setup(state, null);
416                state.population = state.initializer.setupPopulation(state, 0);
417               
418
419                // Is this a Simple or Grouped ProblemForm?
420                int problemType;
421                try
422                    {
423                    while (true)
424                        {
425                        EvolutionState newState = state;
426                       
427                        if (runEvolve)
428                            {
429                            // Construct and use a new EvolutionState.  This will be inefficient the first time around
430                            // as we've set up TWO EvolutionStates in a row with no good reason.
431                            ParameterDatabase coverDatabase = new ParameterDatabase();  // protect the underlying one
432                            coverDatabase.addParent(state.parameters);
433                            newState = (EvolutionState) Evolve.initialize(coverDatabase, 0);
434                            newState.startFresh();
435                            newState.output.message("Replacing random number generators, ignore above seed message");
436                            newState.random = state.random;  // continue with RNG
437                            }
438                       
439                        // 0 means to shut down
440                        System.err.println("reading next problem");
441                        problemType = dataIn.readByte();
442                        System.err.println("Read problem: " + (int)problemType);
443                        switch (problemType)
444                            {
445                            case V_SHUTDOWN:
446                                socket.close();
447                                return;  // we're outa here
448                            case V_EVALUATESIMPLE:
449                                evaluateSimpleProblemForm(newState, returnIndividuals, dataIn, dataOut, args);
450                                break;
451                            case V_EVALUATEGROUPED:
452                                evaluateGroupedProblemForm(newState, returnIndividuals, dataIn, dataOut);
453                                break;
454                            default:
455                                state.output.fatal("Unknown problem form specified: "+problemType);
456                            }
457                        //System.err.println("Done Evaluating Individual");
458                        }
459
460                    } catch (IOException e)   
461                    {
462                    // Since an IOException can happen here if the peer closes the socket
463                    // on it's end, we don't necessarily have to exit.  Maybe we don't
464                    // even need to print a warning, but we'll do so just to indicate
465                    // something happened.
466                    state.output.warning("Unable to read type of evaluation from master.  Maybe the master closed its socket and exited?:\n"+e);
467                    }
468                }
469            catch (UnknownHostException e)
470                {
471                state.output.fatal(e.getMessage());
472                }
473            catch (IOException e)
474                {
475                state.output.fatal("Unable to connect to master:\n" + e);
476                }
477            }
478        }
479           
480    public static void evaluateSimpleProblemForm( EvolutionState state, boolean returnIndividuals,
481        DataInputStream dataIn, DataOutputStream dataOut, String[] args )
482        {
483        ParameterDatabase params=null;
484       
485        // first load the individuals
486        int numInds=1;
487        try
488            {
489            numInds = dataIn.readInt();
490            }
491        catch (IOException e)
492            {
493            state.output.fatal("Unable to read the number of individuals from the master:\n"+e);
494            }
495       
496        // load the subpops
497        int[] subpops = new int[numInds];  // subpops desired by each ind
498        int[] indsPerSubpop = new int[state.population.subpops.length];  // num inds for each subpop
499        for(int i = 0; i < numInds; i++)
500            {
501            try
502                {
503                subpops[i] = dataIn.readInt();
504                if (subpops[i] < 0 || subpops[i] >= state.population.subpops.length)
505                    state.output.fatal("Bad subpop number for individual #" + i + ": " + subpops[i]);
506                indsPerSubpop[subpops[i]]++;
507                }
508            catch (IOException e)
509                {
510                state.output.fatal("Unable to read the subpop number from the master:\n"+e);
511                }
512            }
513       
514               
515        // Read the individual(s) from the stream  and evaluate
516       
517        boolean[] updateFitness = new boolean[numInds];
518        Individual[] inds = new Individual[numInds];
519        try
520            {
521            for (int i=0; i < numInds; i++)
522                {
523                inds[i] = state.population.subpops[subpops[i]].species.newIndividual(state, dataIn);
524                if (!runEvolve)
525                    ((SimpleProblemForm)(state.evaluator.p_problem)).evaluate( state, inds[i], subpops[i], 0 );
526                updateFitness[i] = dataIn.readBoolean();
527                }
528            }
529        catch (IOException e)
530            {
531            state.output.fatal("Unable to read individual from master." + e);
532            }
533       
534       
535        if (runEvolve)
536            {
537            long startTime = System.currentTimeMillis();
538            long endTime=0;
539
540            // Now we need to reset the subpopulations.  They were already set up with the right
541            // classes, Species, etc. in state.setup(), so all we need to do is modify the number
542            // of individuals in each subpopulation.
543       
544            for(int subpop = 0; subpop < state.population.subpops.length; subpop++)
545                {
546                if (state.population.subpops[subpop].individuals.length != indsPerSubpop[subpop])
547                    state.population.subpops[subpop].individuals = new Individual[indsPerSubpop[subpop]];
548                }
549           
550            // Disperse into the population
551            int[] counts = new int[state.population.subpops.length];
552            for(int i =0; i < numInds; i++)
553                state.population.subpops[subpops[i]].individuals[counts[subpops[i]]++] = inds[i];
554           
555            // Evaluate the population until time is up, or the evolution stops
556            int result = state.R_NOTDONE;
557            while (result == state.R_NOTDONE)
558                {
559                result = state.evolve();
560                endTime = System.currentTimeMillis();
561                if ((endTime - startTime) > runTime)
562                    break;
563                }
564               
565            // re-gather from population in the same order
566            counts = new int[state.population.subpops.length];
567            for(int i =0; i < numInds; i++)
568                inds[i] = state.population.subpops[subpops[i]].individuals[counts[subpops[i]]++];
569            state.finish(result);
570            Evolve.cleanup(state);
571            }
572
573
574        //System.err.println("Returning Individuals ");
575        // Return the evaluated individual to the master
576        try
577            {
578            returnIndividualsToMaster(state, inds, updateFitness, dataOut, returnIndividuals);
579            }
580        catch( IOException e ) { state.output.fatal("Caught fatal IOException\n"+e ); }
581        }
582   
583    public static void evaluateGroupedProblemForm( EvolutionState state, boolean returnIndividuals,
584        DataInputStream dataIn, DataOutputStream dataOut )
585        {
586        boolean countVictoriesOnly = false;
587
588        // first load the individuals
589        int numInds = 1;
590        try
591            {
592            countVictoriesOnly = dataIn.readBoolean();
593            numInds = dataIn.readInt();
594            }
595        catch (IOException e)
596            {
597            state.output.fatal("Unable to read the number of individuals from the master:\n"+e);
598            }
599
600        // load the subpops
601        int[] subpops = new int[numInds];  // subpops desired by each ind
602        int[] indsPerSubpop = new int[state.population.subpops.length];  // num inds for each subpop
603        for(int i = 0; i < numInds; i++)
604            {
605            try
606                {
607                subpops[i] = dataIn.readInt();
608                if (subpops[i] < 0 || subpops[i] >= state.population.subpops.length)
609                    state.output.fatal("Bad subpop number for individual #" + i + ": " + subpops[i]);
610                indsPerSubpop[subpops[i]]++;
611                }
612            catch (IOException e)
613                {
614                state.output.fatal("Unable to read the subpop number from the master:\n"+e);
615                }
616            }
617
618        // Read the individuals from the stream
619        Individual inds[] = new Individual[numInds];
620        boolean updateFitness[] = new boolean[numInds];
621        try
622            {
623            for(int i=0;i<inds.length;++i)
624                {
625                inds[i] = state.population.subpops[subpops[i]].species.newIndividual( state, dataIn );
626                updateFitness[i] = dataIn.readBoolean();
627                }
628            }
629        catch (IOException e)
630            {
631            state.output.fatal("Unable to read individual from master.");
632            }
633               
634        // Evaluate the individuals together
635        ((GroupedProblemForm)(state.evaluator.p_problem)).evaluate( state, inds, updateFitness, countVictoriesOnly, subpops, 0 );
636                               
637        try
638            {
639            returnIndividualsToMaster(state, inds, updateFitness, dataOut, returnIndividuals);
640            }
641        catch( IOException e ) { state.output.fatal("Caught fatal IOException\n"+e ); }
642        }
643       
644    private static void returnIndividualsToMaster(EvolutionState state, Individual []inds, boolean[] updateFitness,
645        DataOutputStream dataOut, boolean returnIndividuals) throws IOException
646        {
647        // Return the evaluated individual to the master
648        // just write evaluated and fitness
649        for(int i=0;i<inds.length;i++)
650            {
651            //System.err.println("Returning Individual " + i);
652            //System.err.println("writing byte: " + ( returnIndividuals ? V_INDIVIDUAL : (updateFitness[i] ? V_FITNESS : V_NOTHING)));
653            dataOut.writeByte(returnIndividuals ? V_INDIVIDUAL : (updateFitness[i] ? V_FITNESS : V_NOTHING));
654            //System.err.println("wrote byte");
655            if (returnIndividuals)
656                {
657//              System.err.println("Writing Individual");
658                inds[i].writeIndividual(state, dataOut);
659//              System.err.println("Wrote Individual");
660                }
661            else if (updateFitness[i])
662                {
663                dataOut.writeBoolean(inds[i].evaluated);
664                inds[i].fitness.writeFitness(state,dataOut);
665                }
666            }
667//      System.err.println("flushing");
668        dataOut.flush();
669//      System.err.println("flushed");
670        }
671    }
Note: See TracBrowser for help on using the repository browser.