/// <summary>
        /// Calculates how much hypervolume each point dominates exclusively. The points
        /// have to be transformed beforehand, to accommodate the assumptions of Zitzler's
        /// hypervolume code.
        /// </summary>
        /// <param name="front">transformed objective values</param>
        /// <returns>HV contributions</returns>
        private double[] HvContributions(double[][] front)
        {
            int numberOfObjectives = Problem.NumberOfObjectives;

            double[]   contributions = new double[front.Length];
            double[][] frontSubset   = new double[front.Length - 1][];
            for (int i = 0; i < front.Length - 1; i++)
            {
                frontSubset[i] = new double[front[0].Length];
            }

            List <double[]> frontCopy = new List <double[]>();

            frontCopy.AddRange(front);
            double[][] totalFront  = frontCopy.ToArray <double[]>();
            double     totalVolume = hv.CalculateHypervolume(totalFront, totalFront.Length, numberOfObjectives);

            for (int i = 0; i < front.Length; i++)
            {
                double[] evaluatedPoint = frontCopy[i];
                frontCopy.RemoveAt(i);

                frontSubset = frontCopy.ToArray <double[]>();
                // STEP4. The hypervolume (control is passed to java version of Zitzler code)
                double chv          = hv.CalculateHypervolume(frontSubset, frontSubset.Length, numberOfObjectives);
                double contribution = totalVolume - chv;
                contributions[i] = contribution;
                // put point back
                frontCopy.Insert(i, evaluatedPoint);
            }
            return(contributions);
        }
Пример #2
0
        /// <summary>
        /// Calculates the hv contribution of different populations. Receives an
        /// array of populations and computes the contribution to HV of the
        /// population consisting in the union of all of them
        /// </summary>
        /// <param name="archive"></param>
        /// <param name="populations">Consisting in all the populatoins</param>
        /// <returns>HV contributions of each population</returns>
        public double[] HVContributions(SolutionSet archive, SolutionSet[] populations)
        {
            SolutionSet union;
            int         size    = 0;
            double      offset_ = 0.0;

            //determining the global size of the population
            foreach (SolutionSet population in populations)
            {
                size += population.Size();
            }

            //allocating space for the union
            union = archive;

            //determining the number of objectives
            int numberOfObjectives = union.Get(0).NumberOfObjectives;

            //writing everything in matrices
            double[][][] frontValues = new double[populations.Length + 1][][];

            frontValues[0] = union.WriteObjectivesToMatrix();
            for (int i = 0; i < populations.Length; i++)
            {
                if (populations[i].Size() > 0)
                {
                    frontValues[i + 1] = populations[i].WriteObjectivesToMatrix();
                }
                else
                {
                    frontValues[i + 1] = new double[0][];
                }
            }

            // obtain the maximum and minimum values of the Pareto front
            double[] maximumValues = GetMaximumValues(union.WriteObjectivesToMatrix(), numberOfObjectives);
            double[] minimumValues = GetMinimumValues(union.WriteObjectivesToMatrix(), numberOfObjectives);

            // normalized all the fronts
            double[][][] normalizedFront = new double[populations.Length + 1][][];
            for (int i = 0; i < normalizedFront.Length; i++)
            {
                if (frontValues[i].Length > 0)
                {
                    normalizedFront[i] = GetNormalizedFront(frontValues[i], maximumValues, minimumValues);
                }
                else
                {
                    normalizedFront[i] = new double[0][];
                }
            }

            // compute offsets for reference point in normalized space
            double[] offsets = new double[maximumValues.Length];
            for (int i = 0; i < maximumValues.Length; i++)
            {
                offsets[i] = offset_ / (maximumValues[i] - minimumValues[i]);
            }

            //Inverse all the fronts front. This is needed because the original
            //metric by Zitzler is for maximization problems
            double[][][] invertedFront = new double[populations.Length + 1][][];
            for (int i = 0; i < invertedFront.Length; i++)
            {
                if (normalizedFront[i].Length > 0)
                {
                    invertedFront[i] = InvertedFront(normalizedFront[i]);
                }
                else
                {
                    invertedFront[i] = new double[0][];
                }
            }

            // shift away from origin, so that boundary points also get a contribution > 0
            foreach (double[][] anInvertedFront in invertedFront)
            {
                foreach (double[] point in anInvertedFront)
                {
                    for (int i = 0; i < point.Length; i++)
                    {
                        point[i] += offsets[i];
                    }
                }
            }

            // calculate contributions
            double[]    contribution = new double[populations.Length];
            HyperVolume hyperVolume  = new HyperVolume();

            for (int i = 0; i < populations.Length; i++)
            {
                if (invertedFront[i + 1].Length == 0)
                {
                    contribution[i] = 0;
                }
                else
                {
                    int auxSize = 0;
                    for (int j = 0; j < populations.Length; j++)
                    {
                        if (j != i)
                        {
                            auxSize += invertedFront[j + 1].Length;
                        }
                    }

                    if (size == archive.Size())
                    {                     // the contribution is the maximum hv
                        contribution[i] = hyperVolume.CalculateHypervolume(invertedFront[0], invertedFront[0].Length, numberOfObjectives);
                    }
                    else
                    {
                        //make a front with all the populations but the target one
                        int        index = 0;
                        double[][] aux   = new double[auxSize][];
                        for (int j = 0; j < populations.Length; j++)
                        {
                            if (j != i)
                            {
                                for (int k = 0; k < populations[j].Size(); k++)
                                {
                                    aux[index++] = invertedFront[j + 1][k];
                                }
                            }
                        }
                        contribution[i] = hyperVolume.CalculateHypervolume(invertedFront[0], invertedFront[0].Length, numberOfObjectives)
                                          - hyperVolume.CalculateHypervolume(aux, aux.Length, numberOfObjectives);
                    }
                }
            }

            return(contribution);
        }
