コード例 #1
0
        /// <summary>
        /// Creates the next generation of programs.  This method also keeps tabs on memory
        /// as it creates the new Population.  If we run out of physical memory then the
        /// new Population size is changed to wherever we ran out of memory.
        /// </summary>
        /// <param name="nGeneration">Which generation is currently being processed</param>
        /// <param name="Population">Reference to the Population just computed for fitness</param>
        /// <param name="Fitness">Fitness object with the fitness computation results</param>
        /// <param name="AutoReproduce">List of programs to automatically reproduce into the next generation</param>
        /// <returns>Reference to the new Population to use</returns>
        public GPPopulation ComputeNext(int nGeneration, GPPopulation Population, GPFitness Fitness, List <GPProgram> AutoReproduce)
        {
            m_PopCurrent = Population;
            m_Fitness    = Fitness;

            //
            // Setup the program selection delegate
            switch (m_ModelerConfig.Profile.Reproduction)
            {
            case GPEnums.Reproduction.Tournament:
                ExecProgramSelection = new DELProgramSelection(Fitness.FitnessSelection.SelectProgramTournament);
                break;

            case GPEnums.Reproduction.OverSelection:
                ExecProgramSelection = new DELProgramSelection(Fitness.FitnessSelection.SelectProgramOverSelection);
                break;
            }

            //
            // Create a Tree Factory object - It helps in support of the mutation and
            // crossover operations
            m_TreeFactory = new GPProgramTreeFactory(m_ModelerConfig, m_InputDimension);

            return(ComputeNext(Population, Fitness, AutoReproduce));
        }
コード例 #2
0
        /// <summary>
        /// Use the SPEA2 algorithm to compute fitness, with RawFitness and Program
        /// Complexity the two objectives to minimize.
        /// </summary>
        /// <param name="RawFitness"></param>
        /// <param name="Population"></param>
        public override void PrepareFitness(double[] RawFitness, GPPopulation Population)
        {
            m_RawFitness = RawFitness;

            //
            // --- Run The SPEA2 Algorithm ---
            m_Archive = UpdateArchive(Population);

            //
            // Create a new RawFitness based upon the Archive SPEA2 fitness values
            double[] SPEA2Fitness = new double[m_Archive.Count];
            for (int Program = 0; Program < m_Archive.Count; Program++)
            {
                SPEA2Fitness[Program] = m_Archive[Program].SPEA2Fitness;
            }

            //
            // In case the archive size changes, let the base class know so it can resize
            // its storage to match the new size.
            base.PopulationSize = m_Archive.Count;

            //
            // Use the base class to get the final program selection stats computed.
            base.PrepareFitness(SPEA2Fitness, Population);
        }
コード例 #3
0
        /// <summary>
        /// Create the next generation of programs.
        /// </summary>
        public void ComputeNextGeneration(int Generation)
        {
            if (m_PopulatonFactory == null)
            {
                m_PopulatonFactory = new GPPopulationFactory(this, this.Training.Columns);
            }
            //
            // Create the next generation of programs
            GPPopulation popNew = m_PopulatonFactory.ComputeNext(Generation, m_Population, m_Fitness, m_SeedPrograms);

            //
            // If the Population size changed, update the configuration
            if (popNew.Count != m_Population.Count)
            {
                this.Profile.PopulationSize = popNew.Count;
                Console.WriteLine("GPServer: Memory is low, Population size reduced to ({0})", popNew.Count);

                //
                // Reset the Fitness object
                m_Fitness.TerminateProcessingThreads();
                m_Fitness = null;
            }

            m_Population = popNew;

            //
            // Clear out any seed programs we just used
            ResetSeedPrograms();
        }
