Esempio n. 1
0
    public void alternate()
    {
        // 適応度を昇順に並び替える
        quickSort(0, Simulation.ROCKET_NUM - 1);
        Debug.Log($"第{Simulation.curGeneration-1}世代 最良適応度: {this.curIndividuals[0].fitness}");

        // 前世代にTargetに到達した数を現世代のエリート数とする
        elite      = 2;
        superElite = 0;
        for (int i = 0; i < Simulation.ROCKET_NUM; i++)
        {
            if (curIndividuals[i].isReachedTarget)
            {
                superElite++;
            }
        }
        elite = Mathf.Max(elite + superElite, 5); // elite上限5

        // エリートは無条件に保存する
        for (int i = 0; i < elite; i++)
        {
            for (int j = 0; j < Rocket.LIFESPAN; j++)
            {
                nextIndividuals[i].chrom[j] = curIndividuals[i].chrom[j];
            }
        }

        float totalFitness = 0;
        float worstFitness = curIndividuals[Simulation.ROCKET_NUM - 1].fitness; // ソート後、配列最後尾に最悪適応度が格納されている

        for (int i = 0; i < Simulation.ROCKET_NUM; i++)
        {
            trFit[i]      = (worstFitness - curIndividuals[i].fitness + 0.001f) / worstFitness;
            trFit[i]      = Mathf.Pow(trFit[i], 4.0f);
            totalFitness += trFit[i];
        }

        // 交叉
        for (int i = elite; i < Simulation.ROCKET_NUM; i++)
        {
            int parent = rouletteSelection(totalFitness);
            int r      = Random.Range(0, 3);
            if (r == 0)
            {
                nextIndividuals[i].prevFitness = trFit[i] * trFit[parent];
                nextIndividuals[i].Crossover(curIndividuals[i], curIndividuals[parent]);
            }
            else if (r == 1)
            {
                nextIndividuals[i].prevFitness = trFit[i] * trFit[parent];
                nextIndividuals[i].Crossover(curIndividuals[parent], curIndividuals[i]);
            }
            else
            {
                int anotherParent = rouletteSelection(totalFitness);
                nextIndividuals[i].prevFitness = trFit[anotherParent] * trFit[parent];
                nextIndividuals[i].Crossover(curIndividuals[parent], curIndividuals[anotherParent]);
            }
        }

        // 突然変異
        for (int i = superElite; i < Simulation.ROCKET_NUM; i++)
        {
            nextIndividuals[i].Mutate();
        }

        // 次世代に受け継ぐ
        Rocket[] tmp = new Rocket[Simulation.ROCKET_NUM];
        curIndividuals.CopyTo(tmp, 0);
        nextIndividuals.CopyTo(curIndividuals, 0);
        tmp.CopyTo(nextIndividuals, 0);

        // reset all rockets
        for (int i = 0; i < Simulation.ROCKET_NUM; i++)
        {
            curIndividuals[i].Reset();
        }
    }