public void GenerateInitalPopulation() { population = new List <GeneticPlayer>(); aliveCount = populationCount; for (int i = 0; i < populationCount; i++) { Vector3 pos = GetPos(i); GeneticPlayer geneticPlayer = Instantiate(geneticPlayerPrefab, pos, Quaternion.Euler(spawnRotation)); Genom genom; if (geneticPlayerPrefab.mode == Mode.LoadAndTrain) { genom = Genom.LoadFromFile(geneticPlayerPrefab.GetSavePath()); if (i > 0) { genom = Genom.MutateAll(genom, 0.01f); } } else { genom = geneticPlayer.InitGenom(); genom.RandomizeAll(); //случайные гены } geneticPlayer.SetGenom(genom); population.Add(geneticPlayer); } }
// Update is called once per frame void Update() { if (aliveCount <= 0 && generation < maxGenerations) { //сортровка по score population.Sort((x, y) => (y.score.CompareTo(x.score))); GeneticPlayer best = population[0]; Debug.Log("generation " + generation + " best \np1: " + best.score); if (bestScore < best.score) { bestScore = best.score; bestGenom = best.GetGenom(); Genom.SaveToFile(bestGenom, geneticPlayerPrefab.GetSavePath()); } Debug.Log("global best score: " + bestScore); /* * передавая отсортированный список генов всех особей можно всегда надеятся, * что гены лучшей особи передадутся самому большому кол-ву детей. * но если разнится между 1 и 2 коосальная, есть ли смысл оставлять гены второго в популяции? * (возможно, стоит переделать сам алгорим скрещевания) * ((но делать я этого, конечно же, не буду)) */ List <Genom> populationGenom = new List <Genom>(); foreach (GeneticPlayer p in population) { // коосальная разница = 50% if (p.score >= best.score * 0.5f) { populationGenom.Add(p.GetGenom()); } } /* * в список генов родителей 100% попадет хотя бы 1 ген - лучший. * если попадет только он - поколение сгенерируется на основе полных случайных мутаций лучшего */ GenerateNextPopulation(populationGenom); generation++; } }
//генерирует популяцию того же размера, что и предедущая public void GenerateNextPopulation(List <Genom> parents) { aliveCount = populationCount; for (int i = 0; i < populationCount; i++) { Destroy(population[i].gameObject); } List <Genom> childsGenes = Genom.GetChilds(parents, populationCount, true); for (int i = 0; i < populationCount; i++) { Vector3 pos = GetPos(i); GeneticPlayer geneticPlayer = Instantiate(geneticPlayerPrefab, pos, Quaternion.Euler(spawnRotation)); geneticPlayer.SetGenom(childsGenes[i]); geneticPlayer.name += " #" + i; population[i] = geneticPlayer; } }