docs: def plot_observer(population, num_generations, num_evaluations, args):    
      """Plot the output of the evolutionary computation as a graph.
      
      This function plots the performance of the EC as a line graph 
      using matplotlib and numpy. The graph consists of a blue line 
      representing the best fitness, a green line representing the 
      average fitness, and a red line representing the median fitness.
      It modifies the keyword arguments variable 'args' by including an
      entry called 'plot_data'.
      
      If this observer is used, the calling script should also import
      the matplotlib library and should end the script with::
      
          matplotlib.pyplot.show()
      
      Otherwise, the program may generate a runtime error.
      
      .. note::
      
         This function makes use of the matplotlib and numpy libraries.
      
      .. 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
      
      """
      import matplotlib.pyplot as plt
      import numpy
      
      stats = inspyred.ec.analysis.fitness_statistics(population)
      best_fitness = stats['best']
      worst_fitness = stats['worst']
      median_fitness = stats['median']
      average_fitness = stats['mean']
      colors = ['black', 'blue', 'green', 'red']
      labels = ['average', 'median', 'best', 'worst']
      data = []
      if num_generations == 0:
          plt.ion()
          data = [[num_evaluations], [average_fitness], [median_fitness], [best_fitness], [worst_fitness]]
          lines = []
          for i in range(4):
              line, = plt.plot(data[0], data[i+1], color=colors[i], label=labels[i])
              lines.append(line)
          # Add the legend when the first data is added.
          plt.legend(loc='lower right')
          args['plot_data'] = data
          args['plot_lines'] = lines
          plt.xlabel('Evaluations')
          plt.ylabel('Fitness')
      else:
          data = args['plot_data']
          data[0].append(num_evaluations)
          data[1].append(average_fitness)
          data[2].append(median_fitness)
          data[3].append(best_fitness)
          data[4].append(worst_fitness)
          lines = args['plot_lines']
          for i, line in enumerate(lines):
              line.set_xdata(numpy.array(data[0]))
              line.set_ydata(numpy.array(data[i+1]))
          args['plot_data'] = data
          args['plot_lines'] = lines
      ymin = min([min(d) for d in data[1:]])
      ymax = max([max(d) for d in data[1:]])
      yrange = ymax - ymin
      plt.xlim((0, num_evaluations))
      plt.ylim((ymin - 0.1*yrange, ymax + 0.1*yrange))
      plt.draw()