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); } }
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); }
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); } } }
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); }