Пример #3
0
        /// <summary>
        /// Calculates the hv contribution of different populations. Receives an
        /// array of populations and computes the contribution to HV of the
        /// population consisting in the union of all of them
        /// </summary>
        /// <param name="populations">Consisting in all the populatoins</param>
        /// <returns>HV contributions of each population</returns>
        public double[] HVContributions(SolutionSet[] populations)
        {
            bool empty = true;

            foreach (SolutionSet population2 in populations)
            {
                if (population2.Size() > 0)
                {
                    empty = false;
                }
            }

            if (empty)
            {
                double[] contributions = new double[populations.Length];
                for (int i = 0; i < populations.Length; i++)
                {
                    contributions[i] = 0;
                }
                for (int i = 0; i < populations.Length; i++)
                {
                    Logger.Log.Info("Contributions: " + contributions[i]);
                    Console.WriteLine(contributions[i]);
                }
                return(contributions);
            }

            SolutionSet union;
            int         size    = 0;
            double      offset_ = 0.0;

            //determining the global size of the population
            foreach (SolutionSet population1 in populations)
            {
                size += population1.Size();
            }

            //allocating space for the union
            union = new SolutionSet(size);

            // filling union
            foreach (SolutionSet population in populations)
            {
                for (int j = 0; j < population.Size(); j++)
                {
                    union.Add(population.Get(j));
                }
            }

            //determining the number of objectives
            int numberOfObjectives = union.Get(0).NumberOfObjectives;

            //writing everything in matrices
            double[][][] frontValues = new double[populations.Length + 1][][];

            frontValues[0] = union.WriteObjectivesToMatrix();
            for (int i = 0; i < populations.Length; i++)
            {
                if (populations[i].Size() > 0)
                {
                    frontValues[i + 1] = populations[i].WriteObjectivesToMatrix();
                }
                else
                {
                    frontValues[i + 1] = new double[0][];
                }
            }

            // obtain the maximum and minimum values of the Pareto front
            double[] maximumValues = GetMaximumValues(union.WriteObjectivesToMatrix(), numberOfObjectives);
            double[] minimumValues = GetMinimumValues(union.WriteObjectivesToMatrix(), numberOfObjectives);

            // normalized all the fronts
            double[][][] normalizedFront = new double[populations.Length + 1][][];
            for (int i = 0; i < normalizedFront.Length; i++)
            {
                if (frontValues[i].Length > 0)
                {
                    normalizedFront[i] = GetNormalizedFront(frontValues[i], maximumValues, minimumValues);
                }
                else
                {
                    normalizedFront[i] = new double[0][];
                }
            }

            // compute offsets for reference point in normalized space
            double[] offsets = new double[maximumValues.Length];
            for (int i = 0; i < maximumValues.Length; i++)
            {
                offsets[i] = offset_ / (maximumValues[i] - minimumValues[i]);
            }

            //Inverse all the fronts front. This is needed because the original
            //metric by Zitzler is for maximization problems
            double[][][] invertedFront = new double[populations.Length + 1][][];
            for (int i = 0; i < invertedFront.Length; i++)
            {
                if (normalizedFront[i].Length > 0)
                {
                    invertedFront[i] = InvertedFront(normalizedFront[i]);
                }
                else
                {
                    invertedFront[i] = new double[0][];
                }
            }

            // shift away from origin, so that boundary points also get a contribution > 0
            foreach (double[][] anInvertedFront in invertedFront)
            {
                foreach (double[] point in anInvertedFront)
                {
                    for (int i = 0; i < point.Length; i++)
                    {
                        point[i] += offsets[i];
                    }
                }
            }

            // calculate contributions
            double[]    contribution = new double[populations.Length];
            HyperVolume hyperVolume  = new HyperVolume();

            for (int i = 0; i < populations.Length; i++)
            {
                if (invertedFront[i + 1].Length == 0)
                {
                    contribution[i] = 0;
                }
                else
                {
                    if (invertedFront[i + 1].Length != invertedFront[0].Length)
                    {
                        double[][] aux = new double[invertedFront[0].Length - invertedFront[i + 1].Length][];
                        int        startPoint = 0, endPoint;
                        for (int j = 0; j < i; j++)
                        {
                            startPoint += invertedFront[j + 1].Length;
                        }
                        endPoint = startPoint + invertedFront[i + 1].Length;
                        int index = 0;
                        for (int j = 0; j < invertedFront[0].Length; j++)
                        {
                            if (j < startPoint || j >= (endPoint))
                            {
                                aux[index++] = invertedFront[0][j];
                            }
                        }

                        contribution[i] = hyperVolume.CalculateHypervolume(invertedFront[0], invertedFront[0].Length, numberOfObjectives)
                                          - hyperVolume.CalculateHypervolume(aux, aux.Length, numberOfObjectives);
                    }
                    else
                    {
                        contribution[i] = hyperVolume.CalculateHypervolume(invertedFront[0], invertedFront[0].Length, numberOfObjectives);
                    }
                }
            }

            return(contribution);
        }