Example #1
0
        private static int swapChance = 9900; // 2 / 10000

        #endregion Fields

        #region Methods

        private static double CalculateFitness(Chromosome c)
        {
            return CalculateFitness(c, false);
        }
Example #2
0
        // Lower = better.
        private static double CalculateFitness(Chromosome c, bool explain)
        {
            double targetValue = 0;

            c.FitnessBonus = 1;
            c.Fitness = 0;

            // I forget why I comment out trying to get other variables.
            foreach (KeyValuePair<string, Dictionary<string, double>> kvp in dict)
            {
                double r, s, u, v, w, x, y, z;
                // For now, gotta change these when changing problem sets!
                //kvp.Value.TryGetValue("R", out r);
                //kvp.Value.TryGetValue("S", out s);
                //kvp.Value.TryGetValue("U", out u);
                //kvp.Value.TryGetValue("V", out v);
                //kvp.Value.TryGetValue("W", out w);
                kvp.Value.TryGetValue("X", out x);
                kvp.Value.TryGetValue("Y", out y);
                kvp.Value.TryGetValue("Z", out z);

                //c.R = r;
                //c.S = s;
                //targetValue = u;
                //c.U = u; // Er, we don't want this in the equation. This is our target!
                //c.V = v;
                //c.W = w;
                c.X = x; // For simple equations, X is our target.
                //c.Y = y; // For simple equations, Y is our target.
                targetValue = y;
                //targetValue = z;
                //c.Z = z;
                c.ForceCalculate();

                if (explain) Console.WriteLine(targetValue);
                if (explain) Console.WriteLine(c.X);
                if (explain) Console.WriteLine(c.Y);

                //Console.WriteLine(c.Result);
                //Console.WriteLine(c.Result / targetValue);
                //Console.WriteLine(c.Genes.Count);

                if (explain) Console.WriteLine(c.IsValid);

                if (!c.IsValid)
                {
                    c.Fitness += maxFitness;
                    break;
                }

                double tFitness = Math.Max(Math.Abs(c.Result - targetValue), minFitness);

                if (explain) Console.WriteLine("Base: " + tFitness);

                // Penalize Chromosomes that differ between real and validated lengths.
                // Because validation can increase the length of the string for evaluation purposes - turning XX into X*X, for example - we won't use this right now.
                //int ld = Math.Abs(c.GeneString.Length - c.GeneStringValidated.Length);
                int ld = 0;

                // On second thought, just penalize long strings.
                int thresholdLength = 20;

                int deltaLength = (c.GeneString.Length - thresholdLength);

                ld = (deltaLength > 0) ? deltaLength : 0;

                if (explain) Console.WriteLine("LD: " + ld);

                if (ld != 0)
                {
                    if (explain) Console.WriteLine("Length Penalty");
                    tFitness *= malusLength * ld;
                    c.FitnessBonus *= malusLength * ld;
                }
                //else
                //{
                //    tFitness /= bonusValid;
                //    c.FitnessBonus /= bonusValid;
                //}

                //deltaLength = (c.GeneString.Length - bestEverChromosomeString.Length);

                //ld = (deltaLength > 0) ? deltaLength : 0;

                //if (explain) Console.WriteLine("LD: " + ld);

                //if (ld != 0)
                //{
                //    if (explain) Console.WriteLine("Length Penalty");
                //    tFitness *= malusLength * ld;
                //    c.FitnessBonus *= malusLength * ld;
                //}

                //deltaLength = (c.GeneString.Length - c.GeneStringValidated.Length);

                //ld = (deltaLength > 0) ? deltaLength : 0;

                //if (explain) Console.WriteLine("Silence: " + ld);

                //if (ld != 0)
                //{
                //    if (explain) Console.WriteLine("Silence Penalty");
                //    tFitness *= malusSilence * ld;
                //    c.FitnessBonus *= malusSilence * ld;
                //}

                // *0 or 0* is a pain.
                // As is 0X or X0... so variables negated in such a fashion should result in penalty as well.
                if (c.GeneString.Contains("*0") || c.GeneString.Contains("0*") || c.GeneStringValidated.Contains("*0") || c.GeneStringValidated.Contains("0*"))
                {
                    if (explain) Console.WriteLine("*Zero Penalty");
                    tFitness *= malusTimesZero;
                    c.FitnessBonus *= malusTimesZero;
                }

                // For now, gotta change these when changing problem sets!
                //char[] vars = { 'V', 'W', 'X', 'Y', 'Z' };
                //char[] vars = { 'V', 'W', 'X' };
                char[] vars = { 'X' };
                char[] vars2 = { 'R', 'S', 'T', 'U', 'V', 'W', 'Y', 'Z' };
                //List<char> varsAllList = new List<char>();

                // Penalize 0X, X0, 1X, and X1.
                foreach (char ch in "RSTUVWXYZ")
                {
                    if (c.GeneString.Contains("0" + ch) || c.GeneString.Contains(ch + "0"))
                    {
                        if (explain) Console.WriteLine(ch + "*Zero Penalty");
                        tFitness *= malusTimesZero;
                        c.FitnessBonus *= malusTimesZero;
                    }
                    //varsAllList.Add(ch);
                }

                foreach (char ch in "RSTUVWXYZ")
                {
                    if (
                            c.GeneString.Contains("1" + ch) || c.GeneString.Contains(ch + "1") ||
                            c.GeneString.Contains("1*" + ch) || c.GeneString.Contains(ch + "*1") ||
                            c.GeneString.Contains(ch + "/1")
                        )
                    {
                        if (explain) Console.WriteLine(ch + "*One Penalty");
                        tFitness *= malusTimesOne;
                        c.FitnessBonus *= malusTimesOne;
                    }
                }

                // I don't recall why I penalize this.
                foreach (char ch1 in "RSTUVWYZ")
                {
                    foreach (char ch2 in "RSTUVWXYZ")
                    {
                        if (c.GeneString.Contains(ch1.ToString() + ch2.ToString()) || c.GeneString.Contains(ch2.ToString() + ch1.ToString()))
                        {
                            if (explain) Console.WriteLine(ch1 + ch2 + " Penalty");
                            tFitness *= malusTimesZero;
                            c.FitnessBonus *= malusTimesZero;
                        }
                    }
                }

                //char[] varsAll = varsAllList.ToArray();

                // Select against variables we don't want in the string.
                foreach (char ch in vars2)
                {
                    if (c.GeneString.Count(n => n.Equals(ch)) >= 1)
                    {
                        if (explain) Console.WriteLine(ch + " Penalty");
                        tFitness *= malusGene * c.GeneString.Count(n => n.Equals(ch));
                        c.FitnessBonus *= malusGene * c.GeneString.Count(n => n.Equals(ch));
                    }
                }

                foreach (char ch in vars)
                {
                    // Penalize the Chromosome if our intended variables aren't included.
                    if (!c.GeneStringValidated.Contains(ch))
                    {
                        if (explain) Console.WriteLine("Required Var Penalty");
                        tFitness *= malusRequiredVariable;
                        c.FitnessBonus *= malusRequiredVariable;
                    }
                    // Reward if our intended variable(s) are.
                    else
                    {
                        if (explain) Console.WriteLine("Required Var Bonus");
                        tFitness /= bonusGene;
                        c.FitnessBonus /= bonusGene;
                    }
                }

                if (explain) Console.WriteLine(tFitness);

                if (explain) Console.ReadLine();

                if (tFitness > maxFitness) tFitness = maxFitness;

                c.Fitness += tFitness;
            }

            return c.Fitness;
        }
