docs: def _create_genetic_expander(problem, mutation_chance):
      '''
      Creates an expander that expands the bests nodes of the population,
      crossing over them.
      '''
      def _expander(fringe, iteration, viewer):
          fitness = [x.value for x in fringe]
          sampler = InverseTransformSampler(fitness, fringe)
          new_generation = []
  
          expanded_nodes = []
          expanded_neighbors = []
  
          for _ in fringe:
              node1 = sampler.sample()
              node2 = sampler.sample()
              child = problem.crossover(node1.state, node2.state)
              action = 'crossover'
              if random.random() < mutation_chance:
                  # Noooouuu! she is... he is... *IT* is a mutant!
                  child = problem.mutate(child)
                  action += '+mutation'
  
              child_node = SearchNodeValueOrdered(state=child, problem=problem, action=action)
              new_generation.append(child_node)
  
              expanded_nodes.append(node1)
              expanded_neighbors.append([child_node])
              expanded_nodes.append(node2)
              expanded_neighbors.append([child_node])
  
          if viewer:
              viewer.event('expanded', expanded_nodes, expanded_neighbors)
  
          fringe.clear()
          for node in new_generation:
              fringe.append(node)
  
      return _expander