/**
   * Fills in oldPopulation with new individuals.
   *
   * @param oldPopulation EnhancedHeuristicsNet[] population to be filled in.
   * @return EnhancedHeuristicsNet[] population with new individuals. There are no duplicated
   *     individuals in this population.
   */
  public HeuristicsNet[] build(HeuristicsNet[] oldPopulation) {

    int size = 0;
    HNSet singleton = null;

    population = oldPopulation;

    size = population.length;

    for (int i = 0; i < size; i++) {
      // create an individual
      population[i] =
          new HeuristicsNet(
              logReader.getLogSummary().getLogEvents(),
              geneticMiningMatrices.getDuplicatesMapping(),
              geneticMiningMatrices.getReverseDuplicatesMapping());

      // create its input/output sets
      for (int j = 0; j < population[i].size(); j++) {
        population[i].setInputSet(j, buildInputSet(j));
        population[i].setOutputSet(j, buildOutputSet(j));

        if (geneticMiningMatrices.getStartMatrix().get(j) > 0) {
          // because this is the artificial START tasks....
          if (population[i].getStartTasks() == null) {
            HNSubSet startTasks = new HNSubSet();
            startTasks.add(j);
            population[i].setStartTasks(startTasks);

          } else {
            population[i].getStartTasks().add(j);
          }
          singleton = new HNSet();
          singleton.add(population[i].getAllElementsOutputSet(j));
          population[i].setOutputSet(j, singleton);
        }

        if (geneticMiningMatrices.getEndMatrix().get(j) > 0) {
          // because this is the artificial END tasks....
          if (population[i].getEndTasks() == null) {
            HNSubSet endTasks = new HNSubSet();
            endTasks.add(j);
            population[i].setEndTasks(endTasks);
          } else {
            population[i].getEndTasks().add(j);
          }
          singleton = new HNSet();
          singleton.add(population[i].getAllElementsInputSet(j));
          population[i].setInputSet(j, singleton);
        }
      }

      // generate new matrices for next individual
      geneticMiningMatrices.rebuildAllMatrices();
    }

    return population;
  }
  private double checkIntersectingElements(
      HNSubSet[] duplicates, int[] duplicatesLabel, HNSet[] sets) {
    double structuralPunishment = 0;

    for (int i = 0; i < duplicates.length; i++) {
      // creating the counter for the intersections...
      int[] intersection = new int[duplicates.length];

      if (duplicates[i].size() > 1) { // the element has duplicates...
        for (int k = 0; k < duplicates[i].size(); k++) {
          int[] union =
              mapToDuplicateLabel(duplicatesLabel, HNSet.getUnionSet(sets[duplicates[i].get(k)]));
          for (int m = 0; m < union.length; m++) {
            intersection[union[m]]++;
          }
        }

        // add the partial punishment due to intersections...
        for (int j = 0; j < intersection.length; j++) {
          if (intersection[j] > 1) {
            structuralPunishment += intersection[j];
          }
        }
      }
    }

    return structuralPunishment;
  }