// ----------------------------------------------------------------------
 // ASF: Achivement Scalarization Function
 // I implement here a effcient version of it, which only receives the index
 // of the objective which uses 1.0; the rest will use 0.00001. This is
 // different to the one impelemented in C++
 // ----------------------------------------------------------------------
 private double ASF(S s, int index) {
   double max_ratio = Double.NEGATIVE_INFINITY;
   for (int i = 0; i < s.getNumberOfObjectives(); i++) {
     double weight = (index == i) ? 1.0 : 0.000001;
     max_ratio = Math.max(max_ratio, s.getObjective(i) / weight);
   }
   return max_ratio;
 }
  public List<Double> constructHyperplane(List<S> population, List<S> extreme_points) {
    // Check whether there are duplicate extreme points.
    // This might happen but the original paper does not mention how to deal with it.
    boolean duplicate = false;
    for (int i = 0; !duplicate && i < extreme_points.size(); i += 1) {
      for (int j = i + 1; !duplicate && j < extreme_points.size(); j += 1) {
        duplicate = extreme_points.get(i).equals(extreme_points.get(j));
      }
    }

    List<Double> intercepts = new ArrayList<>();

    if (duplicate) // cannot construct the unique hyperplane (this is a casual method to deal with
                   // the condition)
    {
      for (int f = 0; f < numberOfObjectives; f += 1) {
        // extreme_points[f] stands for the individual with the largest value of objective f
        intercepts.add(extreme_points.get(f).getObjective(f));
      }
    } else {
      // Find the equation of the hyperplane
      List<Double> b = new ArrayList<>(); // (pop[0].objs().size(), 1.0);
      for (int i = 0; i < numberOfObjectives; i++) b.add(1.0);

      List<List<Double>> A = new ArrayList<>();
      for (S s : extreme_points) {
        List<Double> aux = new ArrayList<>();
        for (int i = 0; i < numberOfObjectives; i++) aux.add(s.getObjective(i));
        A.add(aux);
      }
      List<Double> x = guassianElimination(A, b);

      // Find intercepts
      for (int f = 0; f < numberOfObjectives; f += 1) {
        intercepts.add(1.0 / x.get(f));
      }
    }
    return intercepts;
  }
  public List<Double> translateObjectives(List<S> population) {
    List<Double> ideal_point;
    ideal_point = new ArrayList<>(numberOfObjectives);

    for (int f = 0; f < numberOfObjectives; f += 1) {
      double minf = Double.MAX_VALUE;
      for (int i = 0; i < fronts.get(0).size(); i += 1) // min values must appear in the first front
      {
        minf = Math.min(minf, fronts.get(0).get(i).getObjective(f));
      }
      ideal_point.add(minf);

      for (List<S> list : fronts) {
        for (S s : list) {
          if (f == 0) // in the first objective we create the vector of conv_objs
          setAttribute(s, new ArrayList<Double>());

          getAttribute(s).add(s.getObjective(f) - minf);
        }
      }
    }

    return ideal_point;
  }