コード例 #4
0
        /// <summary>
        /// Select two parents, based upon fitness, for a crossover operation.
        /// Place the two children into the new Population.
        /// </summary>
        /// <param name="PopNew">Population to add the newly created program to</param>
        private void Crossover(GPPopulation PopNew, GPFitnessObjectiveBase FitnessSelection)
        {
            GPProgram Child1 = (GPProgram)FitnessSelection.Programs(ExecProgramSelection()).Clone();
            GPProgram Child2 = (GPProgram)FitnessSelection.Programs(ExecProgramSelection()).Clone();

            //
            // Convert to trees
            Child1.ConvertToTree(m_ModelerConfig.FunctionSet, false);
            Child2.ConvertToTree(m_ModelerConfig.FunctionSet, false);

            //
            // Perform the crossover
            m_TreeFactory.Attach(Child1);
            Child2 = m_TreeFactory.Crossover(Child2);

            //
            // Convert to arrays
            Child1.ConvertToArray(m_ModelerConfig.FunctionSet);
            Child2.ConvertToArray(m_ModelerConfig.FunctionSet);

            //
            // Add them to the new Population
            PopNew.Programs.Add(Child1);
            if (PopNew.Count < m_PopCurrent.Count)
            {
                PopNew.Programs.Add(Child2);
            }
        }
コード例 #5
0
 /// <summary>
 /// This method instructs the server object to clean up as much memory
 /// as possible.
 /// </summary>
 public void ForceCleanup()
 {
     m_Population = null;
     m_Fitness.TerminateProcessingThreads();
     m_Fitness  = null;
     m_Training = null;
     System.GC.Collect();
 }
コード例 #6
0
        /// <summary>
        /// Select a program based upon fitness to reproduce into the next generation.
        /// </summary>
        /// <param name="PopNew">Population to add the reproduced program into</param>
        private void Reproduce(GPPopulation PopNew, GPFitnessObjectiveBase FitnessSelection)
        {
            GPProgram Copy = (GPProgram)FitnessSelection.Programs(ExecProgramSelection()).Clone();

            //
            // Add this copied child into the new Population
            PopNew.Programs.Add(Copy);
        }
コード例 #7
0
        /// <summary>
        /// Assign the Population complexity values for use in the MOO domination calculation
        /// </summary>
        /// <param name="Population"></param>
        private int[] PrepareComplexity(GPPopulation Population)
        {
            int[] Complexity = new int[Population.Count];
            for (int Program = 0; Program < Population.Count; Program++)
            {
                Complexity[Program] = Population.Programs[Program].CountNodes;
            }

            return(Complexity);
        }
コード例 #8
0
        /// <summary>
        /// Creates the initial Population on this server.  The Population size
        /// is sent as a parameter, rather than relying upon the profile, because
        /// this might be one of many remote objects and it is only working with
        /// some subset of the Population.
        /// </summary>
        /// <param name="PopulationSize">How many individuals to create initially</param>
        public void InitializePopulation(int PopulationSize)
        {
            //
            // Go ahead and replace, there is no need to have any knowledge of the
            // original Population size;
            m_Profile.PopulationSize = PopulationSize;
            m_Population             = new GPPopulation(this);
            m_Population.Build(this.Profile.PopulationBuild, (short)Training.Columns);

            //
            // Need to get this initialized somewhere, so this seems like a good time
            ResetSeedPrograms();
        }
