docs: def genetic(problem, population_size=100, mutation_chance=0.1,
              iterations_limit=0, viewer=None):
      '''
      Genetic search.
  
      population_size specifies the size of the population (ORLY).
      mutation_chance specifies the probability of a mutation on a child,
      varying from 0 to 1.
      If iterations_limit is specified, the algorithm will end after that
      number of iterations. Else, it will continue until it can't find a
      better node than the current one.
      Requires: SearchProblem.generate_random_state, SearchProblem.crossover,
      SearchProblem.mutate and SearchProblem.value.
      '''
      return _local_search(problem,
                           _create_genetic_expander(problem, mutation_chance),
                           iterations_limit=iterations_limit,
                           fringe_size=population_size,
                           random_initial_states=True,
                           stop_when_no_better=iterations_limit==0,
                           viewer=viewer)