Example #1
0
    public GeneticAlgorithm(int size, int inputs, int hidden, int[] hiddenNodes, int outputs)
    {
        populationSize         = size;
        currentGeneration      = 0;
        innovations            = null;
        nextGenomeID           = 0;
        nextSpeciesID          = 0;
        FittestGenome          = 0;
        bestFitnessSoFar       = 0;
        totalAdjustedFitness   = 0;
        averageAdjustedFitness = 0;

        genomes     = new List <Genome>();
        bestGenomes = new List <Genome>();
        species     = new List <Species>();
        oldGenomes  = new List <List <Genome> >();

        for (int i = 0; i < size; i++)
        {
            genomes.Add(new Genome(nextGenomeID, inputs, hidden, hiddenNodes, outputs, new Genome.MutParameters()));
            nextGenomeID++;
        }

        Genome genome = new Genome(nextGenomeID, inputs, hidden, hiddenNodes, outputs, new Genome.MutParameters());

        innovations = new Innovations(genome.GetConnectionGenes(), genome.GetPerceptronGenes());
        GA_Parameters.maxSpecies = GA_Parameters.populationSize - 1;
    }
        /// <summary>
        /// Create a new innovation.
        /// </summary>
        /// <param name="input">The input neuron.</param>
        /// <param name="output">The output neuron.</param>
        /// <param name="type">The type.</param>
        public void CreateNewInnovation(long input, long output,
                                        NEATInnovationType type)
        {
            NEATInnovation newInnovation = new NEATInnovation(input, output, type,
                                                              this.population.AssignInnovationID());

            if (type == NEATInnovationType.NewNeuron)
            {
                newInnovation.NeuronID = AssignNeuronID();
            }

            Innovations.Add(newInnovation);
        }
        /// <summary>
        /// Create a new innovation.
        /// </summary>
        /// <param name="from">The from neuron.</param>
        /// <param name="to">The to neuron.</param>
        /// <param name="innovationType">The innovation type.</param>
        /// <param name="neuronType">The neuron type.</param>
        /// <param name="x">The x-coordinate.</param>
        /// <param name="y">The y-coordinate.</param>
        /// <returns>The new innovation.</returns>
        public long CreateNewInnovation(long from, long to,
                                        NEATInnovationType innovationType,
                                        NEATNeuronType neuronType, double x, double y)
        {
            NEATInnovation newInnovation = new NEATInnovation(from, to,
                                                              innovationType, population.AssignInnovationID(), neuronType, x, y);

            if (innovationType == NEATInnovationType.NewNeuron)
            {
                newInnovation.NeuronID = AssignNeuronID();
            }

            Innovations.Add(newInnovation);

            return(this.nextNeuronID - 1);  // ??????? should it be innov?
        }
        /// <summary>
        /// Construct an innovation list.
        /// </summary>
        /// <param name="population">The population.</param>
        /// <param name="links">The links.</param>
        /// <param name="neurons">The neurons.</param>
        public NEATInnovationList(IPopulation population, Chromosome links, Chromosome neurons)
        {
            this.population = population;
            foreach (IGene gene in neurons.Genes)
            {
                NEATNeuronGene neuronGene = (NEATNeuronGene)gene;

                NEATInnovation innovation = new NEATInnovation(neuronGene,
                                                               population.AssignInnovationID(), AssignNeuronID());

                Innovations.Add(innovation);
            }

            foreach (IGene gene in links.Genes)
            {
                NEATLinkGene   linkGene   = (NEATLinkGene)gene;
                NEATInnovation innovation = new NEATInnovation(linkGene
                                                               .FromNeuronID, linkGene.ToNeuronID,
                                                               NEATInnovationType.NewLink, this.population.AssignInnovationID());
                Innovations.Add(innovation);
            }
        }
