def calc_homogeneity_l2(agent_stats, skill_headers=None, verbose=False, pop=None, punish_youth=True):
    'Use L2 distance to punish agents for having high mean pairwise distance. Optimal state is all agents at the same\n   point in skill-space, with maximal lifespans.'
    if ('skills' not in agent_stats):
        raise Exception('We should be including dead agents in this calculation, so we should get at least some skill stats back here')
    agent_skills = get_pop_stats(agent_stats['skills'], pop)
    lifespans = get_pop_stats(agent_stats['lifespans'], pop)
    assert (len(agent_skills) == len(lifespans))
    if punish_youth:
        agent_skills = expand_by_lifespan(agent_skills, lifespans)
    n_agents = agent_skills.shape[0]
    a = agent_skills
    b = a.reshape(n_agents, 1, a.shape[1])
    distances = np.sqrt(np.einsum('ijk, ijk->ij', (a - b), (a - b)))
    score = (np.sum(distances) / (n_agents ** 2))
    if verbose:
        print('agent skills:\n{}'.format(a.transpose()))
        print('lifespans:\n{}'.format(lifespans))
        print('score:\n{}\n'.format(score))
    return (- score)
Use L2 distance to punish agents for having high mean pairwise distance. Optimal state is all agents at the same
point in skill-space, with maximal lifespans.
def calc_homogeneity_l2(agent_stats, skill_headers=None, verbose=False, pop=None, punish_youth=True):
    'Use L2 distance to punish agents for having high mean pairwise distance. Optimal state is all agents at the same\n   point in skill-space, with maximal lifespans.'
    if ('skills' not in agent_stats):
        raise Exception('We should be including dead agents in this calculation, so we should get at least some skill stats back here')
    agent_skills = get_pop_stats(agent_stats['skills'], pop)
    lifespans = get_pop_stats(agent_stats['lifespans'], pop)
    assert (len(agent_skills) == len(lifespans))
    if punish_youth:
        agent_skills = expand_by_lifespan(agent_skills, lifespans)
    n_agents = agent_skills.shape[0]
    a = agent_skills
    b = a.reshape(n_agents, 1, a.shape[1])
    distances = np.sqrt(np.einsum('ijk, ijk->ij', (a - b), (a - b)))
    score = (np.sum(distances) / (n_agents ** 2))
    if verbose:
        print('agent skills:\n{}'.format(a.transpose()))
        print('lifespans:\n{}'.format(lifespans))
        print('score:\n{}\n'.format(score))
    return (- score)