Beispiel #1
0
        /// <summary>Loads a ParameterDatabase from checkpoint if "-params" is in the command-line arguments. </summary>
        public static IParameterDatabase LoadParameterDatabase(string paramsFileName)
        {
            if (string.IsNullOrEmpty(paramsFileName))
            {
                Output.InitialError("The parameter file name is null or empty.", false);
                Environment.Exit(1); // This was originally part of the InitialError call in ECJ. But we make Evolve responsible.
            }

            if (!File.Exists(paramsFileName))
            {
                Output.InitialError($"The specified parameter file does not exist: {paramsFileName}", false);
                Environment.Exit(1); // This was originally part of the InitialError call in ECJ. But we make Evolve responsible.
            }

            IParameterDatabase parameters = null;

            try
            {
                if (!string.IsNullOrEmpty(paramsFileName))
                {
                    parameters = new ParameterDatabase(new FileInfo(paramsFileName));
                }
            }
            catch (Exception e)
            {
                Output.InitialError($"Error reading the parameter file \"{paramsFileName}\": {e.Message}", false);
                Environment.Exit(1); // This was originally part of the InitialError call in ECJ. But we make Evolve responsible.
            }
            if (parameters == null)
            {
                Output.InitialError("No parameter file was specified.", false);
                Environment.Exit(1); // This was originally part of the InitialError call in ECJ. But we make Evolve responsible.
            }
            return(parameters);
        }
Beispiel #2
0
        /** Override this method to revise the provided parameter database to reflect the "parameters" specified in the
         *  given meta-individual.  'Run' is the current run number for this individual's evaluation.  */
        public void ModifyParameters(IEvolutionState state, IParameterDatabase database, int run,
                                     Individual metaIndividual)
        {
            if (!(metaIndividual is DoubleVectorIndividual))
            {
                state.Output.Fatal("Meta-individual is not a DoubleVectorIndividual.");
            }
            var individual = (DoubleVectorIndividual)metaIndividual;
            var species    = (FloatVectorSpecies)individual.Species;

            double[] genome = individual.genome;

            IParameter pb = ParamBase.Push(P_PARAM);

            for (int i = 0; i < genome.Length; i++)
            {
                IParameter p     = pb.Push("" + i);
                String     param = state.Parameters.GetString(p, null);
                if (param == null)
                {
                    state.Output.Fatal("Meta parameter number " + i + " missing.", p);
                }
                // load it
                database.SetParameter(new Parameter(param), "" + Map(state, genome, species, i));
            }
        }
Beispiel #3
0
        /// <summary>Loads the number of threads. </summary>
        public static int DetermineThreads(Output output, IParameterDatabase parameters, IParameter threadParameter)
        {
            var thread = 1;
            var tmp_s  = parameters.GetString(threadParameter, null);

            if (tmp_s == null)
            // uh oh
            {
                output.Fatal("Threads number must exist.", threadParameter, null);
            }
            else if (V_THREADS_AUTO.ToUpper().Equals(tmp_s.ToUpper()))
            {
            }
            else
            {
                try
                {
                    thread = parameters.GetInt(threadParameter, null);
                }
                catch (FormatException)
                {
                    output.Fatal("Invalid, non-integer threads value (" + thread + ")", threadParameter, null);
                }
            }
            return(thread);
        }
Beispiel #4
0
        /// <summary>
        /// Initializes an evolutionary run given the parameters and a random seed adjustment (added to each random seed).
        /// The adjustment offers a convenient way to change the seeds of the random number generators each time you
        /// do a new evolutionary run.  You are of course welcome to replace the random number generators after initialize(...)
        /// but before startFresh(...)
        /// </summary>
        public static EvolutionState Initialize(IParameterDatabase parameters, int randomSeedOffset)
        {
            var output = BuildOutput();

            // now continue intialization
            return(Initialize(parameters, randomSeedOffset, output));
        }
