Creates a bunch of machines, runs them for a number of steps and then
    gives them a fitness score.  The best produce offspring that are passed on
    to the next generation.

    Args:
        setup: Function taking a Machine argument, makes the machine ready
        machine_class: A class that should inherit from Machine and contain the
        following methods:
            setUp(self) [optional]: Run before each new run, should at least
            call self.reset() for each run.

            tearDown(self) [optional]: Run after each run.

            crossover(self, other): Returns a Machine offspring between itself and
            another Machine.

            score(self):  Score the machine. Lower is better. Can return a
            tuple of values used to sort the machines from best to worst in
            fitness.

        stop_function: An optional function that takes the current generation
        number and returns True if the processing should stop.

        machines: The number of machines to create for each generation.

        steps: The number of instructions each machine is allowed to execute in
        each run.

        code_length: Tuple of (minimum code length, maximum code length) for a
        Machine.

        survival_ratio: Ratio of the best Machines which are allowed to produce
        offspring for the next generation.

        mutation_rate: Rate for each machine's chance of being mutated.

def iterate(MachineClass, stop_function=lambda iterations: iterations < 10000,
        machines=1000, survival_rate=0.05, mutation_rate=0.075, silent=False):
    """Creates a bunch of machines, runs them for a number of steps and then
    gives them a fitness score.  The best produce offspring that are passed on
    to the next generation.

    Args:
        setup: Function taking a Machine argument, makes the machine ready
        machine_class: A class that should inherit from Machine and contain the
        following methods:
            setUp(self) [optional]: Run before each new run, should at least
            call self.reset() for each run.

            tearDown(self) [optional]: Run after each run.

            crossover(self, other): Returns a Machine offspring between itself and
            another Machine.

            score(self):  Score the machine. Lower is better. Can return a
            tuple of values used to sort the machines from best to worst in
            fitness.

        stop_function: An optional function that takes the current generation
        number and returns True if the processing should stop.

        machines: The number of machines to create for each generation.

        steps: The number of instructions each machine is allowed to execute in
        each run.

        code_length: Tuple of (minimum code length, maximum code length) for a
        Machine.

        survival_ratio: Ratio of the best Machines which are allowed to produce
        offspring for the next generation.

        mutation_rate: Rate for each machine's chance of being mutated.
    """
    def make_random(n):
        return MachineClass().randomize()

    def run_once(m):
        m.setUp()
        m.run()
        m.tearDown()
        return m

    def make_offspring(survivors):
        a = stochastic_choice(survivors)
        b = stochastic_choice(survivors)
        return a.crossover(b)

    generation = map(make_random, xrange(machines))
    survivors = generation

    if silent:
        log = lambda s,stream=None: None
    else:
        log = _log

    try:
        iterations = 0
        while not stop_function(iterations, survivors):
            iterations += 1
            log("running ... ")

            # Run all machines in this generation
            generation = map(run_once, generation)

            # Sort machines from best to worst
            generation = sorted(generation, key=lambda m: m.score())

            # Select the best
            survivors = generation[:int(survival_rate * len(generation))]

            # Remove code larger than 50
            for s in survivors:
                if len(s.code) >= 50:
                    s.code = s.code[:50]

            # Remove dead ones
            survivors = [s for s in survivors if len(s.code)>0]

            #survivors = [s for s in survivors if len(s.code)<=50]
            # All dead? start with a new set
            if len(survivors) == 0:
                log("\nNo survivors, restarting")
                survivors = map(make_random, xrange(machines))
                generation = survivors
                continue

            # Create a new generation based on the survivors.
            log("crossover ... ")
            cross = lambda _: make_offspring(survivors)
            generation = map(cross, xrange(machines))

            # Add mutations from time to time
            for m in generation:
                if random.random() > mutation_rate:
                    m.mutate()

            log("\rgen %d 1-fitness %.12f avg code len %.2f avg stack len %.2f\n" %
                (iterations,
                 average(survivors, lambda m: m.score()),
                 average(survivors, lambda m: len(m.code)),
                 average(survivors, lambda m: len(m.stack) + len(m.return_stack))))
    except KeyboardInterrupt:
        pass

    return survivors