private void Crossover(CarBrain[] brains, List <CarBrain> bestBrainsList, List <CarBrain> weakerBrainsList) { // Reproduce / clone the best cars in each Species (instead of cross better half of random cars): int speciesMaxSize = brains.Length / speciesList.Count; int rest = brains.Length - speciesMaxSize * speciesList.Count; int weakerBrainsIndex = 0; for (int speciesIndex = 0; speciesIndex < speciesList.Count; speciesIndex++) { // Clear carsBrainsList in Species and add again the best car into this list: speciesList[speciesIndex].BrainsList.Clear(); speciesList[speciesIndex].BrainsList.Add(bestBrainsList[speciesIndex]); // speciesList count is equal to bestCarsBrainsList count. // Add weaker cars into the Species and modifiy their Genomes, cloning Genome from the best car: bool restAdded = false; for (int i = 1; i < speciesMaxSize; i++) { CarBrain modifiedBrain = weakerBrainsList[weakerBrainsIndex]; modifiedBrain.Genome.CloneGenome(speciesList[speciesIndex].BrainsList[0].Genome); speciesList[speciesIndex].BrainsList.Add(modifiedBrain); weakerBrainsIndex++; // Add to the list extra car: if (!restAdded && rest > 0) { i--; rest--; restAdded = true; } } } }
Import() { Debug.Log("importing phenotypes..."); if (File.Exists("phenotypes.neat")) { string json = File.ReadAllText("phenotypes.neat"); SerializablePhenotypes serializablePhenotypes = JsonUtility.FromJson <SerializablePhenotypes> (json); if (serializablePhenotypes.phenotypes.Count != brains.Count) { Debug.LogError("phenotypes and genomes mismatch error. (" + serializablePhenotypes.phenotypes.Count + " / " + brains.Count + ")"); return; } this.phenotypes = serializablePhenotypes.phenotypes; for (int i = 0; i < brains.Count; i++) { CarBrain brain = brains[i]; brain.AssignPhenotype(phenotypes[i]); brain.runOnlyMode = true; brain.Reset(); } runOnlyMode = true; } }
/// <summary> /// Initializes the singleton application object. This is the first line of authored code /// executed, and as such is the logical equivalent of main() or WinMain(). /// </summary> public App() { Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync( Microsoft.ApplicationInsights.WindowsCollectors.Metadata | Microsoft.ApplicationInsights.WindowsCollectors.Session); this.InitializeComponent(); this.Suspending += OnSuspending; brain = new CarBrain(); }
/// <summary> /// Create new Species which will have reference list to the cars with similar Genome. /// </summary> public Species(CarBrain firstBrain) { allCreatedSpeciesSum++; speciesNumber = allCreatedSpeciesSum; PickColor(); brainsList.Add(firstBrain); bestGenomePattern = new Genome(CarBrain.InNodesNumber, CarBrain.OutNodesNumber); bestGenomePattern.CloneGenome(firstBrain.Genome); }
private bool CanDrawGenome(CarBrain brain) { if (Input.GetMouseButtonDown(0)) { lastBrainIsLocked = true; genomeDataText.fontStyle = FontStyles.Underline; } return(brain != lastBrain && (!lastBrainIsLocked || Input.GetMouseButtonDown(0))); }
SetBestCar(CarBrain newBest) { if (best != null) { best.car.doUpdateUI = false; } annRenderer.UpdateNeural(newBest.Phenotype()); best = newBest; best.car.doUpdateUI = true; follower.target = newBest.transform; }
//MonoBehaviour callbacks private void Start() { _carBrain = GetComponentInParent <CarBrain>(); GetComponent <BoxCollider>().isTrigger = true; Rigidbody rb = GetComponent <Rigidbody>(); rb.isKinematic = true; rb.useGravity = false; isAtSafeDistance = true; }
private void DrawNodesConnections(CarBrain brain, GameObject[] nodesUI) { int nodesConnectionsNumber = brain.Genome.NodesConnectionsList.Count; for (int i = 0; i < nodesConnectionsNumber; i++) { NodesConnection connection = brain.Genome.NodesConnectionsList[i]; GameObject connectionUI = GetGenomeDataUIElementFromPool(genomeDataNodesConnectionsQueue, genomeDataNodesConnectionPrefab, genomeDataPanelNodesConnections); RectTransform rectTransform = connectionUI.GetComponent <RectTransform>(); TextMeshProUGUI connectionNumberText = connectionUI.GetComponentInChildren <TextMeshProUGUI>(true); connectionNumberText.text = connection.Weight.ToString("F"); Vector2 startPoint = Vector2.zero; foreach (GameObject nodeUI in nodesUI) { TextMeshProUGUI nodeNumberText = nodeUI.GetComponentInChildren <TextMeshProUGUI>(); if (nodeNumberText.text.Equals(connection.InNode.Number.ToString())) { startPoint = nodeUI.GetComponent <RectTransform>().anchoredPosition; break; } } Vector2 endPoint = Vector2.zero; foreach (GameObject nodeUI in nodesUI) { TextMeshProUGUI nodeNumberText = nodeUI.GetComponentInChildren <TextMeshProUGUI>(); if (nodeNumberText.text.Equals(connection.OutNode.Number.ToString())) { endPoint = nodeUI.GetComponent <RectTransform>().anchoredPosition; break; } } // Position: Vector2 connectionUIPosition = (endPoint + startPoint) / 2; rectTransform.anchoredPosition = connectionUIPosition; // Rotation: Vector2 distance = endPoint - startPoint; float z = Mathf.Atan2(distance.y, distance.x) * Mathf.Rad2Deg; rectTransform.rotation = Quaternion.AngleAxis(z, Vector3.forward); // Width: rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, distance.magnitude); // Color: float hsvColorPercent = (connection.Weight + 1) / 2 * 0.32f; // 0% (min) = red, 16% (mid) = yellow, 32% (max) = green. connectionUI.GetComponent <Image>().color = Color.HSVToRGB(hsvColorPercent, 1, 1); } }
private void DrawGenome(CarBrain brain) { ClearGenomePanel(false); lastBrain = brain; Color textColor = brain.CrashedCarMaterial.GetColor("_BaseColor"); genomeDataText.color = new Color(textColor.r, textColor.g, textColor.b, 1); genomeDataTextAnimator.Play("WindowPopUp2", 0, 0); GameObject[] nodesUI = DrawNodes(brain); DrawNodesConnections(brain, nodesUI); }
GameObject Breed(GameObject parent1, GameObject parent2) { GameObject offspring = Instantiate(botPrefab, startingPos.transform.position, Quaternion.Euler(0, -45f, 0)); CarBrain b = offspring.GetComponent <CarBrain>(); if (Random.Range(0, 100) == 1) //mutate 1 in 100 { b.Init(); b.dna.Mutate(); } else { b.Init(); b.dna.Combine(parent1.GetComponent <CarBrain>().dna, parent2.GetComponent <CarBrain>().dna); } return(offspring); }
GetFitnessScores() { Dictionary <int, float> scores = new Dictionary <int, float> (); /* * brains.Sort(delegate (CarBrain a, CarBrain b) { * return b.Fitness().CompareTo(a.Fitness()); * });*/ for (int i = 0; i < brains.Count; i++) { CarBrain brain = brains[i]; scores.Add(brain.genomeID, brain.Fitness()); } return(scores); }
private IEnumerator DrawBestGenomeFromSpecies(Species species) { while (true) { CarBrain bestBrain = species.BrainsList[0]; for (int i = 1; i < species.BrainsList.Count; i++) { if (bestBrain.Fitness < species.BrainsList[i].Fitness) { bestBrain = species.BrainsList[i]; } } if (bestBrain != lastBrain) { DrawGenome(bestBrain); } yield return(new WaitForSeconds(1)); } }
/// <summary> /// Update the best Species fitness and Genome pattern. /// </summary> public void UpdateBestFitness() { int bestFitness = int.MinValue; CarBrain bestBrain = null; foreach (CarBrain brain in brainsList) { if (bestFitness < brain.Fitness) { bestFitness = brain.Fitness; bestBrain = brain; } } this.bestFitness = bestFitness; if (bestBrain != null) { bestGenomePattern.CloneGenome(bestBrain.Genome); } }
public void CreateBots() { Time.timeScale = Gamespeed;//Ustawia tempo gry, co moze przyspieszyc dlugi trening if (cars != null) { for (int i = 0; i < cars.Count; ++i) { GameObject.Destroy(cars[i].gameObject); } SortNetworks(); } cars = new List <CarBrain>(); for (int i = 0; i < populationSize; ++i) { CarBrain car = (Instantiate(prefab, new Vector3(0, 1.6f, -30), new Quaternion(0, 0, 1, 0))).GetComponent <CarBrain>(); //Tworzy pojazdy car.network = networks[i]; //Przypisuje sieci neuronowe do pojazdow cars.Add(car); } }
InstantiatePopulation() { for (int i = 0; i < _params.NumGenomesToSpawn; i++) { GameObject car = Instantiate(carPrefab); CarBrain brain = car.GetComponent <CarBrain> (); brain.genomeID = population.Genomes()[i].ID(); brain.AssignPhenotype(population.Genomes()[i].Phenotype()); brains.Add(brain); Car carController = car.GetComponent <Car> (); carController.sliderLeft = sliderLeft; carController.sliderRight = sliderRight; carController.slowDown = slowDown; carController.progress = progress; carController.avgSpeed = avgSpeed; carController.id.text = "" + brain.genomeID; TrackManager trackMgr = car.GetComponent <TrackManager> (); trackMgr.activeTrack = activeTrack; } }
private void Selection(CarBrain[] brains, out List <CarBrain> bestBrainsList, out List <CarBrain> weakerBrainsList) { // Find the best CarBrain in each Species: bestBrainsList = new List <CarBrain>(); for (int speciesIndex = 0; speciesIndex < speciesList.Count; speciesIndex++) { CarBrain bestBrain = speciesList[speciesIndex].BrainsList[0]; for (int brainIndex = 1; brainIndex < speciesList[speciesIndex].BrainsList.Count; brainIndex++) { CarBrain nextBrain = speciesList[speciesIndex].BrainsList[brainIndex]; if (bestBrain.Fitness < nextBrain.Fitness) { bestBrain = nextBrain; } } bestBrainsList.Add(bestBrain); } // Get the weaker cars and set them into temporary list (later they Genomes will be modified): weakerBrainsList = new List <CarBrain>(); for (int i = 0; i < brains.Length; i++) { bool isBestBrain = false; for (int j = 0; j < bestBrainsList.Count; j++) { if (brains[i] == bestBrainsList[j]) { isBestBrain = true; break; } } if (!isBestBrain) { weakerBrainsList.Add(brains[i]); } } }
/// <summary> /// Reset the genomeDataPanel view. Disable the Nodes and NodesConnections UI elements and add them to the pool. /// </summary> public void ClearGenomePanel(bool unlockLastBrain) { // Deactivate NodesConnection weight, reset the panel colors and lastBrain data: NodesConnectionUIListener.DeactivateLastShowedInfo(); genomeDataText.color = Color.white; genomeDataPanelImage.color = new Color(1, 1, 1, 0.39f); lastBrain = null; nodesActivationTexts = null; if (unlockLastBrain) { lastBrainIsLocked = false; genomeDataText.fontStyle = FontStyles.Normal; StopDrawBestGenomeFromSpeciesCoroutine(); } // Add Nodes to the pool: genomeDataNodesQueue.Clear(); int childrenNumberInPanel = genomeDataPanelNodes.childCount; for (int i = 0; i < childrenNumberInPanel; i++) { GameObject child = genomeDataPanelNodes.GetChild(i).gameObject; child.SetActive(false); genomeDataNodesQueue.Enqueue(child); } // Add NodesConnections to the pool: genomeDataNodesConnectionsQueue.Clear(); childrenNumberInPanel = genomeDataPanelNodesConnections.childCount; for (int i = 0; i < childrenNumberInPanel; i++) { GameObject child = genomeDataPanelNodesConnections.GetChild(i).gameObject; child.SetActive(false); genomeDataNodesConnectionsQueue.Enqueue(child); } }
private void Start() { carBrain = GetComponent <CarBrain>(); carMover = GetComponent <CarMover>(); GetComponent <Renderer>().material.color = UnityEngine.Random.ColorHSV(0f, 1f, 1f, 1f, 0.5f, 1f); }
private GameObject[] DrawNodes(CarBrain brain) { int nodesNumber = brain.Genome.NodesList.Count; Vector2 genomeDataPanelSize = genomeDataPanel.GetComponent <RectTransform>().rect.size; #region Calculate the offset for UI Nodes in the genomeDataPanel: // Input Nodes: float inNodesOffsetY = genomeDataPanelSize.y / (CarBrain.InNodesNumber + 1); // +1 because of Bias Node. int inNodesOffsetMultiplier = 1; // Output Nodes: float outNodesOffsetY = genomeDataPanelSize.y / CarBrain.OutNodesNumber; int outNodesOffsetMultiplier = 1; // Hidden Nodes: int hiddenLayersNumber = brain.Genome.MaxNodeLayer - 2; int[] hiddenNodesNumberInLayers = new int[hiddenLayersNumber]; for (int i = 0; i < nodesNumber; i++) { Node node = brain.Genome.NodesList[i]; if (node.Layer != 1 && node.Layer != brain.Genome.MaxNodeLayer) { hiddenNodesNumberInLayers[node.Layer - 2]++; } } float[] hiddenNodesOffsetsY = new float[hiddenLayersNumber]; int[] hiddenNodesOffsetMultipliers = new int[hiddenLayersNumber]; // Different multiplier for each hidden layer. for (int i = 0; i < hiddenLayersNumber; i++) { hiddenNodesOffsetsY[i] = genomeDataPanelSize.y / hiddenNodesNumberInLayers[i]; hiddenNodesOffsetMultipliers[i] = 1; } float hiddenNodeOffsetX = genomeDataPanelSize.x / brain.Genome.MaxNodeLayer; #endregion Calculate the offset for UI Nodes in the genomeDataPanel. GameObject[] nodesUI = new GameObject[nodesNumber]; nodesActivationTexts = new TextMeshProUGUI[nodesNumber]; for (int i = 0; i < nodesNumber; i++) { Node node = brain.Genome.NodesList[i]; GameObject nodeUI = GetGenomeDataUIElementFromPool(genomeDataNodesQueue, genomeDataNodePrefab, genomeDataPanelNodes); nodesUI[i] = nodeUI; RectTransform rectTransform = nodeUI.GetComponent <RectTransform>(); TextMeshProUGUI[] nodeTexts = nodeUI.GetComponentsInChildren <TextMeshProUGUI>(); nodeTexts[0].text = node.Number + ""; nodeTexts[1].text = node.Activation.ToString("F"); nodesActivationTexts[i] = nodeTexts[1]; if (node.Layer == 1) // Draw Nodes in the first layer. { float x = 10; float y = (CarBrain.InNodesNumber > 1) ? -inNodesOffsetY * inNodesOffsetMultiplier + inNodesOffsetY / 2 : inNodesOffsetY / 2; rectTransform.anchoredPosition = new Vector2(x, y); inNodesOffsetMultiplier++; } else if (node.Layer == brain.Genome.MaxNodeLayer) // Draw Nodes in the last layer. { float x = genomeDataPanelSize.x - 10; float y = (CarBrain.OutNodesNumber > 1) ? -outNodesOffsetY * outNodesOffsetMultiplier + outNodesOffsetY / 2 : outNodesOffsetY / 2; rectTransform.anchoredPosition = new Vector2(x, y); outNodesOffsetMultiplier++; } else // Draw Nodes in the hidden layers. { float x = hiddenNodeOffsetX / 2 + hiddenNodeOffsetX * (node.Layer - 1); float y; if (hiddenNodesNumberInLayers[node.Layer - 2] > 1) { y = -hiddenNodesOffsetsY[node.Layer - 2] * hiddenNodesOffsetMultipliers[node.Layer - 2] + hiddenNodesOffsetsY[node.Layer - 2] / 2; } else { y = -hiddenNodesOffsetsY[node.Layer - 2] / 2; } rectTransform.anchoredPosition = new Vector2(x, y); hiddenNodesOffsetMultipliers[node.Layer - 2]++; // Hidden layers are beginning from 2 layer so "[node.Layer-2]". } } return(nodesUI); }
public void UpdateView(CarBrain car) { SteeringIndicator.value = car.SteeringDecision; ThrottleIndicator.value = car.ThrottleDecision; BrakeIndicator.value = car.BrakingDecision; }
Update() { if (!initalized) { return; } if (runningSimulation || runOnlyMode) { bool keepRunning = false; for (int i = 0; i < brains.Count; i++) { CarBrain brain = brains[i]; if (brain.isAlive) { keepRunning = true; if (brain.Fitness() > best.Fitness() || !best.isAlive) { SetBestCar(brain); } } } if (!keepRunning) { if (runOnlyMode) { for (int i = 0; i < brains.Count; i++) { CarBrain brain = brains[i]; brain.Reset(); } } else { // If all genomes are dead we stop the simulation. runningSimulation = false; } } } if (!runningSimulation && !runOnlyMode) { generationCount++; // Keep track of the all time best phenotype if (best.Fitness() > population.BestFitness()) { bestPhenotype = best.Phenotype(); } /* * Using the genetic algorithm try to improve the brains for each * genome in the hope that it will perform better. */ phenotypes = population.Epoch(GetFitnessScores()); // TODO: clean up the mess below Dictionary <int, CGenome> genomeIDs = new Dictionary <int, CGenome>(); foreach (CGenome genome in population.Genomes()) { genomeIDs.Add(genome.ID(), genome); } List <CarBrain> brainsToBeAssigned = new List <CarBrain> (brains); for (int i = brainsToBeAssigned.Count - 1; i >= 0; i--) { int oldGenomeID = brainsToBeAssigned[i].genomeID; if (genomeIDs.ContainsKey(oldGenomeID) && genomeIDs[oldGenomeID].Phenotype() != null) { brainsToBeAssigned[i].AssignPhenotype(genomeIDs[oldGenomeID].Phenotype()); genomeIDs.Remove(oldGenomeID); brainsToBeAssigned[i].GetComponent <Car>().id.text = "" + brains[i].genomeID; brainsToBeAssigned[i].Reset(); brainsToBeAssigned.RemoveAt(i); } } for (int i = 0; i < brainsToBeAssigned.Count; i++) { brainsToBeAssigned[i].genomeID = genomeIDs.ElementAt(0).Key; brainsToBeAssigned[i].AssignPhenotype(genomeIDs.ElementAt(0).Value.Phenotype()); genomeIDs.Remove(genomeIDs.ElementAt(0).Key); brainsToBeAssigned[i].GetComponent <Car>().id.text = "" + brains[i].genomeID; brainsToBeAssigned[i].Reset(); } generation.text = "Generation:\t" + generationCount; bestFitness.text = string.Format("Best fitness:\t{0:#.0000}", population.BestFitness()); Dictionary <int, int> allSpecies = new Dictionary <int, int> (); CSpecies theBestSpecies = null; float bestSpeciesFitness = -1; for (int i = 0; i < population.Species().Count; i++) { CSpecies species = population.Species()[i]; allSpecies.Add(species.ID(), species.NumMembers()); if (species.BestFitness() > bestSpeciesFitness) { bestSpeciesFitness = species.BestFitness(); theBestSpecies = species; } if (species.Leader() == null) { continue; } } numSpecies.text = "Num species:\t" + allSpecies.Count; bestSpecies.text = "Best species:\t" + theBestSpecies.ID(); numMembers.text = "Num members:\t" + theBestSpecies.NumMembers(); speciesAge.text = "Species age:\t" + theBestSpecies.Age(); gensWithoutImproving.text = "Gens no impr:\t" + theBestSpecies.GensNoImprovement(); bar.UpdateBar(allSpecies); runningSimulation = true; } }