Beispiel #5
0
        /// <summary>
        /// Initializes an evolutionary run given the parameters and a random seed adjustment (added to each random seed),
        /// with the Output pre-constructed.
        /// The adjustment offers a convenient way to change the seeds of the random number generators each time you
        /// do a new evolutionary run.  You are of course welcome to replace the random number generators after initialize(...)
        /// but before startFresh(...).
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="randomSeedOffset"></param>
        /// <param name="output"></param>
        /// <returns></returns>
        public static EvolutionState Initialize(IParameterDatabase parameters, int randomSeedOffset, Output output)
        {
            var breedthreads = 1;
            var evalthreads  = 1;

            //bool store;
            //int x;

            // output was already created for us.
            output.SystemMessage(ECVersion.Message());

            // 2. set up thread values

            breedthreads = DetermineThreads(output, parameters, new Parameter(P_BREEDTHREADS));
            evalthreads  = DetermineThreads(output, parameters, new Parameter(P_EVALTHREADS));

            var auto = (V_THREADS_AUTO.ToUpper().Equals(parameters.GetString(new Parameter(P_BREEDTHREADS), null).ToUpper())
                        ||
                        V_THREADS_AUTO.ToUpper().Equals(
                            parameters.GetString(new Parameter(P_EVALTHREADS), null).ToUpper()));
            // at least one thread is automatic.  Seeds may need to be dynamic.

            // 3. create the Mersenne Twister random number generators,
            // one per thread

            var random = new MersenneTwisterFast[1];

            var seedMessage = "Seed: ";

            // Get time in milliseconds
            var time = (int)DateTimeHelper.CurrentTimeMilliseconds;

            var seed = 0;

            seed = DetermineSeed(output, parameters, new Parameter(P_SEED).Push("" + 0),
                                 time + 0, random.Length * randomSeedOffset, auto);

            random[0] = PrimeGenerator(new MersenneTwisterFast(seed));
            // we prime the generator to be more sure of randomness.
            seedMessage = seedMessage + seed + " ";

            // 4.  Start up the evolution

            // what evolution state to use?
            var state = (EvolutionState)parameters.GetInstanceForParameter(new Parameter(P_STATE), null, typeof(IEvolutionState));

            state.Parameters       = parameters;
            state.Random           = random;
            state.Output           = output;
            state.EvalThreads      = evalthreads;
            state.BreedThreads     = breedthreads;
            state.RandomSeedOffset = randomSeedOffset;

            output.SystemMessage($"Threads:  breed/{breedthreads} eval/{evalthreads}");
            output.SystemMessage(seedMessage);

            return(state);
        }
Beispiel #6
0
        // NOTE: We should use the framework's thread pool!
        //public static ThreadPool Pool = new ThreadPool();

        #endregion // Static
        #region Operations

        public static void EvaluateSimpleProblem(IEvolutionState state, bool returnIndividuals,
                                                 BinaryReader dataIn, BinaryWriter dataOut, string[] args)
        {
            IParameterDatabase parameters = null;

            // first load the individuals
            var numInds = 1;

            try
            {
                numInds = dataIn.ReadInt32();
            }
            catch (IOException e)
            {
                state.Output.Fatal("Unable to read the number of individuals from the master:\n" + e);
            }

            // load the subpops
            var subpops       = new int[numInds];                        // subpops desired by each ind
            var indsPerSubpop = new int[state.Population.Subpops.Count]; // num inds for each subpop

            for (var i = 0; i < numInds; i++)
            {
                try
                {
                    subpops[i] = dataIn.ReadInt32();
                    if (subpops[i] < 0 || subpops[i] >= state.Population.Subpops.Count)
                    {
                        state.Output.Fatal("Bad subpop number for individual #" + i + ": " + subpops[i]);
                    }
                    indsPerSubpop[subpops[i]]++;
                }
                catch (IOException e)
                {
                    state.Output.Fatal("Unable to read the subpop number from the master:\n" + e);
                }
            }

            // Read the individual(s) from the stream and evaluate

            // Either evaluate all the individuals once and return them immediately
            // (we'll do so in a steady-state-ish fashion, firing off threads as soon as we read in individuals,
            // and returning them as soon as they come in, albeit in the proper order)
            if (!RunEvolve)
            {
                EvaluateSimpleProblemCore(state, returnIndividuals, dataIn, dataOut, numInds, subpops);
            }
            // OR we will do some evolution.  Here we'll read in ALL the individuals, do some evolution, then
            // write them ALL out, very slightly less efficient
            else // (runEvolve)
            {
                EvolveSimpleProblemCore(state, returnIndividuals, dataIn, dataOut, numInds, subpops, indsPerSubpop);
            }
        }
