Exemplo n.º 1
0
        // 초기 개체를 생성하는 함수
        public void Initialize()
        {
            Genome g = CreateBasicConnectedGenome();

            for (int i = 0; i < Population; ++i)
            {
                AddToSpecies(g.Clone());
            }
        }
Exemplo n.º 2
0
        // 적합도를 평가하고 이를 바탕으로 선택, 교차, 변이를 통해서 새로운 세대를 생성하는 함수
        //
        // 다음 순서로 작동함
        // 1) 모든 개체의 적합도를 판단함
        // 2) Staleness가 높은 종을 판단하여 제거함
        // 3) 적합도를 바탕으로 하여 자식을 만듦. 이때 교차와 변이 모두를 통해서 자식을 만들기도 하며, 변이만으로 자식을 생성하기도 함.
        //   - 이때, 자식을 만들 확률은 종과 개체의 적합도에 따라서 다름. 즉 개체의 평균 적합도가 높은 종은 더 많은 자식을 만들고, 또 종 내에서 적합도가 높은 개체는 더 많은 자식을 만듦)
        // 4) 각 종마다 SurviveRate에 해당하는 개체만 남기고 나머지는 제거함
        // 5) 새로운 자식들을 기존의 종에 추가함.
        public void Evaluate()
        {
            TopFitness = long.MinValue;
            BestGenome = null;
            if (Writer != null)
            {
                Writer.Record();
            }
            // 과정 1)
            while (true)
            {
                Genome g = GetCurrentGenome();
                g.GenerateNetwork();
                // 적합도 평가
                insw.Reset();
                insw.Start();
                g.Fitness = Agent.Evaluate(g, DataDictionary);
                g.Checked = true;
                insw.Stop();
                g.ExecutionTime = insw.ElapsedMilliseconds;

                g.AdjustedFitness = (double)g.Fitness / Species[speciesCursor].Genomes.Count;

                Species[speciesCursor].AddFitness(g.AdjustedFitness);
                if (g.Fitness > TopFitness)
                {
                    TopFitness = g.Fitness;
                    BestGenome = g;
                }
                bool newGen = false;
                while (IsFitnessMeasured())
                {
                    if (NextGenome())
                    {
                        newGen = true;
                        break;
                    }
                }

                if (newGen)
                {
                    break;
                }
            }

            if (Generation != 0 && Generation % DisplayTop == 0)
            {
                Agent.Display(BestGenome, DataDictionary);
            }
            if (Writer != null)
            {
                Writer.Write(BestGenome, DataDictionary);
                if (WritePlayData)
                {
                    Writer.WriteGene(BestGenome, DataDictionary);
                }
                if (WriteSpecies)
                {
                    Writer.WriteSpecies(Species, DataDictionary);
                }
            }
            DataDictionary.Clear();

            sw.Reset();
            sw.Start();

            // for debug
            Console.Write("Generation:" + Generation);
            Console.Write("\tHighest Fitness:" + TopFitness);
            Console.WriteLine("\tAmount Species:" + Species.Count);
            ++Generation;
            List <Genome> child    = new List <Genome>();
            int           survived = 0;

            // 과정 2)
            for (int i = Species.Count - 1; i >= 0; --i)
            {
                Species s        = Species[i];
                Genome  prevBest = s.Genomes[0];
                s.Genomes.Sort((a, b) => a.Fitness.CompareTo(b.Fitness));
                Genome currentBest = s.Genomes[s.Genomes.Count - 1];
                // 종에서 기존의 가장 우수한 개체보다 더 적합도가 높은 개체가 등장하지 못했을 경우
                if (prevBest == currentBest)
                {
                    ++s.Staleness;
                    // staleness가 일정 수준 이상이고, 전체에서 가장 우수한 개체가 속한 종이 아니라면, 종을 제거함
                    if (s.Staleness > Staleness && BestGenome != currentBest)
                    {
                        Species.RemoveAt(i);
                    }
                }
                else // 종에서 기존의 가장 우수한 개체보다 더 적합도가 높은 개체가 등장할 경우
                {
                    s.Staleness = 0;
                }
            }

            // surviveRate를 바탕으로 생성할 자식 개체의 수를 계산

            if (SurviveRate == 0)
            {
                survived = Species.Count;
            }
            else
            {
                foreach (Species s in Species)
                {
                    survived += (int)Math.Ceiling(s.Genomes.Count * SurviveRate);
                }
            }

            // 과정 3)
            while (survived + child.Count < Population)
            {
                Genome c;
                // 교차 및 변이로 자식 생성
                if (random.NextDouble() < BreedChance)
                {
                    Species s = SelectSpecies(random);

                    Genome g1 = SelectGenome(s, random);
                    Genome g2 = SelectGenome(s, random);


                    if (g1.Fitness > g2.Fitness)
                    {
                        c = Genome.Crossover(g1, g2, random);
                    }
                    else
                    {
                        c = Genome.Crossover(g2, g1, random);
                    }

                    c.Mutate(random);
                }
                else // 변이로만 자식 생성
                {
                    Species s  = SelectSpecies(random);
                    Genome  g1 = SelectGenome(s, random);
                    c = g1.Clone();

                    c.Mutate(random);
                }

                child.Add(c);
            }
            // 과정 4) SurviveRate에 따라서 기존의 종을 제거함
            foreach (Species s in Species)
            {
                int cut = 0;
                if (SurviveRate == 0)
                {
                    cut = s.Genomes.Count - 1;
                }
                else
                {
                    cut = s.Genomes.Count - (int)Math.Ceiling(s.Genomes.Count * SurviveRate);
                }
                s.ResetFitness();
                s.Genomes.RemoveRange(0, cut);
                s.Genomes[0].Fitness = 0;
                s.Genomes[0].Checked = false;
                // to fix;
            }

            // 과정 5) 새로 만들어진 자식 종을 추가함
            foreach (Genome g in child)
            {
                AddToSpecies(g);
            }

            sw.Stop();
            if (Writer != null)
            {
                Writer.Set("Breed", sw.ElapsedMilliseconds);
            }
        }