コード例 #9
0
        /// <summary>
        /// Works through the Population to compute the fitness for each program, keeping
        /// track of a few statistics, such as best program, worst fitness and
        /// average fitness.  Makes a call to the abstract method "ComputeFitness" that
        /// must be implemented by all GPFitness derived classes.
        /// </summary>
        /// <param name="Generation">Current modeling generation</param>
        /// <param name="Population">Current generation Population of programs</param>
        /// <returns></returns>
        private int EvaluatePopulation(int Generation, GPPopulation Population)
        {
            //
            // Check to see if the Population size changed, if so, reallocate the array
            // that holds the fitness values
            if (Population.Count != m_PrevPopulationSize)
            {
                if (m_Config.Profile.SPEA2MultiObjective)
                {
                    m_FitnessSelection = new GPFitnessSPEA2(Population.Count);
                }
                else
                {
                    m_FitnessSelection = new GPFitnessSingle(Population.Count);
                }
            }

            FitnessMaximum = 0.0;
            FitnessAverage = 0.0;

            //
            // Go through each program in the Population.  First, compute the raw
            // fitness result of the program.  Once that is done, a call to the
            // abstract ComputeFitness function is made where the User Defined Fitness
            // function is called.
            m_BestProgramGeneration  = 0;
            m_WorstProgramGeneration = 0;
            m_CurrentProgram         = 0;
            m_CompletedPrograms      = 0;
            m_Population             = Population;

            //
            // Create the event to be signed when the last program is done processing
            wh_LastProgramDone = new EventWaitHandle(false, EventResetMode.ManualReset);

            //
            // Signal the suspend event
            wh_Suspend.Set();

            //
            // Wait for the last program to be computed
            wh_LastProgramDone.WaitOne();

            //
            // Finish up the average Population fitness
            FitnessAverage /= Population.Count;

            return(m_BestProgramGeneration);
        }
コード例 #10
0
        /// <summary>
        /// Performs the fitness computation over the Population
        /// </summary>
        /// <param name="Generation"></param>
        /// <param name="Population"></param>
        /// <returns></returns>
        public GPProgram Compute(int Generation, GPPopulation Population)
        {
            m_Abort = false;
            //
            // Go through the Population and compute the fitness of each
            // program, returning the best program index.
            BestProgram      = EvaluatePopulation(Generation, Population);
            m_BestProgramRef = Population.Programs[BestProgram];
            if (!m_Abort)
            {
                m_FitnessSelection.PrepareFitness(this.FitnessMeasure, Population);
            }

            //
            // return the best program
            return(m_BestProgramRef);
        }
コード例 #11
0
        /// <summary>
        /// Select a program, based on fitness, for mutation.  Place
        // the mutated program into the new Population.
        /// </summary>
        /// <param name="PopNew">Population to add the newly created program to</param>
        private void Mutate(GPPopulation PopNew, GPFitnessObjectiveBase FitnessSelection)
        {
            GPProgram Copy = (GPProgram)FitnessSelection.Programs(ExecProgramSelection()).Clone();

            //
            // Convert it to a tree
            Copy.ConvertToTree(m_ModelerConfig.FunctionSet, false);

            //
            // Perform the mutation
            m_TreeFactory.Attach(Copy);
            m_TreeFactory.Mutate();

            //
            // Return it back to an array
            Copy.ConvertToArray(m_ModelerConfig.FunctionSet);

            //
            // Add this mutated individual to the new Population
            PopNew.Programs.Add(Copy);
        }
