void onAllCarsDisabled() { Generation++; System.Random rnd = new System.Random((int)DateTime.Now.Ticks); List <CarNeuralCore> sortedCarsByFitness = getCarsSortedByFitness(); List <CarNeuralCore> sortedCarsByDistace = getCarsSortedByDistTravelled(); refreshGhostCarsPositions(sortedCarsByDistace); double [] fitnesses = new double [sortedCarsByFitness.Count]; List <CarSimpleData> newGenCars = new List <CarSimpleData> (); newGenCars.Add(sortedCarsByFitness [0].GetCarSimpleData()); for (int i = 0; i < sortedCarsByFitness.Count; i++) { fitnesses [i] = sortedCarsByFitness [i].GetComponent <CarFitness> ().Fitness; } double avgFitness = getAverage(fitnesses); if (avgFitness < GlobalConst.MIN_AVG_FITNESS) { ResetSimulation(); ActivateCars(); OnNewGenCreated?.Invoke(); return; } float prevBestDistance = prevCarWithFurthestDistTravelled.DistTravelled; float prevBestFitness = (float)prevCarWithHighestFitness.Fitness; float currentBestFitness = (float)fitnesses [0]; float currentBestDistance = sortedCarsByDistace [0].GetComponent <CarFitness> ().DistanceTravelled; //Debug.Log ("Avg fitness: " + avgFitness); if (currentBestFitness > prevCarWithHighestFitness.Fitness) { prevCarWithHighestFitness = sortedCarsByFitness [0].GetCarSimpleData(); } else if (prevCarWithHighestFitness.Weights != null) { newGenCars.Add(prevCarWithHighestFitness.GetCopy()); } if (currentBestDistance > prevCarWithFurthestDistTravelled.DistTravelled) { prevCarWithFurthestDistTravelled = sortedCarsByDistace [0].GetCarSimpleData(); } else if (sortedCarsByDistace [0] != sortedCarsByFitness [0] && prevCarWithFurthestDistTravelled.Weights != null) { newGenCars.Add(prevCarWithFurthestDistTravelled.GetCopy()); } if (AdaptiveMutationProbability) { if (prevBestFitness > currentBestFitness) { float d = currentBestFitness / prevBestFitness; d = 1f - d; mutationProbability += mutationProbabilityD * d; } else { mutationProbability = DEFAULT_MUTATION_PROBABILITY; } //Debug.Log ("prev best: " + prevBestFitness); //Debug.Log ("current best: " + currentBestFitness); mutationProbability = Mathf.Clamp(mutationProbability, 0.05f, 0.5f); } while (newGenCars.Count < carsCount - newRandomCarsCount) { int parent1index = genetics.RouletteSelect(fitnesses); int parent2index = genetics.RouletteSelect(fitnesses); int helpIndex = 0; while (parent1index == parent2index) { parent2index = genetics.RouletteSelect(fitnesses); helpIndex++; if (helpIndex > carsCount) { break; } } CarSimpleData c1; CarSimpleData c2; genetics.CrossoverCars(sortedCarsByFitness [parent1index].GetCarSimpleData(), sortedCarsByFitness [parent2index].GetCarSimpleData(), out c1, out c2, Genetics.CrossType.ARYTM); newGenCars.Add(c1); newGenCars.Add(c2); } for (int i = 0; i < newGenCars.Count; i++) { //different approach //if (rnd.NextDouble () < mutationProbability) //{ // genetics.Mutation (newGenCars [i].Weights, mutationProbability); //} genetics.Mutation(newGenCars [i].Weights, mutationProbability); } if (CrossbreedSensors) { for (int i = 0; i < newGenCars.Count; i++) { if (rnd.NextDouble() < mutationProbability) { float d = ((float)rnd.NextDouble() * SENSOR_LENGTH_D) - (SENSOR_LENGTH_D / 2f); float newLenght = newGenCars [i].SensorsLength + d; if (newLenght < 0) { newLenght = 0; } newGenCars [i].SensorsLength = newLenght; } else if (rnd.NextDouble() < mutationProbability) { float d = ((float)rnd.NextDouble() * ANGLE_BETWEEN_SENSORS_D) - (ANGLE_BETWEEN_SENSORS_D / 2f); float newAngle = newGenCars [i].AngleBetweenSensors + d; if (newAngle < 0) { newAngle = 0; } newGenCars [i].AngleBetweenSensors = newAngle; } } } while (newGenCars.Count < carsCount) { CarSimpleData carSimpleData = new CarSimpleData(); carSimpleData.Weights = sortedCarsByFitness [0].GetRandomNeuralNetworkWeights(); carSimpleData.AngleBetweenSensors = (float)rnd.NextDouble() * MAX_ANGLE_BETWEEN_SENSORS; carSimpleData.SensorsLength = (float)rnd.NextDouble() * MAX_SENSOR_LENGTH; newGenCars.Add(carSimpleData); } int diff = newGenCars.Count - cars.Count; if (diff > 0) { for (int i = 0; i < diff; i++) { CarNeuralCore carNeuralCore = createNewCarObject(); carNeuralCore.Init(currentTopology); } } for (int i = 0; i < newGenCars.Count; i++) { cars [i].SetWeights(newGenCars [i].Weights); if (CrossbreedSensors) { cars [i].SetSensorsLength(newGenCars [i].SensorsLength); cars [i].SetAngleBetweenSensors(newGenCars [i].AngleBetweenSensors); } } diff = cars.Count - newGenCars.Count; if (diff > 0) { for (int i = 0; i < diff; i++) { deleteLastCarObject(); } } ResetCars(); OnNewGenCreated?.Invoke(); ActivateCars(); }