code: def _next_generation(self, sorted_trials):
          
  
          candidate = []
          next_generation = []
          num_population = self._next_population_size(len(sorted_trials))
          top_num = int(max(num_population * self._keep_top_ratio, 2))
  
          for i in range(top_num):
              candidate.append(sorted_trials[i].extra_arg)
              next_generation.append(sorted_trials[i].extra_arg)
  
          for i in range(top_num, num_population):
              flip_coin = np.random.uniform()
              if flip_coin < self._selection_bound:
                  next_generation.append(GeneticSearch._selection(candidate))
              else:
                  if flip_coin < self._selection_bound + self._crossover_bound:
                      next_generation.append(GeneticSearch._crossover(candidate))
                  else:
                      next_generation.append(GeneticSearch._mutation(candidate))
          return next_generation
docs: Generate genes (encodings) for the next generation.
  
          Use the top K (_keep_top_ratio) trials of the last generation
          as candidates to generate the next generation. The action could
          be selection, crossover and mutation according corresponding
          ratio (_selection_bound, _crossover_bound).
  
          Args:
              sorted_trials: List of finished trials with top
                  performance ones first.
  
          Returns:
              A list of new genes (encodings)