Genetic algorithm in Python that plots its evolution After programming in Haskell for a while, I've gotten attached to a functional style.  This is clearly evident in the code for my genetic algorithm. 

Could you provide me with some hints as to how I can make this code more pythonic?  By that, I mean provide some method of organisation rather than throwing a bunch of functions around.  Any other recommendations are also welcome.

import copy
import matplotlib.pyplot as pyplot
import random


def create_member(genes):
    return (sum(genes), genes)


def shuffle(pool):
    pool_shuffled = copy.deepcopy(pool)
    random.shuffle(pool_shuffled)
    return pool_shuffled


def calculate_pool_fitness(pool):
    return sum([member[0] for member in pool])


def calculate_member_fitness(member):
    return sum(member[1])


def recalculate_fitneses(pool):
    return [(calculate_member_fitness(member), member[1]) for member in pool]


def select_members_roulette(pool, count):
    selection = []
    while len(selection) &lt; count:
        member = select_member_roulette(pool)
        selection.append(copy.deepcopy(pool[member]))
    return selection


def select_member_roulette(pool):
    drop = random.randint(0, calculate_pool_fitness(pool))
    total_fitness = 0
    for member in range(0, len(pool)):
        total_fitness += pool[member][0]
        if total_fitness &gt;= drop:
            return member


def mutate_gene(gene, rate=1):
    return 1 - gene if random.random() &lt;= rate else gene


def mutate_genes(genes, rate=1):
    return [mutate_gene(gene, rate) for gene in genes]


def mutate_member(member, rate=1):
    return member[0], mutate_genes(member[1], rate)


def mutate_pool(pool, rate=1):
    return [mutate_member(member, rate) for member in pool]


def create_random_gene():
    return random.choice([0, 1])


def create_random_genes(size):
    return [create_random_gene() for _ in range(size)]


def crossover_genes(mother, father, rate=1):
    if random.random() &lt;= rate:
        split = random.randint(1, len(mother))
        daughter = mother[:split] + father[split:]
        son = father[:split] + mother[split:]
    else:
        daughter = copy.deepcopy(mother)
        son = copy.deepcopy(father)
    return daughter, son


def crossover_members(mother, father, rate=1):
    daughter_genes, son_genes = crossover_genes(mother[1], father[1])
    return [(mother[0], daughter_genes), (father[0], son_genes)]


def crossover_pool(pool, rate=1):
    children = []

    # select every two elements for crossover
    for mother, father in zip(pool[::2], pool[1::2]):
        children.extend(crossover_members(mother, father, rate))

    return children


def generate_pool(size, gene_size):
    pool = []
    for member in range(0, size):
        genes = create_random_genes(gene_size)
        pool.append(create_member(genes))
    return pool


def evolve(pool, rate_crossover=0.9, rate_mutation=0.01):
    successors = copy.deepcopy(pool)

    # perform roulette selection whilst keeping best member
    member_alpha = copy.deepcopy(max(successors, key=lambda member: member[0]))
    successors = select_members_roulette(pool, len(pool) - 1)
    successors.append(member_alpha)

    successors = shuffle(successors)
    successors = crossover_pool(successors, rate_crossover)
    successors = mutate_pool(successors, rate_mutation)
    successors = recalculate_fitneses(successors)
    return successors


def main():
    random.seed
    pyplot.figure(figsize=(14, 8), dpi=400)
    axgraph=pyplot.subplot(111)
    pool_size = 50
    gene_size = 50
    generations = 100
    pool = generate_pool(pool_size, gene_size)
    for generation in range(0, generations):
        pool = evolve(pool)
        axgraph.scatter(generation, sum([member[0] for member in pool]))
    pyplot.grid(True)
    pyplot.axis([0, generations, 0, pool_size * gene_size])
    pyplot.savefig('genetic_algorithms.png')

main()

if __name__ == '__main__':
    main()
random.seed is a bug: add parentheses to actually call the function.
Use collections.namedtuple so you can write member.fitness instead of the less readable member[0]
copy.deepcopy should not be necessary in a functional approach
Keeping the genes in a tuple instead of a list would make the member tuple fully immutable, in line with the functional approach. This eliminates the need to deep-copy objects as you can safely copy just references.


After these changes create_member becomes like this:

import collections
Member = collections.namedtuple("Member", "fitness genes")

def create_member(genes):
    genes = tuple(genes)
    return Member(sum(genes), genes)


In some places you create members without calling create_member. Be sure to change them, for example:

def mutate_member(member, rate=1):
    return create_member(mutate_genes(member.genes, rate))



With immutable members there is no need to recalculate fitnesses. You can delete such functions.