docs: def adaptive_grid_archiver(random, population, archive, args):
      """Archive only the best individual(s) using a fixed size grid.
      
      This function archives the best solutions by using a fixed-size grid
      to determine which existing solutions should be removed in order to
      make room for new ones. This archiver is designed specifically for
      use with the Pareto Archived Evolution Strategy (PAES).
  
      .. Arguments:
         random -- the random number generator object
         population -- the population of individuals
         archive -- the current archive of individuals
         args -- a dictionary of keyword arguments
  
      Optional keyword arguments in args:
      
      - *max_archive_size* -- the maximum number of individuals in the archive
        (default len(population))
      - *num_grid_divisions* -- the number of grid divisions (default 1)
      
      """
      def get_grid_location(fitness, num_grid_divisions, global_smallest, global_largest):
          loc = 0
          n = 1
          num_objectives = len(fitness)
          inc = [0 for _ in range(num_objectives)]
          width = [0 for _ in range(num_objectives)]
          local_smallest = global_smallest[:]
          for i, f in enumerate(fitness):
              if f < local_smallest[i] or f > local_smallest[i] + global_largest[i] - global_smallest[i]:
                  return -1
          for i in range(num_objectives):
              inc[i] = n
              n *= 2
              width[i] = global_largest[i] - global_smallest[i]
          for d in range(num_grid_divisions):
              for i, f in enumerate(fitness):
                  if f < width[i] / 2.0 + local_smallest[i]:
                      loc += inc[i]
                  else:
                      local_smallest[i] += width[i] / 2.0
              for i in range(num_objectives):
                  inc[i] *= num_objectives * 2
                  width[i] /= 2.0
          return loc
   
      def update_grid(individual, archive, num_grid_divisions, global_smallest, global_largest, grid_population):
          if len(archive) == 0:
              num_objectives = len(individual.fitness)
              smallest = [individual.fitness[o] for o in range(num_objectives)]
              largest = [individual.fitness[o] for o in range(num_objectives)]
          else:
              num_objectives = min(min([len(a.fitness) for a in archive]), len(individual.fitness))
              smallest = [min(min([a.fitness[o] for a in archive]), individual.fitness[o]) for o in range(num_objectives)] 
              largest = [max(max([a.fitness[o] for a in archive]), individual.fitness[o]) for o in range(num_objectives)]
          for i in range(num_objectives):
              global_smallest[i] = smallest[i] - abs(0.2 * smallest[i])
              global_largest[i] = largest[i] + abs(0.2 * largest[i])
          for i in range(len(grid_population)):
              grid_population[i] = 0
          for a in archive:
              loc = get_grid_location(a.fitness, num_grid_divisions, global_smallest, global_largest)
              a.grid_location = loc
              grid_population[loc] += 1
          loc = get_grid_location(individual.fitness, num_grid_divisions, global_smallest, global_largest)
          individual.grid_location = loc
          grid_population[loc] += 1
  
      max_archive_size = args.setdefault('max_archive_size', len(population))
      num_grid_divisions = args.setdefault('num_grid_divisions', 1)
          
      if not 'grid_population' in dir(adaptive_grid_archiver):
          adaptive_grid_archiver.grid_population = [0 for _ in range(2**(min([len(p.fitness) for p in population]) * num_grid_divisions))]
      if not 'global_smallest' in dir(adaptive_grid_archiver):
          adaptive_grid_archiver.global_smallest = [0 for _ in range(min([len(p.fitness) for p in population]))]
      if not 'global_largest' in dir(adaptive_grid_archiver):
          adaptive_grid_archiver.global_largest = [0 for _ in range(min([len(p.fitness) for p in population]))]
       
      new_archive = archive
      for ind in population:
          update_grid(ind, new_archive, num_grid_divisions, adaptive_grid_archiver.global_smallest, 
                      adaptive_grid_archiver.global_largest, adaptive_grid_archiver.grid_population)
          should_be_added = True
          for a in new_archive:
              if ind == a or a > ind:
                  should_be_added = False
                  
          if should_be_added:
              if len(new_archive) == 0:
                  new_archive.append(ind)
              else:
                  join = False
                  nondominated = True
                  removal_set = []
                  for i, a in enumerate(new_archive):
                      if ind > a and not join:
                          new_archive[i] = ind
                          join = True
                      elif ind > a:
                          if not a in removal_set: 
                              removal_set.append(a)
                      # Otherwise, the individual is nondominated against this archive member.
                      
                  # We can't use set difference because Individual objects are not hashable.
                  # We'd like to say...
                  #     new_archive = list(set(new_archive) - set(removal_set))
                  # So this code gets that same result without using sets.
                  temp_archive = []
                  for ind in new_archive:
                      if ind not in removal_set:
                          temp_archive.append(ind)
                  new_archive = temp_archive
                  
                  if not join and nondominated:
                      if len(new_archive) == max_archive_size:
                          replaced_index = 0
                          found_replacement = False
                          loc = get_grid_location(ind.fitness, num_grid_divisions, 
                                                  adaptive_grid_archiver.global_smallest, 
                                                  adaptive_grid_archiver.global_largest)
                          ind.grid_location = loc
                          if ind.grid_location >= 0:
                              most = adaptive_grid_archiver.grid_population[ind.grid_location]
                          else:
                              most = -1
                          for i, a in enumerate(new_archive):
                              pop_at_a = adaptive_grid_archiver.grid_population[a.grid_location]
                              if pop_at_a > most:
                                  most = pop_at_a
                                  replaced_index = i
                                  found_replacement = True
                          if found_replacement:
                              new_archive[replaced_index] = ind
                      else:
                          new_archive.append(ind)
      return new_archive