/// <inheritdoc/> public void PerformOperation(EncogRandom rnd, IGenome[] parents, int parentIndex, IGenome[] offspring, int offspringIndex) { IArrayGenome parent = (IArrayGenome)parents[parentIndex]; offspring[offspringIndex] = this.owner.Population.GenomeFactory.Factor(); IArrayGenome child = (IArrayGenome)offspring[offspringIndex]; child.Copy(parent); int length = parent.Size; int iswap1 = (int)(rnd.NextDouble() * length); int iswap2 = (int)(rnd.NextDouble() * length); // can't be equal if (iswap1 == iswap2) { // move to the next, but // don't go out of bounds if (iswap1 > 0) { iswap1--; } else { iswap1++; } } // make sure they are in the right order if (iswap1 > iswap2) { int temp = iswap1; iswap1 = iswap2; iswap2 = temp; } child.Swap(iswap1, iswap2); }
/// <inheritdoc/> public void PerformOperation(EncogRandom rnd, IGenome[] parents, int parentIndex, IGenome[] offspring, int offspringIndex) { DoubleArrayGenome parent = (DoubleArrayGenome)parents[parentIndex]; offspring[offspringIndex] = parent.Population.GenomeFactory.Factor(); DoubleArrayGenome child = (DoubleArrayGenome)offspring[offspringIndex]; for (int i = 0; i < parent.Size; i++) { double value = parent.Data[i]; value += (perturbAmount - (rnd.NextDouble() * perturbAmount * 2)); child.Data[i] = value; } }
/// <inheritdoc /> public override ProgramNode CreateNode(EncogRandom rnd, EncogProgram program, int depthRemaining, IList<EPLValueType> types) { int actualDepthRemaining = depthRemaining; if (rnd.NextDouble() > 0.5) { return _fullGenerator.CreateNode(rnd, program, actualDepthRemaining, types); } return _growGenerator.CreateNode(rnd, program, actualDepthRemaining, types); }
/// <summary> /// Choose a parent to favor. /// </summary> /// <param name="rnd">Random generator.</param> /// <param name="mom">The mother.</param> /// <param name="dad">The father</param> /// <returns></returns> private NEATGenome FavorParent(EncogRandom rnd, NEATGenome mom, NEATGenome dad) { // first determine who is more fit, the mother or the father? // see if mom and dad are the same fitness if (Math.Abs(mom.Score - dad.Score) < EncogFramework.DefaultDoubleEqual) { // are mom and dad the same fitness if (mom.NumGenes == dad.NumGenes) { // if mom and dad are the same fitness and have the same number // of genes, // then randomly pick mom or dad as the most fit. if (rnd.NextDouble() > 0.5) { return mom; } return dad; } // mom and dad are the same fitness, but different number of genes // favor the parent with fewer genes if (mom.NumGenes < dad.NumGenes) { return mom; } return dad; } // mom and dad have different scores, so choose the better score. // important to note, better score COULD BE the larger or smaller // score. if (_owner.SelectionComparer.Compare(mom, dad) < 0) { return mom; } return dad; }
/// <inheritdoc/> public void PerformOperation(EncogRandom rnd, IGenome[] parents, int parentIndex, IGenome[] offspring, int offspringIndex) { var mom = (NEATGenome)parents[parentIndex + 0]; var dad = (NEATGenome)parents[parentIndex + 1]; var best = FavorParent(rnd, mom, dad); var notBest = (best == mom) ? mom : dad; var selectedLinks = new List<NEATLinkGene>(); var selectedNeurons = new List<NEATNeuronGene>(); int curMom = 0; // current gene index from mom int curDad = 0; // current gene index from dad NEATLinkGene selectedGene = null; // add in the input and bias, they should always be here int alwaysCount = ((NEATGenome)parents[0]).InputCount + ((NEATGenome)parents[0]).OutputCount + 1; for (int i = 0; i < alwaysCount; i++) { AddNeuronId(i, selectedNeurons, best, notBest); } while ((curMom < mom.NumGenes) || (curDad < dad.NumGenes)) { NEATLinkGene momGene = null; // the mom gene object NEATLinkGene dadGene = null; // the dad gene object long momInnovation = -1; long dadInnovation = -1; // grab the actual objects from mom and dad for the specified // indexes // if there are none, then null if (curMom < mom.NumGenes) { momGene = mom.LinksChromosome[curMom]; momInnovation = momGene.InnovationId; } if (curDad < dad.NumGenes) { dadGene = dad.LinksChromosome[curDad]; dadInnovation = dadGene.InnovationId; } // now select a gene for mom or dad. This gene is for the baby if ((momGene == null) && (dadGene != null)) { if (best == dad) { selectedGene = dadGene; } curDad++; } else if ((dadGene == null) && (momGene != null)) { if (best == mom) { selectedGene = momGene; } curMom++; } else if (momInnovation < dadInnovation) { if (best == mom) { selectedGene = momGene; } curMom++; } else if (dadInnovation < momInnovation) { if (best == dad) { selectedGene = dadGene; } curDad++; } else if (dadInnovation == momInnovation) { selectedGene = rnd.NextDouble() < 0.5f ? momGene : dadGene; curMom++; curDad++; } if (selectedGene != null) { if (selectedLinks.Count == 0) { selectedLinks.Add(selectedGene); } else { if (selectedLinks[selectedLinks.Count - 1] .InnovationId != selectedGene .InnovationId) { selectedLinks.Add(selectedGene); } } // Check if we already have the nodes referred to in // SelectedGene. // If not, they need to be added. AddNeuronId(selectedGene.FromNeuronId, selectedNeurons, best, notBest); AddNeuronId(selectedGene.ToNeuronId, selectedNeurons, best, notBest); } } // now create the required nodes. First sort them into order selectedNeurons.Sort(); // finally, create the genome var factory = (INEATGenomeFactory)_owner .Population.GenomeFactory; var babyGenome = factory.Factor(selectedNeurons, selectedLinks, mom.InputCount, mom.OutputCount); babyGenome.BirthGeneration = _owner.IterationNumber; babyGenome.Population = _owner.Population; babyGenome.SortGenes(); offspring[offspringIndex] = babyGenome; }
/// <summary> /// Called for each node in the progrmam. If this is a const node, then /// mutate it according to the frequency and sigma specified. /// </summary> /// <param name="rnd">Random number generator.</param> /// <param name="node">The node to mutate.</param> private void MutateNode(EncogRandom rnd, ProgramNode node) { if (node.Template == StandardExtensions.EXTENSION_CONST_SUPPORT) { if (rnd.NextDouble() < _frequency) { ExpressionValue v = node.Data[0]; if (v.IsFloat) { double adj = rnd.NextGaussian()*_sigma; node.Data[0] = new ExpressionValue(v.ToFloatValue() + adj); } } } foreach (ITreeNode n in node.ChildNodes) { var childNode = (ProgramNode) n; MutateNode(rnd, childNode); } }
/// <summary> /// Create a new genome with the specified connection density. This /// constructor is typically used to create the initial population. /// </summary> /// <param name="rnd">Random number generator.</param> /// <param name="pop">The population.</param> /// <param name="inputCount">The input count.</param> /// <param name="outputCount">The output count.</param> /// <param name="connectionDensity">The connection density.</param> public NEATGenome(EncogRandom rnd, NEATPopulation pop, int inputCount, int outputCount, double connectionDensity) { AdjustedScore = 0; InputCount = inputCount; OutputCount = outputCount; // get the activation function IActivationFunction af = pop.ActivationFunctions.PickFirst(); // first bias int innovationId = 0; var biasGene = new NEATNeuronGene(NEATNeuronType.Bias, af, inputCount, innovationId++); _neuronsList.Add(biasGene); // then inputs for (var i = 0; i < inputCount; i++) { var gene = new NEATNeuronGene(NEATNeuronType.Input, af, i, innovationId++); _neuronsList.Add(gene); } // then outputs for (int i = 0; i < outputCount; i++) { var gene = new NEATNeuronGene(NEATNeuronType.Output, af, i + inputCount + 1, innovationId++); _neuronsList.Add(gene); } // and now links for (var i = 0; i < inputCount + 1; i++) { for (var j = 0; j < outputCount; j++) { // make sure we have at least one connection if (_linksList.Count < 1 || rnd.NextDouble() < connectionDensity) { long fromId = this._neuronsList[i].Id; long toId = this._neuronsList[inputCount + j + 1].Id; double w = RangeRandomizer.Randomize(rnd, -pop.WeightRange, pop.WeightRange); var gene = new NEATLinkGene(fromId, toId, true, innovationId++, w); _linksList.Add(gene); } } } }
/// <inheritdoc/> public IList<NEATLinkGene> SelectLinks(EncogRandom rnd, NEATGenome genome) { IList<NEATLinkGene> result = new List<NEATLinkGene>(); bool mutated = false; foreach (var linkGene in genome.LinksChromosome) { if (rnd.NextDouble() < _proportion) { mutated = true; result.Add(linkGene); } } if (!mutated) { int idx = rnd.Next(genome.LinksChromosome.Count); NEATLinkGene linkGene = genome.LinksChromosome[idx]; result.Add(linkGene); } return result; }