Example #5
0
    public void RemoveNeuron(float mutationRate, ref Innovations innovation)
    {
        if (Random.Range(0f, 1f) > mutationRate)
        {
            return;
        }
        int[] numIn  = new int[perceptrons.Count];
        int[] numOut = new int[perceptrons.Count];

        for (int i = 0; i < connections.Count; i++)
        {
            ConnectionGene connection = connections[i];
            //Debug.Log("To: " + GetElementPos(connection.to) + " From: " + GetElementPos(connection.from) + " Count: " + perceptrons.Count);
            numIn[GetElementPos(connection.to)]++;
            numOut[GetElementPos(connection.from)]++;
        }

        List <int> removalCandidates = new List <int>();

        for (int i = 0; i < perceptrons.Count; i++)
        {
            if ((numIn[i] <= 1 || numOut[i] <= 1) && perceptrons[i].type == NodeType.Hidden)
            {
                removalCandidates.Add(i);
            }
        }

        if (removalCandidates.Count == 0)
        {
            return;
        }

        int removePercep = removalCandidates[Random.Range(0, removalCandidates.Count)];

        List <int> inConn        = new List <int>();
        List <int> outConn       = new List <int>();
        int        recurrentConn = -1;

        for (int i = 0; i < connections.Count; i++)
        {
            if (GetElementPos(connections[i].from) == removePercep && GetElementPos(connections[i].to) != removePercep)
            {
                outConn.Add(i);
            }
            else if (GetElementPos(connections[i].to) == removePercep && GetElementPos(connections[i].from) != removePercep)
            {
                inConn.Add(i);
            }
            else if (GetElementPos(connections[i].to) == removePercep && GetElementPos(connections[i].from) == removePercep)
            {
                recurrentConn = i;
            }
        }

        List <ConnectionGene> addConnections = new List <ConnectionGene>();

        for (int i = 0; i < inConn.Count; i++)
        {
            for (int j = 0; j < outConn.Count; j++)
            {
                int percep1 = connections[inConn[i]].from;
                int percep2 = connections[outConn[j]].to;

                if (DuplicateLink(percep1, percep2))
                {
                    continue;
                }

                int innovID = innovation.CheckInnovation(percep1, percep2, InnovationType.Connection);

                if (innovID < 0)
                {
                    innovation.CreateNewInnovation(percep1, percep2, InnovationType.Connection);

                    int id = innovation.NextNumber() - 1;

                    ConnectionGene gene = new ConnectionGene(percep1, percep2, true, id, Random.Range(-1f, 1f), false);

                    addConnections.Add(gene);
                }
                else
                {
                    ConnectionGene gene = new ConnectionGene(percep1, percep2, true, innovID, Random.Range(-1f, 1f), false);
                    addConnections.Add(gene);
                }
            }
        }

        List <int> removeRange = new List <int>();

        removeRange.AddRange(inConn);
        removeRange.AddRange(outConn);
        if (recurrentConn >= 0)
        {
            removeRange.Add(recurrentConn);
        }

        removeRange.Sort();

        for (int i = removeRange.Count - 1; i > -1; i--)
        {
            connections.RemoveAt(removeRange[i]);
        }

        for (int i = 0; i > addConnections.Count; i++)
        {
            connections.Add(addConnections[i]);
        }


        perceptrons.RemoveAt(removePercep);
    }