Beispiel #7
0
        /// <summary>
        /// Initializes an evolutionary run given the parameters and a random seed adjustment (added to each random seed).
        /// The adjustment offers a convenient way to change the seeds of the random number generators each time you
        /// do a new evolutionary run.  You are of course welcome to replace the random number generators after initialize(...)
        /// but before startFresh(...)
        /// </summary>
        public static EvolutionState Initialize(IParameterDatabase parameters, int randomSeedOffset)
        {
            var output = new Output(true);

            // stdout is always log #0.  stderr is always log #1.
            // stderr accepts announcements, and both are fully verbose
            // by default.
            output.AddLog(Log.D_STDOUT, false);
            output.AddLog(Log.D_STDERR, true);

            // now continue intialization
            return(Initialize(parameters, randomSeedOffset, output));
        }
Beispiel #8
0
        /// <summary>
        /// Loads a random generator seed.  First, the seed is loaded from the seedParameter.  If the parameter
        /// is V_SEED_TIME, the seed is set to the currentTime value.  Then the seed is incremented by the offset.
        /// This method is broken out of initialize(...) primarily to share code with ec.eval.MasterProblem.
        /// </summary>
        public static int DetermineSeed(Output output, IParameterDatabase parameters, IParameter seedParameter, long currentTime, int offset, bool auto)
        {
            var seed = 1; // have to initialize to make the compiler happy

            try
            {
                seed = parameters.GetInt(seedParameter, null);
            }
            catch (FormatException)
            {
                output.Fatal("Invalid, non-integer seed value (" + seed + ")", seedParameter, null);
            }
            return(seed + offset);
        }
Beispiel #9
0
        /// <summary>
        /// Loads the number of threads.
        /// </summary>
        public static int DetermineThreads(Output output, IParameterDatabase parameters, IParameter threadParameter)
        {
            var thread = 1;
            var tmp_s  = parameters.GetString(threadParameter, null);

            if (tmp_s == null)
            // uh oh
            {
                output.Fatal("Threads number must exist.", threadParameter, null);
            }
            else if (V_THREADS_AUTO.ToUpper().Equals(tmp_s.ToUpper()))
            {
                var runtime = Process.GetCurrentProcess();
                try
                {
                    return(Environment.ProcessorCount);
                }
                catch (Exception)
                {
                    output.Fatal("Whoa! Problem getting processor count.", threadParameter, null);
                }
            }
            else
            {
                try
                {
                    thread = parameters.GetInt(threadParameter, null);
                    if (thread <= 0)
                    {
                        output.Fatal("Threads value must be > 0", threadParameter, null);
                    }
                }
                catch (FormatException)
                {
                    output.Fatal("Invalid, non-integer threads value (" + thread + ")", threadParameter, null);
                }
            }
            return(thread);
        }
