/// <summary> /// Create a fresh start for an <see cref="Neat"/> object /// </summary> private void Reset() { AllConnections.Clear(); AllNodes.Clear(); AllClients.Clear(); for (int i = 0; i < Constants.InputSize; i++) { NodeGene node = CreateNode(); node.X = 0.1;; node.Y = (i + 1) / (double)(Constants.InputSize + 1); } for (int i = 0; i < Constants.OutputSize; i++) { NodeGene node = CreateNode(); node.X = 0.9;; node.Y = (i + 1) / (double)(Constants.OutputSize + 1); ActivationEnumeration a = ActivationEnumeration.Random(); node.Activation = a.Activation; node.ActivationName = a.Name; } for (int i = 0; i < Constants.MaxClients; i++) { Client c = new Client(EmptyGenome()); AllClients.Add(c); } }
///<inheritdoc/> public void MutateActivationRandom() { NodeGene node = Nodes.RandomElement(); if (node?.X > 0.1) { ActivationEnumeration a = ActivationEnumeration.Random(); node.Activation = a.Activation; node.ActivationName = a.Name; } }
///<inheritdoc/> public void MutateNode() { ConnectionGene connection = Connections.RandomElement(); if (connection == null) { return; } NodeGene from = connection.In; NodeGene to = connection.Out; int replaceIndex = Neat.GetReplaceIndex(from, to); NodeGene middle; if (replaceIndex == 0) { ActivationEnumeration a = ActivationEnumeration.Random(); middle = Neat.CreateNode(); middle.X = (from.X + to.X) / 2; middle.Y = ((from.Y + to.Y) / 2) + (ThreadSafeRandom.NormalRand(0, 0.02f) / 2); middle.Activation = a.Activation; middle.ActivationName = a.Name; Neat.SetReplaceIndex(from, to, middle.InnovationNumber); } else { middle = Neat.GetNode(replaceIndex); } ConnectionGene connection1 = Neat.GetConnection(from, middle); ConnectionGene connection2 = Neat.GetConnection(middle, to); connection1.Weight = 1; connection2.Weight = connection.Weight; connection2.Enabled = connection.Enabled; connection.Enabled = false; Connections.Add(connection1); Connections.Add(connection2); Nodes.Add(middle); }