docs: def file_observer(population, num_generations, num_evaluations, args):
      """Print the output of the evolutionary computation to a file.
      
      This function saves the results of the evolutionary computation
      to two files. The first file, which by default is named 
      'inspyred-statistics-file-<timestamp>.csv', contains the basic
      generational statistics of the population throughout the run
      (worst, best, median, and average fitness and standard deviation
      of the fitness values). The second file, which by default is named
      'inspyred-individuals-file-<timestamp>.csv', contains every individual
      during each generation of the run. Both files may be passed to the
      function as keyword arguments (see below).
      
      The format of each line of the statistics file is as follows::
      
         generation number, population size, worst, best, median, average, standard deviation
  
      The format of each line of the individuals file is as follows::
      
         generation number, individual number, fitness, string representation of candidate
      
      .. note::
      
         This function makes use of the ``inspyred.ec.analysis.fitness_statistics`` 
         function, so it is subject to the same requirements.
      
      .. Arguments:
         population -- the population of Individuals
         num_generations -- the number of elapsed generations
         num_evaluations -- the number of candidate solution evaluations
         args -- a dictionary of keyword arguments
  
      Optional keyword arguments in args:
      
      - *statistics_file* -- a file object (default: see text)
      - *individuals_file* -- a file object (default: see text) 
      
      """
      try:
          statistics_file = args['statistics_file']
      except KeyError:
          statistics_file = open('inspyred-statistics-file-{0}.csv'.format(time.strftime('%m%d%Y-%H%M%S')), 'w')
          args['statistics_file'] = statistics_file
      try:
          individuals_file = args['individuals_file']
      except KeyError:
          individuals_file = open('inspyred-individuals-file-{0}.csv'.format(time.strftime('%m%d%Y-%H%M%S')), 'w')
          args['individuals_file'] = individuals_file
  
      stats = inspyred.ec.analysis.fitness_statistics(population)
      worst_fit = stats['worst']
      best_fit = stats['best']
      avg_fit = stats['mean']
      med_fit = stats['median']
      std_fit = stats['std']
      
      statistics_file.write('{0}, {1}, {2}, {3}, {4}, {5}, {6}\n'.format(num_generations, len(population), worst_fit, best_fit, med_fit, avg_fit, std_fit))
      for i, p in enumerate(population):
          individuals_file.write('{0}, {1}, {2}, {3}\n'.format(num_generations, i, p.fitness, str(p.candidate)))
      statistics_file.flush()
      individuals_file.flush()