private void Initialize(IGeneticIndividual progenitor)//called by constructor//randomly decide the aspects of each individual in individuals. { for (int i = 0; i < individuals.Length; i++) { individuals[i] = progenitor; individuals[i].Randomize(); } }
public IGeneticIndividual TrainGeneration(int numGenerations)//execute a number of iterations of the algorithm creating more fit solutions. Return most fit individual { for (int i = 0; i < numGenerations; i++) { generationCount++; //create elite array IGeneticIndividual[] eliteIndividuals = new IGeneticIndividual[numToSave]; for (int j = 0; j < numToSave; j++) { eliteIndividuals[j] = individuals[j]; } //create 2 dim array of parents(1) for each child(0) IGeneticIndividual[,] reproductionGroups = new IGeneticIndividual[numChildrenNeeded, numParents]; //uses tournament selection process to fill array for (int childIter = 0; childIter < reproductionGroups.GetLength(0); childIter++) //iterate once per child { for (int parentIter = 0; parentIter < reproductionGroups.GetLength(1); parentIter++) //iterate once per parent. This will { IGeneticIndividual[] tournamentSubset = new IGeneticIndividual[tournamentSize]; for (int touranmentIter = 0; touranmentIter < tournamentSubset.Length; touranmentIter++) { tournamentSubset[touranmentIter] = individuals[(int)(RandHolder.NextDouble() * populationSize)];//pick a random individual } Array.Sort(tournamentSubset); reproductionGroups[childIter, parentIter] = tournamentSubset[0]; } } //generate children IGeneticIndividual[] newChildren = new IGeneticIndividual[numChildrenNeeded];//create empty array to hold newly generated children for (int childIter = 0; childIter < newChildren.Length; childIter++) { IGeneticIndividual[] reproductionGroup = new IGeneticIndividual[numParents];//fill the single dimensioned array, reproductionGroup, with its corresponding individuals from the 2 dimensional array, reproductionGroups. for (int parentIter = 0; parentIter < reproductionGroup.Length; parentIter++) { reproductionGroup[parentIter] = reproductionGroups[childIter, parentIter]; } newChildren[childIter] = reproductionGroup[0].Reproduce(reproductionGroup, numCrossoverPoints, 1)[0];//generate a single child with reproductionGroup as its parents. Method called by reproductionGroup[0] for convenience. } //mutate over children array for (int mutationIter = 0; mutationIter < populationSize; mutationIter++) { Mutate(mutationIter); } //combine elite and children array and copy into individuals array for (int eliteIter = 0; eliteIter < eliteIndividuals.Length; eliteIter++)//copy the high fitness individuals that were saved from the previous generation { individuals[eliteIter] = eliteIndividuals[eliteIter]; } for (int childIter = 0; childIter < newChildren.Length; childIter++)//copy the newly generated children after the elite individuals { individuals[eliteIndividuals.Length + childIter] = newChildren[childIter]; } FitnessSort(); //order the individuals by fitness } return(individuals[0]); //the highest fitness }
/// <summary> /// Returns a child of the two parents. /// </summary> /// <param name="parentOne"></param> /// <param name="parentTwo"></param> /// <returns></returns> public IGeneticIndividual Reproduce(IGeneticIndividual parentOne, IGeneticIndividual parentTwo) { var one = (parentOne as Individual); var two = (parentTwo as Individual); var childOne = GenerateChild(one, two); var childTwo = GenerateChild(two, one); var child = ChooseRandomChild(childOne, childTwo); return child; }
public IGeneticIndividual[] Reproduce(IGeneticIndividual[] IParents, int numCrossoverPoints, int numChildren) { int numParents = IParents.Length;//convenient variable to have //convert array of type IGeneticIndividual to type TestGeneticIndividual TestGeneticIndividual[] parents = new TestGeneticIndividual[numParents]; for (int i = 0; i < numParents; i++) { parents[i] = IParents[i] as TestGeneticIndividual; } TestGeneticIndividual[] children = new TestGeneticIndividual[numChildren]; //variable to hold generated children. Will be output by method for (int childIter = 0; childIter < numChildren; childIter++) //iterate once for each child to be generated { int[] crossoverPoints = new int[numCrossoverPoints]; //fill crossoverPoints array with random ints which are indexes of genes array for (int i = 0; i < crossoverPoints.Length; i++) { crossoverPoints[i] = (int)(RandHolder.NextDouble() * parents[0].genes.Length); } int activeParentIndex = 0; //generate child children[childIter] = new TestGeneticIndividual(parents[0].genes.Length); for (int i = 0; i < parents[0].genes.Length; i++) { children[childIter].genes[i] = parents[activeParentIndex].genes[i]; for (int iter = 0; iter < numCrossoverPoints; iter++) { if (i == crossoverPoints[iter]) { int temp = (int)(RandHolder.NextDouble() * (parents.Length - 1));//minus one for value exclusion, so between first and second to last index if (temp != activeParentIndex) { activeParentIndex = temp; } else { activeParentIndex = parents.Length - 1;//minus one because it is max index of array } } } } } //convert array of type TestGeneticIndividual to type IGeneticIndividual IGeneticIndividual[] IChildren = new IGeneticIndividual[numChildren]; for (int i = 0; i < numChildren; i++) { IChildren[i] = children[i] as IGeneticIndividual; } return(IChildren); }
public int CompareTo(IGeneticIndividual obj)//to be used by Arrays.sort in GeneticAlgorithm.cs>FitnessSort() { if (this.Fitness() > obj.Fitness()) { return(-1);//precede in sort order } else if (this.Fitness() < obj.Fitness()) { return(1);//succeed in sort order } else { return(0);//equal in sort } }
public int CompareTo(IGeneticIndividual individual) { if (this.Fitness() > individual.Fitness()) { return(-1);//precede in sort order } else if (this.Fitness() < individual.Fitness()) { return(1);//succeed in sort order } else { return(0);//equal in sort } }
public GeneticAlgorithm(IGeneticIndividual progenitor, int populationSize, int numParents, float environmentalPressure, float eliteFraction, int numCrossoverPoints, float mutationChance, int tournamentSize)//initialization of arrays and variables { this.populationSize = populationSize; this.numParents = numParents; this.environmentalPressure = environmentalPressure; this.eliteFraction = eliteFraction; this.numCrossoverPoints = numCrossoverPoints; this.mutationChance = mutationChance; this.tournamentSize = tournamentSize; numToSave = (int)(eliteFraction * populationSize); numChildrenNeeded = populationSize - numToSave;//each child will have its own set of parents individuals = new IGeneticIndividual[populationSize]; Initialize(progenitor); FitnessSort(); }
/// <summary> /// Use the distance formula to assign a distance to each pixel of the individuals from the targets. /// The total fitness is the average fitness of all the pixels. /// </summary> /// <param name="individual"></param> private void EvaluateIndividual(IGeneticIndividual individual) { var target = _configuration.Target; var genome = (individual as Individual).Genome; double fitness = 0; for (int index = 0; index < target.Count; index++) { var targetPixel = target[index]; var individualPixel = genome[index]; float rDistance = (targetPixel.R - individualPixel.R); float gDistance = (targetPixel.G - individualPixel.G); float bDistance = (targetPixel.B - individualPixel.B); float distance = ((rDistance * rDistance) + (gDistance * gDistance) + (bDistance * bDistance)); fitness += Math.Abs(distance - MAXIMUM_FITNESS) + 1; } individual.Fitness = fitness / target.Count; }
public int CompareTo(object obj)//should never be called because should never be compared to other data types but needs to be here to satisfy compiler { if (obj is IGeneticIndividual) { IGeneticIndividual GAObj = (IGeneticIndividual)obj; if (this.Fitness() > GAObj.Fitness()) { return(-1);//precede in sort order } else if (this.Fitness() < GAObj.Fitness()) { return(1);//succeed in sort order } else { return(0);//equal in sort } } else { throw new NotImplementedException(); } }
public int CompareTo(object obj) { if (obj is IGeneticIndividual) { IGeneticIndividual GAObj = (IGeneticIndividual)obj; if (this.Fitness() > GAObj.Fitness()) { return(-1);//precede in sort order } else if (this.Fitness() < GAObj.Fitness()) { return(1);//succeed in sort order } else { return(0);//equal in sort } } else { throw new System.NotImplementedException(); } }
/// <summary> /// Mutate the individual. /// </summary> /// <param name="individual"></param> public void Mutate(IGeneticIndividual individual) { var toMutate = individual as Individual; ChangeGenome(toMutate); }
public IGeneticIndividual[] Reproduce(IGeneticIndividual[] IParents, int numCrossoverPoints, int numChildren) //returns an array of nets given an array of all parents. // Doesn't necessarily need to be called by one of the parents but that's probably convenient. //numCrossover points SHOULD be > numParents-1 (to use all parents at least once), but it's fine if not { int numParents = IParents.Length;//convenient variable to have //convert array of type IGeneticIndividual to type NeuralNet NeuralNet[] parents = new NeuralNet[numParents]; for (int i = 0; i < numParents; i++) { parents[i] = IParents[i] as NeuralNet; } NeuralNet[] children = new NeuralNet[numChildren]; //variable to hold generated children. Will be output by method for (int childIter = 0; childIter < numChildren; childIter++) //iterate once for each child to be generated { //generate random crossoverPoints int[,] crossoverPoints = new int[numCrossoverPoints, 3]; //3 because (i, j, k) are (layer, node, weight) for (int cpIter = 0; cpIter < numCrossoverPoints; cpIter++) //iterate for each crossover point and generate it. Code copied from Mutate() { //layer to cp// int i = (int)(RandHolder.NextDouble() * (parents[0].numHiddenLayers + 1)); //+1 for output //node to cp// int j = -1; //should cause an index out of bounds if not set by subsequent if cases if (i == 0) { //if first hidden layer (same as else case)(same number of nodes as hidden layer so doesn't matter) j = (int)(RandHolder.NextDouble() * parents[0].hiddenLayerSize); } else if (i == parents[0].numHiddenLayers) {//if output layer j = (int)(RandHolder.NextDouble() * parents[0].numOutputs); } else {//if any other hidden layer j = (int)(RandHolder.NextDouble() * parents[0].hiddenLayerSize); } //weight to cp// int k = -1; //should cause an index out of bounds if not set by subsequent if cases if (i == 0) //if first hidden layer (same as else case)(same number of nodes as hidden layer so doesn't matter) { k = (int)(RandHolder.NextDouble() * (parents[0].numInputs) + 1); //+1 for bias } else if (i == parents[0].numHiddenLayers) //if output layer same as else case { k = (int)(RandHolder.NextDouble() * (parents[0].hiddenLayerSize) + 1); //+1 for bias } else//if any other hidden layer { k = (int)(RandHolder.NextDouble() * (parents[0].hiddenLayerSize) + 1);//+1 for bias } //assign i,j,k to crossoverPoints crossoverPoints[cpIter, 0] = i; crossoverPoints[cpIter, 1] = j; crossoverPoints[cpIter, 2] = k;//duplicate crossover points might exist but honestly who cares } //create array to hold new layers, nodes, weights Layer[] newLayers = new Layer[parents[0].numHiddenLayers + 1]; //fill newLayers int activeParentIndex = 0; for (int i = 0; i < parents[0].numHiddenLayers + 1; i++) //+1 for output layer { if (i == 0) //first hidden layer { double[,] newWeights = new double[parents[0].hiddenLayerSize, parents[0].numInputs + 1]; //create empty container, +1 for bias for (int j = 0; j < newWeights.GetLength(0); j++) { for (int k = 0; k < newWeights.GetLength(1); k++)//this will run for each weight and bias { //check if currently at a crossover point if so then swap the activeParentIndex for (int iter = 0; iter < numCrossoverPoints; iter++)//check for each crossover point { if (crossoverPoints[iter, 0] == i && crossoverPoints[iter, 1] == j && crossoverPoints[iter, 2] == k) { activeParentIndex = (int)(RandHolder.NextDouble() * (numParents));//choose a random parent including currently active parent } } newWeights[j, k] = parents[activeParentIndex].layers[i].Weights[j, k];//copy the value from the active aprent } } newLayers[i] = new Layer(parents[0].numInputs, parents[0].hiddenLayerSize, newWeights); //assign new weights to newLayers array in the form of a newly instantiated Layer } else if (i > 0 && i < parents[0].numHiddenLayers) //all other hidden layers { double[,] newWeights = new double[parents[0].hiddenLayerSize, parents[0].hiddenLayerSize + 1]; //create empty container, +1 for bias for (int j = 0; j < newWeights.GetLength(0); j++) { for (int k = 0; k < newWeights.GetLength(1); k++)//this will run for each weight and bias { //check if currently at a crossover point if so then swap the activeParentIndex for (int iter = 0; iter < numCrossoverPoints; iter++)//check for each crossover point { if (crossoverPoints[iter, 0] == i && crossoverPoints[iter, 1] == j && crossoverPoints[iter, 2] == k) { int temp = (int)(RandHolder.NextDouble() * (numParents - 1));//the minus one is because we are avoiding the current activeParentIndex in this reassignment if (temp < activeParentIndex) { activeParentIndex = temp; } else//if greater than or equal to activeParentIndex { activeParentIndex = temp + 1; } } } newWeights[j, k] = parents[activeParentIndex].layers[i].Weights[j, k];//copy the value from the active parent } } newLayers[i] = new Layer(parents[0].numInputs, parents[0].hiddenLayerSize, newWeights); //assign new weights to newLayers array in the form of a newly instantiated Layer } else if (i == parents[0].numHiddenLayers) //output layer { double[,] newWeights = new double[parents[0].numOutputs, parents[0].hiddenLayerSize + 1]; //create empty container, +1 for bias for (int j = 0; j < newWeights.GetLength(0); j++) { for (int k = 0; k < newWeights.GetLength(1); k++)//this will run for each weight and bias { //check if currently at a crossover point if so then swap the activeParentIndex for (int iter = 0; iter < numCrossoverPoints; iter++)//check for each crossover point { if (crossoverPoints[iter, 0] == i && crossoverPoints[iter, 1] == j && crossoverPoints[iter, 2] == k) { int temp = (int)(RandHolder.NextDouble() * (numParents - 1));//the minus one is because we are avoiding the current activeParentIndex in this reassignment if (temp < activeParentIndex) { activeParentIndex = temp; } else//if greater than or equal to activeParentIndex { activeParentIndex = temp + 1; } } } newWeights[j, k] = parents[activeParentIndex].layers[i].Weights[j, k];//copy the value from the active aprent } } newLayers[i] = new Layer(parents[0].hiddenLayerSize, parents[0].numOutputs, newWeights);//assign new weights to newLayers array in the form of a newly instantiated Layer } else { throw new IndexOutOfRangeException(); } } children[childIter] = new NeuralNet(parents[0].numInputs, parents[0].numOutputs, parents[0].numHiddenLayers, parents[0].hiddenLayerSize, parents[0].TestInputSets, parents[0].TestOutputSets) //create empty with same params as parent { layers = newLayers //assign the data to complete the child }; } //convert array of type NeuralNet to type IGeneticIndividual IGeneticIndividual[] IChildren = new IGeneticIndividual[numChildren]; for (int i = 0; i < numChildren; i++) { IChildren[i] = children[i] as IGeneticIndividual; } return(IChildren); }