Example #6
0
    public void AddNeuron(float mutationRate, ref Innovations innovation, int trysFindOldLink)
    {
        for (int i = 0; i < 20; i++)
        {
            if (Random.Range(0f, 1f) > mutationRate)
            {
                return;
            }

            bool done = false;

            int chosenLink = 0;

            int sizeThreshHold = inputs + outputs + 10;

            int from;
            int to;

            if (connections.Count < sizeThreshHold)
            {
                while (trysFindOldLink > 0)
                {
                    chosenLink = Random.Range(0, NumGenes() - 1 - (int)Mathf.Sqrt((float)NumGenes()));
                    Debug.Log(chosenLink);
                    from = connections[chosenLink].from;

                    if (connections[chosenLink].enabled && !connections[chosenLink].recurrent && perceptrons[GetElementPos(from)].type != NodeType.Bias)
                    {
                        done            = true;
                        trysFindOldLink = 0;
                    }
                    trysFindOldLink--;
                }

                if (!done)
                {
                    return;
                }
            }
            else
            {
                while (!done)
                {
                    chosenLink = Random.Range(0, NumGenes() - 1);

                    from = connections[chosenLink].from;
                    if (connections[chosenLink].enabled && !connections[chosenLink].recurrent && perceptrons[GetElementPos(from)].type != NodeType.Bias)
                    {
                        done = true;
                    }
                }
            }

            // Think about this part
            //NodeType type = NodeType.Hidden;
            //if (CParams::bAdaptable && RandFloat() < CParams::dModulatoryChance)
            //{
            //    type = modulatory;
            //}

            connections[chosenLink].enabled = false;
            float orignalWeight = connections[chosenLink].weight;

            from = connections[chosenLink].from;
            to   = connections[chosenLink].to;

            Vector2 splitValues  = (perceptrons[GetElementPos(from)].splitValues + perceptrons[GetElementPos(to)].splitValues) / 2;
            int     connectionID = innovation.CheckInnovation(from, to, InnovationType.Perceptron);

            if (connectionID >= 0)
            {
                int ID = innovation.GetNeuronID(connectionID);

                if (AlreadyHaveThisNeuronID(ID))
                {
                    connectionID = -1;
                }
            }

            if (connectionID < 0)
            {
                int ID = innovation.CreateNewInnovation(from, to, InnovationType.Perceptron, NodeType.Hidden, splitValues);

                perceptrons.Add(new NodeGene(NodeType.Hidden, ID, splitValues));
                int link1 = innovation.NextNumber();
                innovation.CreateNewInnovation(from, ID, InnovationType.Connection);
                ConnectionGene link1Gene = new ConnectionGene(from, ID, true, link1, 1.0f);
                connections.Add(link1Gene);

                int link2 = innovation.NextNumber();
                innovation.CreateNewInnovation(ID, to, InnovationType.Connection);
                ConnectionGene link2Gene = new ConnectionGene(ID, to, true, link2, orignalWeight);
                connections.Add(link2Gene);
            }
            else
            {
                int ID = innovation.GetNeuronID(connectionID);

                int link1 = innovation.CheckInnovation(from, ID, InnovationType.Connection);
                int link2 = innovation.CheckInnovation(ID, to, InnovationType.Connection);

                if (link1 < 0 || link2 < 0)
                {
                    Debug.LogWarning("Innovation should already exist");
                    return;
                }

                ConnectionGene link1Gene = new ConnectionGene(from, ID, true, link1, 1.0f);
                ConnectionGene link2Gene = new ConnectionGene(ID, to, true, link2, orignalWeight);

                connections.Add(link1Gene);
                connections.Add(link2Gene);

                NodeGene perceptron = new NodeGene(NodeType.Hidden, ID, splitValues);

                perceptrons.Add(perceptron);
            }
        }
    }
