AddNewNeuronLinks(int linkIndex, CInnovation innovations) { float initialWeight = m_vecLinks[linkIndex].Weight; int from = m_vecLinks[linkIndex].FromNeuron; int to = m_vecLinks[linkIndex].ToNeuron; SNeuronGene fromNeuron = m_vecNeurons[GetNeuronIndexById(from)]; SNeuronGene toNeuron = m_vecNeurons[GetNeuronIndexById(from)]; // The depth of the neuron is used to determine if the new link // feeds backwards (i.e it is a recurrent link) or forwards. float newDepth = (fromNeuron.SplitY + toNeuron.SplitY) / 2; float newWidth = (fromNeuron.SplitX + toNeuron.SplitX) / 2; int innovationID = innovations.CheckInnovation(from, to, InnovationType.NewNeuron); bool alreadyUsed = innovationID >= 0 && UsingNeuronID(innovations.GetNeuronID(innovationID)); if (innovationID < 0 || alreadyUsed) { AddNeuronNewInnovation(innovations, from, to, newWidth, newDepth, initialWeight); } else { int newNeuronID = innovations.GetNeuronID(innovationID); AddNeuronExistingInnovation(innovations, newNeuronID, from, to, newWidth, newDepth, initialWeight); } }
Cga(int inputs, int outputs) { m_Population = new List <CGenome> (); for (int i = 0; i < _params.NumGenomesToSpawn; i++) { m_Population.Add(new CGenome(nextGenomeID++, inputs, outputs)); } m_PopSize = m_Population.Count; // Create simple genome used for innovations database CGenome genome = new CGenome(1, inputs, outputs); m_vecSpecies = new List <CSpecies> (); innovation = new CInnovation(genome.GetLinks(), genome.GetNeurons()); vecSplits = new List <SplitDepth> (); // Create the network depth lookup table. Split(0, 1, 0); }
AddNeuronNewInnovation(CInnovation innovations, int from, int to, float newWidth, float newDepth, float initialWeight) { int newNeuronID = innovations.CreateNewInnovation(from, to, InnovationType.NewNeuron, NeuronType.Hidden, newWidth, newDepth); // In addition to adding the new neuron two new links // are created and stored in the innovations database int idLink1 = innovations.NextInnovationID(); innovations.CreateNewInnovation(from, newNeuronID, InnovationType.NewLink); int idLink2 = innovations.NextInnovationID(); innovations.CreateNewInnovation(newNeuronID, to, InnovationType.NewLink); CreateNewNeuronLinks(from, to, newNeuronID, idLink1, idLink2, newWidth, newDepth, initialWeight); }
AddNeuronExistingInnovation(CInnovation innovations, int newNeuronID, int from, int to, float newWidth, float newDepth, float initialWeight) { int idLink1 = innovations.CheckInnovation(from, newNeuronID, InnovationType.NewLink); int idLink2 = innovations.CheckInnovation(newNeuronID, to, InnovationType.NewLink); /* * This should not happen because if we got here the * links should logically already have a innovation */ if (idLink1 < 0 || idLink2 < 0) { Debug.LogError("Error: no link genes found for neuron"); return; } CreateNewNeuronLinks(from, to, newNeuronID, idLink1, idLink2, newWidth, newDepth, initialWeight); }
AddNeuron(float mutationRate, CInnovation innovations, int numTriesToFindOldLink) { if (Random.value > mutationRate) { return; } // If this flag is true a valid link for the new neuron has been // found. bool foundLink = false; // Store the index of the link that will be used. int linkIndex = 0; if (m_vecLinks.Count < (m_iNumInputs + m_iNumOutputs + _params.MinHiddenNeurons)) { foundLink = FindNeuronLinkBiased(out linkIndex, numTriesToFindOldLink); if (!foundLink) { return; } } else /* The genome is complex enough to select any link */ { do { linkIndex = Random.Range(0, NumGenes()); }while (!CanLinkBeSplit(linkIndex)); } // Disable this link first so we can replace it with two new. m_vecLinks[linkIndex].Disable(); AddNewNeuronLinks(linkIndex, innovations); }
AddLink(float mutationRate, float chanceOfLooped, CInnovation innovations, int numTriesToFindLoop, int numTriesToAddLink) { if (Random.value > mutationRate) { return; } int neuron1_ID = -1; int neuron2_ID = -1; // If this flag is true a recurrent link is added. bool setRecurrent = false; // There is a chance that this will be a looped recurrent link // (i.e a neuron that has a link directly to itself). if (Random.value < chanceOfLooped) { setRecurrent = AddLoopedRecurrentLink(out neuron1_ID, out neuron2_ID, numTriesToFindLoop); } else { AddNonReccurentLink(out neuron1_ID, out neuron2_ID, numTriesToAddLink); } if (neuron1_ID < 0 || neuron2_ID < 0) { return; } // Does the database already hold a similar innovation? int innovationID = innovations.CheckInnovation(neuron1_ID, neuron2_ID, InnovationType.NewLink); // Check if this link is a recurrent link (non-looped). // If the link feeds backward it is a recurrent link. // // A backward link is characterized with the fact that the from // neuron has a greater SplitY value than the to neuron. if (m_vecNeurons[GetNeuronIndexById(neuron1_ID)].SplitY > m_vecNeurons[GetNeuronIndexById(neuron2_ID)].SplitY) { setRecurrent = true; } if (innovationID < 0) { // This innovation does not exist so we add a new innovation // to the database with a id so we can later refer to it by // its new id. The new link gene will be tagged with this id. innovations.CreateNewInnovation(neuron1_ID, neuron2_ID, InnovationType.NewLink); innovationID = innovations.NextInnovationID() - 1; } // Assign the innovation id to a new link gene. SLinkGene newGene = new SLinkGene(neuron1_ID, neuron2_ID, true /* enable */, innovationID, Random.Range(-1.0f, 1.0f) /* initial weight */, setRecurrent); m_vecLinks.Add(newGene); }