// create neuron at network initialization public Neuron CreateStartNeuron(Neuron.Type type, int neuronID, float splitX, float splitY) { var oldNeuronInnovID = innovationDB.CheckNeuronStartInnovation(neuronID); Neuron newNeuron; // new innovation if (oldNeuronInnovID == -1) { var neuronInnov = innovationDB.CreateInnovation(InnovationDB.Innovation.Type.NEW_NEURON, -1, -1, type, splitX, splitY); newNeuron = new Neuron(neuronInnov.neuronID, type, splitX, splitY); } else { var newNeuronID = innovationDB.GetNeuronID(oldNeuronInnovID); newNeuron = new Neuron(newNeuronID, type, splitX, splitY); } neurons.Add(newNeuron.ID, newNeuron); return(newNeuron); }
public Genome Crossover(Genome other) { var parentA = this; var parentB = other; Genome best = new Genome(); if (parentA.fitness == parentB.fitness) { // if same fitness pick shortest genome if (parentA.NumGenes() < parentB.NumGenes()) { best = parentA; } else if (parentB.NumGenes() < parentA.NumGenes()) { best = parentB; } else { int randomElement = Random.Range(0, 2); best = randomElement == 0 ? parentA : parentB; } } else if (parentA.fitness > parentB.fitness) { best = parentA; } else { best = parentB; } var childWeights = new IntWeightDictionary(); var childNeurons = new IntNeuronDictionary(); int parentAIndex = 0, parentBIndex = 0; Weight parentAWeight = null, parentBWeight = null; // while end of both genes is not reached while (parentAIndex < parentA.weights.Count || parentBIndex < parentB.weights.Count) { if (parentAIndex < parentA.weights.Count) { parentAWeight = parentA.weights.ElementAt(parentAIndex).Value.Copy(); } if (parentBIndex < parentB.weights.Count) { parentBWeight = parentB.weights.ElementAt(parentBIndex).Value.Copy(); } Weight selectedWeight = null; if (parentAIndex == parentA.weights.Count && parentBIndex != parentB.weights.Count) { // add excess genes if (parentB == best) { selectedWeight = parentBWeight; } parentBIndex++; } else if (parentBIndex == parentB.weights.Count && parentAIndex != parentA.weights.Count) { // add excess genes if (parentA == best) { selectedWeight = parentAWeight; } parentAIndex++; } else if (parentAWeight.innovID < parentBWeight.innovID) { // add parentA disjoint genes if (parentA == best) { selectedWeight = parentAWeight; } parentAIndex++; } else if (parentBWeight.innovID < parentAWeight.innovID) { // add parentB disjoint genes if (parentB == best) { selectedWeight = parentBWeight; } parentBIndex++; } else { int randomElement = Random.Range(0, 2); selectedWeight = randomElement == 0 ? parentAWeight : parentBWeight; if (!parentAWeight.enabled && !parentBWeight.enabled) { float random = Random.value; if (random <= pWeightEnabled) { selectedWeight.enabled = true; } } parentAIndex++; parentBIndex++; } if (selectedWeight != null && !childWeights.ContainsKey(selectedWeight.innovID)) { childWeights.Add(selectedWeight.innovID, selectedWeight); } if (selectedWeight != null) { if (!childNeurons.ContainsKey(selectedWeight.neuronIn)) { Neuron neuron = null; if (parentA.weights.Any(x => x.Value.neuronIn == selectedWeight.neuronIn)) { neuron = parentA.neurons[selectedWeight.neuronIn].Copy(); } else if (parentB.weights.Any(x => x.Value.neuronIn == selectedWeight.neuronIn)) { neuron = parentB.neurons[selectedWeight.neuronIn].Copy(); } if (neuron == null) { Debug.LogError("NEURON IS NULL!"); } childNeurons.Add(neuron.ID, neuron); } if (!childNeurons.ContainsKey(selectedWeight.neuronOut)) { Neuron neuron = null; if (parentA.weights.Any(x => x.Value.neuronOut == selectedWeight.neuronOut)) { neuron = parentA.neurons[selectedWeight.neuronOut].Copy(); } else if (parentB.weights.Any(x => x.Value.neuronOut == selectedWeight.neuronOut)) { neuron = parentB.neurons[selectedWeight.neuronOut].Copy(); } if (neuron == null) { Debug.LogError("NEURON IS NULL!"); } childNeurons.Add(neuron.ID, neuron); } } } return(new Genome(childNeurons, childWeights)); }