用Python实现简单的遗传算法

用Python实现简单的遗传算法
2010-02-15 14:00
这几天一直在用Python写一个简单的遗传算法,好自己拿来实验。断断续续的折腾了几天,今天下午终于写了一个简单的出来。整个代码还是仿照《游戏编程中的人工智能技术》中的代码来写的。如果想简单的学习一下遗传算法以及简单应用《游戏编程中的人工智能技术》是不错的选择。电子版及源代码可以参照找个网址: http://download.csdn.net/source/337118
代码如下( 点击这里下载):

# -*- coding:utf-8 -*-
# file: GA.py
#   by: bluebanboom                 0(0
# mail: bluebanboom@gmail.com       ~
# date: 2008-10-22
# note:
import random

class genome:
        def __init__(self, length = 0):
                 self.fitness = 0
                 self.bits = []
                for i in range(length):
                         self.bits.append(random.randint(0, 1))

class ga:
        """
         simple Genetic Algorithms by bluebanboom
         reference:
         AI Techniques for Game Programming
        """
        def __init__(self,
                         pop_size,
                         genome_len,
                         expr = 'y = 0 - 2 * x * x + 8 * x + 4',
                         crossover_rate = 0.7,
                         mutation_rate = 0.01,
                         max_generation = 1000
                         ):

                 self.crossover_rate = crossover_rate
                 self.mutation_rate = mutation_rate
                 self.pop_size = pop_size
                 self.genome_len = genome_len
                 self.generation = 0
                 self.genomes = []
                 self.busy = False
                 self.fittest_genome = genome()
                 self.best_fitness_score = 0
                 self.total_fitness_score = 0
                 self.expr = expr
                 self.max_generation = max_generation

        def create_start_populations(self):
                del self.genomes[0:]
                for i in range(self.pop_size):
                         self.genomes.append(genome(self.genome_len))
                 self.generation = 0
                 self.best_fitness_score = 0
                 self.total_fitness_score = 0

        def selection(self):
                 f_slice = random.uniform(0, 1) * self.total_fitness_score
                 c_f_slice = 0.0
                 selected_genome = 0
                for i in range(self.pop_size):
                         c_f_slice = c_f_slice + self.genomes[i].fitness
                        if c_f_slice > f_slice:
                                 selected_genome = i
                                break
                return self.genomes[i]

        def crossover(self, mum, dad):
                 baby1 = []
                 baby2 = []
                if (random.uniform(0, 1) > self.crossover_rate):
                         baby1 = mum.bits;
                         baby2 = dad.bits;
                        return baby1, baby2
                 cp = random.randint(0, self.genome_len - 1)
                for i in range(cp):
                         baby1.append(mum.bits[i])
                         baby2.append(dad.bits[i])

                for i in range(cp, self.genome_len):
                         baby1.append(dad.bits[i])
                         baby2.append(mum.bits[i])
                return baby1, baby2
        
        def mutate(self, bits):
                if (random.uniform(0, 1) < self.mutation_rate):
                         mp = random.randint(0, self.genome_len - 1)
                         bits[mp] = int(not bits[mp])
        
        def decode(self, gen):
                 x = self.bin2int(gen)
                exec(self.expr)
                return y

        def bin2int(self, lists):
                 m = 1
                 r = 0
                 lists.reverse()
                for i in range(len(lists)):
                         r = r + m * lists[i]
                         m = m * 2
                 lists.reverse()
                return r

        def update_fitness_scores(self):
                 self.total_fitness_score = 0
                for i in range(self.pop_size):
                         self.genomes[i].fitness = self.decode(self.genomes[i].bits)
                         self.total_fitness_score += self.genomes[i].fitness
                        if self.genomes[i].fitness > self.best_fitness_score:
                                 self.best_fitness_score = self.genomes[i].fitness
                                 self.fittest_genome = self.genomes[i]

        def epoch(self):
                 self.update_fitness_scores()
                 new_babies = 0
                 baby_genomes = []
                 baby1 = genome()
                 baby2 = genome()
                while (new_babies < self.pop_size):
                         mum = self.selection()
                         dad = self.selection()
                         baby1.bits, baby2.bits = self.crossover(mum, dad)
                         self.mutate(baby1.bits)
                         self.mutate(baby2.bits)
                         baby_genomes.append(baby1)
                         baby_genomes.append(baby2)
                         new_babies = new_babies + 2
                 self.genomes = baby_genomes
                 self.generation += 1
                if self.generation >= self.max_generation:
                         self.busy = False
        
        def start(self):
                 self.busy = True
                 self.create_start_populations()

        def get_best_genome(self):
                return self.fittest_genome.bits

        def get_best_variable(self):
                return self.bin2int(self.fittest_genome.bits)

        def get_max_value(self):
                return self.decode(self.fittest_genome.bits)
def main():
        print "-----------------"
         testga = ga(pop_size = 8, genome_len = 4, expr = 'y = 0 - 2 * x * x + 12 * x + 5')
         testga.start()
        while testga.busy:
                 testga.epoch()
        print "Function: %s" % testga.expr
        print "The best genome is: ",
        print testga.get_best_genome()
        print "The variable is: %d" % testga.get_best_variable()
        print "The max value is %d" % testga.get_max_value()
        del testga
        print "-----------------"
         testga = ga(pop_size = 8, genome_len = 4)
         testga.start()
        while testga.busy:
                 testga.epoch()
        print "Function: %s" % testga.expr
        print "The best genome is: ",
        print testga.get_best_genome()
        print "The variable is: %d" % testga.get_best_variable()
        print "The max value is %d" % testga.get_max_value()
        print "-----------------"
if __name__ == '__main__':
         main()

############################################
我写了一个简单的测试函数main
运行后多数情况下会产生如下输出
-----------------
Function: y = 0 - 2 * x * x + 12 * x + 5
The best genome is: [0, 0, 1, 1]
The variable is: 3
The max value is 23
-----------------
Function: y = 0 - 2 * x * x + 8 * x + 4
The best genome is: [0, 0, 1, 0]
The variable is: 2
The max value is 12
-----------------
以y = 0 - 2 * x * x + 8 * x + 4为例,在Matlab中画出该函数的曲线如下图所示:

可以看到该函数的极值点确实在x = 2处,证明算法还是相当成功的。
因为写的测试算法主要针对求函数的极大值,如果是求函数极小值可以乘上-1就OK了。
其实上边的函数,乘上-1,然后求导也可以知道极值为x=8/4=2,这是极小值,乘上-1就得极大值了。

算是初步改写成功了,当然还有很多问题,比如选择时用的轮盘赌,但是AI的书上的算法似乎有点问题,另外似乎变异操作也有点问题,变异我现在只是变异一处,而原书上则是每一处都根据变异率来进行变异。

种群要设置的稍微大点,太小了没效果。变异率也要大一点。

另外,测试函数里的解空间比较小,还有就是终止条件目前仅判断代数是否超过了设置的最大代数,我想还应该在判断适应性分数最高的地方设置终止条件。这样就避免了多余的运算
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值