/**
   * Computes the HV contribution of a solutiontype in a solutiontype set. REQUIRES: the
   * solutiontype belongs to the solutiontype set REQUIRES: the HV of the solutiontype set is
   * computed beforehand and its value is passed as third parameter
   *
   * @return The hv contribution of the solutiontype
   */
  public double computeSolutionHVContribution(
      SolutionSet solutionSet, int solutionIndex, double solutionSetHV) {
    double contribution;

    Solution currentPoint = solutionSet.get(solutionIndex);
    solutionSet.remove(solutionIndex);

    if (numberOfObjectives == 2) {
      contribution = solutionSetHV - get2DHV(solutionSet);
    } else {
      Front front = new Front(solutionSet.size(), numberOfObjectives, solutionSet);
      double hv = new WFGHV(numberOfObjectives, solutionSet.size(), referencePoint).getHV(front);
      contribution = solutionSetHV - hv;
    }
    solutionSet.add(solutionIndex, currentPoint);
    solutionSet.get(solutionIndex).setCrowdingDistance(contribution);

    return contribution;
  }
  /**
   * Computes the HV contribution of the solutions
   *
   * @return
   */
  public void computeHVContributions(SolutionSet solutionSet) {
    double[] contributions = new double[solutionSet.size()];
    double solutionSetHV = 0;

    solutionSetHV = computeHypervolume(solutionSet);

    for (int i = 0; i < solutionSet.size(); i++) {
      Solution currentPoint = solutionSet.get(i);
      solutionSet.remove(i);

      if (numberOfObjectives == 2) {
        contributions[i] = solutionSetHV - get2DHV(solutionSet);
      } else {
        Front front = new Front(solutionSet.size(), numberOfObjectives, solutionSet);
        double hv = new WFGHV(numberOfObjectives, solutionSet.size(), referencePoint).getHV(front);
        contributions[i] = solutionSetHV - hv;
      }
      solutionSet.add(i, currentPoint);
    }

    for (int i = 0; i < solutionSet.size(); i++) {
      solutionSet.get(i).setCrowdingDistance(contributions[i]);
    }
  }