docs: def fitness_proportionate_selection(random, population, args):
      """Return fitness proportionate sampling of individuals from the population.
      
      This function stochastically chooses individuals from the population
      with probability proportional to their fitness. This is often 
      referred to as "roulette wheel" selection. Note that this selection
      is not valid for minimization problems.
      
      .. Arguments:
         random -- the random number generator object
         population -- the population of individuals
         args -- a dictionary of keyword arguments
  
      Optional keyword arguments in args:
      
      - *num_selected* -- the number of individuals to be selected (default 1)
      
      """
      num_selected = args.setdefault('num_selected', 1)
      len_pop = len(population)
      psum = [i for i in range(len_pop)]
      pop_max_fit = (max(population)).fitness
      pop_min_fit = (min(population)).fitness
      
      # If we're actually doing minimimization,
      # fitness proportionate selection is not defined.
      if pop_max_fit < pop_min_fit:
          raise ValueError('Fitness proportionate selection is not valid for minimization.')
      
      # Set up the roulette wheel
      if pop_max_fit == pop_min_fit:
          psum = [(index + 1) / float(len_pop) for index in range(len_pop)]
      elif (pop_max_fit > 0 and pop_min_fit >= 0) or (pop_max_fit <= 0 and pop_min_fit < 0):
          population.sort(reverse=True)
          psum[0] = population[0].fitness
          for i in range(1, len_pop):
              psum[i] = population[i].fitness + psum[i-1]
          for i in range(len_pop):
              psum[i] /= float(psum[len_pop-1])
              
      # Select the individuals
      selected = []
      for _ in range(num_selected):
          cutoff = random.random()
          lower = 0
          upper = len_pop - 1
          while(upper >= lower):
              mid = (lower + upper) // 2
              if psum[mid] > cutoff: 
                  upper = mid - 1
              else: 
                  lower = mid + 1
          lower = max(0, min(len_pop-1, lower))
          selected.append(population[lower])
      return selected