/// <summary> /// Mutates creature's genes. Returns true if the creature did mutate false otherwise. /// </summary> /// <returns>true if the creature did mutate false otherwise</returns> public bool Mutate() { bool didMutate = false; for (int i = 0; i < Genes.Count(); i++) // for each gene { if (Tools.rdm.NextDouble() < Properties.GeneMutationProbability) // if gene has to mutate { didMutate = true; Genes.ElementAt(i).Value.Mutate(); switch (Genes.ElementAt(i).Key) { case "force": UpdateForce(); break; case "energy": case "colorH": case "colorS": case "colorV": UpdateColor(); break; } } } return(didMutate); }
public double GetTravelDistance() { var travelingDistance = 0d; for (var i = 0; i < Genes.Count() - 1; i++) { var currentCity = Genes.ElementAt(i); var nextCity = Genes.ElementAt(i + 1); travelingDistance += currentCity.DistanceTo(nextCity); } return(travelingDistance); }
/// <summary> /// Reproduces this creature with other. Creates a newborn creature with genes from its parents. /// </summary> /// <param name="other">significant other</param> public Creature Cross(Creature other) { Creature newborn = new Creature(this.canvas, this.map, true) .WithPosition(new Point(Position.X + Math.Abs(Position.X - other.Position.X) / 2, Position.Y + Math.Abs(Position.Y - other.Position.Y) / 2)); for (int i = 0; i < Genes.Count(); i++) // for each gene { Gene selfGene = Genes.ElementAt(i).Value; Gene otherGene = other.Genes.ElementAt(i).Value; String name = selfGene.Name; uint mask = selfGene.Mask; uint value = 0; if (Tools.rdm.NextDouble() < Properties.CrossoverKeepAverageProbability) // average between self and other { uint avg = selfGene.Value / 2 + otherGene.Value / 2; double rdmOffset = Tools.rdm.NextDouble() - 0.5; // random between -0.5 and 0.5 rdmOffset *= Math.Floor((double)Math.Abs((int)selfGene.Value - (int)otherGene.Value) / 2); // multiply random by difference to get the offset from avg's value value = avg + (uint)Math.Floor(rdmOffset); // apply offset to average } else { if (Tools.rdm.NextDouble() < Properties.CrossoverKeepOtherProbability) // keep other { value = otherGene.Value; } else // keep self { value = selfGene.Value; } } newborn.AddGene(name, value, mask); } newborn.UpdateColor(); newborn.UpdateForce(); return(newborn); }
/// <summary> /// Add nodes to random connection gene in genome /// </summary> private void AddNode(Random rnd, ref int innovation, ref int number, List <Gene> allGenes) { int index = rnd.Next(0, Genes.Count); var pair = Genes.ElementAt(index); Gene gene = pair.Value; gene.Type = GeneType.Disabled; Node node = null; Gene firstGene = null; Gene latterGene = null; bool exists = FindExistingNode(gene, ref node, ref firstGene, ref latterGene, allGenes, ref innovation, ref number); if (!exists) { node = new Node(NodeType.Hidden, gene.In.Layer + 1, ++number); firstGene = new Gene(gene.In, node, 1f, GeneType.Enabled, ++innovation); latterGene = new Gene(node, gene.Out, gene.Weight, GeneType.Enabled, ++innovation); } // Check if the latter gene connection cannot be from the same layer to the same layer if (gene.Out.Layer == node.Layer) { IncrementLayer(node); } if (!Genes.ContainsKey(firstGene.Innovation)) // should always go to if branch { Genes.Add(firstGene.Innovation, firstGene); firstGene.In.OutgoingConnections.Add(firstGene); if (!exists) { var g = firstGene.ShallowCopy(); g.Type = GeneType.AddNode; allGenes.Add(g); // still points to nodes in this genome } } else { ; } if (!Genes.ContainsKey(latterGene.Innovation)) // should always go to if branch { Genes.Add(latterGene.Innovation, latterGene); latterGene.In.OutgoingConnections.Add(latterGene); if (!exists) { var g = latterGene.ShallowCopy(); g.Type = GeneType.AddNode; allGenes.Add(g); // still points to nodes in this genome } } else { ; } if (!Nodes.Contains(node)) // should always go to if branch { Nodes.Add(node); } else { for (int i = 0; i < Nodes.Count; i++) { if (node.Number == Nodes[i].Number) { if (ReferenceEquals(node, Nodes[i])) { ; } else { ; } } } } }