/// <summary> /// Calculate next size of species population using explicit fitness sharing distribution and breed previous generation asexually (elite) and sexually. /// </summary> private void TestFinished() { testCounter = 0; //reset test counter if (numberOfGenerationsToRun > 0) { //if computing generationNumber++; // increment generation number List <NEATNet> top = speciesManager.GetTopBrains(1); if (top != null && top.Count >= 1) { bestNet = new NEATNet(top[0]); //set best net from the best index bestNet.SetNetFitness(top[0].GetNetFitness()); lineGraph.GetComponent <DataDrawer>().PlotData(top[0].GetNetFitness(), "Generation Number: " + generationNumber + ", Highest Fitness: " + top[0].GetNetFitness() + ", Delta: " + consultor.GetDeltaThreshold()); //plot highest fitness on graph } netDrawer.SendMessage("DrawNet", bestNet); //Draw best network speciesManager.GenerateNewGeneration(populationSize); } //number of generation > 0 if (numberOfGenerationsToRun > 0) { //if computing numberOfGenerationsToRun--; //decrement number of generations to run progressBar.GetComponent <ProgressRadialBehaviour>().IncrementValue(currentIncrement); //increment progress bar by previously caluclated increment value GeneratePopulation(); //Generate population with neural networks } else { //done computing viewMode = false; //view is false computing = false; //computing is false SetCameraLocation(); //ser camera location back to panel } }
/// <summary> /// Get shared cumulative fitness of this population. /// </summary> /// <returns>Fitness</returns> public float GetDistribution(float beta) { float distribution = 0; for (int j = 0; j < population.Count; j++) { float sh = 0; for (int k = j; k < population.Count; k++) { if (k != j) { sh += NEATNet.SameSpeciesV2(population[j], population[k]) == true ? 1 : 0; } } if (sh == 0) { sh = 1; } float f = population[j].GetNetFitness(); if (f < 0) { f = 0; } distribution += Mathf.Pow(f, beta) / sh; } if (distribution < 0) { distribution = 0; } return(distribution); }
/// <summary> /// Create a gameobject to test /// </summary> /// <param name="position">Position to place the object in world space</param> /// <param name="net">Network to activate within this gameobject</param> /// <param name="color">Color of this gameobject</param> /// <param name="id">ID of this gameobject</param> private void CreateIndividual(Vector3 position, NEATNet net, Color color, int[] id, bool randomEular) { GameObject tester; if (randomEular) { tester = (GameObject)Instantiate(testPrefab, position, Quaternion.Euler(0, UnityEngine.Random.Range(0f, 360f), 0)); //Instantiate gameobject with prebaf with random angle } else { tester = (GameObject)Instantiate(testPrefab); //Instantiate gameobject with prebaf } tester.name = id[0] + "_" + id[1]; //set tester name to match id tester.SendMessage(ACTION_ACTIVATE, net); //activate tester with net tester.SendMessage(ACTION_SUBSCRIBE, this); tester.SendMessage("SetColor", color); //Commented out because the Tester object can have any class name //tester.GetComponent<Tester>().TestFinished += OnFinished; //subscribe to a delegate to know when a tester is finished its simulation /*Renderer renderer = tester.GetComponent<Renderer>(); * if (renderer!=null) { * renderer.material.color = color; //gave tester a color * } * * //color all children inside this object * for (int i = 0; i < tester.transform.childCount; i++) { * renderer = tester.transform.GetChild(i).GetComponent<Renderer>(); * if (renderer != null) { * renderer.material.color = color; //gave tester's children a color * } * }*/ }
/// <summary> /// Generating neural networks and consultor to test /// </summary> public void ActionCreateNew() { if (load == false) { //if loading from database is fasle consultor = new NEATConsultor(numberOfInputNeurons, numberOfOutputNeurons, deltaThreshold, disjointCoefficient, excessCoefficient, averageWeightDifferenceCoefficient); //create a consultor with perceptron and coefficients GenerateInitialNets(); //generate standard NEAT nets lineGraph.GetComponent <DataDrawer>().DisplayActionInformation("Action: New neural networks created"); //information for the user on action performed } else { //loading from database is true if (operations.retrieveNet == null) { consultor = new NEATConsultor(numberOfInputNeurons, numberOfOutputNeurons, deltaThreshold, disjointCoefficient, excessCoefficient, averageWeightDifferenceCoefficient); //create a consultor with perceptron and coefficients GenerateInitialNets(); //generate standard NEAT nets lineGraph.GetComponent <DataDrawer>().DisplayActionInformation("Action: New neural networks created"); //information for the user on action performed } else { consultor = new NEATConsultor(operations.retrieveNet[operations.retrieveNet.Length - 1], deltaThreshold, disjointCoefficient, excessCoefficient, averageWeightDifferenceCoefficient); //create a consultor with NEAT packet retrieved from database and coefficients NEATNet net = new NEATNet(operations.retrieveNet[operations.retrieveNet.Length - 1], consultor); //create a net from NEAT packet retrieved from database and consultor lineGraph.GetComponent <DataDrawer>().DisplayActionInformation("Action: Neural networks copied from sample"); //information for the user on action performed GenerateInitialNetsAsCopy(net); } } }
private void GenerateInitialNetsAsCopy(NEATNet net) { generationNumber = 0; //0 since simulaiton has no been started yet testCounter = 0; //none have been tested speciesManager = new Species(this); for (int i = 0; i < populationSize; i++) { //run through population size NEATNet netCopy = new NEATNet(net); //create net with consultor, perceptron information and test time netCopy.SetNetFitness(0f); netCopy.SetTimeLived(0f); netCopy.SetTestTime(testTime); netCopy.ClearNodeValues(); netCopy.GenerateNeuralNetworkFromGenome(); //< NEW LSES ADDITION Population population = speciesManager.ClosestSpecies(netCopy); if (population == null) { population = speciesManager.CreateNewSpecie(new Color(UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f))); population.Add(netCopy); } else { population.Add(netCopy); } } }
/// <summary> /// Generate initial neural network, where all inputs perceptrons are connected to all output perceptrons. /// Each of these nerual networks is mutated one time for slight change. /// And then they are paired up into species. /// </summary> private void GenerateInitialNets() { generationNumber = 0; //0 since simulaiton has no been started yet testCounter = 0; //none have been tested speciesManager = new Species(this); //species = new List<List<NEATNet>>(); //create an empty population list for (int i = 0; i < populationSize; i++) { //run through population size NEATNet net = new NEATNet(consultor, numberOfInputPerceptrons, numberOfOutputPerceptrons, testTime); //create net with consultor, perceptron information and test time net.Mutate(); //mutate once for diversity (must make sure SJW's aren't triggered) net.GenerateNeuralNetworkFromGenome(); //< NEW LSES ADDITION Population population = speciesManager.ClosestSpecies(net); if (population == null) { population = speciesManager.CreateNewSpecie(new Color(UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f))); population.Add(net); } else { population.Add(net); } /*if (species.Count == 0) { //if nothing exists yet * List<NEATNet> newSpecies = new List<NEATNet>(); //create a new species * newSpecies.Add(net); //add net to this new species * species.Add(newSpecies); //add new species to species list * } * else { //if at least one species exists * int numberOfSpecies = species.Count; //save species count * int location = -1; //-1 means no species match found, 0 >= will mean a species match has been found at a given index * * for (int j = 0; j < numberOfSpecies; j++) { //run through species count * int numberOfNets = species[j].Count; //number of organisum in species at index j * int randomIndex = UnityEngine.Random.Range(0, numberOfNets); //pick a random network within this species * * if (NEATNet.SameSpeciesV2(species[j][randomIndex], net)) { //check if new network and random network belong to the same species * location = j; //new species can be added to index j * break; //break out of loop * } * } * * if (location == -1) { //if no species found * //create new species and add to that * List<NEATNet> newSpecies = new List<NEATNet>(); * newSpecies.Add(net); * species.Add(newSpecies); * } * else { //found species that match this network * species[location].Add(net); //add net to the matched species list * } * }*/ } }
/// <summary> /// Save a given neural network into the databse by called the insert_genotype.php script with appropriate neural network information /// </summary> /// <param name="net">Neural network to save</param> /// <param name="name">Name of the neural network</param> /// <returns>Returns web information on executed url</returns> public IEnumerator SaveNet(NEATNet net, string name) { string page = insertPage; //insert page NEATConsultor consultor = net.GetConsultor(); //get consultor string genome = net.GetGenomeString(); //convert neural network genome to string string consultorGenome = consultor.GetGenomeString(); //convert master consultor genome to string int nodeTotal = net.GetNodeCount(); //node total to save int nodeInputs = net.GetNumberOfInputNodes(); //inputs to save int nodeOutputs = net.GetNumberOfOutputNodes(); //outputs to save int geneTotal = net.GetGeneCount(); //neural network gene count to save int genomeTotal = consultor.GetGeneCount(); //consultor genome gene count to save float fitness = Mathf.Clamp(net.GetNetFitness(), -100000000f, 100000000f); //net fitness to save, clamp it between -100000000 and 100000000 object yeildReturn = null; if (fileSaveMode == false) { page += "&creature_name=" + name + "&creature_fitness=" + fitness + "&node_total=" + nodeTotal + "&node_inputs=" + nodeInputs + "&node_outputs=" + nodeOutputs + "&gene_total=" + geneTotal + "&genome_total=" + genomeTotal + "&genome=" + genome + "&consultor_genome=" + consultorGenome; //create insert page url Debug.Log(page); web = new WWW(page); //run page yeildReturn = web; //yield return web; //return page when finished execution (retruns success echo if inserted corrected) } else { yeildReturn = true; StreamWriter writer = new StreamWriter(name + ".txt"); writer.WriteLine(fitness); writer.WriteLine(nodeTotal); writer.WriteLine(nodeInputs); writer.WriteLine(nodeOutputs); writer.WriteLine(geneTotal); writer.WriteLine(genomeTotal); writer.WriteLine(genome); writer.WriteLine(consultorGenome); writer.Close(); } yield return(yeildReturn); //return page when finished execution (retruns success echo if inserted corrected OR just true) }
/// <summary> /// Find closest species that match this brain /// </summary> /// <param name="brain">Brain to match</param> /// <returns>Species that matches else null</returns> public Population ClosestSpecies(NEATNet brain) { for (int i = 0; i < species.Count; i++) { if (NEATNet.SameSpeciesV2(species[i].GetRandom(), brain) == true) { return(species[i]); } } return(null); }
/// <summary> /// Get shared cumulative fitness of this population. /// </summary> /// <returns>Fitness</returns> public float GetDistribution(float beta) { //float sharedAmount = 0f; float distribution = 0; for (int j = 0; j < population.Count; j++) { /*for (int k = j + 1; k < population.Count; k++) * { * sharedAmount += NEATNet.SameSpeciesV2(population[j], population[k]) == true ? 1 : 0; * }*/ //correct method float sh = 0; for (int k = j; k < population.Count; k++) { if (k != j) { sh += NEATNet.SameSpeciesV2(population[j], population[k]) == true ? 1 : 0; } } if (sh == 0) { sh = 1; } float f = population[j].GetNetFitness(); if (f < 0) { f = 0; } distribution += Mathf.Pow(f, beta) / sh; } if (distribution < 0) { distribution = 0; } //Incorrect way of doing it /*if (sharedAmount == 0f) * { * sharedAmount = 1f; * } * distribution = Mathf.Pow(distribution,1.5f) / sharedAmount; */ return(distribution); }
/// <summary> /// Get the closest species that match a given brain /// </summary> /// <param name="species">Species to match</param> /// <param name="brain">Brain to match to species</param> /// <returns>A population if match otherwise null</returns> public static Population ClosestSpecies(List <Population> species, NEATNet brain) { for (int i = 0; i < species.Count; i++) { NEATNet random = species[i].GetRandom(); if (random == null || NEATNet.SameSpeciesV2(random, brain) == true) { return(species[i]); } } return(null); }
/// <summary> /// Create a gameobject to test /// </summary> /// <param name="position">Position to place the object in world space</param> /// <param name="net">Network to activate within this gameobject</param> /// <param name="color">Color of this gameobject</param> /// <param name="id">ID of this gameobject</param> private void CreateIndividual(Vector3 position, NEATNet net, Color color, int[] id, bool randomEular) { GameObject tester; if (randomEular) { tester = (GameObject)Instantiate(testPrefab, position, Quaternion.Euler(0, UnityEngine.Random.Range(0f, 360f), 0)); //Instantiate gameobject with prebaf with random angle } else { tester = (GameObject)Instantiate(testPrefab); //Instantiate gameobject with prebaf } tester.name = id[0] + "_" + id[1]; //set tester name to match id tester.SendMessage(ACTION_ACTIVATE, net); //activate tester with net tester.SendMessage(ACTION_SUBSCRIBE, this); tester.SendMessage("SetColor", color); }
/// <summary> /// Generating neural networks and consultor to test /// </summary> public void ActionCreateNew() { if (load == false) { //if loading from database is fasle consultor = new NEATConsultor(numberOfInputPerceptrons, numberOfOutputPerceptrons, deltaThreshold, disjointCoefficient, excessCoefficient, averageWeightDifferenceCoefficient); //create a consultor with perceptron and coefficients GenerateInitialNets(); //generate standard NEAT nets lineGraph.GetComponent <DataDrawer>().DisplayActionInformation("Action: New neural networks created"); //information for the user on action performed } else { //loading from database is true if (operations.retrieveNet == null) { consultor = new NEATConsultor(numberOfInputPerceptrons, numberOfOutputPerceptrons, deltaThreshold, disjointCoefficient, excessCoefficient, averageWeightDifferenceCoefficient); //create a consultor with perceptron and coefficients GenerateInitialNets(); //generate standard NEAT nets lineGraph.GetComponent <DataDrawer>().DisplayActionInformation("Action: New neural networks created"); //information for the user on action performed } else { consultor = new NEATConsultor(operations.retrieveNet[operations.retrieveNet.Length - 1], deltaThreshold, disjointCoefficient, excessCoefficient, averageWeightDifferenceCoefficient); //create a consultor with NEAT packet retrieved from database and coefficients NEATNet net = new NEATNet(operations.retrieveNet[operations.retrieveNet.Length - 1], consultor); //create a net from NEAT packet retrieved from database and consultor lineGraph.GetComponent <DataDrawer>().DisplayActionInformation("Action: Neural networks copied from sample"); //information for the user on action performed GenerateInitialNetsAsCopy(net); } //LOADING FROM DATABASE, REMOVE TEMPORARLY /*consultor = new NEATConsultor(operations.retrieveNet[operations.retrieveNet.Length-1], deltaThreshold, disjointCoefficient, excessCoefficient, averageWeightDifferenceCoefficient); //create a consultor with NEAT packet retrieved from database and coefficients * NEATNet net = new NEATNet(operations.retrieveNet[operations.retrieveNet.Length-1], consultor); //create a net from NEAT packet retrieved from database and consultor * * species = new List<List<NEATNet>>(); //create an empty population list * List<NEATNet> newSpecies = new List<NEATNet>(); //create new species * * for (int i = 0; i < populationSize; i++) { //populate new species * NEATNet netCopy = new NEATNet(net); //create a deep copy with net retrieved from database * * //reset copied stats * netCopy.SetNetFitness(0f); * netCopy.SetTimeLived(0f); * netCopy.SetTestTime(testTime); * netCopy.ClearNodeValues(); * newSpecies.Add(netCopy); //add copy to new species * } * species.Add(newSpecies); //add new species to species list * lineGraph.GetComponent<DataDrawer>().DisplayActionInformation("Action: Neural networks copied from sample"); //information for the user on action performed*/ } }
/// <summary> /// Add brain to this population if it matches /// </summary> /// <param name="brain">The brain to match</param> /// <returns>True if added, false if not</returns> public bool AddIfMatch(NEATNet brain) { if (population.Count == 0) { population.Add(brain); return(true); } else { if (NEATNet.SameSpeciesV2(GetRandom(), brain) == true) { population.Add(brain); return(true); } } return(false); }
/// <summary> /// Return brain with highest fitness /// </summary> /// <returns></returns> public NEATNet GetBestBrain() { NEATNet best = null; float highestFitness = float.MinValue; for (int i = 0; i < population.Count; i++) { NEATNet foundBest = population[i]; if (foundBest != null) { if (foundBest.GetNetFitness() > highestFitness) { highestFitness = foundBest.GetNetFitness(); best = foundBest; } } } return(best); }
/// <summary> /// Generate initial neural network, where all inputs neurons are connected to all output neurons. /// Each of these nerual networks is mutated one time for slight change. /// And then they are paired up into species. /// </summary> private void GenerateInitialNets() { generationNumber = 0; //0 since simulaiton has no been started yet testCounter = 0; //none have been tested speciesManager = new Species(this); //species = new List<List<NEATNet>>(); //create an empty population list for (int i = 0; i < populationSize; i++) { //run through population size NEATNet net = new NEATNet(consultor, numberOfInputNeurons, numberOfOutputNeurons, testTime); //create net with consultor, perceptron information and test time net.Mutate(); //mutate once for diversity (must make sure SJW's aren't triggered) net.GenerateNeuralNetworkFromGenome(); //< NEW LSES ADDITION Population population = speciesManager.ClosestSpecies(net); if (population == null) { population = speciesManager.CreateNewSpecie(new Color(UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f))); } population.Add(net); } }
/// <summary> /// Activated the agent when controller give it a brain. /// </summary> /// <param name="net">The brain</param> public void Activate(NEATNet net) { this.net = net; Invoke(ACTION_ON_FINISHED, net.GetTestTime()); isActive = true; }
/// <summary> /// Draw neural network /// </summary> /// <param name="net"></param> public void DrawNet(NEATNet net) { Clear(); // clear previous network // get network information from MEATNet int numberOfInputs = net.GetNumberOfInputNodes(); int numberOfOutputs = net.GetNumberOfOutputNodes(); int numberOfNodes = net.GetNodeCount(); int numberOfHiddens = numberOfNodes - (numberOfInputs + numberOfOutputs); int hiddenStartIndex = numberOfInputs + numberOfOutputs; locations = new Vector3[net.GetNodeCount()]; int locationIndex = 0; //Create input node objects float staryY = topLeft.y; for (int i = 0; i < numberOfInputs; i++) { Vector3 loc = new Vector3(topLeft.x, staryY, 0); GameObject node = (GameObject)Instantiate(nodePrefab, loc, nodePrefab.transform.rotation); node.transform.parent = transform; node.GetComponent <Renderer>().material.color = Color.green; nodeList.Add(node); staryY = staryY - (factor); locations[locationIndex] = loc; locationIndex++; } //create output node objects staryY = (topLeft.y); for (int i = numberOfInputs; i < hiddenStartIndex; i++) { Vector3 loc = new Vector3(topLeft.x + 7f, staryY, 0); GameObject node = (GameObject)Instantiate(nodePrefab, loc, nodePrefab.transform.rotation); node.transform.parent = transform; node.GetComponent <Renderer>().material.color = Color.white; nodeList.Add(node); staryY = staryY - (factor); locations[locationIndex] = loc; locationIndex++; } //create hidden nodes in a circle formation float xn = 0; float yn = 0; float angle = 0; for (int i = hiddenStartIndex; i < numberOfNodes; i++) { xn = Mathf.Sin(Mathf.Deg2Rad * angle) * (2 * factor); yn = Mathf.Cos(Mathf.Deg2Rad * angle) * (2 * factor); Vector3 loc = new Vector3(xn + (5f * factor) + topLeft.x, ((yn + topLeft.y) - (numberOfInputs / 2f)) - (7f * factor), 0); GameObject node = (GameObject)Instantiate(nodePrefab, loc, nodePrefab.transform.rotation); node.transform.parent = transform; node.GetComponent <Renderer>().material.color = Color.red; nodeList.Add(node); angle += (360f / numberOfHiddens); locations[locationIndex] = loc; locationIndex++; } float[][] geneConnections = net.GetGeneDrawConnections(); //get gene connection list int colSize = geneConnections.GetLength(0); //create line connection objects for (int i = 0; i < colSize; i++) { if (geneConnections[i][2] != 0f) { GameObject lineObj = (GameObject)Instantiate(linePrefab); lineObj.transform.parent = transform; lineList.Add(lineObj); LineRenderer lineRen = lineObj.GetComponent <LineRenderer>(); lineRen.SetPosition(0, locations[(int)geneConnections[i][0]]); if ((int)geneConnections[i][0] != (int)geneConnections[i][1]) { lineRen.SetPosition(1, locations[(int)geneConnections[i][1]]); } else { lineRen.SetPosition(1, locations[(int)geneConnections[i][1]] + new Vector3(1f, 0, 0)); } lineRen.material = new Material(Shader.Find("Particles/Additive")); float size = 0.1f; float weight = geneConnections[i][2]; float factor = Mathf.Abs(weight); Color color; if (weight > 0) { color = Color.green; } else if (weight < 0) { color = Color.red; } else { color = Color.cyan; } size = size * factor; if (size < 0.05f) { size = 0.05f; } if (size > 0.15f) { size = 0.15f; } lineRen.SetColors(color, color); lineRen.SetWidth(size, size); } } }
/// <summary> /// Add a member /// </summary> /// <param name="brain">new member</param> public void Add(NEATNet brain) { population.Add(brain); }
/// <summary> /// Calculate next size of species population using explicit fitness sharing distribution and breed previous generation asexually (elite) and sexually. /// </summary> private void TestFinished() { testCounter = 0; //reset test counter if (numberOfGenerationsToRun > 0) { //if computing generationNumber++; // increment generation number List <NEATNet> top = speciesManager.GetTopBrains(1); if (top != null && top.Count >= 1) { bestNet = new NEATNet(top[0]); //set best net from the best index bestNet.SetNetFitness(top[0].GetNetFitness()); lineGraph.GetComponent <DataDrawer>().PlotData(top[0].GetNetFitness(), "Generation Number: " + generationNumber + ", Highest Fitness: " + top[0].GetNetFitness() + ", Delta: " + consultor.GetDeltaThreshold()); //plot highest fitness on graph } netDrawer.SendMessage("DrawNet", bestNet); //Draw best network speciesManager.GenerateNewGeneration(populationSize); /*List<List<NEATNet>> bestSpecies = new List<List<NEATNet>>(); //50% best networks from each species list * * float[,] distribution = new float[species.Count,2]; //population distribution for species in the next generation * float totalSharedFitness = 0f; //total shared fitness of the whole population * float totalNetworks = 0f; //total number of organisums (used for distribution) * float highestFitness = 0f; //highest fitness to saved * * int[] bestIndex = new int[2]; //Index of best creature * * for (int i = 0; i < species.Count; i++) { //run through number of species * float sharedAmount = 0f; //number of networks in species at index i that can be stated to in the same species * //Question: Why not just make shared amount equal to species[i].Count? * //Answer: Due to the fact that when the network was chosen to be part of species[i], it was tested randomly with another network. * //We did not know if it would match other networks. * * distribution[i, 0] = i; //set index on first row * * for (int j = 0; j < species[i].Count; j++) { //run through number of networks at index i * float fitness = species[i][j].GetNetFitness(); * * distribution[i,1] += fitness; //get network fitness from species at index i, and network at j to second row of distribution * * if (fitness > highestFitness) { //if the fitness of the network is greater than highest fitness * highestFitness = fitness; //set new highest fitness * bestIndex[0] = i; bestIndex[1] = j; //change best index * } * * for (int k = j+1; k < species[i].Count; k++) { //run through rest of species * sharedAmount += NEATNet.SameSpeciesV2(species[i][j],species[i][k]) == true?1:0; //if 2 networks are in the same species, then increment shared amount by 1 * } * } * * if (sharedAmount == 0) { //if shared amount is 0 * sharedAmount = 1f; //make shared amount 1 to about division by 0 * } * * distribution[i,1] = distribution[i, 1] / sharedAmount; //converting total added fitness of species at index i to EXPICIT FITNESS * totalSharedFitness += distribution[i,1]; //add new EXPICIT FITNESS to total shared fitness * * float[,] sortedFitness = SortedFitnessIndicies(species[i]); //sort species at index i based on their rank (ascending order) * List<NEATNet> bestNetworks = new List<NEATNet>(); //List of best networks * * for (int j = sortedFitness.GetLength(0) / 2; j < sortedFitness.GetLength(0); j++) { //since it's ranked in ascending order, skip the first 50% of networks * bestNetworks.Add(species[i][(int)sortedFitness[j, 0]]); //add network from species at index i, and networks at j to best network list * } * * bestSpecies.Add(bestNetworks); //add best networks to species list * } * * distribution = SortFitness(distribution); //sort distribution * * bestNet = new NEATNet(species[bestIndex[0]][bestIndex[1]]); //set best net from the best index * bestNet.SetNetFitness(species[bestIndex[0]][bestIndex[1]].GetNetFitness()); * lineGraph.GetComponent<DataDrawer>().PlotData(highestFitness, "Generation Number: " + generationNumber + ", Highest Fitness: " + highestFitness + ", Delta: " + consultor.GetDeltaThreshold()); //plot highest fitness on graph * netDrawer.SendMessage("DrawNet",bestNet); //Draw best network * * for (int i = 0; i < distribution.GetLength(0); i++) { //run through all species (which have been sorted) * distribution[i, 1] = (int)((distribution[i, 1] / totalSharedFitness) * populationSize); //use rank distribution to calculate new population distribution for each species * totalNetworks += distribution[i, 1]; //add up new distribution * } * //The total networks will be slight less than population size due to int type casting on distribution. * //So, we much run another loop to insert the missing networks * * for (int i = 0; i < (populationSize - totalNetworks); i++) { //run the missing amount time (population size - total networks) * int highIndex = distribution.GetLength(0)/2; //since distribution was sort acending order, we will only add networks to the top 50% * int randomInsertIndex = UnityEngine.Random.Range(highIndex, distribution.GetLength(0)); //pick randomly from the top 50% * distribution[randomInsertIndex, 1]++; //increment some species population size in the top 50% * } * * species = new List<List<NEATNet>>(); //create an empty population list * * for (int i = 0; i < distribution.GetLength(0); i++) { //run through new population distribution of each species * if (distribution[i, 1] > 0) { //if distribution of species at index i is more than 0 * for (int j = 0; j < distribution[i, 1]; j++) { //run through new distribution size for index i * List<NEATNet> bestNetworks= bestSpecies[(int)distribution[i, 0]]; //Get best networks from nest species list * NEATNet net = null; //offspring which will represent the new network to add after sexual or asexual reproduction * * if (j > (float)distribution[i, 1] * elite) { //after 10% elite have been chosen * //logarithmic ranked pick to make sure highest fitness networks have a greater chance of being chosen than the less fit * float random = UnityEngine.Random.Range(1f, 100f); * float powerNeeded = Mathf.Log(bestNetworks.Count - 1, 100); * float logIndex = Mathf.Abs(((bestNetworks.Count - 1) - Mathf.Pow(random, powerNeeded))); * * NEATNet organism1 = bestNetworks[UnityEngine.Random.Range(0, bestNetworks.Count)]; //pick randomly from best networks * NEATNet organism2 = bestNetworks[(int)logIndex]; //use logarithmicly chosen random index from best network * * net = NEATNet.Corssover(bestNetworks[UnityEngine.Random.Range(0, bestNetworks.Count)], bestNetworks[UnityEngine.Random.Range(0, bestNetworks.Count)]); //crossover both networks to create an offspring * net.Mutate(); //mutate offspring * } * else { //pick % elite to keep safe * net = new NEATNet(bestNetworks[bestNetworks.Count-1]); //pick randomly and keep elite the same * } * * net.GenerateNeuralNetworkFromGenome(); //< NEW LSES ADDITION * * //reset copied stats * net.SetNetFitness(0f); * net.SetTimeLived(0f); * net.SetTestTime(testTime); * net.ClearNodeValues(); * * if (species.Count == 0) { //if nothing exists yet * List<NEATNet> newSpecies = new List<NEATNet>(); //create a new species * newSpecies.Add(net); //add net to this new species * species.Add(newSpecies); //add new species to species list * } * else { //if at least one species exists * int numberOfSpecies = species.Count; //save species count * int location = -1; //-1 means no species match found, 0 >= will mean a species match has been found at a given index * for (int k = 0; k < numberOfSpecies; k++) { //run through species count * int numberOfNets = species[k].Count; //number of organisum in species at index k * int randomIndex = UnityEngine.Random.Range(0, numberOfNets); //pick a random network within this species * if (NEATNet.SameSpeciesV2(species[k][randomIndex], net)) { //check if new network and random network belong to the same species * location = k; //new species can be added to index j * break; //break out of loop * } * } * * if (location == -1) { //if no species found * //create new species and add to that * List<NEATNet> newSpecies = new List<NEATNet>(); * newSpecies.Add(net); * //net.SetNetID(new int[] {species.Count, 0 }); //set new id * species.Add(newSpecies); //add net to new species * * } * else { //found species that match this network * //net.SetNetID(new int[] {location, species[location].Count}); //set new id * species[location].Add(net); //add net to the matched species list * } * } * } * } * }*/ } //number of generation > 0 if (numberOfGenerationsToRun > 0) { //if computing numberOfGenerationsToRun--; //decrement number of generations to run progressBar.GetComponent <ProgressRadialBehaviour>().IncrementValue(currentIncrement); //increment progress bar by previously caluclated increment value GeneratePopulation(); //Generate population with neural networks } else { //done computing viewMode = false; //view is false computing = false; //computing is false SetCameraLocation(); //ser camera location back to panel } }
/// <summary> /// Create new generation of net's /// </summary> /// <param name="maxCap"></param> public void GenerateNewGeneration(int maxCap) { float totalSharedFitness = 0f; //total shared fitness of the whole population float totalNetworks = 0f; //total number of organisums (used for distribution) List <float> distribution = new List <float>(); for (int i = 0; i < species.Count; i++) { float dist = species[i].GetDistribution(manager.beta); distribution.Add(dist); totalSharedFitness += dist; species[i].RemoveWorst(manager.removeWorst); } for (int i = 0; i < distribution.Count; i++) { if (totalSharedFitness <= 0f) { distribution[i] = 0; } else { distribution[i] = (int)((distribution[i] / totalSharedFitness) * maxCap); } totalNetworks += distribution[i]; } if (maxCap > totalNetworks) { Debug.Log("More added: " + totalNetworks + " " + maxCap + " " + (maxCap - totalNetworks)); for (int i = 0; i < (maxCap - totalNetworks); i++) { int highIndex = species.Count / 2; int randomInsertIndex = UnityEngine.Random.Range(highIndex, species.Count); distribution[randomInsertIndex] = distribution[randomInsertIndex] + 1; } } else if (maxCap < totalNetworks) { Debug.Log("Some removed: " + totalNetworks + " " + maxCap + " " + (maxCap - totalNetworks)); for (int i = 0; i < (totalNetworks - maxCap); i++) { bool removed = false; while (removed == false) { int randomInsertIndex = UnityEngine.Random.Range(0, species.Count); if (distribution[randomInsertIndex] > 0) { distribution[randomInsertIndex] = distribution[randomInsertIndex] - 1; removed = true; } } } } for (int i = species.Count - 1; i >= 0; i--) { if (distribution[i] <= 0 || species[i].GetPopulation().Count == 0) { distribution.RemoveAt(i); species.RemoveAt(i); } } totalNetworks = maxCap; List <Population> newSpecies = new List <Population>(); for (int i = 0; i < distribution.Count; i++) { int newDist = (int)distribution[i]; Population popOldGen = species[i]; newSpecies.Add(new Population(species[i].GetColor())); for (int j = 0; j < newDist; j++) { NEATNet net = null; if (j > newDist * manager.elite) { NEATNet organism1 = popOldGen.GetRandom(); NEATNet organism2 = popOldGen.GetRandom(); net = NEATNet.Corssover(organism1, organism2); net.Mutate(); } else { NEATNet netL = popOldGen.GetLast(); if (netL == null) { Debug.Log(newDist + " " + popOldGen.GetPopulation().Count); } net = new NEATNet(popOldGen.GetLast()); } //reset copied stats net.SetNetFitness(0f); net.SetTimeLived(0f); net.SetTestTime(manager.testTime); net.ClearNodeValues(); net.GenerateNeuralNetworkFromGenome(); //< NEW LSES ADDITION bool added = newSpecies[i].AddIfMatch(net); if (added == false) { Population foundPopulation = Species.ClosestSpecies(newSpecies, net); if (foundPopulation == null) { Population newSpecie = Species.CreateNewSpecie(newSpecies, new Color(UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f))); newSpecie.Add(net); } else { foundPopulation.Add(net); } } } } this.species = newSpecies; }