Example #3
0
        //public static Chromosome Crossover(Chromosome c, Chromosome b)
        //{
        //    return Crossover(c, b, 1);
        //}
        /*
         * Apparently, I very much need to review this code. As noted, my first attempt(s) at making this work properly, er, didn't.
         * There may still be room for different approaches to crossover, but if I can verify that this one works as I intend,
         * and that the fossil code doesn't, I can delete it entirely.
         *
         * Not that it can't be optimized.
         */
        /// <summary>
        /// Takes two parent Chromosomes, and returns a child Chromosome that derives from a crossover of both.
        /// </summary>
        /// <param name="c">One parent Chromosome.</param>
        /// <param name="b">Another parent Chromosome.</param>
        /// <returns>A child Chromosome.</returns>
        public static List<Chromosome> Crossover(Chromosome c, Chromosome b)
        {
            List<Chromosome> children = new List<Chromosome>();

            /*
             * Meh. My first attempt at this sucked. :)
             * Here, we take a random starting point in each Chromosome.
             * Then, we calculate a random length, no longer than the distance between the starting point and the end.
             */
            //int ics = r.Next(0, c.genes.Count);
            //int ibs = r.Next(0, b.genes.Count);
            //int icl = r.Next(1, c.genes.Count - ics);
            //int ibl = r.Next(1, b.genes.Count - ibs);

            int ic = r.Next(1, c.Genes.Count - 1);
            int ib = r.Next(1, b.Genes.Count - 1);

            //icl = Math.Max(icl, minLength);
            //ibl = Math.Max(ibl, minLength);

            //if (ics + icl > c.genes.Count)
            //{
            //    ics -= Math.Abs(ics + icl - c.genes.Count);
            //}

            //if (ibs + ibl > b.genes.Count)
            //{
            //    ibs -= Math.Abs(ibs + ibl - b.genes.Count);
            //}

            //Console.WriteLine("c.Count: " + c.genes.Count + "; b.Count: " + b.genes.Count);
            //Console.WriteLine("c.Indices: " + ics + " " + (c.genes.Count - ics) + "; b.Indices: " + ibs + " " + (b.genes.Count - ibs));
            //Console.WriteLine("c.Length: " + icl + "; b.Length: " + ibl);
            //Console.WriteLine(c.GeneString);
            //Console.WriteLine(b.GeneString);

            // Get a section of Chromosome c.
            ArrayList tcal1, tcal2; // = c.genes.GetRange(ics, icl);

            // Get a section of Chromosome b.
            ArrayList tbal1, tbal2; // = b.genes.GetRange(ibs, ibl);

            //tcal = c.genes.GetRange(0, ics);
            //tbal = b.genes.GetRange(ics, b.genes.Count - ics);

            tcal1 = c.Genes.GetRange(0, ic);
            tcal2 = c.Genes.GetRange(ic, c.Genes.Count - ic);
            tbal1 = b.Genes.GetRange(0, ib);
            tbal2 = b.Genes.GetRange(ib, b.Genes.Count - ib);

            // Create an array list to combine the sections above.
            ArrayList temp = new ArrayList();
            ArrayList temp2 = new ArrayList();

            //temp.AddRange(tcal1);
            //temp.AddRange(tbal2);

            //temp2.AddRange(tbal1);
            //temp2.AddRange(tcal2);

            int ir = r.Next(0, 2);

            //// I could have this entirely randomized - pick part of one, part of the other, at random, and then put them together, at random.
            //// For now, we'll take either a1 + b2, or b1 + a2.

            ir = 0;

            // I could do this in ternary, but this is just clearer.
            switch (ir)
            {
                // Add c first.
                case 0:
                    temp.AddRange(tcal1);
                    temp.AddRange(tbal2);

                    break;
                // Add b first.
                case 1:
                    temp.AddRange(tbal2);
                    temp.AddRange(tcal1);

                    break;
            }

            ir = r.Next(0, 2);

            ir = 0;

            switch (ir)
            {
                // Add c first.
                case 0:
                    temp2.AddRange(tbal1);
                    temp2.AddRange(tcal2);

                    break;
                // Add b first.
                case 1:
                    temp2.AddRange(tcal2);
                    temp2.AddRange(tbal1);

                    break;
            }

            // Create a Chromosome from the resulting combination of ranges.
            Chromosome t = new Chromosome(temp);
            t.parentA = c.GeneString;
            t.parentB = b.GeneString;

            Chromosome t2 = new Chromosome(temp2);
            t2.parentA = b.GeneString;
            t2.parentB = c.GeneString;

            //Console.WriteLine(c.genes.Count);
            //Console.WriteLine(b.genes.Count);

            //Console.WriteLine(t.genes.Count);
            //Console.WriteLine(t2.genes.Count);

            // Testing.
            //Chromosome tc = new Chromosome(tcal);
            //Chromosome tb = new Chromosome(tbal);

            //Console.WriteLine(tc.GeneString);
            //Console.WriteLine(tb.GeneString);

            //Console.WriteLine(t.parentA);
            //Console.WriteLine(t.parentB);
            //Console.WriteLine(t.GeneString);

            children.Add(t);
            children.Add(t2);

            return children;
        }