コード例 #12
0
        /// <summary>
        /// Copys all nondominated programs from ArchivePopulation and PopCurrent into
        /// the next archive...which is returned from the method
        /// </summary>
        /// <param name="ArchivePopulation"></param>
        /// <param name="Population"></param>
        private List <SPEA2ProgramStats> UpdateArchive(GPPopulation Population)
        {
            SPEA2ProgramStats[] SPEA2Population = new SPEA2ProgramStats[Population.Count];

            //
            // Grab the complexity of each program.  We do this here, rather than getting it
            // from the Population object because it saves some computation time due to the
            // complexity values being reused several times.
            int[] Complexity = PrepareComplexity(Population);

            //
            // Init the min/max objective values - arbitrarily choose the first program's complexity value
            m_MinObjectiveFitness    = m_MaxObjectiveFitness = m_RawFitness[0];
            m_MinObjectiveComplexity = m_MaxObjectiveComplexity = Complexity[0];

            //
            // Compute how many solutions each program in the current Population is dominated by
            for (int ProgramA = 0; ProgramA < Population.Count; ProgramA++)
            {
                SPEA2Population[ProgramA]            = new SPEA2ProgramStats();
                SPEA2Population[ProgramA].Program    = Population.Programs[ProgramA];
                SPEA2Population[ProgramA].RawFitness = m_RawFitness[ProgramA];
                SPEA2Population[ProgramA].Complexity = Complexity[ProgramA];
                SPEA2Population[ProgramA].Strength   = 0;

                //
                // Test ProgramA against all programs in the current Population
                for (int ProgramB = 0; ProgramB < Population.Count; ProgramB++)
                {
                    if ((m_RawFitness[ProgramB] > SPEA2Population[ProgramA].RawFitness) &&
                        (Complexity[ProgramB] > SPEA2Population[ProgramA].Complexity))
                    {
                        SPEA2Population[ProgramA].Strength++;
                    }
                }

                //
                // Test ProgramA against all programs in the current archive
                for (int ProgramB = 0; ProgramB < Archive.Count; ProgramB++)
                {
                    if (Archive[ProgramB].RawFitness > SPEA2Population[ProgramA].RawFitness &&
                        Archive[ProgramB].Complexity > SPEA2Population[ProgramA].Complexity)
                    {
                        SPEA2Population[ProgramA].Strength++;
                    }
                }

                //
                // Maintain the min/max objective values from the current Population
                m_MinObjectiveFitness    = Math.Min(SPEA2Population[ProgramA].RawFitness, m_MinObjectiveFitness);
                m_MinObjectiveComplexity = Math.Min(SPEA2Population[ProgramA].Complexity, m_MinObjectiveComplexity);

                m_MaxObjectiveFitness    = Math.Max(SPEA2Population[ProgramA].RawFitness, m_MaxObjectiveFitness);
                m_MaxObjectiveComplexity = Math.Max(SPEA2Population[ProgramA].Complexity, m_MaxObjectiveComplexity);
            }

            //
            // Count how many solutions each program in the archive is dominated by
            for (int ProgramA = 0; ProgramA < Archive.Count; ProgramA++)
            {
                SPEA2ProgramStats ProgramAStats = Archive[ProgramA];
                ProgramAStats.Strength = 0;
                //
                // Test ProgramA against all programs in the current Population
                for (int ProgramB = 0; ProgramB < Population.Count; ProgramB++)
                {
                    if (m_RawFitness[ProgramB] > ProgramAStats.RawFitness &&
                        Complexity[ProgramB] > ProgramAStats.Complexity)
                    {
                        ProgramAStats.Strength++;
                    }
                }

                //
                // Test ProgramA against all programs in the current archive
                for (int ProgramB = 0; ProgramB < Archive.Count; ProgramB++)
                {
                    if (Archive[ProgramB].RawFitness > ProgramAStats.RawFitness &&
                        Archive[ProgramB].Complexity > ProgramAStats.Complexity)
                    {
                        ProgramAStats.Strength++;
                    }
                }
                Archive[ProgramA] = ProgramAStats;

                //
                // Maintain the min/max objective values from the current archive
                m_MinObjectiveFitness    = Math.Min(ProgramAStats.RawFitness, m_MinObjectiveFitness);
                m_MinObjectiveComplexity = Math.Min(ProgramAStats.Complexity, m_MinObjectiveComplexity);

                m_MaxObjectiveFitness    = Math.Max(ProgramAStats.RawFitness, m_MaxObjectiveFitness);
                m_MaxObjectiveComplexity = Math.Max(ProgramAStats.Complexity, m_MaxObjectiveComplexity);
            }

            if (m_MinObjectiveComplexity == m_MaxObjectiveComplexity)
            {
                m_MaxObjectiveComplexity += 1.0;
            }

            //
            // Now, we can compute the SPEA2 fitness for each individual by summing
            // the strenth values for each program it is dominated by.
            for (int ProgramA = 0; ProgramA < Population.Count; ProgramA++)
            {
                SPEA2Population[ProgramA].SPEA2Fitness = 0.0;
                //
                // Test ProgramA against all programs in the current Population
                for (int ProgramB = 0; ProgramB < Population.Count; ProgramB++)
                {
                    if (m_RawFitness[ProgramB] < SPEA2Population[ProgramA].RawFitness &&
                        Complexity[ProgramB] < SPEA2Population[ProgramA].Complexity)
                    {
                        SPEA2Population[ProgramA].SPEA2Fitness += SPEA2Population[ProgramB].Strength;
                    }
                }

                //
                // Test ProgramA against all programs in the current archive
                for (int ProgramB = 0; ProgramB < Archive.Count; ProgramB++)
                {
                    if (Archive[ProgramB].RawFitness < SPEA2Population[ProgramA].RawFitness &&
                        Archive[ProgramB].Complexity < SPEA2Population[ProgramA].Complexity)
                    {
                        SPEA2Population[ProgramA].SPEA2Fitness += Archive[ProgramB].Strength;
                    }
                }
            }

            //
            // Now, do it for the current archive
            for (int ProgramA = 0; ProgramA < Archive.Count; ProgramA++)
            {
                SPEA2ProgramStats ProgramAStats = Archive[ProgramA];
                ProgramAStats.SPEA2Fitness = 0.0;
                //
                // Test ProgramA against all programs in the current Population
                for (int ProgramB = 0; ProgramB < Population.Count; ProgramB++)
                {
                    if (SPEA2Population[ProgramB].RawFitness < ProgramAStats.RawFitness &&
                        SPEA2Population[ProgramB].Complexity < ProgramAStats.Complexity)
                    {
                        ProgramAStats.SPEA2Fitness += SPEA2Population[ProgramB].Strength;
                    }
                }

                //
                // Test ProgramA against all programs in the current archive
                for (int ProgramB = 0; ProgramB < Archive.Count; ProgramB++)
                {
                    if (Archive[ProgramB].RawFitness < ProgramAStats.RawFitness &&
                        Archive[ProgramB].Complexity < ProgramAStats.Complexity)
                    {
                        ProgramAStats.SPEA2Fitness += Archive[ProgramB].Strength;
                    }
                }

                Archive[ProgramA] = ProgramAStats;
            }

            //
            // Compute the Density estimate for each program in the current Population
            for (int ProgramA = 0; ProgramA < Population.Count; ProgramA++)
            {
                SPEA2Population[ProgramA].Density = ComputeDensity(ref SPEA2Population[ProgramA], SPEA2Population, Archive);
            }

            //
            // Compute the Density estimate for each program in the current archive
            for (int ProgramA = 0; ProgramA < Archive.Count; ProgramA++)
            {
                SPEA2ProgramStats ProgramAStats = Archive[ProgramA];
                ProgramAStats.Density = ComputeDensity(ref ProgramAStats, SPEA2Population, Archive);
                Archive[ProgramA]     = ProgramAStats;
            }

            //
            // Final SPEA2 fitness calculation: F(i)=R(i)+D(i)
            for (int ProgramA = 0; ProgramA < Population.Count; ProgramA++)
            {
                SPEA2Population[ProgramA].SPEA2Fitness = SPEA2Population[ProgramA].SPEA2Fitness + SPEA2Population[ProgramA].Density;
            }

            for (int ProgramA = 0; ProgramA < Archive.Count; ProgramA++)
            {
                SPEA2ProgramStats ProgramAStats = Archive[ProgramA];
                ProgramAStats.SPEA2Fitness = ProgramAStats.SPEA2Fitness + ProgramAStats.Density;
                Archive[ProgramA]          = ProgramAStats;
            }

            //
            // Add all nondominated programs from the current Population into the new archive
            // The max complexity program allowed in the archive is 10,000.  There are two reasons for this...
            //   *The List container has an "short" sized counter, so programs bigger than 16 bits can't be stored
            //    in the compressed array representation.  Setting a value of 10,000 keeps programs from
            //    getting too out of hand.
            //   *A program size of 10,000 is ridiculous in size, so don't allow it.
            List <SPEA2ProgramStats>    New_Archive         = new List <SPEA2ProgramStats>();
            SortedDictionary <int, int> New_ArchivePrograms = new SortedDictionary <int, int>();

            for (int Program = 0; Program < Population.Programs.Count; Program++)
            {
                if (SPEA2Population[Program].SPEA2Fitness < 1.0 && SPEA2Population[Program].Complexity > 2 &&
                    SPEA2Population[Program].Complexity < 10000)
                {
                    New_Archive.Add(SPEA2Population[Program]);
                    New_ArchivePrograms.Add(Program, Program);
                }
            }

            //
            // Add all nondominated programs for the current archive into the new archive
            for (int Program = 0; Program < Archive.Count; Program++)
            {
                if (Archive[Program].SPEA2Fitness < 1.0 && Archive[Program].Complexity > 2)
                {
                    New_Archive.Add(Archive[Program]);
                }
            }

#if GPLOG
            GPLog.ReportLine("Archive Size: " + New_Archive.Count, true);
#endif

            //
            // Get the archive to the right size
            int ArchiveSize = Population.Count / ARCHIVESCALE;
            if (New_Archive.Count < ArchiveSize)
            {
                ExpandArchive(New_Archive, ArchiveSize, SPEA2Population, New_ArchivePrograms);
            }
            else if (New_Archive.Count > ArchiveSize)
            {
                ShrinkArchive(New_Archive, ArchiveSize);
            }

            return(New_Archive);
        }
