예제 #1
0
        /// <summary>
        /// Creates a chromosome.
        /// Note: Had a Random inside the method at first, the quick repeat creation of Random caused repeat results.
        /// </summary>
        /// <param name="selector">A random number generator.</param>
        /// <returns>A randomly sequenced chromosome.</returns>
        private Chromosome CreateChromosome(Random selector)
        {
            Chromosome       sequence   = new Chromosome(selector);
            LinkedList <int> usedCities = new LinkedList <int>();
            int city = -1;

            // Select city to start from.
            city = selector.Next(numberOfCites);
            sequence.SetStartCity(city);
            usedCities.AddLast(city);

            // Form path through cities
            while (usedCities.Count < numberOfCites)
            {
                while (usedCities.Contains(city))
                {
                    city = selector.Next(numberOfCites);
                }

                sequence.AddCityToPath(city);
                usedCities.AddLast(city);
            }

            sequence = checker.ProduceFitnessOfChromosome(sequence);

            return(sequence);
        }
        /// <summary>
        /// Evolve a population of chromosomes.
        /// Note: Cross mutation 60% of population from worse and mutate a cell for every 10% of range from best fitness.
        /// </summary>
        /// <param name="population">Population of chromosomes to be evolved.</param>
        /// <returns>New evolved population, same size as previous.</returns>
        public List <Chromosome> EvolvePopulation(List <Chromosome> population)
        {
            this.population = population;
            Chromosome travelPlan       = new Chromosome(randomNumberGenerator);
            Chromosome secondTravelPlan = new Chromosome(randomNumberGenerator);

            // Ensure newPopulation is empty, If running multiple times.
            newPopulation.Clear();

            // Find out range of population and workout required value for evolving.
            bestFitness    = population.ElementAt(0).getFitness();
            worseFitness   = population.ElementAt(population.Count - 1).getFitness();
            rangeOfFitness = worseFitness - bestFitness; // Best will be the lower value as want the shortest distance travelled.

            mutationDivValue   = rangeOfFitness * mutationFactor;
            crossMuttionCutOff = worseFitness - (rangeOfFitness * (1 - crossMutationFactor)); // 1 - factor as want that percentage from the worse fitness.

            // Variables needed for cell mutation.
            int cellsToMutate      = 0;
            int preMutationFitness = 0;
            // Variable needed for cross-mutation.
            LinkedList <int> temp;
            int tempIndex = 0;
            int preCrossMutationFitnessOfSecond = 0;

            for (int count = population.Count - 1; count > -1; count--)
            {
                travelPlan         = population.ElementAt(count);
                preMutationFitness = travelPlan.getFitness();
                // Determine if cross-mutation or individual cell mutation should be applied.
                if (preMutationFitness < crossMuttionCutOff)
                {
                    IndividualCellMutationOption(cellsToMutate, preMutationFitness, travelPlan);
                }
                else
                {
                    // Cross-mutation option.

                    // Set up second chromosome to cross mutate with.
                    secondTravelPlan = population.ElementAt(count - 1);
                    preCrossMutationFitnessOfSecond = secondTravelPlan.getFitness();

                    // Set up cross point and get path segment from first chromosome.
                    temp      = travelPlan.CrossMutationRequest();
                    tempIndex = travelPlan.CrossMutationIndexPoint();

                    // Apply cross-mutations and get new fitness values.
                    travelPlan.CrossMutationApplication(secondTravelPlan.CrossMutationRequest(tempIndex), tempIndex);
                    secondTravelPlan.CrossMutationApplication(temp, tempIndex);
                    travelPlan       = checker.ProduceFitnessOfChromosome(travelPlan);
                    secondTravelPlan = checker.ProduceFitnessOfChromosome(secondTravelPlan);

                    // If either or both new fitness is higher than old, revert.
                    if (travelPlan.getFitness() > preMutationFitness)
                    {
                        travelPlan.RevertChromosome();
                    }
                    if (secondTravelPlan.getFitness() > preCrossMutationFitnessOfSecond)
                    {
                        secondTravelPlan.RevertChromosome();
                    }

                    // Add best out of pre and post mutation to new population.
                    newPopulation.AddLast(travelPlan);
                    newPopulation.AddLast(secondTravelPlan);

                    // Adjust count as two chromosomes have changed, otherwise population will grow each evolution.
                    count--;
                }
            }

            return(newPopulation.OrderBy(Chromosome => Chromosome.getFitness()).ToList());
        }
