code: def _new_population_genalg(population,
                             fitnesses,
                             mutation_chance=0.02,
                             crossover_chance=0.7,
                             selection_function=gaoperators.tournament_selection,
                             crossover_function=gaoperators.one_point_crossover):
      
      # Selection
      # Create the population of parents that will be crossed and mutated.
      intermediate_population = selection_function(population, fitnesses)
  
      # Crossover
      new_population = _crossover(intermediate_population, crossover_chance,
                                  crossover_function)
  
      # Mutation
      # Mutates chromosomes in place
      gaoperators.random_flip_mutate(new_population, mutation_chance)
  
      # Return new population
      return new_population
docs: Perform all genetic algorithm operations on a population, and return a new population.
  
      population must have an even number of chromosomes.
  
      Args:
          population: A list of binary lists, ex. [[0,1,1,0], [1,0,1,0]]
          fitness: A list of fitnesses that correspond with chromosomes in the population,
                   ex. [1.2, 10.8]
          mutation_chance: the chance that a bit will be flipped during mutation
          crossover_chance: the chance that two parents will be crossed during crossover
          selection_function: A function that will select parents for crossover and mutation
          crossover_function: A function that will cross two parents
  
      Returns:
          list; A new population of chromosomes, that should be more fit.