硕士毕业论文的时候使用了遗传算法,所以研究了一段时间,曾经用Python写一个简单的遗传算法,好自己拿来实验。整个代码还是仿照《游戏编程中的人工智能技术》中的代码来写的。如果想简单的学习一下遗传算法以及简单应用《游戏编程中的人工智能技术》是不错的选择。代码如下面所附。
我写了一个简单的测试函数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的书上的算法似乎有点问题,另外似乎变异操作也有点问题,变异我现在只是变异一处,而原书上则是每一处都根据变异率来进行变异。
种群要设置的稍微大点,太小了没效果。变异率也要大一点。
另外,测试函数里的解空间比较小,还有就是终止条件目前仅判断代数是否超过了设置的最大代数,我想还应该在判断适应性分数最高的地方设置终止条件。这样就避免了多余的运算
[code lang="python"]
# -*- coding:utf-8 -*-
# file: GA.py
# date: 2011-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:
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()
[/code]