code: def assignCrowdingDist(individuals):
      """Assign a crowding distance to each individual's fitness. The
      crowding distance can be retrieve via the :attr:`crowding_dist`
      attribute of each individual's fitness.
      """
      if len(individuals) == 0:
          return
  
      distances = [0.0] * len(individuals)
      crowd = [
          (ind.fitness.values, i) for i, ind in enumerate(individuals)
      ]
  
      nobj = len(individuals[0].fitness.values)
  
      for i in range(nobj):
          crowd.sort(key=lambda element: element[0][i])
          distances[crowd[0][1]] = float("inf")
          distances[crowd[-1][1]] = float("inf")
          if crowd[-1][0][i] == crowd[0][0][i]:
              continue
          norm = nobj * float(crowd[-1][0][i] - crowd[0][0][i])
          for prev, cur, next in zip(
              crowd[:-2], crowd[1:-1], crowd[2:]
          ):
              distances[cur[1]] += (next[0][i] - prev[0][i]) / norm
  
      for i, dist in enumerate(distances):
          individuals[i].fitness.crowding_dist = dist
  
imports: import bisect
  from collections import defaultdict, namedtuple
  from itertools import chain
  import math
  from operator import attrgetter, itemgetter
  import random
  import numpy
label_desc: Use image node_id 3 for calling a global function with example usage: assignCrowdingDist(individuals) without return types