Beispiel #10
0
        /// <summary>
        /// Loads a random generator seed.  First, the seed is loaded from the seedParameter.  If the parameter
        /// is V_SEED_TIME, the seed is set to the currentTime value.  Then the seed is incremented by the offset.
        /// This method is broken out of initialize(...) primarily to share code with ec.eval.MasterProblem.
        /// </summary>
        public static int DetermineSeed(Output output, IParameterDatabase parameters, IParameter seedParameter, long currentTime, int offset, bool auto)
        {
            var seed  = 1; // have to initialize to make the compiler happy
            var tmp_s = parameters.GetString(seedParameter, null);

            if (tmp_s == null && !auto)
            // uh oh
            {
                output.Fatal("Seed must exist.", seedParameter, null);
            }
            //else if (V_SEED_TIME.Equals(tmp_s, StringComparison.InvariantCultureIgnoreCase) || (tmp_s == null && auto))
            else if (tmp_s == null && auto || V_SEED_TIME.Equals(tmp_s, StringComparison.InvariantCultureIgnoreCase)) // BRS : Just flipped
            {
                if (tmp_s == null && auto)                                                                            // BRS : What?
                {
                    output.WarnOnce("Using automatic determination number of threads, but not all seeds are defined."
                                    + "\nThe rest will be defined using the wall clock time.");
                }
                seed = (int)currentTime; // using low-order bits so it's probably okay
                if (seed == 0)
                {
                    output.Fatal("Whoa! This Java version is returning 0 for currentTimeMillis(), which ain't right."
                                 + " This means you can't use '" + V_SEED_TIME + "' as a seed ", seedParameter, null);
                }
            }
            else
            {
                try
                {
                    seed = parameters.GetInt(seedParameter, null);
                }
                catch (FormatException)
                {
                    output.Fatal("Invalid, non-integer seed value (" + seed + ")", seedParameter, null);
                }
            }
            return(seed + offset);
        }
Beispiel #11
0
        /// <summary>
        /// Initializes an evolutionary run given the parameters and a random seed adjustment (added to each random seed),
        /// with the Output pre-constructed.
        /// The adjustment offers a convenient way to change the seeds of the random number generators each time you
        /// do a new evolutionary run.  You are of course welcome to replace the random number generators after initialize(...)
        /// but before startFresh(...).
        /// </summary>
        public static EvolutionState Initialize(IParameterDatabase parameters, int randomSeedOffset, Output output)
        {
            var breedthreads = 1;
            var evalthreads  = 1;

            // Should we muzzle stdout and stderr?

            if (parameters.ParameterExists(new Parameter(P_MUZZLE), null))
            {
                output.Warning("" + new Parameter(P_MUZZLE) + " has been deprecated.  We suggest you use " +
                               new Parameter(P_SILENT) + " or similar newer options.");
            }

            if (parameters.GetBoolean(new Parameter(P_SILENT), null, false) ||
                parameters.GetBoolean(new Parameter(P_MUZZLE), null, false))
            {
                output.GetLog(0).Silent = true;
                output.GetLog(1).Silent = true;
            }

            //bool store;
            int x;

            // output was already created for us.
            output.SystemMessage(ECVersion.Message());

            // 2. set up thread values

            breedthreads = DetermineThreads(output, parameters, new Parameter(P_BREEDTHREADS));
            evalthreads  = DetermineThreads(output, parameters, new Parameter(P_EVALTHREADS));
            var auto = (V_THREADS_AUTO.ToUpper().Equals(
                            parameters.GetString(new Parameter(P_BREEDTHREADS), null).ToUpper())
                        ||
                        V_THREADS_AUTO.ToUpper().Equals(
                            parameters.GetString(new Parameter(P_EVALTHREADS), null).ToUpper()));
            // at least one thread is automatic.  Seeds may need to be dynamic.

            // 3. create the Mersenne Twister random number generators,
            // one per thread

            var random = new IMersenneTwister[breedthreads > evalthreads ? breedthreads : evalthreads];
            var seeds  = new int[random.Length];

            var seedMessage = "Seed: ";

            // Get time in milliseconds
            var time = (int)DateTimeHelper.CurrentTimeMilliseconds;

            for (x = 0; x < random.Length; x++)
            {
                seeds[x] = DetermineSeed(output, parameters, new Parameter(P_SEED).Push("" + x),
                                         time + x, random.Length * randomSeedOffset, auto);

                for (var y = 0; y < x; y++)
                {
                    if (seeds[x] == seeds[y])
                    {
                        output.Fatal(P_SEED + "." + x + " (" + seeds[x] + ") and "
                                     + P_SEED + "." + y + " (" + seeds[y] + ") ought not be the same seed.", null, null);
                    }
                }

                random[x] = PrimeGenerator(new MersenneTwisterFast(seeds[x]));
                // we prime the generator to be more sure of randomness.
                seedMessage = seedMessage + seeds[x] + " ";
            }

            // 4.  Start up the evolution

            // what evolution state to use?
            var state = (EvolutionState)parameters.GetInstanceForParameter(new Parameter(P_STATE), null, typeof(IEvolutionState));

            state.Parameters       = parameters;
            state.Random           = random;
            state.Output           = output;
            state.EvalThreads      = evalthreads;
            state.BreedThreads     = breedthreads;
            state.RandomSeedOffset = randomSeedOffset;

            output.SystemMessage($"Threads:  breed/{breedthreads} eval/{evalthreads}");
            output.SystemMessage(seedMessage);

            return(state);
        }
