docs: def n_point_crossover(random, mom, dad, args):
      """Return the offspring of n-point crossover on the candidates.
  
      This function performs n-point crossover (NPX). It selects *n* 
      random points without replacement at which to 'cut' the candidate 
      solutions and recombine them.
  
      .. Arguments:
         random -- the random number generator object
         mom -- the first parent candidate
         dad -- the second parent candidate
         args -- a dictionary of keyword arguments
  
      Optional keyword arguments in args:
      
      - *crossover_rate* -- the rate at which crossover is performed 
        (default 1.0)
      - *num_crossover_points* -- the number of crossover points used (default 1)
      
      """
      crossover_rate = args.setdefault('crossover_rate', 1.0)
      num_crossover_points = args.setdefault('num_crossover_points', 1)
      children = []
      if random.random() < crossover_rate:
          num_cuts = min(len(mom)-1, num_crossover_points)
          cut_points = random.sample(range(1, len(mom)), num_cuts)
          cut_points.sort()
          bro = copy.copy(dad)
          sis = copy.copy(mom)
          normal = True
          for i, (m, d) in enumerate(zip(mom, dad)):
              if i in cut_points:
                  normal = not normal
              if not normal:
                  bro[i] = m
                  sis[i] = d
                  normal = not normal
          children.append(bro)
          children.append(sis)
      else:
          children.append(mom)
          children.append(dad)
      return children