/// <summary> /// Create a link between two neuron id's. Create or find any necessary /// innovation records. /// </summary> /// <param name="target">The target genome.</param> /// <param name="neuron1Id">The id of the source neuron.</param> /// <param name="neuron2Id">The id of the target neuron.</param> /// <param name="weight">The weight of this new link.</param> public void CreateLink(NEATGenome target, long neuron1Id, long neuron2Id, double weight) { // first, does this link exist? (and if so, hopefully disabled, // otherwise we have a problem) foreach (NEATLinkGene linkGene in target.LinksChromosome) { if ((linkGene.FromNeuronId == neuron1Id) && (linkGene.ToNeuronId == neuron2Id)) { // bring the link back, at the new weight linkGene.Enabled = true; linkGene.Weight = weight; return; } } // check to see if this innovation has already been tried NEATInnovation innovation = ((NEATPopulation)target .Population).Innovations.FindInnovation(neuron1Id, neuron2Id); // now create this link var lg = new NEATLinkGene(neuron1Id, neuron2Id, true, innovation.InnovationId, weight); target.LinksChromosome.Add(lg); }
IEnumerator Gestation() { gestating = true; yield return(new WaitForSeconds(2f)); Color[] cs = new Color[2]; for (int i = 0; i < colors.Length; i++) { float r = Mutate() ? Random.Range(0f, 1f) : partner != null ? (Random.Range(0, 2) == 0 ? partner.colors[i].r : colors[i].r) : colors[i].r; float g = Mutate() ? Random.Range(0f, 1f) : partner != null ? (Random.Range(0, 2) == 0 ? partner.colors[i].g : colors[i].g) : colors[i].g; float b = Mutate() ? Random.Range(0f, 1f) : partner != null ? (Random.Range(0, 2) == 0 ? partner.colors[i].b : colors[i].b) : colors[i].b; cs[i] = new Color(r, g, b, 1f); } if (!neat) { NeuralNet newNet = net.MutateAndReproduce(2, partner == null ? null : partner.net, true); SimulationStarter.SpawnCreature(transform.position, newNet, cs); } else { if (neatNet != null && partner != null && gameObject != null && partner.neatNet != null) { SimulationStarter.SpawnCreature(transform.position, new NEATNetwork(NEATGenome.Reproduce(neatNet.genome, partner == null ? neatNet.genome : partner.neatNet.genome)), cs); } } vitality /= 2f; gestating = false; partner = null; }
/// <summary> /// Determines if a neuron is still needed. If all links to/from a neuron /// have been removed, then the neuron is no longer needed. /// </summary> /// <param name="target">The target genome.</param> /// <param name="neuronID">The neuron id to check for.</param> /// <returns>Returns true, if the neuron is still needed.</returns> public bool IsNeuronNeeded(NEATGenome target, long neuronID) { // do not remove bias or input neurons or output foreach (NEATNeuronGene gene in target.NeuronsChromosome) { if (gene.Id == neuronID) { NEATNeuronGene neuron = gene; if ((neuron.NeuronType == NEATNeuronType.Input) || (neuron.NeuronType == NEATNeuronType.Bias) || (neuron.NeuronType == NEATNeuronType.Output)) { return(true); } } } // Now check to see if the neuron is used in any links foreach (NEATLinkGene gene in target.LinksChromosome) { NEATLinkGene linkGene = gene; if (linkGene.FromNeuronId == neuronID) { return(true); } if (linkGene.ToNeuronId == neuronID) { return(true); } } return(false); }
/// <summary> /// Construct a starting NEAT population. /// </summary> /// /// <param name="inputCount">The input neuron count.</param> /// <param name="outputCount">The output neuron count.</param> /// <param name="populationSize">The population size.</param> public NEATPopulation(int inputCount, int outputCount, int populationSize) : base(populationSize) { _neatActivationFunction = new ActivationSigmoid(); _outputActivationFunction = new ActivationLinear(); InputCount = inputCount; OutputCount = outputCount; if (populationSize == 0) { throw new NeuralNetworkError( "Population must have more than zero genomes."); } // create the initial population for (int i = 0; i < populationSize; i++) { var genome = new NEATGenome(AssignGenomeID(), inputCount, outputCount); Add(genome); } // create initial innovations var genome2 = (NEATGenome)Genomes[0]; Innovations = new NEATInnovationList(this, genome2.Links, genome2.Neurons); }
/// <summary> /// Find the best neuron, between two parents by the specified neuron id. /// </summary> /// <param name="nodeId">The neuron id.</param> /// <param name="best">The best genome.</param> /// <param name="notBest">The non-best (second best) genome. Also the worst, since this /// is the 2nd best of 2.</param> /// <returns>The best neuron genome by id.</returns> private NEATNeuronGene FindBestNeuron(long nodeId, NEATGenome best, NEATGenome notBest) { NEATNeuronGene result = best.FindNeuron(nodeId) ?? notBest.FindNeuron(nodeId); return(result); }
void SpawnCreature(bool neat = false) { GameObject go = Instantiate(creature, GetSpawn(), Quaternion.Euler(0, 0, Random.Range(0, 360))); Creature c = go.GetComponent <Creature>(); creatures.Add(c); Color[] cs = { new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f), 1f), new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f), 1f) }; if (neat) { NEATGenome g = new NEATGenome(ls[0], ls[ls.Length - 1]); for (int j = 0; j < startConnections; j++) { g.CreateNewConnection(); } for (int j = 0; j < startConnections / 2; j++) { g.CreateNewNode(); } c.InitCreature(new NEATNetwork(g), cs); } else { c.InitCreature(new NeuralNet(ls, ac), cs); } }
/// <summary> /// Remove the specified neuron. /// </summary> /// <param name="target">The target genome.</param> /// <param name="neuronId">The neuron to remove.</param> public void RemoveNeuron(NEATGenome target, long neuronId) { foreach (NEATNeuronGene gene in target.NeuronsChromosome) { if (gene.Id == neuronId) { target.NeuronsChromosome.Remove(gene); return; } } }
/// <inheritdoc/> public override void PerformOperation(EncogRandom rnd, IGenome[] parents, int parentIndex, IGenome[] offspring, int offspringIndex) { int countTrysToAddLink = Owner.MaxTries; NEATGenome target = ObtainGenome(parents, parentIndex, offspring, offspringIndex); // the link will be between these two neurons long neuron1Id = -1; long neuron2Id = -1; // try to add a link while ((countTrysToAddLink--) > 0) { NEATNeuronGene neuron1 = ChooseRandomNeuron(target, true); NEATNeuronGene neuron2 = ChooseRandomNeuron(target, false); if (neuron1 == null || neuron2 == null) { return; } // do not duplicate // do not go to a bias neuron // do not go from an output neuron // do not go to an input neuron if (!IsDuplicateLink(target, neuron1.Id, neuron2.Id) && (neuron2.NeuronType != NEATNeuronType.Bias) && (neuron2.NeuronType != NEATNeuronType.Input)) { if (((NEATPopulation)Owner.Population).ActivationCycles != 1 || neuron1.NeuronType != NEATNeuronType.Output) { neuron1Id = neuron1.Id; neuron2Id = neuron2.Id; break; } } } // did we fail to find a link if ((neuron1Id < 0) || (neuron2Id < 0)) { return; } double r = ((NEATPopulation)target.Population).WeightRange; CreateLink(target, neuron1Id, neuron2Id, RangeRandomizer.Randomize(rnd, -r, r)); target.SortGenes(); }
/// <summary> /// Get the specified neuron's index. /// </summary> /// <param name="target">The neuron id to check for.</param> /// <param name="neuronId">The neuron id.</param> /// <returns>The index.</returns> public int GetElementPos(NEATGenome target, long neuronId) { for (int i = 0; i < target.NeuronsChromosome.Count; i++) { NEATNeuronGene neuronGene = target.NeuronsChromosome[i]; if (neuronGene.Id == neuronId) { return(i); } } return(-1); }
/// <summary> /// Add a neuron. /// </summary> /// <param name="nodeId">The neuron id.</param> /// <param name="vec">The id's used.</param> /// <param name="best">The best genome.</param> /// <param name="notBest">The non-best genome.</param> public void AddNeuronId(long nodeId, IList <NEATNeuronGene> vec, NEATGenome best, NEATGenome notBest) { for (int i = 0; i < vec.Count; i++) { if (vec[i].Id == nodeId) { return; } } vec.Add(FindBestNeuron(nodeId, best, notBest)); }
/// <summary> /// Determine if this is a duplicate link. /// </summary> /// <param name="target">The target genome.</param> /// <param name="fromNeuronId">The from neuron id.</param> /// <param name="toNeuronId">The to neuron id.</param> /// <returns>True if this is a duplicate link.</returns> public bool IsDuplicateLink(NEATGenome target, long fromNeuronId, long toNeuronId) { foreach (NEATLinkGene linkGene in target.LinksChromosome) { if ((linkGene.Enabled) && (linkGene.FromNeuronId == fromNeuronId) && (linkGene.ToNeuronId == toNeuronId)) { return(true); } } return(false); }
/// <inheritdoc/> public override void PerformOperation(EncogRandom rnd, IGenome[] parents, int parentIndex, IGenome[] offspring, int offspringIndex) { NEATGenome target = ObtainGenome(parents, parentIndex, offspring, offspringIndex); double weightRange = ((NEATPopulation)Owner.Population).WeightRange; IList <NEATLinkGene> list = _linkSelection.SelectLinks(rnd, target); foreach (NEATLinkGene gene in list) { _weightMutation.MutateWeight(rnd, gene, weightRange); } }
/// <inheritdoc/> public IList <NEATLinkGene> SelectLinks(EncogRandom rnd, NEATGenome genome) { IList <NEATLinkGene> result = new List <NEATLinkGene>(); int cnt = Math.Min(_linkCount, genome.LinksChromosome.Count); while (result.Count < cnt) { int idx = rnd.Next(genome.LinksChromosome.Count); NEATLinkGene link = genome.LinksChromosome[idx]; if (!result.Contains(link)) { result.Add(link); } } return(result); }
/// <summary> /// Create an initial random population. /// </summary> public void Reset() { // create the genome factory if (IsHyperNEAT) { CODEC = new HyperNEATCODEC(); GenomeFactory = new FactorHyperNEATGenome(); } else { CODEC = new NEATCODEC(); GenomeFactory = new FactorNEATGenome(); } // create the new genomes Species.Clear(); // reset counters GeneIdGenerate.CurrentID = 1; InnovationIDGenerate.CurrentID = 1; EncogRandom rnd = RandomNumberFactory.Factor(); // create one default species BasicSpecies defaultSpecies = new BasicSpecies(); defaultSpecies.Population = this; // create the initial population for (int i = 0; i < PopulationSize; i++) { NEATGenome genome = GenomeFactory.Factor(rnd, this, InputCount, OutputCount, InitialConnectionDensity); defaultSpecies.Add(genome); } defaultSpecies.Leader = defaultSpecies.Members[0]; Species.Add(defaultSpecies); // create initial innovations Innovations = new NEATInnovationList(this); }
/// <summary> /// Choose a random neuron. /// </summary> /// <param name="target">The target genome. Should the input and bias neurons be /// included.</param> /// <param name="choosingFrom">True if we are chosing from all neurons, false if we exclude /// the input and bias.</param> /// <returns>The random neuron.</returns> public NEATNeuronGene ChooseRandomNeuron(NEATGenome target, bool choosingFrom) { int start; if (choosingFrom) { start = 0; } else { start = target.InputCount + 1; } // if this network will not "cycle" then output neurons cannot be source // neurons if (!choosingFrom) { int ac = ((NEATPopulation)target.Population) .ActivationCycles; if (ac == 1) { start += target.OutputCount; } } int end = target.NeuronsChromosome.Count - 1; // no neurons to pick! if (start > end) { return(null); } int neuronPos = RangeRandomizer.RandomInt(start, end); NEATNeuronGene neuronGene = target.NeuronsChromosome[neuronPos]; return(neuronGene); }
/// <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); }
private void OnCollisionEnter2D(Collision2D collision) { if (collision.gameObject.layer == 10) { Creature c = collision.gameObject.GetComponent <Creature>(); if (neat) { if (c != null && c.neatNet != null) { if (NEATGenome.GetCompababliltyRating(neatNet.genome, c.neatNet.genome) < 0.5f) { c.partner = this; partner = c; } } } else { c.partner = this; partner = c; } } }
/// <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); }
/// <summary> /// Add a neuron. /// </summary> /// <param name="nodeId">The neuron id.</param> /// <param name="vec">The id's used.</param> /// <param name="best">The best genome.</param> /// <param name="notBest">The non-best genome.</param> public void AddNeuronId(long nodeId, IList<NEATNeuronGene> vec, NEATGenome best, NEATGenome notBest) { for (int i = 0; i < vec.Count; i++) { if (vec[i].Id == nodeId) { return; } } vec.Add(FindBestNeuron(nodeId, best, notBest)); }
/// <summary> /// Read the object. /// </summary> /// <param name="mask0">The stream to read the object from.</param> /// <returns>The object that was loaded.</returns> public virtual Object Read(Stream mask0) { var result = new NEATPopulation(); var innovationList = new NEATInnovationList { Population = result }; result.Innovations = innovationList; var ins0 = new EncogReadHelper(mask0); IDictionary <Int32, ISpecies> speciesMap = new Dictionary <Int32, ISpecies>(); IDictionary <ISpecies, Int32> leaderMap = new Dictionary <ISpecies, Int32>(); IDictionary <Int32, IGenome> genomeMap = new Dictionary <Int32, IGenome>(); EncogFileSection section; while ((section = ins0.ReadNextSection()) != null) { if (section.SectionName.Equals("NEAT-POPULATION") && section.SubSectionName.Equals("INNOVATIONS")) { foreach (String line in section.Lines) { IList <String> cols = EncogFileSection.SplitColumns(line); var innovation = new NEATInnovation { InnovationID = Int32.Parse(cols[0]), InnovationType = StringToInnovationType(cols[1]), NeuronType = StringToNeuronType(cols[2]), SplitX = CSVFormat.EgFormat.Parse(cols[3]), SplitY = CSVFormat.EgFormat.Parse(cols[4]), NeuronID = Int32.Parse(cols[5]), FromNeuronID = Int32.Parse(cols[6]), ToNeuronID = Int32.Parse(cols[7]) }; result.Innovations.Add(innovation); } } else if (section.SectionName.Equals("NEAT-POPULATION") && section.SubSectionName.Equals("SPECIES")) { foreach (String line in section.Lines) { String[] cols = line.Split(','); var species = new BasicSpecies { SpeciesID = Int32.Parse(cols[0]), Age = Int32.Parse(cols[1]), BestScore = CSVFormat.EgFormat.Parse(cols[2]), GensNoImprovement = Int32.Parse(cols[3]), SpawnsRequired = CSVFormat.EgFormat .Parse(cols[4]) }; species.SpawnsRequired = CSVFormat.EgFormat .Parse(cols[5]); leaderMap[(species)] = (Int32.Parse(cols[6])); result.Species.Add(species); speciesMap[((int)species.SpeciesID)] = (species); } } else if (section.SectionName.Equals("NEAT-POPULATION") && section.SubSectionName.Equals("GENOMES")) { NEATGenome lastGenome = null; foreach (String line in section.Lines) { IList <String> cols = EncogFileSection.SplitColumns(line); if (cols[0].Equals("g", StringComparison.InvariantCultureIgnoreCase)) { lastGenome = new NEATGenome { NeuronsChromosome = new Chromosome(), LinksChromosome = new Chromosome() }; lastGenome.Chromosomes.Add(lastGenome.NeuronsChromosome); lastGenome.Chromosomes.Add(lastGenome.LinksChromosome); lastGenome.GenomeID = Int32.Parse(cols[1]); lastGenome.SpeciesID = Int32.Parse(cols[2]); lastGenome.AdjustedScore = CSVFormat.EgFormat .Parse(cols[3]); lastGenome.AmountToSpawn = CSVFormat.EgFormat .Parse(cols[4]); lastGenome.NetworkDepth = Int32.Parse(cols[5]); lastGenome.Score = CSVFormat.EgFormat.Parse(cols[6]); result.Add(lastGenome); genomeMap[(int)lastGenome.GenomeID] = lastGenome; } else if (cols[0].Equals("n", StringComparison.InvariantCultureIgnoreCase)) { var neuronGene = new NEATNeuronGene { Id = Int32.Parse(cols[1]), NeuronType = StringToNeuronType(cols[2]), Enabled = Int32.Parse(cols[3]) > 0, InnovationId = Int32.Parse(cols[4]), ActivationResponse = CSVFormat.EgFormat .Parse(cols[5]), SplitX = CSVFormat.EgFormat.Parse(cols[6]), SplitY = CSVFormat.EgFormat.Parse(cols[7]) }; lastGenome.Neurons.Add(neuronGene); } else if (cols[0].Equals("l", StringComparison.InvariantCultureIgnoreCase)) { var linkGene = new NEATLinkGene(); linkGene.Id = Int32.Parse(cols[1]); linkGene.Enabled = Int32.Parse(cols[2]) > 0; linkGene.Recurrent = Int32.Parse(cols[3]) > 0; linkGene.FromNeuronID = Int32.Parse(cols[4]); linkGene.ToNeuronID = Int32.Parse(cols[5]); linkGene.Weight = CSVFormat.EgFormat.Parse(cols[6]); linkGene.InnovationId = Int32.Parse(cols[7]); lastGenome.Links.Add(linkGene); } } } else if (section.SectionName.Equals("NEAT-POPULATION") && section.SubSectionName.Equals("CONFIG")) { IDictionary <String, String> paras = section.ParseParams(); result.NeatActivationFunction = EncogFileSection .ParseActivationFunction(paras, NEATPopulation.PropertyNEATActivation); result.OutputActivationFunction = EncogFileSection .ParseActivationFunction(paras, NEATPopulation.PropertyOutputActivation); result.Snapshot = EncogFileSection.ParseBoolean(paras, PersistConst.Snapshot); result.InputCount = EncogFileSection.ParseInt(paras, PersistConst.InputCount); result.OutputCount = EncogFileSection.ParseInt(paras, PersistConst.OutputCount); result.OldAgePenalty = EncogFileSection.ParseDouble(paras, PopulationConst.PropertyOldAgePenalty); result.OldAgeThreshold = EncogFileSection.ParseInt(paras, PopulationConst.PropertyOldAgeThreshold); result.PopulationSize = EncogFileSection.ParseInt(paras, PopulationConst.PropertyPopulationSize); result.SurvivalRate = EncogFileSection.ParseDouble(paras, PopulationConst.PropertySurvivalRate); result.YoungBonusAgeThreshhold = EncogFileSection.ParseInt( paras, PopulationConst.PropertyYoungAgeThreshold); result.YoungScoreBonus = EncogFileSection.ParseDouble(paras, PopulationConst.PropertyYoungAgeBonus); result.GenomeIDGenerate.CurrentID = EncogFileSection.ParseInt(paras, PopulationConst. PropertyNextGenomeID); result.InnovationIDGenerate.CurrentID = EncogFileSection.ParseInt(paras, PopulationConst. PropertyNextInnovationID); result.GeneIDGenerate.CurrentID = EncogFileSection.ParseInt(paras, PopulationConst. PropertyNextGeneID); result.SpeciesIDGenerate.CurrentID = EncogFileSection.ParseInt(paras, PopulationConst. PropertyNextSpeciesID); } } // now link everything up // first put all the genomes into correct species foreach (IGenome genome in result.Genomes) { var neatGenome = (NEATGenome)genome; var speciesId = (int)neatGenome.SpeciesID; if (speciesMap.ContainsKey(speciesId)) { ISpecies s = speciesMap[speciesId]; s.Members.Add(neatGenome); } neatGenome.InputCount = result.InputCount; neatGenome.OutputCount = result.OutputCount; } // set the species leader links foreach (ISpecies species in leaderMap.Keys) { int leaderID = leaderMap[species]; IGenome leader = genomeMap[leaderID]; species.Leader = leader; ((BasicSpecies)species).Population = result; } return(result); }
/// <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; }
/// <summary> /// Determines if a neuron is still needed. If all links to/from a neuron /// have been removed, then the neuron is no longer needed. /// </summary> /// <param name="target">The target genome.</param> /// <param name="neuronID">The neuron id to check for.</param> /// <returns>Returns true, if the neuron is still needed.</returns> public bool IsNeuronNeeded(NEATGenome target, long neuronID) { // do not remove bias or input neurons or output foreach (NEATNeuronGene gene in target.NeuronsChromosome) { if (gene.Id == neuronID) { NEATNeuronGene neuron = gene; if ((neuron.NeuronType == NEATNeuronType.Input) || (neuron.NeuronType == NEATNeuronType.Bias) || (neuron.NeuronType == NEATNeuronType.Output)) { return true; } } } // Now check to see if the neuron is used in any links foreach (NEATLinkGene gene in target.LinksChromosome) { NEATLinkGene linkGene = gene; if (linkGene.FromNeuronId == neuronID) { return true; } if (linkGene.ToNeuronId == neuronID) { return true; } } return false; }
/// <summary> /// Remove the specified neuron. /// </summary> /// <param name="target">The target genome.</param> /// <param name="neuronId">The neuron to remove.</param> public void RemoveNeuron(NEATGenome target, long neuronId) { foreach (NEATNeuronGene gene in target.NeuronsChromosome) { if (gene.Id == neuronId) { target.NeuronsChromosome.Remove(gene); return; } } }
/// <summary> /// Get the specified neuron's index. /// </summary> /// <param name="target">The neuron id to check for.</param> /// <param name="neuronId">The neuron id.</param> /// <returns>The index.</returns> public int GetElementPos(NEATGenome target, long neuronId) { for (int i = 0; i < target.NeuronsChromosome.Count; i++) { NEATNeuronGene neuronGene = target.NeuronsChromosome[i]; if (neuronGene.Id == neuronId) { return i; } } return -1; }
/// <summary> /// Determine if this is a duplicate link. /// </summary> /// <param name="target">The target genome.</param> /// <param name="fromNeuronId">The from neuron id.</param> /// <param name="toNeuronId">The to neuron id.</param> /// <returns>True if this is a duplicate link.</returns> public bool IsDuplicateLink(NEATGenome target, long fromNeuronId, long toNeuronId) { foreach (NEATLinkGene linkGene in target.LinksChromosome) { if ((linkGene.Enabled) && (linkGene.FromNeuronId == fromNeuronId) && (linkGene.ToNeuronId == toNeuronId)) { return true; } } return false; }
/// <summary> /// Create a link between two neuron id's. Create or find any necessary /// innovation records. /// </summary> /// <param name="target">The target genome.</param> /// <param name="neuron1Id">The id of the source neuron.</param> /// <param name="neuron2Id">The id of the target neuron.</param> /// <param name="weight">The weight of this new link.</param> public void CreateLink(NEATGenome target, long neuron1Id, long neuron2Id, double weight) { // first, does this link exist? (and if so, hopefully disabled, // otherwise we have a problem) foreach (NEATLinkGene linkGene in target.LinksChromosome) { if ((linkGene.FromNeuronId == neuron1Id) && (linkGene.ToNeuronId == neuron2Id)) { // bring the link back, at the new weight linkGene.Enabled = true; linkGene.Weight = weight; return; } } // check to see if this innovation has already been tried NEATInnovation innovation = ((NEATPopulation)target .Population).Innovations.FindInnovation(neuron1Id, neuron2Id); // now create this link var lg = new NEATLinkGene(neuron1Id, neuron2Id, true, innovation.InnovationId, weight); target.LinksChromosome.Add(lg); }
/// <summary> /// Choose a random neuron. /// </summary> /// <param name="target">The target genome. Should the input and bias neurons be /// included.</param> /// <param name="choosingFrom">True if we are chosing from all neurons, false if we exclude /// the input and bias.</param> /// <returns>The random neuron.</returns> public NEATNeuronGene ChooseRandomNeuron(NEATGenome target, bool choosingFrom) { int start; if (choosingFrom) { start = 0; } else { start = target.InputCount + 1; } // if this network will not "cycle" then output neurons cannot be source // neurons if (!choosingFrom) { int ac = ((NEATPopulation)target.Population) .ActivationCycles; if (ac == 1) { start += target.OutputCount; } } int end = target.NeuronsChromosome.Count - 1; // no neurons to pick! if (start > end) { return null; } int neuronPos = RangeRandomizer.RandomInt(start, end); NEATNeuronGene neuronGene = target.NeuronsChromosome[neuronPos]; return neuronGene; }
/// <inheritdoc/> public Object Read(Stream istream) { long nextInnovationId = 0; long nextGeneId = 0; var result = new NEATPopulation(); var innovationList = new NEATInnovationList { Population = result }; result.Innovations = innovationList; var reader = new EncogReadHelper(istream); EncogFileSection section; while ((section = reader.ReadNextSection()) != null) { if (section.SectionName.Equals("NEAT-POPULATION") && section.SubSectionName.Equals("INNOVATIONS")) { foreach (String line in section.Lines) { IList <String> cols = EncogFileSection .SplitColumns(line); var innovation = new NEATInnovation(); var innovationId = int.Parse(cols[1]); innovation.InnovationId = innovationId; innovation.NeuronId = int.Parse(cols[2]); result.Innovations.Innovations[cols[0]] = innovation; nextInnovationId = Math.Max(nextInnovationId, innovationId + 1); } } else if (section.SectionName.Equals("NEAT-POPULATION") && section.SubSectionName.Equals("SPECIES")) { NEATGenome lastGenome = null; BasicSpecies lastSpecies = null; foreach (String line in section.Lines) { IList <String> cols = EncogFileSection.SplitColumns(line); if (String.Compare(cols[0], "s", StringComparison.OrdinalIgnoreCase) == 0) { lastSpecies = new BasicSpecies { Population = result, Age = int.Parse(cols[1]), BestScore = CSVFormat.EgFormat.Parse(cols[2]), GensNoImprovement = int.Parse(cols[3]) }; result.Species.Add(lastSpecies); } else if (String.Compare(cols[0], "g", StringComparison.OrdinalIgnoreCase) == 0) { bool isLeader = lastGenome == null; lastGenome = new NEATGenome { InputCount = result.InputCount, OutputCount = result.OutputCount, Species = lastSpecies, AdjustedScore = CSVFormat.EgFormat.Parse(cols[1]), Score = CSVFormat.EgFormat.Parse(cols[2]), BirthGeneration = int.Parse(cols[3]) }; lastSpecies.Add(lastGenome); if (isLeader) { lastSpecies.Leader = lastGenome; } } else if (String.Compare(cols[0], "n", StringComparison.OrdinalIgnoreCase) == 0) { var neuronGene = new NEATNeuronGene(); int geneId = int.Parse(cols[1]); neuronGene.Id = geneId; IActivationFunction af = EncogFileSection.ParseActivationFunction(cols[2]); neuronGene.ActivationFunction = af; neuronGene.NeuronType = PersistNEATPopulation.StringToNeuronType(cols[3]); neuronGene.InnovationId = int.Parse(cols[4]); lastGenome.NeuronsChromosome.Add(neuronGene); nextGeneId = Math.Max(geneId + 1, nextGeneId); } else if (String.Compare(cols[0], "l", StringComparison.OrdinalIgnoreCase) == 0) { var linkGene = new NEATLinkGene { Id = int.Parse(cols[1]), Enabled = (int.Parse(cols[2]) > 0), FromNeuronId = int.Parse(cols[3]), ToNeuronId = int.Parse(cols[4]), Weight = CSVFormat.EgFormat.Parse(cols[5]), InnovationId = int.Parse(cols[6]) }; lastGenome.LinksChromosome.Add(linkGene); } } } else if (section.SectionName.Equals("NEAT-POPULATION") && section.SubSectionName.Equals("CONFIG")) { IDictionary <string, string> prm = section.ParseParams(); string afStr = prm[NEATPopulation.PropertyNEATActivation]; if (String.Compare(afStr, TypeCppn, StringComparison.OrdinalIgnoreCase) == 0) { HyperNEATGenome.BuildCPPNActivationFunctions(result.ActivationFunctions); } else { result.NEATActivationFunction = EncogFileSection.ParseActivationFunction(prm, NEATPopulation.PropertyNEATActivation); } result.ActivationCycles = EncogFileSection.ParseInt(prm, PersistConst.ActivationCycles); result.InputCount = EncogFileSection.ParseInt(prm, PersistConst.InputCount); result.OutputCount = EncogFileSection.ParseInt(prm, PersistConst.OutputCount); result.PopulationSize = EncogFileSection.ParseInt(prm, NEATPopulation.PropertyPopulationSize); result.SurvivalRate = EncogFileSection.ParseDouble(prm, NEATPopulation.PropertySurvivalRate); result.ActivationCycles = EncogFileSection.ParseInt(prm, NEATPopulation.PropertyCycles); } } // set factories if (result.IsHyperNEAT) { result.GenomeFactory = new FactorHyperNEATGenome(); result.CODEC = new HyperNEATCODEC(); } else { result.GenomeFactory = new FactorNEATGenome(); result.CODEC = new NEATCODEC(); } // set the next ID's result.InnovationIDGenerate.CurrentID = nextInnovationId; result.GeneIdGenerate.CurrentID = nextGeneId; // find first genome, which should be the best genome if (result.Species.Count > 0) { ISpecies species = result.Species[0]; if (species.Members.Count > 0) { result.BestGenome = species.Members[0]; } } return(result); }
/// <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 IList<NEATLinkGene> SelectLinks(EncogRandom rnd, NEATGenome genome) { IList<NEATLinkGene> result = new List<NEATLinkGene>(); int cnt = Math.Min(_linkCount, genome.LinksChromosome.Count); while (result.Count < cnt) { int idx = rnd.Next(genome.LinksChromosome.Count); NEATLinkGene link = genome.LinksChromosome[idx]; if (!result.Contains(link)) { result.Add(link); } } return result; }
/// <summary> /// Find the best neuron, between two parents by the specified neuron id. /// </summary> /// <param name="nodeId">The neuron id.</param> /// <param name="best">The best genome.</param> /// <param name="notBest">The non-best (second best) genome. Also the worst, since this /// is the 2nd best of 2.</param> /// <returns>The best neuron genome by id.</returns> private NEATNeuronGene FindBestNeuron(long nodeId, NEATGenome best, NEATGenome notBest) { NEATNeuronGene result = best.FindNeuron(nodeId) ?? notBest.FindNeuron(nodeId); return result; }
public void Render() { NEATGenome genome = (NEATGenome)this.pop.BestGenome; Substrate substrate = SubstrateFactory.factorSandwichSubstrate(resolution, resolution); HyperNEATCODEC codec = new HyperNEATCODEC(); NEATNetwork phenotype = (NEATNetwork)codec.Decode(this.pop, substrate, genome); TrialEvaluation trial = new TrialEvaluation(phenotype, this.testCase); IntPair actualPos = trial.Query(resolution); // clear what was there before GridCanvas.Children.Clear(); // double boxWidth = GridCanvas.ActualWidth / resolution; double boxHeight = GridCanvas.ActualHeight / resolution; double delta = 2.0 / resolution; int index = 0; for (int row = 0; row < resolution; row++) { double y = -1 + (row * delta); double boxY = row * boxHeight; for (int col = 0; col < resolution; col++) { double x = -1 + (col * delta); double boxX = col * boxWidth; Rectangle r = new Rectangle(); r.SetValue(Canvas.LeftProperty, boxX); r.SetValue(Canvas.TopProperty, boxY); r.Width = boxWidth; r.Height = boxHeight; if (this.testCase.GetPixel(x, y) > 0) { r.Fill = Brushes.Blue; } else { double d = trial.Output[index]; int c = trial.Normalize(d, 255); SolidColorBrush b = new SolidColorBrush(Color.FromRgb(255, (byte)c, 255)); r.Fill = b; r.Stroke = Brushes.Black; } GridCanvas.Children.Add(r); index++; } } Rectangle target = new Rectangle(); target.SetValue(Canvas.LeftProperty, actualPos.X * boxWidth); target.SetValue(Canvas.TopProperty, actualPos.Y * boxHeight); target.Width = boxWidth; target.Height = boxHeight; target.Fill = Brushes.Red; GridCanvas.Children.Add(target); }