예제 #1
0
        /// <summary>
        /// Runs the NSGA-II algorithm.
        /// </summary>
        /// <returns>a <code>SolutionSet</code> that is a set of non dominated solutions as a result of the algorithm execution</returns>
        public override SolutionSet Execute()
        {
            // !!!! NEEDED PARAMETES !!! start
            //J* Parameters
            int populationSize = -1; // J* store population size
            int maxEvaluations = -1; // J* store number of max Evaluations
            int evaluations;         // J* number of current evaluations

            // J* Objects needed to illustrate the use of quality indicators inside the algorithms
            QualityIndicator indicators = null; // QualityIndicator object
            int requiredEvaluations;            // Use in the example of use of the
            // indicators object (see below)

            // J* populations needed to implement NSGA-II
            SolutionSet population;          //J* Current population
            SolutionSet offspringPopulation; //J* offspring population
            SolutionSet union;               //J* population resultant from current and offpring population

            //J* Genetic Operators
            Operator mutationOperator;
            Operator crossoverOperator;
            Operator selectionOperator;

            //J* Used to evaluate crowding distance
            Distance distance = new Distance();

            //J* !!!! NEEDED PARAMETES !!! end

            //J* !!! INITIALIZING PARAMETERS - start !!!

            //Read the parameters
            JMetalCSharp.Utils.Utils.GetIntValueFromParameter(this.InputParameters, "maxEvaluations", ref maxEvaluations);  //J* required
            JMetalCSharp.Utils.Utils.GetIntValueFromParameter(this.InputParameters, "populationSize", ref populationSize);  //J* required
            JMetalCSharp.Utils.Utils.GetIndicatorsFromParameters(this.InputParameters, "indicators", ref indicators);       //J* optional

            //Initialize the variables
            population  = new SolutionSet(populationSize);
            evaluations = 0;

            requiredEvaluations = 0;

            //Read the operators
            mutationOperator  = Operators["mutation"];
            crossoverOperator = Operators["crossover"];
            selectionOperator = Operators["selection"];

            //J* !!! INITIALIZING PARAMETERS - end !!!


            //J* !!! Creating first population !!!

            JMetalRandom.SetRandom(comp.MyRand);
            comp.LogAddMessage("Random seed = " + comp.Seed);

            // Create the initial solutionSet
            Solution newSolution;

            for (int i = 0; i < populationSize; i++)
            {
                newSolution = new Solution(Problem);
                Problem.Evaluate(newSolution);
                Problem.EvaluateConstraints(newSolution);
                evaluations++;
                population.Add(newSolution);
            }

            // Generations
            while (evaluations < maxEvaluations)
            {
                // Create the offSpring solutionSet
                offspringPopulation = new SolutionSet(populationSize);
                Solution[] parents = new Solution[2];
                for (int i = 0; i < (populationSize / 2); i++)
                {
                    if (evaluations < maxEvaluations)
                    {
                        //obtain parents
                        parents[0] = (Solution)selectionOperator.Execute(population);
                        parents[1] = (Solution)selectionOperator.Execute(population);
                        Solution[] offSpring = (Solution[])crossoverOperator.Execute(parents);
                        mutationOperator.Execute(offSpring[0]);
                        mutationOperator.Execute(offSpring[1]);
                        Problem.Evaluate(offSpring[0]);
                        Problem.EvaluateConstraints(offSpring[0]);
                        Problem.Evaluate(offSpring[1]);
                        Problem.EvaluateConstraints(offSpring[1]);
                        offspringPopulation.Add(offSpring[0]);
                        offspringPopulation.Add(offSpring[1]);
                        evaluations += 2;
                    }
                }

                // Create the solutionSet union of solutionSet and offSpring
                union = ((SolutionSet)population).Union(offspringPopulation);

                // Ranking the union
                Ranking ranking = new Ranking(union);

                int         remain = populationSize;
                int         index  = 0;
                SolutionSet front  = null;
                population.Clear();

                // Obtain the next front
                front = ranking.GetSubfront(index);

                while ((remain > 0) && (remain >= front.Size()))
                {
                    //Assign crowding distance to individuals
                    distance.CrowdingDistanceAssignment(front, Problem.NumberOfObjectives);
                    //Add the individuals of this front
                    for (int k = 0; k < front.Size(); k++)
                    {
                        population.Add(front.Get(k));
                    }

                    //Decrement remain
                    remain = remain - front.Size();

                    //Obtain the next front
                    index++;
                    if (remain > 0)
                    {
                        front = ranking.GetSubfront(index);
                    }
                }

                // Remain is less than front(index).size, insert only the best one
                if (remain > 0)
                {  // front contains individuals to insert
                    distance.CrowdingDistanceAssignment(front, Problem.NumberOfObjectives);
                    front.Sort(new CrowdingComparator());
                    for (int k = 0; k < remain; k++)
                    {
                        population.Add(front.Get(k));
                    }

                    remain = 0;
                }

                // This piece of code shows how to use the indicator object into the code
                // of NSGA-II. In particular, it finds the number of evaluations required
                // by the algorithm to obtain a Pareto front with a hypervolume higher
                // than the hypervolume of the true Pareto front.
                if ((indicators != null) && (requiredEvaluations == 0))
                {
                    double HV = indicators.GetHypervolume(population);
                    if (HV >= (0.98 * indicators.TrueParetoFrontHypervolume))
                    {
                        requiredEvaluations = evaluations;
                    }
                }
            }



            // Return as output parameter the required evaluations
            SetOutputParameter("evaluations", requiredEvaluations);

            comp.LogAddMessage("Evaluations = " + evaluations);
            // Return the first non-dominated front
            Ranking rank = new Ranking(population);

            Result = rank.GetSubfront(0);

            return(Result);
        }
