public Population BreedPopulation(ref Population sourcePopulation) { for(int m = 0; m < sourcePopulation.masterAgentArray.Length; m++) { //sourcePopulation.masterAgentArray[m].brain.genome.PrintBiases("sourcePop " + sourcePopulation.masterAgentArray[m].fitnessScore.ToString() + ", " + m.ToString() + ", "); //newPop.masterAgentArray[m].brain.genome.PrintBiases("newPop " + m.ToString() + ", "); } // rank sourcePop by fitness score // maybe do this as a method of Population class? sourcePopulation.RankAgentArray(); Population newPopulation = new Population(); newPopulation = sourcePopulation.CopyPopulationSettings(); // Calculate total fitness score: float totalScore = 0f; if(survivalByRaffle) { for(int a = 0; a < sourcePopulation.populationMaxSize; a++) { // iterate through all agents totalScore += sourcePopulation.masterAgentArray[a].fitnessScore; } } // Create the Population that will hold the next Generation agentArray: Population newPop = sourcePopulation.CopyPopulationSettings(); // Figure out How many Agents survive int numSurvivors = Mathf.RoundToInt(survivalRate * (float)newPop.populationMaxSize); //Depending on method, one at a time, select an Agent to survive until the max Number is reached int newChildIndex = 0; // For ( num Agents ) { for(int i = 0; i < numSurvivors; i++) { // If survival is by fitness score ranking: if(survivalByRank) { // Pop should already be ranked, so just traverse from top (best) to bottom (worst) newPopulation.masterAgentArray[newChildIndex] = sourcePopulation.masterAgentArray[newChildIndex]; newChildIndex++; } // if survival is completely random, as a control: if(survivalStochastic) { int randomAgent = UnityEngine.Random.Range (0, numSurvivors-1); // Set next newChild slot to a completely randomly-chosen agent newPopulation.masterAgentArray[newChildIndex] = sourcePopulation.masterAgentArray[randomAgent]; newChildIndex++; } // if survival is based on a fitness lottery: if(survivalByRaffle) { // Try when Fitness is normalized from 0-1 float randomSlicePosition = UnityEngine.Random.Range(0f, totalScore); float accumulatedFitness = 0f; for(int a = 0; a < sourcePopulation.populationMaxSize; a++) { // iterate through all agents accumulatedFitness += sourcePopulation.masterAgentArray[a].fitnessScore; // if accum fitness is on slicePosition, copy this Agent Debug.Log ("NumSurvivors: " + numSurvivors.ToString() + ", Surviving Agent " + a.ToString() + ": AccumFitness: " + accumulatedFitness.ToString() + ", RafflePos: " + randomSlicePosition.ToString() + ", TotalScore: " + totalScore.ToString() + ", newChildIndex: " + newChildIndex.ToString()); if(accumulatedFitness >= randomSlicePosition) { newPopulation.masterAgentArray[newChildIndex] = sourcePopulation.masterAgentArray[a]; newChildIndex++; } } } // set newPop Agent to lucky sourcePop index ////////// Agent survivingAgent = sourcePopulation.Select // Fill up newPop agentArray with the surviving Agents // Keep track of Index, as that will be needed for new agents } // Figure out how many new agents must be created to fill up the new population: int numNewChildAgents = newPopulation.populationMaxSize - numSurvivors; int numEligibleBreederAgents = Mathf.RoundToInt(breedingRate * (float)newPop.populationMaxSize); int currentRankIndex = 0; float totalScoreBreeders = 0f; if(breedingByRaffle) { for(int a = 0; a < numEligibleBreederAgents; a++) { // iterate through all agents totalScoreBreeders += sourcePopulation.masterAgentArray[a].fitnessScore; } } //float[][] parentAgentChromosomes = new float[][]; // Iterate over numAgentsToCreate : // Change to While loop? int newChildrenCreated = 0; while(newChildrenCreated < numNewChildAgents) { // Find how many parents random number btw min/max int numParentAgents = UnityEngine.Random.Range (minNumParents, maxNumParents); int numChildAgents = 1; if(numNewChildAgents - newChildrenCreated >= 2) { // room for two more! numChildAgents = 2; //Debug.Log ("numNewChildAgents: " + numNewChildAgents.ToString() + " - newChildrenCreated: " + newChildrenCreated.ToString() + " = numChildAgents: " + numChildAgents.ToString()); } float[][] parentAgentBiases = new float[numParentAgents][]; float[][] parentAgentWeights = new float[numParentAgents][]; for(int p = 0; p < numParentAgents; p++) { // Iterate over numberOfParents : // Depending on method, select suitable agents' genome.Arrays until the numberOfPArents is reached, collect them in an array of arrays // If breeding is by fitness score ranking: if(breedingByRank) { // Pop should already be ranked, so just traverse from top (best) to bottom (worst) to select parentAgents if(currentRankIndex >= numEligibleBreederAgents) { // if current rank index is greater than the num of eligible breeders, then restart the index to 0; currentRankIndex = 0; } //parentAgentChromosomes[p] = new float[sourcePopulation.masterAgentArray[currentRankIndex].genome.genomeBiases.Length]; parentAgentBiases[p] = sourcePopulation.masterAgentArray[currentRankIndex].genome.genomeBiases; parentAgentWeights[p] = sourcePopulation.masterAgentArray[currentRankIndex].genome.genomeWeights; currentRankIndex++; } // if survival is completely random, as a control: if(breedingStochastic) { int randomAgent = UnityEngine.Random.Range (0, numEligibleBreederAgents-1); // check if minus 1 is needed // Set next newChild slot to a completely randomly-chosen agent parentAgentBiases[p] = sourcePopulation.masterAgentArray[randomAgent].genome.genomeBiases; parentAgentWeights[p] = sourcePopulation.masterAgentArray[randomAgent].genome.genomeWeights; } // if survival is based on a fitness lottery: if(breedingByRaffle) { float randomSlicePosition = UnityEngine.Random.Range(0f, totalScoreBreeders); float accumulatedFitness = 0f; for(int a = 0; a < numEligibleBreederAgents; a++) { // iterate through all agents accumulatedFitness += sourcePopulation.masterAgentArray[a].fitnessScore; // if accum fitness is on slicePosition, copy this Agent Debug.Log ("Breeding Agent " + a.ToString() + ": AccumFitness: " + accumulatedFitness.ToString() + ", RafflePos: " + randomSlicePosition.ToString() + ", totalScoreBreeders: " + totalScoreBreeders.ToString() + ", numEligibleBreederAgents: " + numEligibleBreederAgents.ToString()); if(accumulatedFitness >= randomSlicePosition) { parentAgentBiases[p] = sourcePopulation.masterAgentArray[a].genome.genomeBiases; parentAgentWeights[p] = sourcePopulation.masterAgentArray[a].genome.genomeWeights; } } } } // Combine the genes in the parentArrays and return the specified number of children genomes // Pass that array of parentAgent genome.Arrays into the float-based MixFloatChromosomes() function, float[][] childAgentBiases = MixFloatChromosomes(parentAgentBiases, numChildAgents); float[][] childAgentWeights = MixFloatChromosomes(parentAgentWeights, numChildAgents); // It can return an Array of Arrays (of new childAgent genome.Arrays) // Iterate over ChildArray.Length : // how many newAgents created for(int c = 0; c < numChildAgents; c++) { // for number of child Agents in floatArray[][]: for(int b = 0; b < sourcePopulation.masterAgentArray[0].genome.genomeBiases.Length; b++) { //Debug.Log ("ChildNumber: " + c.ToString() + ", BiasIndex: " + b.ToString() + ", biasValue: " + childAgentBiases[c][b].ToString () + ", newChildIndex: " + newChildIndex.ToString() + ", numNewChildren: " + numNewChildAgents.ToString() + ", numChildAgents: " + numChildAgents.ToString() + ", newChildrenCreated: " + newChildrenCreated.ToString()); newPopulation.masterAgentArray[newChildIndex].genome.genomeBiases[b] = childAgentBiases[c][b]; // weights and functions and more! } for(int w = 0; w < sourcePopulation.masterAgentArray[0].genome.genomeWeights.Length; w++) { //Debug.Log ("ChildNumber: " + c.ToString() + ", BiasIndex: " + b.ToString() + ", biasValue: " + childAgentBiases[c][b].ToString () + ", newChildIndex: " + newChildIndex.ToString() + ", numNewChildren: " + numNewChildAgents.ToString() + ", numChildAgents: " + numChildAgents.ToString() + ", newChildrenCreated: " + newChildrenCreated.ToString()); newPopulation.masterAgentArray[newChildIndex].genome.genomeWeights[w] = childAgentWeights[c][w]; // weights and functions and more! } newPopulation.masterAgentArray[newChildIndex].brain.SetBrainFromGenome(newPopulation.masterAgentArray[newChildIndex].genome); newChildIndex++; // new child created! newChildrenCreated++; } } //newPop.isFunctional = true; return newPopulation; }
public void PerformCrossover(ref Population sourcePopulation) { Population newPop = sourcePopulation.CopyPopulationSettings(); if(numFactions > 1) { Population[] sourceFactions = sourcePopulation.SplitPopulation(numFactions); Population[] newFactions = new Population[numFactions]; for(int i = 0; i < numFactions; i++) { // Make a Genome array of each faction // Then BreedAgentPool on each Array? // Then Add those genomes to new Population masterAgentArray? //newFactions[i] = sourceFactions[i].CopyPopulationSettings(); Debug.Log ("FactionSize: " + sourceFactions[i].populationMaxSize.ToString()); newFactions[i] = BreedPopulation(ref sourceFactions[i]); } // Add them back together! newPop.SetToCombinedPopulations(newFactions); } else { newPop = BreedPopulation(ref sourcePopulation); } sourcePopulation = newPop; }