def calculate_inequality(districts, lookup):
    """
    Calculate spatial inequality based on a school/district assignment and
    defined districts' neighborhoods, following the (latex) definition:

    \\[
    \\frac{
        \\sum_{j=1}^{N} \\sum_{i=1}^{N} \\left| y_i - y_j \\right|
    }{
        2 N \\sum_{i=1}^{N} y_i
    }
    \\]

    Args:
        districts (list of optimization.entity_nodes.District): List of all
            District instances.
        lookup (optimization.lookup.Lookup): Lookup instance for fast
            information querying.

    Returns:
        float: Spatial inequality for a school/district assignment.
    """
    get_per_student_funding = lambda district: district.get_total_funding() / district.get_total_students()
    abs_funding_diff = lambda x,y: abs(get_per_student_funding(x) - get_per_student_funding(y))
    overall_inequality = 0
    normalization_factor = 0
    for district in districts:
        neighboring_districts = lookup.get_neighboor_districts_by_district_id(district.get_id())
        full_neighborhood = [*neighboring_districts, district]
        ineq_contribution = sum(map(
            lambda x: abs_funding_diff(district, x),
            full_neighborhood
        ))
        overall_inequality += ineq_contribution / len(full_neighborhood)
        normalization_factor += get_per_student_funding(district)
    return overall_inequality / normalization_factor