예제 #2
0
        public SolutionSet Mix()
        {
            QualityIndicator indicators = new QualityIndicator(problem, fileRead.Qi); // QualityIndicator object
            int requiredEvaluations     = 0;                                          // Use in the example of use of the

            // indicators object (see below)

            evaluations = 0;

            iteration        = 0;
            populationSize   = int.Parse(fileRead.Ps);
            iterationsNumber = int.Parse(fileRead.Itn);
            dataDirectory    = "Data/Parameters/Weight";


            Logger.Log.Info("POPSIZE: " + populationSize);
            Console.WriteLine("POPSIZE: " + populationSize);

            population = new SolutionSet(populationSize);
            indArray   = new Solution[problem.NumberOfObjectives];

            t     = int.Parse(fileRead.T);
            nr    = int.Parse(fileRead.Nr);
            delta = double.Parse(fileRead.Delta);
            gamma = double.Parse(fileRead.Gamma);

            neighborhood = new int[populationSize][];
            for (int i = 0; i < populationSize; i++)
            {
                neighborhood[i] = new int[t];
            }

            z = new double[problem.NumberOfObjectives];
            //znad = new double[Problem.NumberOfObjectives];

            lambda = new double[populationSize][];
            for (int i = 0; i < populationSize; i++)
            {
                lambda[i] = new double[problem.NumberOfObjectives];
            }

            /*string dir = "Result/" + fileRead.Al + "_" + fileRead.Co + "_" + fileRead.Co2 + "/" + fileRead.Pb + "_" + fileRead.St + "/Record/SBX(" + double.Parse(fileRead.Ra).ToString("#0.00") + ")+ACOR(" + (1-double.Parse(fileRead.Ra)).ToString("#0.00") + ")";
             * if (Directory.Exists(dir))
             * {
             *  Console.WriteLine("The directory {0} already exists.", dir);
             * }
             * else
             * {
             *  Directory.CreateDirectory(dir);
             *  Console.WriteLine("The directory {0} was created.", dir);
             * }*/

            //Step 1. Initialization
            //Step 1.1 Compute euclidean distances between weight vectors and find T
            InitUniformWeight();

            InitNeighborhood();

            //Step 1.2 Initialize population
            InitPoputalion();

            //Step 1.3 Initizlize z
            InitIdealPoint();

            //Step 2 Update
            for (int a = 0; a < iterationsNumber; a++)
            {
                int[] permutation = new int[populationSize];
                JMetalCSharp.Metaheuristics.MOEAD.Utils.RandomPermutation(permutation, populationSize);

                Solution[] parents = new Solution[2];
                int        t       = 0;

                if (a >= double.Parse(fileRead.Ra) * iterationsNumber)
                {
                    for (int i = 0; i < populationSize; i++)
                    {
                        int n = permutation[i];
                        // or int n = i;


                        int    type;
                        double rnd = JMetalRandom.NextDouble();

                        // STEP 2.1. ACOR selection based on probability
                        if (rnd < gamma) // if (rnd < realb)
                        {
                            type = 1;    // minmum
                            //parents[0] = population.Get(ACOrSelection2(n, type, pro_T));
                        }
                        else
                        {
                            type = 2;   // whole neighborhood probability
                            //parents[0] = population.Get(ACOrSelection2(n, type, pro_A));
                        }
                        GetStdDev(neighborhood);
                        //GetStdDev1(neighborhood, type);

                        //List<int> p = new List<int>();
                        //MatingSelection(p, n, 1, type);

                        // STEP 2.2. Reproduction
                        Solution child;

                        parents[0] = population.Get(ACOrSelection(n, type));
                        parents[1] = population.Get(n);
                        //parents[0] = population.Get(p[0]);

                        // Apply ACOR crossover
                        child = (Solution)crossover2.Execute(parents);

                        child.NumberofReplace = t;

                        // // Apply mutation
                        mutation.Execute(child);

                        // Evaluation
                        problem.Evaluate(child);

                        evaluations++;

                        // STEP 2.3. Repair. Not necessary

                        // STEP 2.4. Update z_
                        UpdateReference(child);

                        // STEP 2.5. Update of solutions
                        t = UpdateProblemWithReplace(child, n, 1);
                    }
                }
                else
                {
                    // Create the offSpring solutionSet
                    SolutionSet offspringPopulation = new SolutionSet(populationSize);
                    for (int i = 0; i < (populationSize / 2); i++)
                    {
                        int n = permutation[i]; // or int n = i;

                        int    type;
                        double rnd = JMetalRandom.NextDouble();

                        // STEP 2.1. Mating selection based on probability
                        if (rnd < delta) // if (rnd < realb)
                        {
                            type = 1;    // neighborhood
                        }
                        else
                        {
                            type = 2;   // whole population
                        }
                        List <int> p = new List <int>();
                        MatingSelection(p, n, 2, type);

                        parents[0] = population.Get(p[0]);
                        parents[1] = population.Get(p[1]);

                        //obtain parents
                        Solution[] offSpring = (Solution[])crossover1.Execute(parents);
                        //Solution child;
                        mutation.Execute(offSpring[0]);
                        mutation.Execute(offSpring[1]);

                        /*if(rnd < 0.5)
                         * {
                         *  child = offSpring[0];
                         * }
                         * else
                         * {
                         *  child = offSpring[1];
                         * }*/
                        problem.Evaluate(offSpring[0]);
                        problem.Evaluate(offSpring[1]);
                        problem.EvaluateConstraints(offSpring[0]);
                        problem.EvaluateConstraints(offSpring[1]);
                        offspringPopulation.Add(offSpring[0]);
                        offspringPopulation.Add(offSpring[1]);
                        evaluations += 2;

                        // STEP 2.3. Repair. Not necessary

                        // STEP 2.4. Update z_
                        UpdateReference(offSpring[0]);
                        UpdateReference(offSpring[1]);

                        // STEP 2.5. Update of solutions
                        UpdateProblem(offSpring[0], n, type);
                        UpdateProblem(offSpring[1], n, type);
                    }

                    //for (int i = 0; i < populationSize; i++)
                    //{
                    //    int n = permutation[i]; // or int n = i;

                    //    int type;
                    //    double rnd = JMetalRandom.NextDouble();

                    //    // STEP 2.1. Mating selection based on probability
                    //    if (rnd < delta) // if (rnd < realb)
                    //    {
                    //        type = 1;   // neighborhood
                    //    }
                    //    else
                    //    {
                    //        type = 2;   // whole population
                    //    }
                    //    List<int> p = new List<int>();
                    //    MatingSelection(p, n, 2, type);

                    //    // STEP 2.2. Reproduction
                    //    Solution child;
                    //    Solution[] parent = new Solution[3];

                    //    parent[0] = population.Get(p[0]);
                    //    parent[1] = population.Get(p[1]);

                    //    parent[2] = population.Get(n);

                    //    // Apply DE crossover
                    //    child = (Solution)crossover1.Execute(new object[] { population.Get(n), parent });

                    //    // Apply mutation
                    //    mutation.Execute(child);

                    //    // Evaluation
                    //    problem.Evaluate(child);

                    //    evaluations++;

                    //    // STEP 2.3. Repair. Not necessary

                    //    // STEP 2.4. Update z_
                    //    UpdateReference(child);

                    //    // STEP 2.5. Update of solutions
                    //    UpdateProblem(child, n, type);
                    //}
                }

                /*string filevar = dir + "/VAR" + iteration;
                *  string filefun = dir + "/FUN" + iteration;
                *  population.PrintVariablesToFile(filevar);
                *  population.PrintObjectivesToFile(filefun);*/

                iteration++;

                if ((indicators != null) && (requiredEvaluations == 0))
                {
                    double HV = indicators.GetHypervolume(population);
                    if (HV >= (0.98 * indicators.TrueParetoFrontHypervolume))
                    {
                        requiredEvaluations = evaluations;
                    }
                }
            }

            Logger.Log.Info("ITERATION: " + iteration);
            Console.WriteLine("ITERATION: " + iteration);

            SolutionSet Result = population;

            //return population;

            // Return the first non-dominated front
            Ranking rank = new Ranking(population);

            //SolutionSet Result = rank.GetSubfront(0);

            return(Result);
        }