Example #7
0
    public void AddLink(float mutationRate, float loopChance, ref Innovations innovation, int trysToFindLoop, int trysToAddLink)
    {
        if (Random.Range(0f, 1f) > mutationRate)
        {
            return;
        }

        int percep1 = -1;
        int percep2 = -1;

        bool recurrent = false;

        if (Random.Range(0f, 1f) < loopChance)
        {
            while (trysToFindLoop > 0)
            {
                int percepPos = Random.Range(inputs, perceptrons.Count - 1);

                if (!perceptrons[percepPos].recurrent && perceptrons[percepPos].type != NodeType.Bias && perceptrons[percepPos].type != NodeType.Sensor && perceptrons[percepPos].type != NodeType.Output)
                {
                    percep1 = perceptrons[percepPos].ID;
                    percep2 = percep1;

                    perceptrons[percepPos].recurrent = true;

                    recurrent = true;


                    trysToFindLoop = 0;
                }
                trysToFindLoop--;
            }
        }
        else
        {
            while (trysToAddLink > 0)
            {
                percep1 = perceptrons[Random.Range(0, perceptrons.Count - 1)].ID;
                percep2 = perceptrons[Random.Range(inputs, perceptrons.Count - 1)].ID;

                if (DuplicateLink(percep1, percep2) || percep1 == percep2 ||
                    (perceptrons[GetElementPos(percep1)].type == NodeType.Sensor && perceptrons[GetElementPos(percep2)].type == NodeType.Sensor) ||
                    (perceptrons[GetElementPos(percep1)].type == NodeType.Output && perceptrons[GetElementPos(percep2)].type == NodeType.Output) ||
                    (perceptrons[GetElementPos(percep1)].type == NodeType.Output && perceptrons[GetElementPos(percep2)].type == NodeType.Sensor) ||
                    perceptrons[GetElementPos(percep2)].type == NodeType.Sensor || perceptrons[GetElementPos(percep2)].type == NodeType.Bias)
                {
                    percep1 = -1;
                    percep2 = -1;
                }
                else
                {
                    trysToAddLink = 0;
                }
                trysToAddLink--;
            }
        }

        if (percep1 < 0 || percep2 < 0)
        {
            return;
        }

        int innovID = innovation.CheckInnovation(percep1, percep2, InnovationType.Connection);

        if (perceptrons[GetElementPos(percep1)].splitValues.x - perceptrons[GetElementPos(percep2)].splitValues.x > 0.01f)
        {
            recurrent = true;
        }
        if (innovID < 0)
        {
            innovation.CreateNewInnovation(percep1, percep2, InnovationType.Connection);

            int id = innovation.NextNumber() - 1;

            ConnectionGene gene = new ConnectionGene(percep1, percep2, true, id, Random.Range(-1f, 1f), recurrent);

            connections.Add(gene);
        }
        else
        {
            ConnectionGene gene = new ConnectionGene(percep1, percep2, true, innovID, Random.Range(-1f, 1f), recurrent);
            connections.Add(gene);
        }
    }
        /// <summary>
        /// Perform a cross over.
        /// </summary>
        /// <param name="mom">The mother genome.</param>
        /// <param name="dad">The father genome.</param>
        /// <returns></returns>
        public new NEATGenome Crossover(NEATGenome mom, NEATGenome dad)
        {
            NEATParent best;

            // first determine who is more fit, the mother or the father?
            if (mom.Score == dad.Score)
            {
                if (mom.NumGenes == dad.NumGenes)
                {
                    if (ThreadSafeRandom.NextDouble() > 0)
                    {
                        best = NEATParent.Mom;
                    }
                    else
                    {
                        best = NEATParent.Dad;
                    }
                }

                else
                {
                    if (mom.NumGenes < dad.NumGenes)
                    {
                        best = NEATParent.Mom;
                    }
                    else
                    {
                        best = NEATParent.Dad;
                    }
                }
            }
            else
            {
                if (Comparator.IsBetterThan(mom.Score, dad.Score))
                {
                    best = NEATParent.Mom;
                }

                else
                {
                    best = NEATParent.Dad;
                }
            }

            var babyNeurons = new Chromosome();
            var babyGenes   = new Chromosome();

            var vecNeurons = new List <long>();

            int curMom = 0;
            int curDad = 0;

            NEATLinkGene momGene;
            NEATLinkGene dadGene;

            NEATLinkGene selectedGene = null;

            while ((curMom < mom.NumGenes) || (curDad < dad.NumGenes))
            {
                if (curMom < mom.NumGenes)
                {
                    momGene = (NEATLinkGene)mom.Links.Get(curMom);
                }
                else
                {
                    momGene = null;
                }

                if (curDad < dad.NumGenes)
                {
                    dadGene = (NEATLinkGene)dad.Links.Get(curDad);
                }
                else
                {
                    dadGene = null;
                }

                if ((momGene == null) && (dadGene != null))
                {
                    if (best == NEATParent.Dad)
                    {
                        selectedGene = dadGene;
                    }
                    curDad++;
                }
                else if ((dadGene == null) && (momGene != null))
                {
                    if (best == NEATParent.Mom)
                    {
                        selectedGene = momGene;
                    }
                    curMom++;
                }
                else if (momGene.InnovationId < dadGene.InnovationId)
                {
                    if (best == NEATParent.Mom)
                    {
                        selectedGene = momGene;
                    }
                    curMom++;
                }
                else if (dadGene.InnovationId < momGene.InnovationId)
                {
                    if (best == NEATParent.Dad)
                    {
                        selectedGene = dadGene;
                    }
                    curDad++;
                }
                else if (dadGene.InnovationId == momGene.InnovationId)
                {
                    if (ThreadSafeRandom.NextDouble() < 0.5f)
                    {
                        selectedGene = momGene;
                    }

                    else
                    {
                        selectedGene = dadGene;
                    }
                    curMom++;
                    curDad++;
                }

                if (babyGenes.Size() == 0)
                {
                    babyGenes.Add(selectedGene);
                }

                else
                {
                    if (((NEATLinkGene)babyGenes.Get(babyGenes.Size() - 1))
                        .InnovationId != selectedGene.InnovationId)
                    {
                        babyGenes.Add(selectedGene);
                    }
                }

                // Check if we already have the nodes referred to in SelectedGene.
                // If not, they need to be added.
                AddNeuronID(selectedGene.FromNeuronID, vecNeurons);
                AddNeuronID(selectedGene.ToNeuronID, vecNeurons);
            } // end while

            // now create the required nodes. First sort them into order
            vecNeurons.Sort();

            for (int i = 0; i < vecNeurons.Count; i++)
            {
                babyNeurons.Add(Innovations.CreateNeuronFromID(
                                    vecNeurons[i]));
            }

            // finally, create the genome
            var babyGenome = new NEATGenome(Population
                                            .AssignGenomeID(), babyNeurons, babyGenes, mom.InputCount,
                                            mom.OutputCount);

            babyGenome.GA         = this;
            babyGenome.Population = Population;

            return(babyGenome);
        }