Example #1
0
        /// <summary>
        /// Breed
        /// </summary>
        private void Breed()
        {
            // Logs Setup
            int weightMutationNb          = 0;
            int addConnectionNb           = 0;
            int addNodeNb                 = 0;
            int enableDisableConnectionNb = 0;

            _mutationLogs = "";

            while (_nextEvaluationGenomes.Count() < _config.populationSize)
            {
                Genome child = null;
                Genome mom   = null;
                Genome dad   = null;

                // Get Child

                Species species   = null;
                int     maxToKeep = ((_config.populationSize * _config.percentageToKeep) / 100) - 1;
                if (_config.species)
                {
                    species = GetRandomSpecies(_r);
                }
                if (_config.crossover)
                {
                    if (species != null)
                    {
                        mom = GetRandomGenome(species, _r);
                        dad = GetRandomGenome(species, _r);
                    }
                    else
                    {
                        mom = _genomes[UnityEngine.Random.Range(0, maxToKeep)];
                        dad = _genomes[UnityEngine.Random.Range(0, maxToKeep)];
                    }

                    // Crossover between Mom & Dad
                    child = mom.Fitness >= dad.Fitness ? Genome.Crossover(mom, dad, _r, _config.disabledConnectionInheritChance) : Genome.Crossover(dad, mom, _r, _config.disabledConnectionInheritChance);
                }
                else
                {
                    child = species != null ? new Genome(GetRandomGenome(species, _r)) : new Genome(_genomes[UnityEngine.Random.Range(0, maxToKeep)]);
                }

                // Weights Mutation
                if ((float)_r.NextDouble() < _config.mutationRate)
                {
                    child.WeightsMutation(_r);
                    weightMutationNb++;
                }

                if (_config.genomeMutations)
                {
                    // Add Connection Mutation
                    if ((float)_r.NextDouble() < _config.addConnectionRate)
                    {
                        // If for Logs
                        if (child.AddConnectionMutation(_r, _connectionInnovation, 10))
                        {
                            addConnectionNb++;
                        }
                    }

                    // Add Node Mutation
                    if ((float)_r.NextDouble() < _config.addNodeRate)
                    {
                        child.AddNodeMutation(_r, _connectionInnovation, _nodeInnovation);
                        addNodeNb++;
                    }

                    // Enable/Disable a Random Connection
                    if ((float)_r.NextDouble() < _config.enableDisableRate)
                    {
                        // If for Logs
                        if (child.EnableOrDisableRandomConnection())
                        {
                            enableDisableConnectionNb++;
                        }
                    }
                }

                // Add Child to Next Evaluation Genomes
                _nextEvaluationGenomes.Add(child);
            }

            _mutationLogs += string.Format(
                "Weights Mutation: {0}, Add Connection: {1}, Add Node: {2}, Enable/Disable Connection: {3}\nCrossover is {4}, Genome Mutations is {5}, Species is {6}",
                weightMutationNb,
                addConnectionNb,
                addNodeNb,
                enableDisableConnectionNb,
                _config.crossover,
                _config.genomeMutations,
                _config.species
                );

            _genomes.Clear();
            _genomes = new List <Genome>(_nextEvaluationGenomes);
            _nextEvaluationGenomes = new List <Genome>();
        }
        // Runs one generation

        public void Evaluate()
        {
            // Reset everything for next generation
            foreach (Species s in species)
            {
                s.Reset(random);
            }
            fitnessMap.Clear();
            speciesMap.Clear();
            nextGenGenomes.Clear();
            highestFitness = float.MinValue;
            fittestGenome  = null;

            // Place genomes into species
            foreach (Genome g in genomes)
            {
                bool foundSpecies = false;
                foreach (Species s in species)
                {
                    if (Genome.CompatibilityDistance(g, s.mascot, C1, C2, C3) < DT)
                    { // compatibility distance is less than DT, so genome belongs to this species
                        s.members.Add(g);
                        speciesMap[g] = s;
                        foundSpecies  = true;
                        break;
                    }
                }
                if (!foundSpecies)
                { // if there is no appropiate species for genome, make a new one
                    Species newSpecies = new Species(g);
                    species.Add(newSpecies);
                    speciesMap[g] = newSpecies;
                }
            }

            // Remove unused species

            foreach (Species s in species)
            {
                if (!s.members.Any())
                {
                    species.Remove(s);
                }
            }


            // Evaluate genomes and assign score
            foreach (Genome g in genomes)
            {
                Species s = speciesMap[g];               // Get species of the genome

                float score         = evaluateGenome(g); // fitness of Genome
                float adjustedScore = score / speciesMap[g].members.Count;

                s.AddAdjustedFitness(adjustedScore);
                s.fitnessPop.Add(new FitnessGenome(g, adjustedScore));
                fitnessMap[g] = adjustedScore;
                if (score > highestFitness)
                {
                    highestFitness = score;
                    fittestGenome  = g;
                }
            }

            // put best genome from each species into next generation
            // species = species.OrderByDescending(s => s.fitnessPop).ToList();
            foreach (Species s in species)
            {
                FitnessGenome fittestInSpecies = s.fitnessPop.Max();
                nextGenGenomes.Add(fittestInSpecies.genome);
            }

            // Breed the rest of the genomes
            while (nextGenGenomes.Count < populationSize)
            { // replace removed genomes by randomly breeding
                Species s = getRandomSpeciesBiasedAjdustedFitness(random);

                Genome p1 = getRandomGenomeBiasedAdjustedFitness(s, random);
                Genome p2 = getRandomGenomeBiasedAdjustedFitness(s, random);

                Genome child = new Genome();
                if (fitnessMap[p1] >= fitnessMap[p2])
                {
                    child.Crossover(p1, p2);
                }
                else
                {
                    child.Crossover(p2, p1);
                }
                if (Random.Range(0f, 1f) < MUTATION_RATE)
                {
                    child.Mutation();
                }
                if (Random.Range(0f, 1f) < ADD_CONNECTION_RATE)
                {
                    //Debug.Log("Adding connection mutation...");
                    child.AddConnectionMutation(connectionInnovation, 10);
                }
                if (Random.Range(0f, 1f) < ADD_NODE_RATE)
                {
                    //Debug.Log("Adding node mutation...");
                    child.AddNodeMutation(connectionInnovation, nodeInnovation);
                }
                nextGenGenomes.Add(child);
            }

            genomes        = nextGenGenomes;
            nextGenGenomes = new List <Genome>();
        }
