/// Finds a link and expands it void AddNewHiddenNeuron() { if (linkCount == 0) { Debug.LogError("Cannot create new hidden neuron because link list count is zero"); return; } int randLinkID = Random.Range(0, linkCount); // Create new neuron //NeuronGenome newNeuronGenome = new NeuronGenome("HidNew", NeuronType.Hid, BrainModuleID.Undefined, hiddenNeurons.Count); var newHiddenNeuron = new NeuronGenome(hiddenTemplate, inOutNeurons.Count + hiddenNeurons.Count); hiddenNeurons.Add(newHiddenNeuron); // create 2 new links LinkGenome linkGenome1 = new LinkGenome(links[randLinkID].from, newHiddenNeuron, 1f, true); LinkGenome linkGenome2 = new LinkGenome(newHiddenNeuron, links[randLinkID].to, links[randLinkID].weight, true); // delete old link links[randLinkID].enabled = false; // *** not needed? **** links.RemoveAt(randLinkID); // add new links links.Add(linkGenome1); links.Add(linkGenome2); //Debug.Log("New Neuron! " + newNeuronGenome.nid.neuronID.ToString() + // " - from: [" + linkGenome1.fromModuleID.ToString() + ", " + // linkGenome1.fromNeuronID.ToString() + "], to: [" + linkGenome2.toModuleID.ToString() + // ", " + linkGenome2.toNeuronID.ToString() + "]"); }
List <LinkGenome> MutateLinks(List <LinkGenome> original, MutationSettingsInstance settings) { var result = new List <LinkGenome>(); foreach (var element in original) { LinkGenome newLinkGenome = new LinkGenome(element.from, element.to, element.weight, true); // Remove fully??? ***** if (RandomStatics.CoinToss(settings.brainRemoveLinkChance)) { newLinkGenome.weight = 0f; } if (RandomStatics.CoinToss(settings.brainWeightMutationChance)) { float randomWeight = Gaussian.GetRandomGaussian(); newLinkGenome.weight += Mathf.Lerp(0f, randomWeight, settings.brainWeightMutationStepSize); } newLinkGenome.weight *= settings.brainWeightDecayAmount; result.Add(newLinkGenome); } return(result); }
/// Apply a random chance of connecting two neurons with a random weight void RequestConnection(NeuronGenome from, NeuronGenome to, float connectionChance, float weightMultiplier) { var connectNeurons = RandomStatics.CoinToss(connectionChance); if (!connectNeurons) { return; } var randomWeight = Gaussian.GetRandomGaussian() * weightMultiplier; var linkGenome = new LinkGenome(from, to, randomWeight, true); links.Add(linkGenome); }
void AddNewLink(MutationSettingsInstance settings) { foreach (var neuron in hiddenNeurons) { inputNeurons.Add(neuron); outputNeurons.Add(neuron); } if (inputNeurons.Count <= 0 || outputNeurons.Count <= 0) { Debug.LogError("Cannot create new list because input or output list count is zero. " + $"Input count = {inputNeurons.Count}, output count = {outputNeurons.Count}"); return; } // Try x times to find new connection -- random scattershot approach at first: // other methods: // -- make sure all bodyNeurons are fully-connected when modifying body int maxChecks = 8; for (int k = 0; k < maxChecks; k++) { int randInputID = Random.Range(0, inputNeurons.Count); var from = inputNeurons[randInputID]; int randOutputID = Random.Range(0, outputNeurons.Count); var to = outputNeurons[randOutputID]; if (LinkExists(from, to)) { continue; } float randomWeight = Gaussian.GetRandomGaussian() * settings.brainWeightMutationStepSize; LinkGenome linkGenome = new LinkGenome(from, to, randomWeight, true); links.Add(linkGenome); //Debug.Log("New Link! from: [" + fromNID.moduleID.ToString() + ", " + fromNID.neuronID.ToString() + "], to: [" + toNID.moduleID.ToString() + ", " + toNID.neuronID.ToString() + "]"); break; } }
public void CreateSpeciesLeaderboardGenomeTexture() { int width = 32; int height = 96; speciesPoolGenomeTex.Resize(width, height); SpeciesGenomePool pool = simulationManager.GetSelectedGenomePool(); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { LinkGenome linkGenome = pool.GetLeaderboardLinkGenome(x, y); Color testColor = linkGenome == null ? CLEAR : Color.Lerp(negativeColor, positiveColor, linkGenome.normalizedWeight); speciesPoolGenomeTex.SetPixel(x, y, testColor); } } // Body Genome //int xI = curLinearIndex % speciesPoolGenomeTex.width; //int yI = Mathf.FloorToInt(curLinearIndex / speciesPoolGenomeTex.width); speciesPoolGenomeTex.Apply(); }
public void SetToMutatedCopyOfParentGenome(BrainGenome parentGenome, TrainingSettingsManager settings) { this.bodyNeuronList = parentGenome.bodyNeuronList; // UNSUSTAINABLE!!! might work now since all neuronLists are identical // Alternate: SetBodyNeuronsFromTemplate(BodyGenome templateBody); // Existing Hidden Neurons!! hiddenNeuronList = new List <NeuronGenome>(); for (int i = 0; i < parentGenome.hiddenNeuronList.Count; i++) { NeuronGenome newHiddenNeuronGenome = new NeuronGenome(parentGenome.hiddenNeuronList[i]); // create new neuron as a copy of parent neuron // Might be able to simply copy hiddenNeuronList or individual hiddenNeuronGenomes from parent if they are functionally identical... // for now going with the thorough approach of a reference-less copy hiddenNeuronList.Add(newHiddenNeuronGenome); } // Existing Links!! linkList = new List <LinkGenome>(); for (int i = 0; i < parentGenome.linkList.Count; i++) { LinkGenome newLinkGenome = new LinkGenome(parentGenome.linkList[i].fromModuleID, parentGenome.linkList[i].fromNeuronID, parentGenome.linkList[i].toModuleID, parentGenome.linkList[i].toNeuronID, parentGenome.linkList[i].weight, true); float randChance = UnityEngine.Random.Range(0f, 1f); if (randChance < settings.mutationChance) { float randomWeight = Gaussian.GetRandomGaussian(); newLinkGenome.weight = Mathf.Lerp(newLinkGenome.weight, randomWeight, settings.mutationStepSize); } linkList.Add(newLinkGenome); } // Add Brand New Link: // float randLink = UnityEngine.Random.Range(0f, 1f); if (randLink < settings.newLinkChance) { List <NeuronGenome> inputNeuronList = new List <NeuronGenome>(); //List<NeuronGenome> hiddenNeuronList = new List<NeuronGenome>(); List <NeuronGenome> outputNeuronList = new List <NeuronGenome>(); for (int j = 0; j < bodyNeuronList.Count; j++) { if (bodyNeuronList[j].neuronType == NeuronGenome.NeuronType.In) { inputNeuronList.Add(bodyNeuronList[j]); } if (bodyNeuronList[j].neuronType == NeuronGenome.NeuronType.Out) { outputNeuronList.Add(bodyNeuronList[j]); } } for (int j = 0; j < hiddenNeuronList.Count; j++) { inputNeuronList.Add(hiddenNeuronList[j]); outputNeuronList.Add(hiddenNeuronList[j]); } // Try x times to find new connection -- random scattershot approach at first: // other methods: // -- make sure all bodyNeurons are fully-connected when modifying body int maxChecks = 8; for (int k = 0; k < maxChecks; k++) { int randID = UnityEngine.Random.Range(0, inputNeuronList.Count); NID fromNID = inputNeuronList[randID].nid; randID = UnityEngine.Random.Range(0, outputNeuronList.Count); NID toNID = outputNeuronList[randID].nid; // check if it exists: bool linkExists = false; for (int l = 0; l < linkList.Count; l++) { if (linkList[l].fromModuleID == fromNID.moduleID && linkList[l].fromNeuronID == fromNID.neuronID && linkList[l].toModuleID == toNID.moduleID && linkList[l].toNeuronID == toNID.neuronID) { linkExists = true; break; } } if (linkExists) { } else { float randomWeight = Gaussian.GetRandomGaussian() * 0f; LinkGenome linkGenome = new LinkGenome(fromNID.moduleID, fromNID.neuronID, toNID.moduleID, toNID.neuronID, randomWeight, true); //Debug.Log("New Link! from: [" + fromNID.moduleID.ToString() + ", " + fromNID.neuronID.ToString() + "], to: [" + toNID.moduleID.ToString() + ", " + toNID.neuronID.ToString() + "]"); linkList.Add(linkGenome); break; } } } // Add Brand New Hidden Neuron: float randNeuronChance = UnityEngine.Random.Range(0f, 1f); if (randNeuronChance < settings.newHiddenNodeChance) { // find a link and expand it: int randLinkID = UnityEngine.Random.Range(0, linkList.Count); // create new neuron NeuronGenome newNeuronGenome = new NeuronGenome(NeuronGenome.NeuronType.Hid, -1, hiddenNeuronList.Count); hiddenNeuronList.Add(newNeuronGenome); // create 2 new links LinkGenome linkGenome1 = new LinkGenome(linkList[randLinkID].fromModuleID, linkList[randLinkID].fromNeuronID, newNeuronGenome.nid.moduleID, newNeuronGenome.nid.neuronID, 1f, true); LinkGenome linkGenome2 = new LinkGenome(newNeuronGenome.nid.moduleID, newNeuronGenome.nid.neuronID, linkList[randLinkID].toModuleID, linkList[randLinkID].toNeuronID, linkList[randLinkID].weight, true); // delete old link linkList.RemoveAt(randLinkID); // add new links linkList.Add(linkGenome1); linkList.Add(linkGenome2); //Debug.Log("New Neuron! " + newNeuronGenome.nid.neuronID.ToString() + " - from: [" + linkGenome1.fromModuleID.ToString() + ", " + linkGenome1.fromNeuronID.ToString() + "], to: [" + linkGenome2.toModuleID.ToString() + ", " + linkGenome2.toNeuronID.ToString() + "]"); } }
public void InitializeAxons(float initialWeightMultiplier) { int numInputs = 0; for (int i = 0; i < bodyNeuronList.Count; i++) { if (bodyNeuronList[i].neuronType == NeuronGenome.NeuronType.In) { numInputs++; } } // !!!!! ===== UPGRADE NOTE: !!!!!!!!!!!! // Add support for initial traditional hidden layers - generalize down to 0 to support all initializations // !!!!! ===== UPGRADE NOTE: !!!!!!!!!!!! // Create Hidden nodes TEMP!!!! for (int i = 0; i < numInputs; i++) { //NeuronGenome neuron = new NeuronGenome(NeuronGenome.NeuronType.Hid, 20, i); //brainGenome.neuronList.Add(neuron); } // Create initial connections -- : List <NeuronGenome> inputNeuronList = new List <NeuronGenome>(); //List<NeuronGenome> hiddenNeuronList = new List<NeuronGenome>(); List <NeuronGenome> outputNeuronList = new List <NeuronGenome>(); for (int i = 0; i < bodyNeuronList.Count; i++) { if (bodyNeuronList[i].neuronType == NeuronGenome.NeuronType.In) { inputNeuronList.Add(bodyNeuronList[i]); } //if (brainGenome.neuronList[i].neuronType == NeuronGenome.NeuronType.Hid) { // hiddenNeuronList.Add(brainGenome.neuronList[i]); //} if (bodyNeuronList[i].neuronType == NeuronGenome.NeuronType.Out) { outputNeuronList.Add(bodyNeuronList[i]); } } // Initialize fully connected with all weights Random for (int i = 0; i < outputNeuronList.Count; i++) { for (int j = 0; j < inputNeuronList.Count; j++) { float randomWeight = Gaussian.GetRandomGaussian() * initialWeightMultiplier; LinkGenome linkGenome = new LinkGenome(inputNeuronList[j].nid.moduleID, inputNeuronList[j].nid.neuronID, outputNeuronList[i].nid.moduleID, outputNeuronList[i].nid.neuronID, randomWeight, true); linkList.Add(linkGenome); } } /*for (int i = 0; i < outputNeuronList.Count; i++) { * for(int j = 0; j < hiddenNeuronList.Count; j++) { * float randomWeight = Gaussian.GetRandomGaussian() * initialWeightMultiplier; * LinkGenome linkGenome = new LinkGenome(hiddenNeuronList[j].nid.moduleID, hiddenNeuronList[j].nid.neuronID, outputNeuronList[i].nid.moduleID, outputNeuronList[i].nid.neuronID, randomWeight, true); * brainGenome.linkList.Add(linkGenome); * } * } * for (int i = 0; i < hiddenNeuronList.Count; i++) { * for (int j = 0; j < inputNeuronList.Count; j++) { * float randomWeight = Gaussian.GetRandomGaussian() * initialWeightMultiplier; * LinkGenome linkGenome = new LinkGenome(inputNeuronList[j].nid.moduleID, inputNeuronList[j].nid.neuronID, hiddenNeuronList[i].nid.moduleID, hiddenNeuronList[i].nid.neuronID, randomWeight, true); * brainGenome.linkList.Add(linkGenome); * } * }*/ //PrintBrainGenome(); }
public void InitializeAxons(float initialWeightMultiplier) { int numInputs = 0; for (int i = 0; i < bodyNeuronList.Count; i++) { if (bodyNeuronList[i].neuronType == NeuronGenome.NeuronType.In) { numInputs++; } } // Create Hidden nodes TEMP!!!! for (int i = 0; i < numInputs; i++) { NeuronGenome neuron = new NeuronGenome(NeuronGenome.NeuronType.Hid, -1, i); hiddenNeuronList.Add(neuron); } // Create initial connections -- : List <NeuronGenome> inputNeuronList = new List <NeuronGenome>(); //List<NeuronGenome> hiddenNeuronList = new List<NeuronGenome>(); List <NeuronGenome> outputNeuronList = new List <NeuronGenome>(); for (int i = 0; i < bodyNeuronList.Count; i++) { if (bodyNeuronList[i].neuronType == NeuronGenome.NeuronType.In) { inputNeuronList.Add(bodyNeuronList[i]); } //if (brainGenome.neuronList[i].neuronType == NeuronGenome.NeuronType.Hid) { // hiddenNeuronList.Add(brainGenome.neuronList[i]); //} if (bodyNeuronList[i].neuronType == NeuronGenome.NeuronType.Out) { outputNeuronList.Add(bodyNeuronList[i]); } } // Initialize fully connected with all weights Random for (int i = 0; i < outputNeuronList.Count; i++) { for (int j = 0; j < inputNeuronList.Count; j++) { float randomWeight = Gaussian.GetRandomGaussian() * initialWeightMultiplier; LinkGenome linkGenome = new LinkGenome(inputNeuronList[j].nid.moduleID, inputNeuronList[j].nid.neuronID, outputNeuronList[i].nid.moduleID, outputNeuronList[i].nid.neuronID, randomWeight, true); linkList.Add(linkGenome); } } for (int i = 0; i < outputNeuronList.Count; i++) { for (int j = 0; j < hiddenNeuronList.Count; j++) { float randomWeight = Gaussian.GetRandomGaussian() * initialWeightMultiplier; LinkGenome linkGenome = new LinkGenome(hiddenNeuronList[j].nid.moduleID, hiddenNeuronList[j].nid.neuronID, outputNeuronList[i].nid.moduleID, outputNeuronList[i].nid.neuronID, randomWeight, true); linkList.Add(linkGenome); } } for (int i = 0; i < hiddenNeuronList.Count; i++) { for (int j = 0; j < inputNeuronList.Count; j++) { float randomWeight = Gaussian.GetRandomGaussian() * initialWeightMultiplier; LinkGenome linkGenome = new LinkGenome(inputNeuronList[j].nid.moduleID, inputNeuronList[j].nid.neuronID, hiddenNeuronList[i].nid.moduleID, hiddenNeuronList[i].nid.neuronID, randomWeight, true); linkList.Add(linkGenome); } } //PrintBrainGenome(); //Debug.Log("numAxons: " + linkList.Count.ToString()); }