예제 #3
0
        public void MyAlgorithm()
        {
            Problem   problem   = null;  // The problem to solve
            Algorithm algorithm = null;  // The algorithm to use
            Operator  crossover = null;  // Crossover operator
            Operator  mutation  = null;  // Mutation operator
            Operator  selection = null;  // Selection operator

            QualityIndicator indicators; // Object to get quality indicators

            FileRead fileRead = new FileRead();

            fileRead.fileread();
            problem   = fileRead.GetProblem();
            algorithm = fileRead.GetAlgorithm();
            //crossover = fileRead.GetCrossover();
            mutation  = fileRead.GetMutation();
            selection = fileRead.GetSelection();

            // Quality Indicators Operator
            //indicators = new QualityIndicator(problem, "DTLZ1.3D.pf");
            indicators = new QualityIndicator(problem, fileRead.Qi);
            //indicators = new QualityIndicator(problem, "LZ09_F1.pf");

            // Add the operators to the algorithm
            algorithm.AddOperator("crossover", crossover);
            algorithm.AddOperator("mutation", mutation);
            algorithm.AddOperator("selection", selection);

            // Add the indicator object to the algorithm
            algorithm.SetInputParameter("indicators", indicators);

            for (int i = 1; i <= int.Parse(fileRead.Rt); i++)
            {
                // Logger object and file to store log messages
                var logger = Logger.Log;

                var appenders    = logger.Logger.Repository.GetAppenders();
                var fileAppender = appenders[0] as log4net.Appender.FileAppender;
                fileAppender.File = fileRead.DirPath + "/" + fileRead.Al + i + ".log";
                fileAppender.ActivateOptions();

                string filevar = fileRead.DirPath + "/VAR" + i;
                string filefun = fileRead.DirPath + "/FUN" + i;

                FileStream   file      = new FileStream(fileRead.DirPath + "/" + fileRead.Al + "new" + i + ".txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
                StreamWriter newlogger = new StreamWriter(file);

                // Execute the Algorithm
                long        initTime      = Environment.TickCount;
                SolutionSet population    = algorithm.Execute();
                long        estimatedTime = Environment.TickCount - initTime;

                // Result messages
                logger.Info("Total execution time: " + estimatedTime + "ms");
                logger.Info("Variables values have been writen to file " + filevar);
                newlogger.WriteLine("Total execution time: " + estimatedTime + "ms" + "\n");
                newlogger.WriteLine("Variables values have been writen to file " + filevar + "\n");
                population.PrintVariablesToFile(filevar);
                logger.Info("Objectives values have been writen to file " + filefun);
                population.PrintObjectivesToFile(filefun);
                Console.WriteLine("Time: " + estimatedTime);
                newlogger.WriteLine("Time: " + estimatedTime + "\n");
                Console.ReadLine();
                if (indicators != null)
                {
                    logger.Info("Quality indicators");
                    logger.Info("Hypervolume: " + indicators.GetHypervolume(population));
                    logger.Info("GD         : " + indicators.GetGD(population));
                    logger.Info("IGD        : " + indicators.GetIGD(population));
                    logger.Info("Spread     : " + indicators.GetSpread(population));
                    logger.Info("Epsilon    : " + indicators.GetEpsilon(population));

                    newlogger.WriteLine("Quality indicators");
                    newlogger.WriteLine("Hypervolume: " + indicators.GetHypervolume(population).ToString("F18") + "\n");
                    newlogger.WriteLine("GD         : " + indicators.GetGD(population).ToString("F18") + "\n");
                    newlogger.WriteLine("IGD        : " + indicators.GetIGD(population).ToString("F18") + "\n");
                    newlogger.WriteLine("Spread     : " + indicators.GetSpread(population).ToString("F18") + "\n");
                    newlogger.WriteLine("Epsilon    : " + indicators.GetEpsilon(population).ToString("F18") + "\n");

                    int evaluations = (int)algorithm.GetOutputParameter("evaluations");
                    logger.Info("Speed      : " + evaluations + "     evaluations");
                    newlogger.WriteLine("Speed      : " + evaluations + "     evaluations" + "\n");
                }
                newlogger.Close();
                file.Close();
                algorithm.AddOperator("mutation", mutation);
            }
        }
예제 #4
0
        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            FileRead read = new FileRead();

            read.fileread();
            Problem          problem    = read.GetProblem();
            Algorithm        algorithm  = read.GetAlgorithm();
            QualityIndicator indicators = new QualityIndicator(problem, read.Qi);

            NewAlgorithmTest test = new NewAlgorithmTest();

            for (int i = 1; i <= int.Parse(read.Rt); i++)
            {
                // Logger object and file to store log messages
                var logger = Logger.Log;

                var appenders    = logger.Logger.Repository.GetAppenders();
                var fileAppender = appenders[0] as log4net.Appender.FileAppender;
                fileAppender.File = read.DirPath + "/" + read.Al + i + ".log";
                fileAppender.ActivateOptions();

                string filevar = read.DirPath + "/VAR" + i;
                string filefun = read.DirPath + "/FUN" + i;

                FileStream   file      = new FileStream(read.DirPath + "/MOEADnew" + i + ".txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
                StreamWriter newlogger = new StreamWriter(file);

                // Execute the Algorithm
                long        initTime      = Environment.TickCount;
                SolutionSet population    = test.Mix();
                long        estimatedTime = Environment.TickCount - initTime;

                // Result messages
                logger.Info("Total execution time: " + estimatedTime + "ms");
                logger.Info("Variables values have been writen to file " + filevar);
                newlogger.WriteLine("Total execution time: " + estimatedTime + "ms" + "\n");
                newlogger.WriteLine("Variables values have been writen to file " + filevar + "\n");
                population.PrintVariablesToFile(filevar);
                logger.Info("Objectives values have been writen to file " + filefun);
                population.PrintObjectivesToFile(filefun);
                Console.WriteLine("Time: " + estimatedTime);
                newlogger.WriteLine("Time: " + estimatedTime + "\n");
                Console.ReadLine();
                if (indicators != null)
                {
                    logger.Info("Quality indicators");
                    logger.Info("Hypervolume: " + indicators.GetHypervolume(population));
                    logger.Info("GD         : " + indicators.GetGD(population));
                    logger.Info("IGD        : " + indicators.GetIGD(population));
                    logger.Info("Spread     : " + indicators.GetSpread(population));
                    logger.Info("Epsilon    : " + indicators.GetEpsilon(population));

                    newlogger.WriteLine("Quality indicators");
                    newlogger.WriteLine("Hypervolume: " + indicators.GetHypervolume(population).ToString("F18") + "\n");
                    newlogger.WriteLine("GD         : " + indicators.GetGD(population).ToString("F18") + "\n");
                    newlogger.WriteLine("IGD        : " + indicators.GetIGD(population).ToString("F18") + "\n");
                    newlogger.WriteLine("Spread     : " + indicators.GetSpread(population).ToString("F18") + "\n");
                    newlogger.WriteLine("Epsilon    : " + indicators.GetEpsilon(population).ToString("F18") + "\n");

                    int evaluations = test.GetEvaluations();
                    logger.Info("Speed      : " + evaluations + "     evaluations");
                    newlogger.WriteLine("Speed      : " + evaluations + "     evaluations" + "\n");
                }
                newlogger.Close();
                file.Close();
            }
        }
예제 #5
0
        /// <summary>
        /// Runs the NSGA-II algorithm.
        /// </summary>
        /// <returns>a <code>SolutionSet</code> that is a set of non dominated solutions as a result of the algorithm execution</returns>
        public override SolutionSet Execute()
        {
            int populationSize = -1;
            int maxEvaluations = -1;
            int evaluations;

            QualityIndicator indicators = null; // QualityIndicator object
            int requiredEvaluations;            // Use in the example of use of the
                                                // indicators object (see below)

            SolutionSet population;
            SolutionSet offspringPopulation;
            SolutionSet union;

            Operator mutationOperator;
            Operator crossoverOperator;
            Operator selectionOperator;

            Distance distance = new Distance();

            //Read the parameters
            JMetalCSharp.Utils.Utils.GetIntValueFromParameter(this.InputParameters, "maxEvaluations", ref maxEvaluations);
            JMetalCSharp.Utils.Utils.GetIntValueFromParameter(this.InputParameters, "populationSize", ref populationSize);
            JMetalCSharp.Utils.Utils.GetIndicatorsFromParameters(this.InputParameters, "indicators", ref indicators);

            //Initialize the variables
            population  = new SolutionSet(populationSize);
            evaluations = 0;

            requiredEvaluations = 0;

            //Read the operators
            mutationOperator  = Operators["mutation"];
            crossoverOperator = Operators["crossover"];
            selectionOperator = Operators["selection"];
            var    plotCounter = 0;
            var    plotModulo  = 4;
            Random random      = new Random(2);

            JMetalRandom.SetRandom(random);

            // Create the initial solutionSet
            IntergenSolution newSolution;

            for (int i = 0; i < populationSize; i++)
            {
                //var test = (IntergenProblem) Problem;
                newSolution = new IntergenSolution((IntergenProblem)Problem);
                Problem.Evaluate(newSolution);
                Problem.EvaluateConstraints(newSolution);
                evaluations++;
                population.Add(newSolution);
            }

            // Generations
            while (evaluations < maxEvaluations)
            {
                // Create the offSpring solutionSet
                offspringPopulation = new SolutionSet(populationSize);
                IntergenSolution[] parents = new IntergenSolution[2];
                for (int i = 0; i < (populationSize / 2); i++)
                {
                    if (evaluations < maxEvaluations)
                    {
                        //obtain parents
                        parents[0] = (IntergenSolution)selectionOperator.Execute(population);
                        parents[1] = (IntergenSolution)selectionOperator.Execute(population);
                        IntergenSolution[] offSpring = (IntergenSolution[])crossoverOperator.Execute(parents);
                        mutationOperator.Execute(offSpring[0]);
                        mutationOperator.Execute(offSpring[1]);
                        Problem.Evaluate(offSpring[0]);
                        Problem.EvaluateConstraints(offSpring[0]);
                        Problem.Evaluate(offSpring[1]);
                        Problem.EvaluateConstraints(offSpring[1]);
                        offspringPopulation.Add(offSpring[0]);
                        offspringPopulation.Add(offSpring[1]);
                        evaluations += 2;
                    }
                }
                // Create the solutionSet union of solutionSet and offSpring
                union = ((SolutionSet)population).Union(offspringPopulation);

                // Ranking the union
                Ranking ranking = new Ranking(union);

                int         remain = populationSize;
                int         index  = 0;
                SolutionSet front  = null;
                population.Clear();

                // Obtain the next front
                front = ranking.GetSubfront(index);

                while ((remain > 0) && (remain >= front.Size()))
                {
                    //Assign crowding distance to individuals
                    distance.CrowdingDistanceAssignment(front, Problem.NumberOfObjectives);
                    //Add the individuals of this front
                    for (int k = 0; k < front.Size(); k++)
                    {
                        population.Add(front.Get(k));
                    }

                    //Decrement remain
                    remain = remain - front.Size();

                    //Obtain the next front
                    index++;
                    if (remain > 0)
                    {
                        front = ranking.GetSubfront(index);
                    }
                }

                // Remain is less than front(index).size, insert only the best one
                if (remain > 0)
                {  // front contains individuals to insert
                    distance.CrowdingDistanceAssignment(front, Problem.NumberOfObjectives);
                    front.Sort(new CrowdingComparator());
                    for (int k = 0; k < remain; k++)
                    {
                        population.Add(front.Get(k));
                    }

                    remain = 0;
                }

                // This piece of code shows how to use the indicator object into the code
                // of NSGA-II. In particular, it finds the number of evaluations required
                // by the algorithm to obtain a Pareto front with a hypervolume higher
                // than the hypervolume of the true Pareto front.
                if ((indicators != null) && (requiredEvaluations == 0))
                {
                    double HV = indicators.GetHypervolume(population);
                    if (HV >= (0.98 * indicators.TrueParetoFrontHypervolume))
                    {
                        requiredEvaluations = evaluations;
                    }
                }

                var sol0 = front.Best(new CrowdingComparator());
                //if (plotCounter%plotModulo == 0)

                SolutionPlotter.Plot(sol0);
                ProgressReporter.ReportSolution(evaluations, sol0, _worker);
            }

            // Return as output parameter the required evaluations
            SetOutputParameter("evaluations", requiredEvaluations);

            // Return the first non-dominated front
            Ranking rank = new Ranking(population);

            Result = rank.GetSubfront(0);

            return(Result);
        }