code: @Override
    protected List<S> reproduction(List<S> population) {
      int numberOfParents = crossoverOperator.getNumberOfRequiredParents() ;
  
      checkNumberOfParents(population, numberOfParents);
  
      List<S> offspringPopulation = new ArrayList<>(getMaxPopulationSize());
      for (int i = 0; i < getMaxPopulationSize(); i += numberOfParents) {
        List<S> parents = new ArrayList<>(numberOfParents);
        for (int j = 0; j < numberOfParents; j++) {
          parents.add(population.get(i+j));
        }
  
        List<S> offspring = crossoverOperator.execute(parents);
  
        for(S s: offspring){
          mutationOperator.execute(s);
          offspringPopulation.add(s);
        }
      }
      return offspringPopulation;
    }
docs: This methods iteratively applies a {@link CrossoverOperator} a  {@link MutationOperator} to the population to
  create the offspring population. The population size must be divisible by the number of parents required
  by the {@link CrossoverOperator}; this way, the needed parents are taken sequentially from the population.
  
  No limits are imposed to the number of solutions returned by the {@link CrossoverOperator}.
  
  @param population
  @return The new created offspring population