コード例 #13
0
 public virtual void PrepareFitness(double[] RawFitness, GPPopulation Population)
 {
     m_Population    = Population;
     this.RawFitness = RawFitness;
 }
コード例 #14
0
        public GPPopulation ComputeNext(GPPopulation PopCurrent, GPFitness Fitness, List <GPProgram> AutoReproduce)
        {
            GPPopulation PopNew = new GPPopulation(m_ModelerConfig);

            //
            // Add the new programs into the next generation automatically
            foreach (GPProgram Seed in AutoReproduce)
            {
                PopNew.Programs.Add(Seed);
            }
            //
            // Automatically reproduce the best program into the next generation
            PopNew.Programs.Add((GPProgram)Fitness.BestProgramRef.Clone());

            //
            // Now, go ahead and fill out the rest of the Population
            while (PopNew.Count < m_ModelerConfig.Profile.PopulationSize)
            {
                //
                // Make a probabilistic selection between...
                //	Reproduction
                //	Mutation
                //	Crossover
                double Choice     = GPUtilities.rngNextDouble();
                double Cumulative = m_ModelerConfig.Profile.ProbabilityReproductionD;
                bool   bSelected  = false;

                if (Choice <= Cumulative)
                {
                    Reproduce(PopNew, Fitness.FitnessSelection);
                    bSelected = true;
                }
                Cumulative += m_ModelerConfig.Profile.ProbabilityMutationD;
                if (!bSelected && (Choice <= Cumulative))
                {
                    Mutate(PopNew, Fitness.FitnessSelection);
                    bSelected = true;
                }
                Cumulative += m_ModelerConfig.Profile.ProbabilityCrossoverD;
                if (!bSelected && (Choice <= Cumulative))
                {
                    Crossover(PopNew, Fitness.FitnessSelection);
                    bSelected = true;
                }

                //
                // Only check every 100 times to save a little time on doing this
                // check.
                if (PopNew.Count % 100 == 0)
                {
                    if (!CheckMemory())
                    {
                        //
                        // Do a garbage collect just to be sure and check again
                        System.GC.Collect();
                        if (!CheckMemory())
                        {
                            break;
                        }
                    }
                }
            }

            return(PopNew);
        }