/// <summary> /// Generates a brain from a parent brain using mutability for random changes /// </summary> /// <param name="parent">Parent brain</param> /// <param name="mutability">Mutability</param> public void GenerateFromBrain(Brain parent, double mutability) { if (Generated) { throw new InvalidOperationException("Brain already generated!"); } //Copy and mutate neurons while remembering target synapse neurons and synapse weight var inputNeuronTargetParameters = new Tuple <int, double> [InputWidth + MemoryWidth][]; for (int i = 0; i < inputNeurons.Length; i++) { inputNeurons[i] = new SensoryNeuron(parent.inputNeurons[i]); inputNeuronTargetParameters[i] = parent.inputNeurons[i].OutputParameters(parent.thinkingNeurons); inputNeurons[i].Mutate(mutability); } var thinkingNeuronTargetParameters = new Tuple <int, double> [ThinkingWidth][]; for (int i = 0; i < thinkingNeurons.Length; i++) { thinkingNeurons[i] = new Neuron(parent.thinkingNeurons[i]); thinkingNeuronTargetParameters[i] = parent.thinkingNeurons[i].OutputParameters(parent.outputNeurons); thinkingNeurons[i].Mutate(mutability); } for (int i = 0; i < outputNeurons.Length; i++) { outputNeurons[i] = new Neuron(parent.outputNeurons[i]); outputNeurons[i].Mutate(mutability); } //Copy and mutate synapses for (int i = 0; i < inputNeurons.Length; i++) { var x = 0; foreach (var targetParameters in inputNeuronTargetParameters[i]) { var copiedSynapse = new Synapse(inputNeurons[i], thinkingNeurons[targetParameters.Item1], targetParameters.Item2); x++; } inputNeurons[i].MutateSynapses(mutability, thinkingNeurons); } for (int i = 0; i < thinkingNeurons.Length; i++) { var x = 0; foreach (var targetParameters in thinkingNeuronTargetParameters[i]) { var copiedSynapse = new Synapse(inputNeurons[i], thinkingNeurons[targetParameters.Item1], targetParameters.Item2); x++; } thinkingNeurons[i].MutateSynapses(mutability, outputNeurons); } Generated = true; }
/// <summary> /// Generates a random brain /// </summary> public void GenerateRandom() { if (Generated) { throw new InvalidOperationException("Brain already generated!"); } for (int i = 0; i < inputNeurons.Length; i++) { inputNeurons[i] = new SensoryNeuron(); } for (int i = 0; i < thinkingNeurons.Length; i++) { thinkingNeurons[i] = new Neuron(); } for (int i = 0; i < outputNeurons.Length; i++) { outputNeurons[i] = new Neuron(); } for (int i = 0; i < memory.Length; i++) { memory[i] = RandomThreadSafe.NextDouble(); } //Not the true max, as we do not limit multiple synapses between the same neurons, but it is the count of possible unique ones var MaxSynapsesBetweenLayers = inputNeurons.Length * thinkingNeurons.Length; for (int i = 0; i < RandomThreadSafe.Next(MaxSynapsesBetweenLayers); i++) { var fromIndex = RandomThreadSafe.Next(inputNeurons.Length); var toIndex = RandomThreadSafe.Next(thinkingNeurons.Length); var synapse = new Synapse(inputNeurons[fromIndex], thinkingNeurons[toIndex], RandomThreadSafe.NextDouble()); } MaxSynapsesBetweenLayers = thinkingNeurons.Length * outputNeurons.Length; for (int i = 0; i < RandomThreadSafe.Next(MaxSynapsesBetweenLayers); i++) { var fromIndex = RandomThreadSafe.Next(thinkingNeurons.Length); var toIndex = RandomThreadSafe.Next(outputNeurons.Length); var synapse = new Synapse(thinkingNeurons[fromIndex], outputNeurons[toIndex], RandomThreadSafe.NextDouble()); } Generated = true; }
/// <summary> /// Mutates the neuron's synapses /// </summary> /// <param name="mutability">Mutation rate</param> /// <param name="targetNeurons">Possible neurons to connect new synapses to</param> public void MutateSynapses(double mutability, Neuron[] targetNeurons) { var synapsesToDie = new List <Synapse>(); foreach (var synapse in outputs) { synapse.Mutate(mutability); if (RandomThreadSafe.NextDouble() < mutability) { synapsesToDie.Add(synapse); } } foreach (var synapseToDie in synapsesToDie) { outputs.Remove(synapseToDie); synapseToDie.To.inputs.Remove(synapseToDie); } if (RandomThreadSafe.NextDouble() < mutability) { var possibleTarget = targetNeurons[RandomThreadSafe.Next(0, targetNeurons.Length)]; var newSynapse = new Synapse(this, possibleTarget, RandomThreadSafe.NextDouble()); } }
public override void AddInput(Synapse synapse) { throw new InvalidOperationException("Sensory neurons do not get neural inputs, use the SetOutput method"); }
/// <summary> /// Registers a synapse as output /// </summary> /// <param name="synapse">The output synapse</param> public void AddOutput(Synapse synapse) { outputs.AddFirst(synapse); }
/// <summary> /// Registers a synapse as input /// </summary> /// <param name="synapse">The input synapse</param> public virtual void AddInput(Synapse synapse) { inputs.AddFirst(synapse); }