Example #3
0
        /// <summary>
        /// Breed
        /// </summary>
        private Genome Breed(Genome mom = null, Genome dad = null)
        {
            Genome child = null;

            // Get Child
            if (dad != null && mom != null)
            {
                // Crossover between Mom & Dad
                if (mom.Fitness >= dad.Fitness)
                {
                    child = Genome.Crossover(mom, dad, _r, _config.disabledConnectionInheritChance);
                }
                else
                {
                    child = Genome.Crossover(dad, mom, _r, _config.disabledConnectionInheritChance);
                }
            }
            else
            {
                int maxToKeep = ((_currentPop * _config.percentageToKeep) / 100) - 1;
                mom = _genomes[UnityEngine.Random.Range(0, maxToKeep)];
                dad = _genomes[UnityEngine.Random.Range(0, maxToKeep)];

                // Crossover between Mom & Dad
                if (mom.Fitness >= dad.Fitness)
                {
                    child = Genome.Crossover(mom, dad, _r, _config.disabledConnectionInheritChance);
                }
                else
                {
                    child = Genome.Crossover(dad, mom, _r, _config.disabledConnectionInheritChance);
                }
            }

            // Weights Mutation
            if ((float)_r.NextDouble() < _config.mutationRate)
            {
                child.WeightsMutation(_r);
            }

            if (_config.genomeMutations)
            {
                // Add Connection Mutation
                if ((float)_r.NextDouble() < _config.addConnectionRate)
                {
                    child.AddConnectionMutation(_r, _connectionInnovation, 10);
                }

                // Add Node Mutation
                if ((float)_r.NextDouble() < _config.addNodeRate)
                {
                    child.AddNodeMutation(_r, _connectionInnovation, _nodeInnovation);
                }

                // Enable/Disable a Random Connection
                if ((float)_r.NextDouble() < _config.enableDisableRate)
                {
                    child.EnableOrDisableRandomConnection();
                }
            }
            return(child);
        }