Example #4
0
        static void DisplayChromosomeAt(Chromosome c, int x, int y)
        {
            ConsoleColor fc = Console.ForegroundColor;
            ConsoleColor bc = Console.BackgroundColor;

            Console.SetCursorPosition(x, y);
            Console.WriteLine("Raw:       " + c.GeneString);
            Console.SetCursorPosition(x, y + 1);
            Console.WriteLine("Processed: " + c.GeneStringValidated);
            Console.SetCursorPosition(x, y + 2);
            if (!c.IsValid) Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Evaluated: " + c.Result);
            Console.SetCursorPosition(x, y + 3);
            if (!c.IsValid) Console.ForegroundColor = ConsoleColor.Red;
            if (c.Fitness <= minFitness * dict.Count) Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("Fitness: " + c.Fitness + " " + c.FitnessBonus);
            Console.ForegroundColor = fc;

            Console.SetCursorPosition(0, y + 4);
            Console.WriteLine("A: " + c.ParentA);
            Console.SetCursorPosition(0, y + 5);
            Console.WriteLine("B: " + c.ParentB);
        }
 //private void getData()
 //{
 //    XmlSerializer xmlS = new XmlSerializer(typeof(List<Chromosome>));
 //    try
 //    {
 //        FileStream fs = new FileStream("C:/data.xml", FileMode.Open);
 //        population = (List<Chromosome>)xmlS.Deserialize(fs);
 //        fs.Close();
 //        historyPresent = true;
 //    }
 //    catch (Exception _e) {
 //        population = new List<Chromosome>();
 //        historyPresent = false;
 //    }
 //}
 //private void saveData()
 //{
 //    XmlSerializer xmlS = new XmlSerializer(typeof(List<Chromosome>));
 //    try
 //    {
 //        FileStream fs = new FileStream("C:/data.xml", FileMode.OpenOrCreate);
 //        if(population.Count == 0)
 //            getNewPopulation();
 //        xmlS.Serialize(fs, population);
 //        fs.Flush();
 //        fs.Close();
 //    }
 //    catch (Exception _e)
 //    {
 //        population = new List<Chromosome>();
 //    }
 //}
 public void getNewPopulation(int problemSize, bool flag)
 {
     if (flag)
     {
         for (int i = 0; i < 10; i++)
         {
             Chromosome c = new Chromosome(problemSize);
             for (int j = 0; j < c.mass.Count; j++)
             {
                 c.mass[j] = rand.NextDouble();
                 c.force[j] = rand.NextDouble();
             }
             population.Add(c);
         }
     }
     else
     {
         crossOver();
     }
 }
 public void mutation(Chromosome c)
 {
     if(population.FirstOrDefault().mass.Count <= 2)
         return;
     int pointOfMutation = rand.Next(0, c.force.Count);
     c.force[pointOfMutation] = rand.NextDouble();
     c.mass[pointOfMutation] = rand.NextDouble();
 }
        public double fitnessFuction(Chromosome c)
        {
            double average = 0;
            for (int i = 0; i < c.force.Count; i++)
            {
                //We want a good amount of force.
                average += c.force[i];

                //mass is not good.
                average -= c.mass[i];
            }
            //averaging over all the values inside chromosome.
            average = average / c.mass.Count;

            //finding the max
            if (average > max)
            {
                max = average;
                bestFit = c;
                Debug.Log("Max : " + average);
            }

            return average;
        }
        private void Initialize()
        {
            Lx = MathF.Ceiling(MathF.Log2((b - a) * MathF.Pow(10, q) + 1));
            Ly = MathF.Ceiling(MathF.Log2((d - c) * MathF.Pow(10, q) + 1));

            hx = (b - a) / (MathF.Pow(2, Lx) - 1);
            hy = (d - c) / (MathF.Pow(2, Ly) - 1);

            var   points = new List <Vector2>();
            float fitnessFunctionsSum = 0;

            float stepX = (b - a) / 4f;
            float stepY = (d - c) / 3f;

            points.Add(new Vector2(a + stepX, c + stepY));

            for (int i = 1; i <= _population.Count - 1; i++)
            {
                var point = points[i - 1];

                if (i % 3 == 0)
                {
                    points.Add(new Vector2(points[0].X, point.Y + stepY));
                    continue;
                }

                points.Add(new Vector2(point.X + stepX, point.Y));
            }

            for (int i = 0; i < points.Count; i++)
            {
                var chromosomeX = new Chromosome {
                    Parameter = points[i].X
                };
                var chromosomeY = new Chromosome {
                    Parameter = points[i].Y
                };

                var fitnessFunctionValue = _fitnessFunction(chromosomeX.Parameter, chromosomeY.Parameter);
                fitnessFunctionsSum += fitnessFunctionValue;

                var individual = new Individual
                {
                    Сhromosomes = new List <Chromosome> {
                        chromosomeX, chromosomeY
                    },
                    FitnessFunctionValue = fitnessFunctionValue
                };

                _population.Individuals.Add(individual);
            }

            _population.FitnessFunctionSum = fitnessFunctionsSum;

            if (CheckIfExistsFitnessFunctionValueLessZero())
            {
                RecalculateFitnessFunctionValues();
            }

            max = _population.FitnessFunctionSum / _population.Count;
            Console.WriteLine(_population.FitnessFunctionSum / _population.Count);
        }
