def execute_iterated(self, board, genetic_steps, hierarchical_steps = 10):

        first_boards = fill_steps(board, steps = 3)

        top_solution_boards = first_boards

        for i in range(hierarchical_steps):

            boards = top_solution_boards[:self.population_size]

            population = []
            for b in boards:
                population.extend(generate_population(b, self.population_size // len(boards)))

            population.extend(generate_population(boards[-1], self.population_size % len(boards)))

            (output_population, solution) = self.genetic.execute(population=population, steps=genetic_steps)

            if solution != None:
                return (output_population, solution)
            sort_by_fitness = lambda p: p.fitness if p.fitness is not None else 100
            top_solutions = sorted(output_population, key=sort_by_fitness, reverse = True)[:50]

            top_solutions_boards = [g.board.copy() for g in top_solutions]
            # Leave just the invariants
            for b in top_solutions_boards:
                for (r, row) in enumerate(b):
                    for (c, col) in enumerate(row):
                        b[r,c] = 0
                b.fix_invariants()
            top_solution_boards.extend(boards)

        return (output_population, solution)
    def execute(self, board, genetic_steps):

        boards = fill_steps(board, steps = 4)

        boards = boards[:self.population_size]

        population = []
        for b in boards:
            population.extend(generate_population(b, self.population_size // len(boards)))

        population.extend(generate_population(boards[-1], self.population_size % len(boards)))
        
        (output_population, solution) = self.genetic.execute(population=population, steps=genetic_steps)

        return (output_population, solution)