int[] FillInGaps(int[] DNA, RouteGenome parent, int randomPoint)
        {
            int[] dna = DNA;
            for (int c = randomPoint; c < dna.Length; c++) //New dna position
            {
                for (int d = 0; d < dna.Length; d++)       //Parent 2 position
                {
                    bool newGenome = true;

                    for (int e = 0; e < c; e++)//Check new dna previous numbers to get fresh number(If parent 2 has old numbers = newGenome is flase)
                    {
                        //To avoid city repetition
                        if (dna[e] == parent.DNA[d])
                        {
                            newGenome = false;
                        }
                    }
                    //If the character is not already in the array
                    //it adds the character from parent 2
                    if (newGenome)
                    {
                        dna[c] = parent.DNA[d];
                    }
                }
            }
            return(dna);
        }
        int[] FillInGaps(int[] DNA, RouteGenome parent, int start, int end, int maxRange)
        {
            int[] dna = DNA;
            for (int c = start; c < end; c++)
            {
                for (int d = 0; d < dna.Length; d++)
                {
                    bool newGenome = true;

                    for (int e = 0; e < maxRange; e++)
                    {
                        //To avoid city repetition
                        if (parent.DNA[d] == dna[e])
                        {
                            newGenome = false;
                        }
                    }
                    //If the character is not already in the array
                    //it adds the character from parent 2
                    if (newGenome)
                    {
                        dna[c] = parent.DNA[d];
                        d      = dna.Length;
                    }
                }
            }
            return(dna);
        }
        /// <summary>
        /// Old Version
        /// </summary>
        /// <param name="parent1"></param>
        /// <param name="parent2"></param>
        /// <param name="crossoverChance"></param>
        /// <returns></returns>
        public RouteGenome Crossover(RouteGenome parent1, RouteGenome parent2, int crossoverChance)
        {
            Random random = new Random();
            //random percentage to determine if crossover is necessary
            int percentage = new Random().Next(0, 100);
            //Selecting a random point to work with
            int randPoint1 = random.Next(0, parent1.DNA.Length / 2);
            int randPoint2 = random.Next(parent1.DNA.Length / 2, parent1.DNA.Length);

            int[] dna   = new int[parent1.DNA.Length];
            int   index = 0;

            if (crossoverChance > percentage)
            {
                //using parent 2 to add to the new generation
                //from the random point in reverse order
                for (int i = randPoint1; i >= 0; i--)
                {
                    dna[index] = parent2.DNA[i];
                    index++;
                }

                //Adding parent 2 to the new genome from point 2 till the end of the genome
                for (int i = randPoint2; i < parent1.DNA.Length; i++)
                {
                    dna[i] = parent2.DNA[i];
                }

                //Completing the new generation by filling in the blanks
                for (int c = randPoint1; c < dna.Length; c++)
                {
                    for (int d = 0; d < dna.Length; d++)
                    {
                        bool newGenome = true;

                        for (int e = 0; e < dna.Length; e++)
                        {
                            //To avoid city repetition
                            if (parent1.DNA[d] == dna[e])
                            {
                                newGenome = false;
                            }
                        }

                        //If the character is not already in the array
                        //it adds the character from parent 2
                        if (newGenome)
                        {
                            dna[c] = parent1.DNA[d];
                            d      = dna.Length;
                        }
                    }
                }

                return(new RouteGenome(dna, 0));
            }

            return(parent1);
        }
        public RouteGenome Crossover(RouteGenome parent1, RouteGenome parent2, int crossoverChance)
        {
            int[] p1 = parent1.DNA;
            int[] p2 = parent2.DNA;
            int[] c1 = new int[p1.Length];



            int percentage = new Random().Next(0, 100);

            int y = 0;

            int index1 = new Random().Next(0, parent1.DNA.Length / 3);
            int index2 = new Random().Next((parent1.DNA.Length / 3), (parent1.DNA.Length / 3) + (parent1.DNA.Length / 3));
            int index3 = new Random().Next((p1.Length / 3) + (p1.Length / 3), p1.Length);


            if (crossoverChance > percentage)
            {
                int point1 = p1[index1];
                int point2 = p1[index2];
                int point3 = p1[index3];

                int[] points = { point1, point2, point3 };

                for (int f = 0; f < p1.Length; f++)
                {
                    if (p2[f] == point1 || p2[f] == point2 || p2[f] == point3)
                    {
                        c1[f] = points[y];
                        y++;
                    }
                    else
                    {
                        c1[f] = p2[f];
                    }
                }

                return(new RouteGenome(c1, 0));
            }


            return(parent1);
        }
        public RouteGenome Mutate(RouteGenome genome, int mutateChance)
        {
            int    percentage = new Random().Next(0, 100);
            Random ran        = new Random();

            if (mutateChance > percentage)
            {
                //Selecting 2 random positions to swop
                int pos1 = ran.Next(0, genome.DNA.Length);
                int pos2 = ran.Next(0, genome.DNA.Length);

                //Swopping gene positions
                int tempPos = genome.DNA[pos1];
                genome.DNA[pos1] = genome.DNA[pos2];
                genome.DNA[pos2] = tempPos;
            }

            return(genome);
        }
        /// <summary>
        ///Main Loop to run (Epoch)
        /// </summary>
        public void Begin()
        {
            RouteGenome[] nextGen     = new RouteGenome[PopSize];
            double        totalLength = 0;


            for (int c = 0; c < PopSize; c++)
            {
                //creation of initial population
                CreateGenome();
                //calculating length
                double length = CalcLength(dna, CityPoints);
                nextGen[c] = new RouteGenome(dna, length);
                //including the length to the total length
                totalLength += length;
            }
            //determining total length of all the genomes combined
            TotalLength = totalLength;

            int totalFit = 0;

            //Loop to calculate the genomes fitness and total fitness of the generation
            for (int i = 0; i < PopSize; i++)
            {
                //Makes it f*****g fast
                nextGen[i].Fitness = CalcFitness(nextGen[i].Length / 10, TotalLength / 10);
                totalFit          += nextGen[i].Fitness;
            }
            TotalFitness = totalFit;

            //The genomes are in order from best to worst,
            //therefore genome at index 0 would be the most fit
            //and the genome at the last index will be the least fit
            Sort(nextGen);
            Best  = nextGen[0];
            Worst = nextGen[PopSize - 1];

            //Continuing to the next generation count
            GenCount++;

            //setting current gen to the newly generated next gen
            currentGen = nextGen;
        }
        public RouteGenome Crossover(RouteGenome parent1, RouteGenome parent2, int crossoverChance)
        {
            //random percentage to determine if crossover is necessary
            percentage = random.Next(0, 100);

            if (crossoverChance > percentage)
            {
                parentSelected = random.Next(1, 3);
                //Selecting a random point to work with
                randPoint1 = random.Next(0, parent1.DNA.Length / 2);
                randPoint2 = random.Next(parent1.DNA.Length / 2, parent1.DNA.Length);
                dna        = new int[parent1.DNA.Length];
                index      = randPoint1;

                //using parent 2 to add to the new generation
                //from the random point in reverse order
                for (int i = randPoint2; i >= randPoint1; i--)
                {
                    if (parentSelected == 1)
                    {
                        dna[index] = parent2.DNA[i];
                    }
                    else
                    {
                        dna[index] = parent1.DNA[i];
                    }
                    index++;
                }
                //Completing the new generation by filling in the blanks
                if (parentSelected == 1)
                {
                    dna = FillInGaps(dna, parent1, 0, randPoint1, randPoint2);
                    dna = FillInGaps(dna, parent1, randPoint2, dna.Length, dna.Length);
                }
                else
                {
                    dna = FillInGaps(dna, parent2, 0, randPoint1, randPoint2);
                    dna = FillInGaps(dna, parent2, randPoint2, dna.Length, dna.Length);
                }
                return(new RouteGenome(dna, 0));
            }
            return(parent1);
        }
        public RouteGenome Select(RouteGenome[] genome, int length)
        {
            //Random number to between 0 and genome length
            int         count    = ranNum.Next(0, genome.Length);
            RouteGenome best     = genome[0];
            int         selected = 0;

            for (int i = 0; i < count; i++)
            {
                //Comparing the current genome with the best genomes length
                //if greater, this genome will be selected
                //within the for loop. Different genomes may trigger this
                //if statement and therefore win the fight and become the "stronger" genome.
                if (genome[i].Length > best.Length)
                {
                    selected = i;
                }
                best = genome[i];
            }

            return(genome[selected]);
        }
        /// <summary>
        /// Method to sort Genomes by length
        /// This will put the best genomes at the lower indexes.
        /// making it easier to apply elitism and determine the current best genome.
        /// </summary>
        /// <param name="genome"></param>
        public void Sort(RouteGenome[] genome)
        {
            bool sorted = false;
            int  c      = genome.Length;

            while (!sorted)
            {
                sorted = true;

                for (int i = 1; i < c; i++)
                {
                    if (genome[i - 1].Length > genome[i].Length)
                    {
                        sorted = false;
                        RouteGenome tempGenome = genome[i - 1];
                        genome[i - 1] = genome[i];
                        genome[i]     = tempGenome;
                    }
                }
                c--;
            }
        }
        public RouteGenome Mutate(RouteGenome genome, int mutateChance)
        {
            Random ran = new Random();

            int[] dna = genome.DNA;
            int[] child = new int[dna.Length];
            int   point1, point2 = 0;

            do
            {
                point1 = ran.Next(0, genome.DNA.Length / 2);
                point2 = ran.Next(point1 + 1, dna.Length);
            } while (point1 == point2);
            if (point2 == point1)
            {
                point2 = ran.Next(point1 + 1, dna.Length);
            }
            int temp = 0;

            temp = dna[point1];
            int percent = new Random().Next(100);

            if (mutateChance > percent)
            {
                for (int i = 0; i < dna.Length; i++)
                {
                    child[i] = dna[i];
                }
                for (int i = point1; i < point2; i++)
                {
                    child[i] = dna[i + 1];
                }
                child[point2] = temp;
                genome.DNA    = child;
            }
            return(genome);
        }
        public RouteGenome Crossover(RouteGenome parent1, RouteGenome parent2, int crossoverChance)
        {
            percentage = random.Next(0, 100);
            //random percentage to determine if crossover is necessary
            if (percentage <= crossoverChance)
            {
                parentSelected = random.Next(1, 3);
                //Selecting a random point to work with
                int   randPoint = random.Next(parent1.DNA.Length);
                int[] dna       = new int[parent1.DNA.Length];
                //using parent 1 to add to the new generation
                //up to the random point
                for (int i = 0; i < randPoint; i++)
                {
                    if (parentSelected == 1)
                    {
                        dna[i] = parent1.DNA[i];
                    }
                    else
                    {
                        dna[i] = parent2.DNA[i];
                    }
                }
                //Completing the new generation by filling in the blanks
                if (parentSelected == 1)
                {
                    dna = FillInGaps(dna, parent2, randPoint);
                }
                else
                {
                    dna = FillInGaps(dna, parent1, randPoint);
                }
                return(new RouteGenome(dna, 0));
            }

            return(parent1);
        }
        //Complete working mutation
        public RouteGenome Mutate(RouteGenome genome, int mutateChance)
        {
            Random ran = new Random();

            int[] dna    = genome.DNA;
            int[] child  = new int[dna.Length];
            int   point1 = ran.Next(2, genome.DNA.Length / 2);
            int   point2 = ran.Next(point1 + 1, dna.Length);

            int index = point1;

            int percent = new Random().Next(100);

            if (mutateChance > percent)
            {
                //moving the selected genes to the beginning of the genome
                for (int c = 0; c < point2 - point1; c++)
                {
                    child[c] = dna[index];
                    index++;
                }
                index = 0;
                //adding the missing genomes to the child from where the child ended
                for (int i = point2 - point1; i < point2; i++)
                {
                    child[i] = dna[index];
                    index++;
                }
                //filling in the genome from the 2nd position till the end
                for (int j = point2; j < dna.Length; j++)
                {
                    child[j] = dna[j];
                }
                genome.DNA = child;
            }
            return(genome);
        }
        public RouteGenome Mutate(RouteGenome genome, int mutateChance)
        {
            Random ran = new Random();

            int[] dna   = genome.DNA;
            int[] child = new int[dna.Length];

            //Selecting 2 points
            int point1 = ran.Next(1, genome.DNA.Length / 2);
            int point2 = ran.Next(point1 + 1, dna.Length);
            int index  = point1;


            int percent = new Random().Next(100);

            if (mutateChance > percent)
            {
                //Inverting the genes
                for (int c = point2; c > point1; c--)
                {
                    child[index] = dna[c];
                    index++;
                }

                for (int i = point1; i >= 0; i--)
                {
                    child[i] = dna[i];
                }
                //completing the genome with the left over genes
                for (int j = point2; j < dna.Length; j++)
                {
                    child[j] = dna[j];
                }
                genome.DNA = child;
            }
            return(genome);
        }
        //Creating the next generation
        public void NextGeneration()
        {
            int maxElite = 0;

            RouteGenome[] nextGen = new RouteGenome[PopSize];

            //Determining if elite percentage is active
            if (ElitePercent > 0)
            {
                maxElite = (PopSize * ElitePercent) / 100;
            }
            else
            {
                maxElite = (PopSize) / 100;
            }


            double totalLength = 0;
            double length      = 0;

            //making copies of the elites based on the percentage chosen by user
            for (int c = 0; c < maxElite; c++)
            {
                nextGen[c]   = currentGen[c];
                totalLength += nextGen[c].Length;
            }

            //creating the rest of the next generation
            for (int i = maxElite; i < PopSize; i++)
            {
                //Selection
                RouteGenome parent1 = Selection.Select(currentGen, TotalFitness);
                RouteGenome parent2 = Selection.Select(currentGen, TotalFitness);
                //to avoid two of the same parents
                while (parent2.DNA == parent1.DNA)
                {
                    parent2 = Selection.Select(currentGen, TotalFitness);
                }

                //Crossover
                RouteGenome child = Crossover.Crossover(parent1, parent2, CrossoverPercent);

                //Mutate
                child = Mutate.Mutate(child, MutatePercent);

                //calculation of new genomes length
                length       = CalcLength(child.DNA, CityPoints);
                child.Length = length;
                //saving the child to next generation
                nextGen[i]   = child;
                totalLength += length;
            }

            TotalLength = totalLength;

            //Calculating the next generations fitness
            int totalFit = 0;

            for (int j = 0; j < PopSize; j++)
            {
                nextGen[j].Fitness = CalcFitness(nextGen[j].Length / 5, totalLength / 5);
                totalFit          += nextGen[j].Fitness;
            }

            TotalFitness = totalFit;

            //The genomes are in order from best to worst,
            //therefore genome at index 0 would be the most fit
            //and the genome at the last index will be the least fit
            Sort(nextGen);
            Best  = nextGen[0];
            Worst = nextGen[PopSize - 1];

            GenCount += 1;



            //Setting the current gen to next gen
            currentGen = nextGen;
        }
        /// <summary>
        /// Inspiration for this code comes from this paper http://www.ceng.metu.edu.tr/~ucoluk/research/publications/tsp.pdf
        ///
        /// </summary>
        /// <param name="parent1"></param>
        /// <param name="parent2"></param>
        /// <param name="crossoverChance"></param>
        /// <returns></returns>
        public RouteGenome Crossover(RouteGenome parent1, RouteGenome parent2, int crossoverChance)
        {
            Random rand = new Random();

            int[] dna         = new int[parent1.DNA.Length];
            int[] mapper      = new int[parent1.DNA.Length + 1];
            int   crossPoint1 = rand.Next(1, parent1.DNA.Length - 2);
            int   crossPoint2 = rand.Next(1, parent1.DNA.Length - 2);

            parent1.DNA.CopyTo(dna, 0); // Copies everything to the child
            int percentage = rand.Next(0, 100);

            if (crossoverChance > percentage)
            {
                int randPoint = rand.Next(parent1.DNA.Length);

                for (int i = 0; i < dna.Length; i++)
                {
                    mapper[dna[i]] = i;
                }

                if (crossPoint1 > crossPoint2)
                {
                    int temp = crossPoint1;
                    crossPoint1 = crossPoint2;
                    crossPoint2 = temp;
                }


                for (int i = crossPoint1; i <= crossPoint2; i++)
                {
                    int parentValues = parent2.DNA[i];
                    //swap the dna in the child
                    int t = dna[mapper[parentValues]];
                    dna[mapper[parentValues]] = dna[i];
                    dna[i] = t;

                    //swap the points in the map
                    t = mapper[dna[mapper[parentValues]]];
                    mapper[dna[mapper[parentValues]]] = mapper[dna[i]];
                    mapper[dna[i]] = t;
                }



                //Completing the new generation by filling in the blanks
                for (int c = randPoint; c < dna.Length; c++)
                {
                    for (int d = 0; d < dna.Length; d++)
                    {
                        bool newGenome = true;

                        for (int e = 0; e < c; e++)
                        {
                            //To avoid city repetition
                            if (parent2.DNA[d] == dna[e])
                            {
                                newGenome = false;
                            }
                        }

                        //If the character is not already in the array
                        //it adds the character from parent 2
                        if (newGenome)
                        {
                            dna[c] = parent2.DNA[d];
                        }
                    }
                }
                return(new RouteGenome(dna, 0));
            }
            //   RouteGenome child = new RouteGenome(dna,0);


            return(parent1);
        }
        public RouteGenome Mutate(RouteGenome genome, int mutateChance)
        {
            int[] myArray = genome.DNA;
            int[] newArray = new int[myArray.Length];
            int   pos1, pos2;

            Random random = new Random();

            pos1 = random.Next(1, genome.DNA.Length - 1);

            pos2 = pos1;


            int[] middle = new int[pos2 - pos1];

            int[] left  = new int[pos1];
            int[] right = new int[myArray.Length - pos2];

            int[] holder = new int[myArray.Length];

            int count = 0;

            int[] storeRand = new int[myArray.Length];

            if (mutateChance > new Random().Next(100))
            {
                for (int x = pos1; x < pos2; x++)
                {
                    middle[count] = myArray[x];
                    count++;
                }

                for (int v = 0; v < pos1; v++)
                {
                    storeRand[v] = myArray[v];
                }

                var rnd = new Random();

                for (int i = 0; i < middle.Length; ++i)
                {
                    int index = rnd.Next(middle.Length);
                    // swap
                    int temp = middle[index];
                    middle[index] = middle[i];
                    middle[i]     = temp;
                }


                int counter = 0;

                for (int p1 = pos1; p1 < middle.Length + pos1; p1++)
                {
                    storeRand[p1] = middle[counter];
                    counter++;
                }

                for (int p2 = pos2; p2 < myArray.Length; p2++)
                {
                    storeRand[p2] = myArray[p2];
                }

                genome.DNA = storeRand;
            }



            return(genome);
        }
        public RouteGenome Mutate(RouteGenome genome, int mutateChance)
        {
            int[] array1 = genome.DNA;

            Random ran = new Random();

            int point1 = ran.Next(1, array1.Length - 1);



            int point2 = point1;


            int max = Math.Max(point1, point2);
            int min = Math.Min(point2, point1);

            int middle        = 0;
            int afterCounter  = 0;
            int middleCounter = 0;
            int beforeCounter = min;

            int[] swappedArray = new int[array1.Length];

            int percent = new Random().Next(100);

            if (mutateChance > percent)
            {
                for (int i = min; i <= max; i++)
                {
                    middle++;
                }

                int[] beforeArray = new int[middle];
                int[] afterArray  = new int[middle];


                for (int i = 0; i < beforeArray.Length; i++)
                {
                    //Invert the genes before
                    beforeArray[i] = array1[beforeCounter];
                    beforeCounter++;
                }



                for (int e = beforeArray.Length; e > 0; e--)
                {
                    //Invert the genes After
                    afterArray[afterCounter] = beforeArray[e - 1];
                    afterCounter++;
                }


                for (int w = 0; w < array1.Length; w++)
                {
                    //Complies the genes in correct sequence
                    if (w >= min && w <= max)
                    {
                        swappedArray[w] = afterArray[middleCounter];
                        middleCounter++;
                    }
                    else
                    {
                        swappedArray[w] = array1[w];
                    }
                }
                genome.DNA = swappedArray;
            }



            return(genome);
        }