/// <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); }
/// <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); }
/// <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); }