docs: def compare(optimizers, problems, runs=20, all_kwargs={}):
      """Compare a set of optimizers.
  
      Args:
          optimizers: list/Optimizer; Either a list of optimizers to compare,
              or a single optimizer to test on each problem.
          problems: list/Problem; Either a problem instance or a list of problem instances,
              one for each optimizer.
          all_kwargs: dict/list<dict>; Either the Optimizer.optimize keyword arguments
              for all optimizers, or a list of keyword arguments, one for each optimizer.
          runs: int; How many times to run each optimizer (smoothness)
  
      Returns:
          dict; mapping optimizer identifier to stats.
      """
      if not (isinstance(optimizers, collections.Iterable)
              or isinstance(problems, collections.Iterable)):
          raise TypeError('optimizers or problems must be iterable')
  
      # If optimizers is not a list, repeat into list for each problem
      if not isinstance(optimizers, collections.Iterable):
          optimizers = [copy.deepcopy(optimizers) for _ in range(len(problems))]
  
      # If problems is not a list, repeat into list for each optimizer
      if not isinstance(problems, collections.Iterable):
          problems = [copy.deepcopy(problems) for _ in range(len(optimizers))]
  
      # If all_kwargs is not a list, repeat it into a list
      if isinstance(all_kwargs, dict):
          all_kwargs = [all_kwargs] * len(optimizers)
      elif not isinstance(all_kwargs, collections.Iterable):
          raise TypeError('all_kwargs must be dict or list of dict')
  
      stats = {}
      key_counts = {}
      for optimizer, problem, kwargs in zip(optimizers, problems, all_kwargs):
          # For nice human readable dictionaries, extract useful names from
          # optimizer
          class_name = optimizer.__class__.__name__
          fitness_func_name = problem._fitness_function.__name__
          key_name = '{} {}'.format(class_name, fitness_func_name)
  
          # Keep track of how many optimizers of each class / fitness func
          # for better keys in stats dict
          try:
              key_counts[key_name] += 1
          except KeyError:
              key_counts[key_name] = 1
  
          # Foo 1, Foo 2, Bar 1, etc.
          key = '{} {}'.format(key_name, key_counts[key_name])
  
          print key + ': ',
  
          # Finally, get the actual stats
          stats[key] = benchmark(optimizer, problem, runs=runs, **kwargs)
  
          print
  
      return stats