Example #9
0
        public Chromosome ChaoticLS(Chromosome chrom)                      //Jia D , Zheng G , Khan M K . An effective memetic differential evolution algorithm based on chaotic local search[J]. Information ences, 2011, 181(15):3175-3187.
        {
            Chromosome betterChrom = Chromosome.Clone <Chromosome>(chrom); //use this method doing deep copy
            double     beta = myRandom.NextDouble(0.0, 1.0);
            double     u = 4.0, m = 1000;
            double     betac, lambda;

            int Sl = (int)Math.Round(chrom.ChromosomeSize / 5.0);

            if (Sl < 1)
            {
                Sl = 1;
            }

            int[] loc = myRandom.NextUnique(0, chrom.ChromosomeSize - 1, Sl);
            //Random ran = new Random(Guid.NewGuid().GetHashCode());

            while (true)
            {
                if (beta != 0.25 && beta != 0.5 && beta != 0.75)
                {
                    break;
                }
                beta = myRandom.NextDouble(0.0, 1.0);
            }

            for (int i = 0; i < chrom.PopulationSize * 5; i++)
            {
                beta = u * beta * (1 - beta);

                foreach (var j in loc)
                {
                    betac = chrom.LowerBd[j] + beta * (chrom.UpperBd[j] - chrom.LowerBd[j]);
                    if (chrom.Fit > 0.0)
                    {
                        lambda = 1 - Math.Pow(Math.Abs((chrom.Fit - 1) / chrom.Fit), m);
                    }
                    else
                    {
                        lambda = 1 - Math.Pow(Math.Abs((chrom.Fit + 1) / chrom.Fit), m);
                    }

                    betterChrom.chromosome[j] = (1 - lambda) * chrom.chromosome[j] + lambda * betac;
                }
                betterChrom.CheckBoundary();
                betterChrom.SetChromDecimalPlace();
                betterChrom.SolveFitness();

                if (betterChrom.Fit < chrom.Fit)
                {
                    //Console.WriteLine("local search find a better individuals!");
                    break;
                }
            }

            if (betterChrom.Fit < chrom.Fit)
            {
                return(betterChrom);
            }
            else
            {
                return(chrom);
            }
        }
