示例#1
0
        private void SpawnCreatures(BitArray newGenome)
        {
            GameObject creaturesParent = new GameObject("creatures");

            _parents.Add(creaturesParent);
            for (int i = 0; i < CreatureAmount; i++)
            {
                CreatureBehaviour creature = Instantiate(Resources.Load("Prefabs/creature") as GameObject).GetComponent <CreatureBehaviour>();

                if (newGenome != null)
                {
                    newGenome = GeneticAlgorithm.Mutation(newGenome);
                    creature.Genome.SetGenome(newGenome);
                }
                else
                {
                    creature.Genome.BaseMass     = Random.Range(1f, 10f);
                    creature.Genome.VisionLength = 2f;
                }

                Vector2 screenBounds = new Vector2(Width, Height);
                creature.transform.position = Camera.main.ScreenToWorldPoint(new Vector2(Random.Range(0f, screenBounds.x), Random.Range(0f, screenBounds.y)));
                creature.transform.Rotate(0, 0, Random.Range(0, 360));

                creature.transform.SetParent(creaturesParent.transform, true);

                _creatures.Add(creature);
            }
        }
        private static CreatureBehaviour ChooseWinner(CreatureBehaviour[] candidates)
        {
            float             random = Random.value;
            CreatureBehaviour winner = null;

            candidates = candidates.OrderBy(x => x.AccumulatedNormalizedFitness).ToArray();  // Make sure the list is ordered right (high norm fitness = better score)

            //foreach (CreatureBehaviour candidate in candidates.Reverse()) // Wikipedia doesn't mention reversing the list, but if we don't then we will always pick the latest one in the list (with the highest accNormFitness)
            //    if (candidate.AccumulatedNormalizedFitness >= random)
            //        winner = candidate;
            foreach (CreatureBehaviour candidate in candidates) // Isn't this a better option? This way if random = 0.9, the closest one below 0.9 would be taken instead of the ones above 0.9 (higher accumulated fitness, the worse you are)
            {
                if (candidate.AccumulatedNormalizedFitness <= random)
                {
                    winner = candidate;
                }
            }

            // If we have no winner, take the best one (fallback)
            // TODO: I don't know why we won't always take the best one? Is it to introduce more diversity? Is mutation not enough for this?
            if (!winner)
            {
                winner = candidates.First();
            }

            Debug.Log($"Winner fitness: {winner.Fitness}, Best fitness: {candidates.Max(x => x.Fitness)}");

            return(winner);
        }
示例#3
0
        public void OnCollisionEnter2D(Collision2D col)
        {
            CreatureBehaviour creature = col.collider.gameObject.GetComponent <CreatureBehaviour>();

            if (creature != null)
            {
                creature.Die();
            }
        }
        public static CreatureBehaviour[] GetParents(List <CreatureBehaviour> candidates)
        {
            CreatureBehaviour parent1 = CalculateWinner(candidates);

            candidates.Remove(parent1);
            CreatureBehaviour parent2 = CalculateWinner(candidates);

            return(new CreatureBehaviour[] { parent1, parent2 });
        }
        // Selection
        //  1. Normalize each fitness (normFitness = fitness / sum(allFitnesses)), so that the sum of all fitnesses is 1
        //  2. Sort population desc fitness
        //  3. Accumulate normalized fitnesses (accFitness = normFitness + allPreviousNormFitnesses)
        //      ex: accFitness1 would be (normFitness1), accFitness2 would be (normFitness2 + normFitness1)
        //          accFitness3 would be (normFitness3 + normFitness2 + normFitness1) ...
        //  4. Choose random number R between 0 and 1
        //  5. Winner is the last one whose accFitness >= R
        // https://en.wikipedia.org/wiki/Selection_(genetic_algorithm)
        public static CreatureBehaviour CalculateWinner(List <CreatureBehaviour> candidates)
        {
            // Calculate total fitness of all candidates summed together
            float totalFitnesses = candidates.Select(x => x.Fitness).Sum();

            // Normalize fitnesses
            candidates.ForEach(x => x.NormalizedFitness = NormalizeFitness(x.Fitness, totalFitnesses));

            // Sort by descending fitness
            candidates = candidates.OrderByDescending(x => x.Fitness).ToList();

            // Accumulate normalized fitnesses
            foreach (CreatureBehaviour candidate in candidates)
            {
                int     index             = candidates.IndexOf(candidate);
                float[] previousFitnesses = candidates.GetRange(0, index).Select(x => x.NormalizedFitness).ToArray();
                candidate.AccumulatedNormalizedFitness = AccumulateNormalizedFitness(candidate.NormalizedFitness, previousFitnesses);
            }

            // Choose winner
            CreatureBehaviour winner = ChooseWinner(candidates.ToArray());

            return(winner);
        }