/// <summary> /// Makes the initial connections frome every inout to every output with random weights. /// </summary> public void InitializeRandom() { for (int i = NumInputs; i < NumInputs + NumOutputs; i++) { Neurons.TryGetValue(i, out Neuron outputNeuron); for (int j = 1; j < NumInputs; j++) { Neurons.TryGetValue(j, out Neuron inputNeuron); Tuple <int, int> fromToPair = new Tuple <int, int>(inputNeuron.ID, outputNeuron.ID); Connection conn; if (InnovationNumbers.ContainsKey(fromToPair)) { lock (InnovationNumbers) { InnovationNumbers.TryGetValue(fromToPair, out int innoNumber); conn = new Connection(innoNumber, inputNeuron, rand.NextDouble() * 4 - 2); } } else { lock (InnovationNumbers) { conn = new Connection(InnovationNumbers.Count(), inputNeuron, rand.NextDouble() * 4 - 2); InnovationNumbers.Add(new Tuple <int, int>(inputNeuron.ID, outputNeuron.ID), InnovationNumbers.Count()); } } Connections.Add(fromToPair); outputNeuron.AddConnection(conn.ID, conn); } } }
/// <summary> /// mutates a random link in the neural network /// </summary> public void MutateNeuron() { while (true) { int neuronId = rand.Next(NumInputs, NumInputs + NumOutputs); if (Neurons.TryGetValue(neuronId, out Neuron farNeuron) && farNeuron.Connections.Count > 0) { Connection conn; int connectionId; do { connectionId = rand.Next(farNeuron.Connections.Count()); conn = farNeuron.Connections.Values.ElementAt(connectionId); } while (conn.From.ID == 0); Neuron newNeuron = new Neuron(Neurons.Count); Tuple <int, int> nearToMidTuple = new Tuple <int, int>(conn.From.ID, newNeuron.ID); Connection nearToMid; lock (InnovationNumbers) { if (InnovationNumbers.TryGetValue(nearToMidTuple, out int innoNumber)) { nearToMid = new Connection(innoNumber, conn.From, 1); } else { nearToMid = new Connection(InnovationNumbers.Count(), conn.From, 1); InnovationNumbers.Add(nearToMidTuple, InnovationNumbers.Count()); } } Connection midToFar; Tuple <int, int> midToFarTuple = new Tuple <int, int>(newNeuron.ID, farNeuron.ID); lock (InnovationNumbers) { if (InnovationNumbers.TryGetValue(midToFarTuple, out int innoNumber2)) { midToFar = new Connection(innoNumber2, newNeuron, conn.Weight); } else { midToFar = new Connection(InnovationNumbers.Count(), newNeuron, conn.Weight); InnovationNumbers.Add(midToFarTuple, InnovationNumbers.Count()); } } Neurons.Add(newNeuron.ID, newNeuron); newNeuron.AddConnection(nearToMid.ID, nearToMid); Connection oldConnection = farNeuron.Connections.Values.ElementAt(connectionId); conn.EnableDisable(); Connections.Add(nearToMidTuple); Connections.Add(midToFarTuple); farNeuron.AddConnection(midToFar.ID, midToFar); NumNeurons++; return; } } }
/// <summary> /// Mutates a random link whithin the neural network. /// </summary> public void MutateLink() { int from; int to; Stopwatch sw = new Stopwatch(); sw.Start(); do { rand = new Random(Guid.NewGuid().GetHashCode()); do { rand = new Random(Guid.NewGuid().GetHashCode()); from = rand.Next(Neurons.Count()); } while (from > NumInputs - 1 && from < NumInputs + NumOutputs); do { rand = new Random(Guid.NewGuid().GetHashCode()); to = rand.Next(NumInputs, Neurons.Count()); } while (to == from || to < NumInputs || (to < from && to >= NumInputs + NumOutputs)); if (sw.ElapsedMilliseconds > 10) { return; } } while (Connections.Contains(new Tuple <int, int>(from, to))); if (Neurons.TryGetValue(to, out Neuron toNeuron)) { if (Neurons.TryGetValue(from, out Neuron fromNeuron)) { Tuple <int, int> fromToPair = new Tuple <int, int>(from, to); Connection conn; if (InnovationNumbers.ContainsKey(fromToPair)) { lock (InnovationNumbers) { InnovationNumbers.TryGetValue(fromToPair, out int innoNumber); conn = new Connection(innoNumber, fromNeuron, rand.NextDouble() * 4 - 2); } } else { lock (InnovationNumbers) { conn = new Connection(InnovationNumbers.Count(), fromNeuron, rand.NextDouble() * 4 - 2); InnovationNumbers.Add(new Tuple <int, int>(from, to), InnovationNumbers.Count()); } } Connections.Add(fromToPair); toNeuron.AddConnection(conn.ID, conn); } } }