Example #1
0
    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();
    }