Beispiel #12
0
        /// <summary>
        /// Loads a ParameterDatabase from checkpoint if "-params" is in the command-line arguments.
        /// </summary>
        public static IParameterDatabase LoadParameterDatabase(string[] args)
        {
            // search for a -file
            IParameterDatabase parameters = null;

            for (var x = 0; x < args.Length - 1; x++)
            {
                if (args[x].Equals(A_FILE))
                {
                    try
                    {
                        parameters = new ParameterDatabase(new FileInfo(args[x + 1]), args);
                        Trace.WriteLine("Using database file location " + parameters.Label);
                        break;
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine(e.Message);
                        Output.InitialError(
                            "An exception was generated upon reading the parameter file \"" + args[x + 1] +
                            "\".\nHere it is:\n" + e, false);
                        Environment.Exit(1);
                        // This was originally part of the InitialError call in ECJ. But we make Evolve responsible.
                    }
                }
            }

            // search for a resource class (we may or may not use this)
            Type cls = null;

            for (var x = 0; x < args.Length - 1; x++)
            {
                if (args[x].Equals(A_AT))
                {
                    try
                    {
                        if (parameters != null) // uh oh
                        {
                            Output.InitialError("Both -file and -at arguments provided.  This is not permitted.\nFor help, try:  java ec.Evolve -help");
                        }
                        else
                        {
                            cls = Type.GetType(args[x + 1]);
                        }
                        break;
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine(e.Message);
                        Output.InitialError(
                            "An exception was generated upon extracting the class to load the parameter file relative to: " +
                            args[x + 1] +
                            "\nFor help, try:  java ec.Evolve -help\n\n" + e);
                    }
                }
            }

            // search for a resource (we may or may not use this)
            for (var x = 0; x < args.Length - 1; x++)
            {
                if (args[x].Equals(A_FROM))
                {
                    try
                    {
                        if (parameters != null) // uh oh
                        {
                            Output.InitialError("Both -file and -from arguments provided.  This is not permitted.\nFor help, try:  java ec.Evolve -help");
                        }
                        else
                        {
                            if (cls == null) // no -at
                            {
                                cls = typeof(Evolve);
                            }
                            parameters = new ParameterDatabase(args[x + 1], cls, args);
                            Trace.WriteLine("Using database resource location " + parameters.Label);
                        }
                        break;
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine(e.Message);
                        Output.InitialError(
                            "The parameter file is missing at the resource location: " + args[x + 1] +
                            " relative to the class: " + cls + "\n\nFor help, try:  java ec.Evolve -help");
                    }
                }
            }

            if (parameters == null)
            {
                Output.InitialError("No parameter or checkpoint file was specified.\nFor help, try:   java ec.Evolve -help", false);
                Environment.Exit(1);
                // This was originally part of the InitialError call in ECJ. But we make Evolve responsible.
            }
            return(parameters);
        }