예제 #3
0
        public void ChromosomeTesting(Random randomNumberGenerator)
        {
            // Create
            Chromosome chrom = new Chromosome(randomNumberGenerator);

            for (int i = 0; i < 10; i++)
            {
                if (i == 0)
                {
                    chrom.SetStartCity(i);
                }
                else
                {
                    chrom.AddCityToPath(i);
                }
            }
            chrom = checker.ProduceFitnessOfChromosome(chrom);

            Console.WriteLine("Chromosome create, should see 0 - 9 followed by zero");
            Console.WriteLine(chrom.ViewChromosome());
            Console.WriteLine("");

            // Get first trip cities.
            Console.WriteLine("Get cities from first trip");
            Console.WriteLine("Start at: " + chrom.TripStartFrom(1) + " end at: " + chrom.TripDestination(1));
            Console.WriteLine("");

            // Get fourth trip cities.
            Console.WriteLine("Get cities from fourth trip");
            Console.WriteLine("Start at: " + chrom.TripStartFrom(4) + " end at: " + chrom.TripDestination(4));
            Console.WriteLine("");

            // Get last trip cities.
            Console.WriteLine("Get cities from last trip");
            Console.WriteLine("Start at: " + chrom.TripStartFrom(10) + " end at: " + chrom.TripDestination(10));
            Console.WriteLine("");

            // Single mutation.
            chrom.Mutation(1);
            chrom = checker.ProduceFitnessOfChromosome(chrom);
            Console.WriteLine("Chromosome has undergone a single mutation.");
            Console.WriteLine(chrom.ViewChromosome());
            Console.WriteLine("");

            // Reversion
            chrom.RevertChromosome();
            Console.WriteLine("Revert Chromosome.");
            Console.WriteLine(chrom.ViewChromosome());
            Console.WriteLine("");

            // Nine mutations. (Watch in debug to see if any mutations are undone)
            chrom.Mutation(9);
            chrom = checker.ProduceFitnessOfChromosome(chrom);
            Console.WriteLine("Chromosome has undergone three mutations.");
            Console.WriteLine(chrom.ViewChromosome());

            // Make a second chromosome and test cross mutation.
            Chromosome chrom2 = new Chromosome(randomNumberGenerator);

            for (int i = 0; i < 10; i++)
            {
                if (i == 0)
                {
                    chrom2.SetStartCity(i);
                }
                else
                {
                    chrom2.AddCityToPath(i);
                }
            }
            chrom2 = checker.ProduceFitnessOfChromosome(chrom2);

            Console.WriteLine("Second Chromosome create to test cross mutation.");
            Console.WriteLine(chrom2.ViewChromosome());
            Console.WriteLine("");

            LinkedList <int> temp = chrom.CrossMutationRequest();
            int tempIndex         = chrom.CrossMutationIndexPoint();

            chrom.CrossMutationApplication(chrom2.CrossMutationRequest(tempIndex), tempIndex);
            chrom2.CrossMutationApplication(temp, tempIndex);
            chrom  = checker.ProduceFitnessOfChromosome(chrom);
            chrom2 = checker.ProduceFitnessOfChromosome(chrom2);

            Console.WriteLine("Cross mutation check using point: " + chrom.CrossMutationIndexPoint() + " giving: ");
            Console.WriteLine(chrom.ViewChromosome());
            Console.WriteLine(chrom2.ViewChromosome());
            Console.WriteLine("");

            // Make a third chromosome and test cross mutation.
            Chromosome chrom3 = new Chromosome(randomNumberGenerator);

            for (int i = 0; i < 10; i++)
            {
                if (i == 4)
                {
                    chrom3.SetStartCity(i);
                }
                else
                {
                    chrom3.AddCityToPath(i);
                }
            }
            chrom3 = checker.ProduceFitnessOfChromosome(chrom3);

            Console.WriteLine("Third Chromosome create to test cross mutation with different start/end point.");
            Console.WriteLine(chrom3.ViewChromosome());
            Console.WriteLine("Second current looks like: " + chrom2.ViewChromosome());
            Console.WriteLine("");

            temp      = chrom2.CrossMutationRequest();
            tempIndex = chrom2.CrossMutationIndexPoint();

            chrom2.CrossMutationApplication(chrom3.CrossMutationRequest(tempIndex), tempIndex);
            chrom3.CrossMutationApplication(temp, tempIndex);
            chrom2 = checker.ProduceFitnessOfChromosome(chrom2);
            chrom3 = checker.ProduceFitnessOfChromosome(chrom3);

            Console.WriteLine("Cross mutation check using point: " + tempIndex + " giving: ");
            Console.WriteLine(chrom2.ViewChromosome());
            Console.WriteLine(chrom3.ViewChromosome());
            Console.WriteLine("");
        }
예제 #4
0
        /// <summary>
        /// Once all the inputs have been entered, use this to prepare the output of the neuron.
        /// </summary>
        public void PrepareOutputForInputNeuron()
        {
            int    lowestIndex  = 0;
            double lowestWeight = inputWeight[0];

            ResetAvailabilities();

            // Get input with lowest weight.
            for (int startIndex = 1; startIndex < inputs.Count(); startIndex++)
            {
                if (inputWeight[startIndex] < lowestWeight)
                {
                    lowestWeight = inputWeight[startIndex];
                    lowestIndex  = startIndex;
                }
            }

            // Set start/end point of journey.
            output.SetStartCity(inputs[lowestIndex]);
            inputAvailable[lowestIndex] = false;

            // Add the rest of the cities to output.
            int    secondLowestIndex  = -1;
            double secondLowestWeight = -1;

            while (output.NumberOfCitiesTravelled() < numberOfInputs)
            {
                for (int index = 0; index < inputs.Count(); index++)
                {
                    // Check second lowest weight has a value.
                    if (secondLowestWeight == -1 && inputAvailable[index] == true)
                    {
                        secondLowestWeight = inputWeight[index];
                        secondLowestIndex  = index;
                        // Change second lowest weight if lower value found (which is not -1)
                    }
                    else if (inputAvailable[index] == true && inputWeight[index] < secondLowestWeight)
                    {
                        secondLowestWeight = inputWeight[index];
                        secondLowestIndex  = index;
                    }
                    // Found lowest value, end for loop.
                    if (lowestWeight == secondLowestWeight)
                    {
                        index = inputs.Count() + 9001;
                    }
                }

                // Update lowest value with new current lowest values
                lowestIndex        = secondLowestIndex;
                lowestWeight       = secondLowestWeight;
                secondLowestIndex  = -1;
                secondLowestWeight = -1;

                // Add to output
                output.AddCityToPath(inputs[lowestIndex]);
                inputAvailable[lowestIndex] = false;
            }

            // With output complete, get it's fitness
            output = checker.ProduceFitnessOfChromosome(output);

            // Set up Threshold value if needed.
            if (setThreshold)
            {
                threshold    = (checker.FitnessOfTwoCities(inputs[0], inputs[1]) * numberOfInputs);
                setThreshold = false;
            }
        }