Ejemplo n.º 1
0
        public void Evaluate(IEvolutionState state,
                             Individual ind,
                             int subpopulation,
                             int threadnum)
        {
            if (ind.Evaluated && !ReevaluateIndividuals)
            {
                return;
            }

            var fits = new ArrayList();

            Individual bestOfRuns = null;

            for (int run = 0; run < Runs; run++)
            {
                // too annoying
                //state.Output.message("Thread " + threadnum + " Run " + run);
                try
                {
                    // The following uses BinaryFormatter to create a separate copy of the ParameterDatabase.
                    CurrentDatabase = (ParameterDatabase)p_database.DeepClone();
                }
                catch (Exception e)
                {
                    state.Output.Fatal("Exception copying database.\n" + e);
                }
                ModifyParameters(state, CurrentDatabase, run, ind);

                var output = new Output(false); // do not store messages, just print them
                output.AddLog(Log.D_STDOUT, false);
                output.AddLog(Log.D_STDERR, true);
                output.ThrowsErrors = true; // don't do System.exit(1);

                EvolutionState evaluatedState = null;
                try
                {
                    evaluatedState = Evolve.Initialize(CurrentDatabase, 0, output);

                    // should we override the seeds?
                    if (SetRandom)
                    {
                        // we use the random number generator to seed the generators
                        // of the underlying process.  This isn't optimal but it should
                        // probably do okay.  To be extra careful we prime the generators.

                        for (int i = 0; i < evaluatedState.Random.Length; i++)
                        {
                            int seed = state.Random[threadnum].NextInt();
                            evaluatedState.Random[i] = Evolve.PrimeGenerator(new MersenneTwisterFast(seed));
                        }
                    }

                    evaluatedState.Run(EvolutionState.C_STARTED_FRESH);

                    // Issue a warning if there's more than one subpopulation
                    if (evaluatedState.Population.Subpops.Count > 1)
                    {
                        state.Output.WarnOnce(
                            "MetaProblem used, but underlying evolution state has more than one subpopulation: only the results from subpopulation 0 will be considered.");
                    }


                    // Identify the best fitness of the underlying EvolutionState run,

                    // we can only easily detect if the underlying EvolutionState has a proper Statistics
                    // object we can use AFTER we've run it because the Statistics object is set up during
                    // run().  We could modify this but I'm too lazy to do so, so...

                    Individual[] inds = null; // will get set, don't worry
                    if (evaluatedState.Statistics != null &&
                        (evaluatedState.Statistics is SimpleStatistics ||
                         evaluatedState.Statistics is SimpleShortStatistics))
                    {
                        inds = null;

                        // obviously we need an interface here rather than this nonsense
                        if (evaluatedState.Statistics is SimpleStatistics)
                        {
                            inds = ((SimpleStatistics)evaluatedState.Statistics).GetBestSoFar();
                        }
                        else
                        {
                            inds = ((SimpleShortStatistics)evaluatedState.Statistics).GetBestSoFar();
                        }
                        if (inds == null)
                        {
                            state.Output.Fatal(
                                "Underlying evolution state has a Statistics object which provides a null best-so-far array.  Can't extract fitness.");
                        }
                        fits.Add((Fitness)(inds[0].Fitness));
                        //System.err.println("" + inds[0] + " " + inds[0].fitness);
                    }
                    else if (evaluatedState.Statistics == null)
                    {
                        state.Output.Fatal(
                            "Underlying evolution state has a null Statistics object.  Can't extract fitness.");
                    }
                    else
                    {
                        state.Output.Fatal(
                            "Underlying evolution state has a Statistics object which doesn't implement ProvidesBestSoFar.  Can't extract fitness.");
                    }


                    // Now we need to suck out the best individual discovered so far.  If the underlying
                    // evoluationary system itself has a MetaProblem, we need to do this recursively.
                    // We presume that the MetaProblem exists in subpopulation 0.

                    if (evaluatedState.Evaluator.p_problem is MetaProblem)
                    {
                        var mp = (MetaProblem)evaluatedState.Evaluator.p_problem;
                        lock (mp.Lock)
                        {
                            Individual bestind = mp.BestUnderlyingIndividual[0];

                            if (bestOfRuns == null || bestind.Fitness.BetterThan(bestOfRuns.Fitness))
                            {
                                bestOfRuns = (Individual)bestind.Clone();
                            }
                        }
                    }
                    // otherwise we grab the best individual found in the underlying evolutionary run,
                    // gathered from the inds array we used earlier.
                    else
                    {
                        // gather the best individual found during the runs
                        if (bestOfRuns == null || inds[0].Fitness.BetterThan(bestOfRuns.Fitness))
                        {
                            bestOfRuns = (Individual)(inds[0].Clone());
                        }
                    }


                    // now clean up
                    Evolve.Cleanup(evaluatedState);
                }
                catch (OutputExitException e)
                {
                    // looks like an error occurred.
                    state.Output.Warning(
                        "Error occurred in underlying evolutionary run.  NOTE: multiple threads may still be running:\n" +
                        e.Message);
                }
                catch (OutOfMemoryException e)
                {
                    // Let's try fixing things
                    evaluatedState = null;
                    //System.gc();
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                    GC.Collect();
                    GC.WaitForPendingFinalizers();

                    state.Output.Warning(
                        "An Out of Memory error occurred in underlying evolutionary run.  Attempting to recover and reset.  NOTE: multiple threads may still be running:\n" +
                        e.Message);
                }
            }


            // Load the fitness into our individual
            var fits2 = new IFitness[fits.Count];

            for (var i = 0; i < fits2.Length; i++)
            {
                fits2[i] = (IFitness)fits[i];
            }
            Combine(state, fits2, ind.Fitness);
            ind.Evaluated = true;

            // store the best individual found during the runs if it's superior.
            // We need to do a lock here, which is rare in ECJ.  This is because the
            // bestUnderlyingIndividual array is shared among MetaProblem instances
            lock (Lock)
            {
                if (bestOfRuns != null &&
                    (BestUnderlyingIndividual[subpopulation] == null ||
                     bestOfRuns.Fitness.BetterThan(BestUnderlyingIndividual[subpopulation].Fitness)))
                {
                    BestUnderlyingIndividual[subpopulation] = bestOfRuns; // no clone necessary
                }
            }
        }