Beispiel #13
0
        public static void Main(string[] args)
        {
            IEvolutionState    state      = null;
            IParameterDatabase parameters = null;
            Output             output     = null;

            //bool store;
            int x;

            // 0. find the parameter database
            for (x = 0; x < args.Length - 1; x++)
            {
                if (args[x].Equals(A_FILE))
                {
                    try
                    {
                        parameters = new ParameterDatabase(new FileInfo(new FileInfo(args[x + 1]).FullName), args);

                        // add the fact that I am a slave:      eval.i-am-slave = true
                        // this is used only by the Evaluator to determine whether to use the MasterProblem
                        parameters.SetParameter(new Parameter(EvolutionState.P_EVALUATOR).Push(Evaluator.P_IAMSLAVE),
                                                "true");
                        break;
                    }
                    catch (FileNotFoundException e)
                    {
                        Output.InitialError(
                            "A File Not Found Exception was generated upon" + " reading the parameter file \""
                            + args[x + 1] + "\".\nHere it is:\n" + e, false);
                        Environment.Exit(1);
                        // This was originally part of the InitialError call in ECJ. But we make Slave responsible.
                    }
                    catch (IOException e)
                    {
                        Output.InitialError("An IO Exception was generated upon reading the" + " parameter file \""
                                            + args[x + 1] + "\".\nHere it is:\n" + e, false);
                        Environment.Exit(1);
                        // This was originally part of the InitialError call in ECJ. But we make Slave responsible.
                    }
                }
            }
            if (parameters == null)
            {
                Output.InitialError("No parameter file was specified.", false);
                Environment.Exit(1);
                // This was originally part of the InitialError call in ECJ. But we make Slave responsible.
            }

            // 5. Determine whether or not to return entire Individuals or just Fitnesses
            //    (plus whether or not the Individual has been evaluated).

            var returnIndividuals = parameters.GetBoolean(new Parameter(P_RETURNINDIVIDUALS), null, false);

            // 5.5 should we silence the whole thing?

            bool silent = parameters.GetBoolean(new Parameter(P_SILENT), null, false);

            if (parameters.ParameterExists(new Parameter(P_MUZZLE), null))
            {
                Output.InitialWarning("" + new Parameter(P_MUZZLE) + " has been deprecated.  We suggest you use " +
                                      new Parameter(P_SILENT) + " or similar newer options.");
            }
            silent = silent || parameters.GetBoolean(new Parameter(P_MUZZLE), null, false);


            // 6. Open a server socket and listen for requests
            var slaveName = parameters.GetString(new Parameter(P_EVALSLAVENAME), null);

            var masterHost = parameters.GetString(new Parameter(P_EVALMASTERHOST), null);

            if (masterHost == null)
            {
                Output.InitialError("Master Host missing", new Parameter(P_EVALMASTERHOST));
            }

            var masterPort = parameters.GetInt(new Parameter(P_EVALMASTERPORT), null, 0);

            if (masterPort == -1)
            {
                Output.InitialError("Master Port missing", new Parameter(P_EVALMASTERPORT));
            }

            var useCompression = parameters.GetBoolean(new Parameter(P_EVALCOMPRESSION), null, false);

            RunTime = parameters.GetInt(new Parameter(P_RUNTIME), null, 0);

            RunEvolve = parameters.GetBoolean(new Parameter(P_RUNEVOLVE), null, false);

            OneShot = parameters.GetBoolean(new Parameter(P_ONESHOT), null, true);

            if (RunEvolve && !returnIndividuals)
            {
                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.",
                    new Parameter(P_RUNEVOLVE), new Parameter(P_RETURNINDIVIDUALS));
                Environment.Exit(1);
                // This was originally part of the InitialError call in ECJ. But we make Slave responsible.
            }

            if (!silent)
            {
                Output.InitialMessage("ECCS Slave");
                if (RunEvolve)
                {
                    Output.InitialMessage("Running in Evolve mode, evolve time is " + RunTime + " milliseconds");
                }
                if (returnIndividuals)
                {
                    Output.InitialMessage("Whole individuals will be returned");
                }
                else
                {
                    Output.InitialMessage("Only fitnesses will be returned");
                }
            }


            // Continue to serve new masters until killed.
            TcpClient socket = null; // BRS: TcpClient is a wrapper around the Socket class

            while (true)
            {
                try
                {
                    long connectAttemptCount = 0;
                    if (!silent)
                    {
                        Output.InitialMessage("Connecting to master at " + masterHost + ":" + masterPort);
                    }

                    while (true)
                    {
                        try
                        {
                            socket = new TcpClient(masterHost, masterPort);
                            break;
                        }
                        catch (Exception)
                        // it's not up yet...
                        {
                            connectAttemptCount++;
                            try
                            {
                                Thread.Sleep(new TimeSpan((Int64)10000 * SLEEP_TIME));
                            }
                            catch (ThreadInterruptedException)
                            {
                            }
                        }
                    }
                    if (!silent)
                    {
                        Output.InitialMessage("Connected to master after " + (connectAttemptCount * SLEEP_TIME) + " ms");
                    }

                    BinaryReader dataIn  = null;
                    BinaryWriter dataOut = null;

                    try
                    {
                        Stream tmpIn  = socket.GetStream();
                        Stream tmpOut = socket.GetStream();
                        if (useCompression)
                        {
                            //Output.InitialError("JDK 1.5 has broken compression.  For now, you must set eval.compression=false");
                            //Environment.Exit(1); // This was originally part of the InitialError call in ECJ. But we make Slave responsible.

                            /*
                             * tmpIn = new CompressingInputStream(tmpIn);
                             * tmpOut = new CompressingOutputStream(tmpOut);
                             */
                            tmpIn  = Output.MakeCompressingInputStream(tmpIn);
                            tmpOut = Output.MakeCompressingOutputStream(tmpOut);
                            if (tmpIn == null || tmpOut == null)
                            {
                                var err = "You do not appear to have JZLib installed on your system, and so must set eval.compression=false.  "
                                          + "To get JZLib, download from the ECJ website or from http://www.jcraft.com/jzlib/";
                                if (!silent)
                                {
                                    Output.InitialMessage(err);
                                }
                                throw new OutputExitException(err);
                            }
                        }

                        dataIn  = new BinaryReader(tmpIn);
                        dataOut = new BinaryWriter(tmpOut);
                    }
                    catch (IOException e)
                    {
                        var err = "Unable to open input stream from socket:\n" + e;
                        if (!silent)
                        {
                            Output.InitialMessage(err);
                        }
                        throw new OutputExitException(err);
                    }

                    // specify the slaveName
                    if (slaveName == null)
                    {
                        // BRS : TODO : Check equivalence of the address returned from .NET socket.Client.LocalEndPoint
                        slaveName = socket.Client.LocalEndPoint + "/" + (DateTime.Now.Ticks - 621355968000000000) / 10000;
                        if (!silent)
                        {
                            Output.InitialMessage("No slave name specified.  Using: " + slaveName);
                        }
                    }

                    dataOut.Write(slaveName); // Default encoding of BinaryWriter is UTF-8
                    dataOut.Flush();

                    // 1. create the output
                    // store = parameters.GetBoolean(new Parameter(P_STORE), null, false);

                    if (output != null)
                    {
                        output.Close();
                    }
                    output = new Output(storeAnnouncementsInMemory: false) // do not store messages, just print them
                    {
                        ThrowsErrors = true                                // don't do System.exit(1)
                    };


                    // stdout is always log #0. stderr is always log #1.
                    // stderr accepts announcements, and both are fully verbose by default.
                    output.AddLog(Log.D_STDOUT, false);
                    output.AddLog(Log.D_STDERR, true);

                    if (silent)
                    {
                        output.GetLog(0).Silent = true;
                        output.GetLog(1).Silent = true;
                    }

                    if (!silent)
                    {
                        output.SystemMessage(ECVersion.Message());
                    }


                    // 2. set up thread values

                    int breedthreads = Evolve.DetermineThreads(output, parameters, new Parameter(Evolve.P_BREEDTHREADS));
                    int evalthreads  = Evolve.DetermineThreads(output, parameters, new Parameter(Evolve.P_EVALTHREADS));

                    // Note that either breedthreads or evalthreads (or both) may be 'auto'.  We don't warn about this because
                    // the user isn't providing the thread seeds.


                    // 3. create the Mersenne Twister random number generators, one per thread

                    var random = new IMersenneTwister[breedthreads > evalthreads ? breedthreads : evalthreads];

                    var seed = dataIn.ReadInt32();
                    for (var i = 0; i < random.Length; i++)
                    {
                        random[i] = Evolve.PrimeGenerator(new MersenneTwisterFast(seed++));
                    }
                    // we prime the generator to be more sure of randomness.

                    // 4. Set up the evolution state

                    // what evolution state to use?
                    state =
                        (IEvolutionState)
                        parameters.GetInstanceForParameter(new Parameter(Evolve.P_STATE), null, typeof(IEvolutionState));
                    state.Parameters = new ParameterDatabase();
                    state.Parameters.AddParent(parameters);
                    state.Random       = random;
                    state.Output       = output;
                    state.EvalThreads  = evalthreads;
                    state.BreedThreads = breedthreads;

                    state.Setup(state, null);
                    state.Population = state.Initializer.SetupPopulation(state, 0);


                    // 5. Optionally do further loading
                    var storage = state.Evaluator.MasterProblem;
                    storage.ReceiveAdditionalData(state, dataIn);
                    storage.TransferAdditionalData(state);

                    try
                    {
                        while (true)
                        {
                            var newState = state;

                            if (RunEvolve)
                            {
                                // Construct and use a new EvolutionState.  This will be inefficient the first time around
                                // as we've set up TWO EvolutionStates in a row with no good reason.
                                IParameterDatabase coverDatabase = new ParameterDatabase();
                                // protect the underlying one
                                coverDatabase.AddParent(state.Parameters);
                                newState = Evolve.Initialize(coverDatabase, 0);
                                newState.StartFresh();
                                newState.Output.Message("Replacing random number generators, ignore above seed message");
                                newState.Random = state.Random;           // continue with RNG
                                storage.TransferAdditionalData(newState); // load the arbitrary data again
                            }

                            // 0 means to shut down
                            //Console.Error.WriteLine("reading next problem");
                            int problemType = dataIn.ReadByte();
                            //Console.Error.WriteLine("Read problem: " + problemType);
                            switch (problemType)
                            {
                            case (int)SlaveEvaluationType.Shutdown:
                                socket.Close();
                                if (OneShot)
                                {
                                    return; // we're outa here
                                }
                                else
                                {
                                    throw new OutputExitException("SHUTDOWN");
                                }

                            case (int)SlaveEvaluationType.Simple:
                                EvaluateSimpleProblem(newState, returnIndividuals, dataIn, dataOut, args);
                                break;

                            case (int)SlaveEvaluationType.Grouped:
                                EvaluateGroupedProblem(newState, returnIndividuals, dataIn, dataOut);
                                break;

                            default:
                                state.Output.Fatal("Unknown problem form specified: " + problemType);
                                break;
                            }
                            //System.err.PrintLn("Done Evaluating Individual");
                        }
                    }
                    catch (IOException e)
                    {
                        // Since an IOException can happen here if the peer closes the socket
                        // on it's end, we don't necessarily have to exit.  Maybe we don't
                        // even need to print a warning, but we'll do so just to indicate
                        // something happened.
                        state.Output.Fatal(
                            "Unable to read type of evaluation from master.  Maybe the master closed its socket and exited?:\n" +
                            e);
                    }
                    catch (Exception e)
                    {
                        if (state != null)
                        {
                            state.Output.Fatal(e.Message);
                        }
                        else if (!silent)
                        {
                            Console.Error.WriteLine("FATAL ERROR (EvolutionState not created yet): " + e.Message);
                        }
                    }
                }
                catch (OutputExitException e)
                {
                    // here we restart if necessary
                    try { socket.Close(); } catch (Exception e2) { }
                    if (OneShot)
                    {
                        Environment.Exit(0);
                    }
                }
                catch (OutOfMemoryException e)
                {
                    // Let's try fixing things
                    state = null;

                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    GC.Collect();
                    GC.WaitForPendingFinalizers();

                    try { socket.Close(); } catch (Exception e2) { }
                    socket = null;

                    // TODO: Overkill? Track memory before and after.
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    GC.Collect();
                    GC.WaitForPendingFinalizers();

                    Console.Error.WriteLine(e);
                    if (OneShot)
                    {
                        Environment.Exit(0);
                    }
                }
                if (!silent)
                {
                    Output.InitialMessage("\n\nResetting Slave");
                }
            }
        }