読者です 読者をやめる 読者になる 読者になる

遺伝的アルゴリズムで遊ぶ 2

突然変異つけないと話にならないので、つけました。ようやくスタートライン一歩手前ですかね

# coding: utf-8
import random
import copy

generation = []
population_size = 10
chrom_size = 10
mutation_rate = 1 
def initialize():
    global population_size
    global generation
    for i in range(population_size):
       chrom = []
       for j in range(chrom_size):
            chrom.append(random.randint(0,1))
       generation.append(chrom)

def fitness(indiv):
    global population_size
    count = 0.0
    for x in indiv:
        if x==1: count+=1
    if count <= 5: return 0.5
    return count/population_size

# 一点交叉
def crossover(p1, p2):
    if len(p1)>len(p2): maximum = len(p2)-1
    else: maximum = len(p1) - 1
    point = random.randint(0,maximum)
    for i in range(point,maximum+1):
        x = p1[i]
        p1[i] = p2[i]
        p2[i] = x
    return p1, p2

# バブルソート
def calculate_fit():
    global generation
    k = len(generation) - 1
    for i in range(k):
        for j in xrange(k,i,-1):
            if fitness(generation[j-1])>fitness(generation[j]):
                t = generation[j-1]
                generation[j-1] = generation[j]
                generation[j] = t
            
        
def simple_crossover():
    global generation
    max = len(generation)-1
    select1 = random.randint(0,max)
    select2 = random.randint(0,max)
    while select1==select2:
        select2 = random.randint(0,max)
    p1 = generation[select1]
    p2 = generation[select2]
    p1,p2 = crossover(p1,p2)
    # fitnessの高い方を返す
    if fitness(p1)>fitness(p2): return p1
    return p2

def fitness_average():
    global generation
    global population_size
    total = 0.0
    for x in generation:
        total += fitness(x)
    return total / population_size

def dump_chrom(gene_count):
    global generation
    print "%d世代" % gene_count
    for x in generation:
        for y in x:
            print y,
        print 
    print "\n"

def mutation(p1,rate, num):
    if num > len(p1):num=len(p1)
    if (rate>1) or (rate<0): return
    if random.randint(0,100)/100.0 <= rate:
        for i in range(num):
            point = random.randint(0,len(p1)-1)
            p1[point] = random.randint(0,1)
    return p1

def simple_mutation():
    return mutation(copy.deepcopy(generation[population_size-1]), 0.91, 5)
    


def main():
    global generation
    global population_size
    global mutation_rate
    initialize()
    calculate_fit()
    for i in range(population_size):
        next_generation = []
        next_generation.append(copy.deepcopy(generation[population_size-1]))
        for j in range(population_size-1-mutation_rate):
            next_generation.append(simple_crossover())
        for k in range(j+1, population_size-1):
            next_generation.append(simple_mutation())
        generation = copy.deepcopy(next_generation)
        calculate_fit()
        for x in generation[population_size-1]:
            print x,
        print fitness_average()
        #dump_chrom(i)
        

if __name__ == '__main__':
    main()

まぁこの程度だと、あんまり違いが分かりませんが。

0 1 1 1 0 1 1 1 0 1 0.57
0 1 1 0 1 1 0 1 1 1 0.6
0 1 1 1 1 1 1 0 0 1 0.61
0 1 1 1 1 1 1 1 1 1 0.77
0 1 1 1 1 1 1 1 1 1 0.79
1 1 1 1 0 1 1 1 1 1 0.79
0 1 1 1 1 1 1 1 1 1 0.81
1 1 1 1 1 1 1 1 1 1 0.8
1 1 1 1 1 1 1 1 1 1 0.88
1 1 1 1 1 1 1 1 1 1 0.93

一番右の値は全体の個体の適応度の平均値です。