def fitness_statistics(population):
    """Return the basic statistics of the population's fitness values.
    
    This function returns a dictionary containing the "best", "worst",
    "mean", "median", and "std" fitness values in the population.
    ("std" is the standard deviation.) A typical usage would be similar
    to the following::
    
       stats = fitness_statistics(population)
       print(stats['best'])
       print(stats['worst'])
       print(stats['mean'])
       print(stats['median'])
       print(stats['std'])
    
    .. note::
    
       This function makes use of the numpy library for calculations. If that
       library is not found, it attempts to complete the calculations 
       internally. However, this second attempt will fail for multiobjective
       fitness values and will return ``nan`` for the mean, median, and 
       standard deviation.
    
    Arguments:
    
    - *population* -- the population of individuals 

    """
    population.sort(reverse=True)
    worst_fit = population[-1].fitness
    best_fit = population[0].fitness
    try:
        import numpy
        f = [p.fitness for p in population]
        med_fit = numpy.median(f)
        avg_fit = numpy.mean(f)
        std_fit = numpy.std(f)
    except ImportError:
        try:
            plen = len(population)
            if plen % 2 == 1:
                med_fit = population[(plen - 1) // 2].fitness
            else:
                med_fit = float(population[plen // 2 - 1].fitness + population[plen // 2].fitness) / 2
            avg_fit = sum([p.fitness for p in population]) / float(plen)
            if plen > 1:
                std_fit = math.sqrt(sum([(p.fitness - avg_fit)**2 for p in population]) / float(plen - 1))
            else:
                std_fit = 0
        except TypeError:
            med_fit = float('nan')
            avg_fit = float('nan')
            std_fit = float('nan')
    return {'best': best_fit, 'worst': worst_fit, 'mean': avg_fit, 
            'median': med_fit, 'std': std_fit}