public Chromosome ToChromosome() { Chromosome chromosome = new Chromosome(); for (int j = 0; j < data.Count; ++j) { // if not black edge if (Math.Abs(data[j].Item1 - data[j].Item2) != 1) { continue; } if (data[j].Item1 % 2 == data[j].Item2 % 2) { continue; } if (data[j].Item1 < data[j].Item2) { chromosome.Add(data[j].Item2 / 2); } else { chromosome.Add(-data[j].Item1 / 2); } } return(chromosome); }
/// <summary> /// Construct a genome, do not provide links and neurons. /// </summary> /// /// <param name="id">The genome id.</param> /// <param name="inputCount_0">The input count.</param> /// <param name="outputCount_1">The output count.</param> public NEATGenome(long id, int inputCount_0, int outputCount_1) { GenomeID = id; AdjustedScore = 0; inputCount = inputCount_0; outputCount = outputCount_1; AmountToSpawn = 0; speciesID = 0; double inputRowSlice = 0.8d / (inputCount_0); neuronsChromosome = new Chromosome(); linksChromosome = new Chromosome(); Chromosomes.Add(neuronsChromosome); Chromosomes.Add(linksChromosome); for (int i = 0; i < inputCount_0; i++) { neuronsChromosome.Add(new NEATNeuronGene(NEATNeuronType.Input, i, 0, 0.1d + i * inputRowSlice)); } neuronsChromosome.Add(new NEATNeuronGene(NEATNeuronType.Bias, inputCount_0, 0, 0.9d)); double outputRowSlice = 1 / (double)(outputCount_1 + 1); for (int i_2 = 0; i_2 < outputCount_1; i_2++) { neuronsChromosome.Add(new NEATNeuronGene( NEATNeuronType.Output, i_2 + inputCount_0 + 1, 1, (i_2 + 1) * outputRowSlice)); } for (int i_3 = 0; i_3 < inputCount_0 + 1; i_3++) { for (int j = 0; j < outputCount_1; j++) { linksChromosome.Add(new NEATLinkGene( ((NEATNeuronGene)neuronsChromosome.Get(i_3)).Id, ((NEATNeuronGene)Neurons.Get( inputCount_0 + j + 1)).Id, true, inputCount_0 + outputCount_1 + 1 + NumGenes, RangeRandomizer.Randomize(-1, 1), false)); } } }
private void addToChildAndSwap(Chromosome child, List <Gene> chosenGeneSet, GraphNode chosenNode, List <Gene> notChosenGeneSet, int choiceIndex) { child.Add(chosenGeneSet[choiceIndex]); var swapIndex = notChosenGeneSet.FindIndex((g) => ((GraphNode)g.ObjectValue).GetHashCode() == chosenNode.GetHashCode()); swapElements(notChosenGeneSet, choiceIndex, swapIndex); }
private void addToChildAndRemoveFromParents(Chromosome child, List <Gene> chosenGeneSet, GraphNode chosenNode, List <Gene> notChosenGeneSet) { child.Add(chosenGeneSet[0]); chosenGeneSet.RemoveAt(0); var removeIndex = notChosenGeneSet.FindIndex((g) => ((GraphNode)g.ObjectValue).GetHashCode() == chosenNode.GetHashCode()); notChosenGeneSet.RemoveAt(0); }
/* * CycleToChromosome(Nodes) * for j ← 1 to |Nodes|/2 * if Node2j−1 < Node2j * Chromosomej ← Node2j /2 * else * Chromosomej ← −Node2j−1/2 * return Chromosome */ public Chromosome ToChromosome() { Chromosome chromosome = new Chromosome(); for (int j = 0; j < Count / 2; ++j) { if (this[2 * j] < this[2 * j + 1]) { chromosome.Add(this[2 * j + 1] / 2); } else { chromosome.Add(-this[2 * j] / 2); } } return(chromosome); }
static void Main(string[] args) { // Initialize the game table, matches and distances WorldCupChronogram.Initialize(); Distances.Initialize(); // Population, with a chromossome length var population = new Population(CHROMOSOME_SIZE); // Random seed var random = new Random(); // Initialize the population for (int i = 0; i < INITIAL_POPULATION_SIZE; i++) { var chromossome = new Chromosome(); for (int j = 0; j < CHROMOSOME_SIZE; j++) { // Somedays have more or less games var maxGamesInDays = WorldCupChronogram.Days[j].NumberOfGames; var gene = new Gene(random.Next(maxGamesInDays)); chromossome.Add(gene); } population.Solutions.Add(chromossome); } // Elite operator var elite = new Elite(ETILISM); // Crossover operator var crossover = new Crossover(CROSSOVER_PROBABILITY); // Mutation operador var mutate = new SwapMutate(MUTATION_PROBABILITY); // GA var ga = new GeneticAlgorithm(population, CalculateFitness); // Add operators ga.Operators.Add(elite); ga.Operators.Add(crossover); ga.Operators.Add(mutate); // Handlers ga.OnGenerationComplete += ga_OnGenerationComplete; ga.OnRunComplete += ga_OnRunComplete; ga.Run(Terminate); Console.ReadLine(); }
/// <summary> /// Calculate a WoC solution from a population /// Each gene value is the most popular value for a gene in that position across the population /// </summary> /// <param name="pop">The input population. Must contain individuals</param> /// <returns>A chromosome representing the WoC solution</returns> private Chromosome CalculateWoC(Population pop) { // Create a hash table. Columns are gene positions and rows are possible gene values // The values are the number of times that gene value occured in that position in the genome byte[,] hash = new byte[numIntsInSolution, solutionValueMax + 1]; int i = 0, j = 0; // Fill the hash table foreach (Chromosome chrom in pop.Solutions) { // Iterate through all individuals i = 0; // i tracks the current gene position in this individual foreach (Gene gene in chrom) { // Iterate through this individuals genes hash[i, (int)gene.ObjectValue]++; // Increment the correct location in the hash table i++; // Increment our iterator } } // Create an empty Chromosome to fill and return Chromosome retChrom = new Chromosome(); // Iterate over hash table again calculating values for return chromosome for (i = 0; i < numIntsInSolution; i++) { // Iterate through columns, which are gene positions that will be colapsed into single gene values based on which value is most populat in that position int mostPop = -1; int timesRepeated = -1; for (j = 0; j < solutionValueMax; j++) { // Iterate through the rows in this column, finding the most popular value // Make current value the most popular value if it's been here more times. If they're tied choose randomly if (hash[i, j] > timesRepeated || (hash[i, j] == timesRepeated && rand.Next(0, 1) == 1)) { timesRepeated = hash[i, j]; mostPop = j; } } // If we don't have any most popular value, the column was empty, something went very wrong, throw an exception. // (This shouldn't be able to happen, but it's still good to double check, as it might take some time to find this otherwise) if (mostPop == -1) { throw new ApplicationException("Something went very wrong in WoC"); } // Add this most popular gene value to the return chromosome var newGene = new Gene(mostPop); retChrom.Add(newGene); } // Let the WoC chromosome we built calculate it's fitness retChrom.Evaluate(CalculateFitness); // Return the WoC chromosome we built return(retChrom); }
private Chromosome CopyChromosome(Chromosome toCopy) { var result = new Chromosome(); for (int i = 0; i < toCopy.Genes.Count; i++) { result.Add(toCopy.Genes[i]); } return(result); }
protected Chromosome GenerateRandomChromosome(int size) { var chromosome = new Chromosome(); for (var i = 0; i < size; i++) { var gene = RandomGenerator.Next(NumberOfColors); chromosome.Add(gene); } return(chromosome); }
private Population GenerateInitialPopulation(int popSize) { var population = new Population(); for (int i = 0; i < popSize; i++) { var chromosome = new Chromosome(); for (int j = 0; j < numIntsInSolution; j++) { chromosome.Add(new Gene(rand.Next(solutionValueMin, solutionValueMax))); } population.Solutions.Add(chromosome); } return(population); }
/// <summary> /// Mutate the genome by adding a neuron. /// </summary> /// /// <param name="mutationRate">The mutation rate.</param> /// <param name="numTrysToFindOldLink">The number of tries to find a link to split.</param> internal void AddNeuron(double mutationRate, int numTrysToFindOldLink) { // should we add a neuron? if (ThreadSafeRandom.NextDouble() > mutationRate) { return; } int countTrysToFindOldLink = numTrysToFindOldLink; // the link to split NEATLinkGene splitLink = null; int sizeBias = inputCount + outputCount + 10; // if there are not at least int upperLimit; if (linksChromosome.Size() < sizeBias) { upperLimit = NumGenes - 1 - (int)Math.Sqrt(NumGenes); } else { upperLimit = NumGenes - 1; } while ((countTrysToFindOldLink--) > 0) { // choose a link, use the square root to prefer the older links int i = RangeRandomizer.RandomInt(0, upperLimit); var link = (NEATLinkGene)linksChromosome .Get(i); // get the from neuron long fromNeuron = link.FromNeuronID; if ((link.Enabled) && (!link.Recurrent) && (((NEATNeuronGene)Neurons.Get( GetElementPos(fromNeuron))).NeuronType != NEATNeuronType.Bias)) { splitLink = link; break; } } if (splitLink == null) { return; } splitLink.Enabled = false; double originalWeight = splitLink.Weight; long from = splitLink.FromNeuronID; long to = splitLink.ToNeuronID; var fromGene = (NEATNeuronGene)Neurons.Get( GetElementPos(from)); var toGene = (NEATNeuronGene)Neurons.Get( GetElementPos(to)); double newDepth = (fromGene.SplitY + toGene.SplitY) / 2; double newWidth = (fromGene.SplitX + toGene.SplitX) / 2; // has this innovation already been tried? NEATInnovation innovation = ((NEATTraining)GA).Innovations.CheckInnovation(from, to, NEATInnovationType .NewNeuron); // prevent chaining if (innovation != null) { long neuronID = innovation.NeuronID; if (AlreadyHaveThisNeuronID(neuronID)) { innovation = null; } } if (innovation == null) { // this innovation has not been tried, create it long newNeuronID = ((NEATTraining)GA).Innovations.CreateNewInnovation(from, to, NEATInnovationType. NewNeuron, NEATNeuronType. Hidden, newWidth, newDepth); neuronsChromosome.Add(new NEATNeuronGene( NEATNeuronType.Hidden, newNeuronID, newDepth, newWidth)); // add the first link long link1ID = (GA).Population.AssignInnovationID(); ((NEATTraining)GA).Innovations .CreateNewInnovation(from, newNeuronID, NEATInnovationType.NewLink); var link1 = new NEATLinkGene(from, newNeuronID, true, link1ID, 1.0d, false); linksChromosome.Add(link1); // add the second link long link2ID = (GA).Population.AssignInnovationID(); ((NEATTraining)GA).Innovations .CreateNewInnovation(newNeuronID, to, NEATInnovationType.NewLink); var link2 = new NEATLinkGene(newNeuronID, to, true, link2ID, originalWeight, false); linksChromosome.Add(link2); } else { // existing innovation long newNeuronID_0 = innovation.NeuronID; NEATInnovation innovationLink1 = ((NEATTraining)GA).Innovations.CheckInnovation(from, newNeuronID_0, NEATInnovationType . NewLink); NEATInnovation innovationLink2 = ((NEATTraining)GA).Innovations.CheckInnovation(newNeuronID_0, to, NEATInnovationType.NewLink); if ((innovationLink1 == null) || (innovationLink2 == null)) { throw new NeuralNetworkError("NEAT Error"); } var link1_1 = new NEATLinkGene(from, newNeuronID_0, true, innovationLink1.InnovationID, 1.0d, false); var link2_2 = new NEATLinkGene(newNeuronID_0, to, true, innovationLink2.InnovationID, originalWeight, false); linksChromosome.Add(link1_1); linksChromosome.Add(link2_2); var newNeuron = new NEATNeuronGene( NEATNeuronType.Hidden, newNeuronID_0, newDepth, newWidth); neuronsChromosome.Add(newNeuron); } return; }
/// <summary> /// Mutate the genome by adding a link to this genome. /// </summary> /// /// <param name="mutationRate">The mutation rate.</param> /// <param name="chanceOfLooped">The chance of a self-connected neuron.</param> /// <param name="numTrysToFindLoop">The number of tries to find a loop.</param> /// <param name="numTrysToAddLink">The number of tries to add a link.</param> internal void AddLink(double mutationRate, double chanceOfLooped, int numTrysToFindLoop, int numTrysToAddLink) { // should we even add the link if (ThreadSafeRandom.NextDouble() > mutationRate) { return; } int countTrysToFindLoop = numTrysToFindLoop; int countTrysToAddLink = numTrysToFindLoop; // the link will be between these two neurons long neuron1ID = -1; long neuron2ID = -1; bool recurrent = false; // a self-connected loop? if (ThreadSafeRandom.NextDouble() < chanceOfLooped) { // try to find(randomly) a neuron to add a self-connected link to while ((countTrysToFindLoop--) > 0) { NEATNeuronGene neuronGene = ChooseRandomNeuron(false); // no self-links on input or bias neurons if (!neuronGene.Recurrent && (neuronGene.NeuronType != NEATNeuronType.Bias) && (neuronGene.NeuronType != NEATNeuronType.Input)) { neuron1ID = neuronGene.Id; neuron2ID = neuronGene.Id; neuronGene.Recurrent = true; recurrent = true; countTrysToFindLoop = 0; } } } else { // try to add a regular link while ((countTrysToAddLink--) > 0) { NEATNeuronGene neuron1 = ChooseRandomNeuron(true); NEATNeuronGene neuron2 = ChooseRandomNeuron(false); if (!IsDuplicateLink(neuron1ID, neuron2ID) && (neuron1.Id != neuron2.Id) && (neuron2.NeuronType != NEATNeuronType.Bias)) { neuron1ID = neuron1.Id; neuron2ID = neuron2.Id; break; } } } // did we fail to find a link if ((neuron1ID < 0) || (neuron2ID < 0)) { return; } // check to see if this innovation has already been tried NEATInnovation innovation = ((NEATTraining)GA).Innovations.CheckInnovation(neuron1ID, neuron1ID, NEATInnovationType .NewLink); // see if this is a recurrent(backwards) link var neuronGene_0 = (NEATNeuronGene)neuronsChromosome .Get(GetElementPos(neuron1ID)); if (neuronGene_0.SplitY > neuronGene_0.SplitY) { recurrent = true; } // is this a new innovation? if (innovation == null) { // new innovation ((NEATTraining)GA).Innovations .CreateNewInnovation(neuron1ID, neuron2ID, NEATInnovationType.NewLink); long id2 = GA.Population.AssignInnovationID(); var linkGene = new NEATLinkGene(neuron1ID, neuron2ID, true, id2, RangeRandomizer.Randomize(-1, 1), recurrent); linksChromosome.Add(linkGene); } else { // existing innovation var linkGene_1 = new NEATLinkGene(neuron1ID, neuron2ID, true, innovation.InnovationID, RangeRandomizer.Randomize(-1, 1), recurrent); linksChromosome.Add(linkGene_1); } }
/// <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); }