Example #10
0
 public Chromosome LocalSearch(Chromosome chrom)
 {
     return(CLSMethodEvent?.Invoke(chrom));
 }
Example #11
0
        public List <Chromosome> Execute()
        {
            //using select method
            Selection SL = new Selection();

            SL.SelectMethodEvent += SL.Select_Tournament;
            //Chromosome result=SL.Select(Population pop);

            //using cross method
            Crossover CX = new Crossover();

            CX.CrossMethodEvent += CX.CrossOver_MIX;
            // List<Chromosome> result=CX.Cross(Chromosome mom, Chromosome dad);

            //using mute method
            Mutation MU = new Mutation();

            MU.MuteMethodEvent += MU.DRM;
            //Chromosome result = MU.Mute(Chromosome chrom);

            //using chaotic local search
            ChaoticLocalSearch LS = new ChaoticLocalSearch();

            LS.CLSMethodEvent += LS.ChaoticLS;



            #region All population evolutionary algebraic processes
            //Iterative evolution
            Random            ran     = new Random(Guid.NewGuid().GetHashCode());
            List <Chromosome> result1 = new List <Chromosome>();
            Chromosome        result2 = new Chromosome();
            int maxSameIt             = 0;
            for (int it = 0; it < MaxIteration; it++)
            {
                #region one population
                for (int popi = 0; popi < NumPopulation; popi++)
                {
                    // Update iteration times
                    PopsOfGa[popi].CurrentIteration   = it;//Current iteration of evolution
                    PopsOfGaCX[popi].CurrentIteration = it;
                    PopsOfGaMU[popi].CurrentIteration = it;
                    //HistBestChromOfPops[popi].CurrentIteration = it;
                    for (int k = 0; k < PopsOfGa[popi].PopulationSize; k++)
                    {
                        PopsOfGa[popi].ChromsOfPop[k].CurrentIteration = it;
                    }
                    for (int k = 0; k < PopsOfGaCX[popi].ChromsOfPop.Count; k++)
                    {
                        PopsOfGaCX[popi].ChromsOfPop[k].CurrentIteration = it;
                    }
                    for (int k = 0; k < PopsOfGaMU[popi].ChromsOfPop.Count; k++)
                    {
                        PopsOfGaMU[popi].ChromsOfPop[k].CurrentIteration = it;
                    }



                    //select and cross
                    for (int k = 0; k < numOffspringsOfCross[popi] - 1; k = k + 2)
                    {
                        //select operator
                        int Chroms1Index = SL.Select(PopsOfGa[popi]);
                        int Chroms2Index = SL.Select(PopsOfGa[popi]);

                        //cross operator
                        result1 = CX.Cross(PopsOfGa[popi].ChromsOfPop[Chroms1Index], PopsOfGa[popi].ChromsOfPop[Chroms2Index]);
                        PopsOfGaCX[popi].ChromsOfPop.AddRange(result1);
                    }
                    PopsOfGaCX[popi].ChromsOfPop.RemoveRange(0, numOffspringsOfCross[popi]);

                    //Console.WriteLine("PopsOfGaCX before solve:");
                    //PopsOfGaCX[popi].ChromsOfPopCWFitAndChroms();
                    PopsOfGaCX[popi].ChromsOfPopSolveFit();// * solve every individuals fitness
                    //Console.WriteLine("PopsOfGaCX after solve:");
                    //PopsOfGaCX[popi].ChromsOfPopCWFitAndChroms();

                    //mute operator
                    for (int k = 0; k < numPointOfMute[popi]; k++)
                    {
                        int Chroms1IndexMu = ran.Next(0, PopsOfGa[popi].ChromsOfPop.Count);
                        result2 = MU.Mute(PopsOfGa[popi].ChromsOfPop[Chroms1IndexMu]);
                        PopsOfGaMU[popi].ChromsOfPop.Add(result2);
                    }
                    PopsOfGaMU[popi].ChromsOfPop.RemoveRange(0, numPointOfMute[popi]);

                    //Console.WriteLine("PopsOfGaMU before solve:");
                    //PopsOfGaMU[popi].ChromsOfPopCWFitAndChroms();
                    //Console.WriteLine("PopsOfGaMU after solve:");
                    PopsOfGaMU[popi].ChromsOfPopSolveFit();
                    //PopsOfGaMU[popi].ChromsOfPopCWFitAndChroms();

                    //combine three population
                    for (int iCx = 0; iCx < PopsOfGaCX[popi].PopulationSize; iCx++)
                    {
                        PopsOfGa[popi].ChromsOfPop.Add(Chromosome.Clone <Chromosome>(PopsOfGaCX[popi].ChromsOfPop[iCx]));
                    }
                    for (int iMu = 0; iMu < PopsOfGaMU[popi].PopulationSize; iMu++)
                    {
                        PopsOfGa[popi].ChromsOfPop.Add(Chromosome.Clone <Chromosome>(PopsOfGaMU[popi].ChromsOfPop[iMu]));
                    }
                    //Console.WriteLine($"PopsOfGa+PopsOfGaCX+PopsOfGaMU[{popi}] solve but before sort:");
                    //PopsOfGa[popi].ChromsOfPopCWFitAndChroms();
                    //Console.WriteLine($"sort:");
                    //sort(ascending) with fitness
                    PopsOfGa[popi].FitSort();//
                    //PopsOfGa[popi].ChromsOfPopCWFitAndChroms();
                    // remove the bad ones
                    PopsOfGa[popi].ChromsOfPop.RemoveRange(PopulationSize[popi], (numOffspringsOfCross[popi] + numPointOfMute[popi]));
                    //Console.WriteLine($"PopsOfGa[{popi}]  after remove:");
                    //PopsOfGa[popi].ChromsOfPopCWFitAndChroms();

                    //Local search
                    PopsOfGa[popi].ChromsOfPop[0] = Chromosome.Clone <Chromosome>(LS.LocalSearch(PopsOfGa[popi].ChromsOfPop[0]));

                    //elitism in a population
                    if (HistBestChromOfPops[popi].Fit > PopsOfGa[popi].ChromsOfPop[0].Fit)
                    {
                        HistBestChromOfPops[popi] = Chromosome.Clone <Chromosome>(PopsOfGa[popi].ChromsOfPop[0]);
                    }
                    else
                    {
                        //PopsOfGa[popi].ChromsOfPop[0] = (Chromosome)DeepClone(HistBestChromOfPops[popi]);//elitism
                        PopsOfGa[popi].ChromsOfPop[0] = Chromosome.Clone <Chromosome>(HistBestChromOfPops[popi]);//elitism
                    }
                    HistBestChromOfPops[popi].CurrentIteration = it;
                }
                #endregion popi


                //Take turns to swap the best:The best value of the next population gives the best value of the previous population
                if (NumPopulation == 1)
                {
                    //HistBestChromOfGa[it] = (Chromosome)DeepClone(HistBestChromOfPops[0]);
                    HistBestChromOfGa[it] = Chromosome.Clone <Chromosome>(HistBestChromOfPops[0]);
                }
                else
                {
                    //Chromosome tmepChromo = (Chromosome)DeepClone(PopsOfGa[0].ChromsOfPop[0]);
                    Chromosome tmepChromo = Chromosome.Clone <Chromosome>(PopsOfGa[0].ChromsOfPop[0]);
                    for (int popi = 0; popi < NumPopulation; popi++)
                    {
                        if (HistBestChromOfGa[it].Fit > PopsOfGa[popi].ChromsOfPop[0].Fit)
                        {
                            //HistBestChromOfGa[it] = (Chromosome)DeepClone(PopsOfGa[popi].ChromsOfPop[0]);
                            HistBestChromOfGa[it] = Chromosome.Clone <Chromosome>(PopsOfGa[popi].ChromsOfPop[0]);
                        }
                        else
                        {
                            //PopsOfGa[popi].ChromsOfPop[0] = (Chromosome)DeepClone(HistBestChromOfGa[it]);
                            PopsOfGa[popi].ChromsOfPop[0] = Chromosome.Clone <Chromosome>(HistBestChromOfGa[it]);
                        }

                        //if (PopsOfGa[popi + 1] != null)
                        if ((popi + 1) < NumPopulation)
                        {
                            //PopsOfGa[popi].ChromsOfPop[0] = (Chromosome)DeepClone(PopsOfGa[popi + 1].ChromsOfPop[0]);
                            PopsOfGa[popi].ChromsOfPop[0] = Chromosome.Clone <Chromosome>(PopsOfGa[popi + 1].ChromsOfPop[0]);
                        }
                        if (popi == (NumPopulation - 1) && popi != 0)
                        {
                            //PopsOfGa[NumPopulation - 1].ChromsOfPop[0] = (Chromosome)DeepClone(tmepChromo);
                            PopsOfGa[NumPopulation - 1].ChromsOfPop[0] = Chromosome.Clone <Chromosome>(tmepChromo);
                        }
                    }
                }

                if (it > (int)Math.Round(MaxIteration * 0.3))
                {
                    for (int itsame = 0; itsame < (int)Math.Round(MaxIteration * 0.3); itsame++)
                    {
                        if (Math.Abs(HistBestChromOfGa[it].Fit - HistBestChromOfGa[it - itsame - 1].Fit) < 1e-30)
                        {
                            maxSameIt++;
                        }
                    }
                    if (maxSameIt > (int)Math.Round(MaxIteration * 0.2))
                    {
                        break;
                    }
                }
                //

                Console.WriteLine($"iteration:{HistBestChromOfGa[it].CurrentIteration},bestFit:{HistBestChromOfGa[it].Fit}");
                foreach (double para in HistBestChromOfGa[it].chromosome)
                {
                    Console.Write($"{para} ");
                }
                Console.WriteLine();
                Console.WriteLine();
            }
            #endregion

            return(HistBestChromOfGa);
            //  return globalBestChrom;
        }