遗传算法是模拟生物变异进化的算法。抽象一下生物的进化:生物的所有性状由DNA决定,DNA在换代(繁殖)的过程中产生变异和交换,形成新的DNA序列。而生物的适应性由性状决定。
过程(from:百度百科):
a)初始化:设置进化代数计数器t=0,设置最大进化代数T,随机生成M个个体作为初始群体P(0)。
b)个体评价:计算群体P(t)中各个个体的适应度。
c)选择运算:将选择算子作用于群体。选择的目的是把优化的个体直接遗传到下一代或通过配对交叉产生新的个体再遗传到下一代。选择操作是建立在群体中个体的适应度评估基础上的。
d)交叉运算:将交叉算子作用于群体。遗传算法中起核心作用的就是交叉算子。
e)变异运算:将变异算子作用于群体。即是对群体中的个体串的某些基因座上的基因值作变动。
群体P(t)经过选择、交叉、变异运算之后得到下一代群体P(t+1)。
f)终止条件判断:若t=T,则以进化过程中所得到的具有最大适应度个体作为最优解输出,终止计算。
所以对于GA中变异这一步,完全的随机性,虽然能够保证对问题的最小假设,但是会导致进化过于盲目。所以我想可以在上下代之间传递fitness和突变的基因,在下一代进行突变时,使用不同的概率对待不同方向的突变。这个有点像蚁群在GA上的移植。把蚁群中,个体对于附近环境的感知和傻傻的随机决策放到个体突变的过程中。
普通GA的代码:
t = 0
T = 10
spieces = [[1, 2],\
[2, 3],\
[3, 4],\
[4, 5],\
[5, 6]]
def target(params):
return params[0] * params[0] + params[1] * params[1]
def fitness(params):
return 10 - target(params)
def live(spieces):
import random
probs = roulette(spieces)
lefts = []
idx = 0
for p in probs:
r = random.random()
if ( r < p ):
lefts.append(spieces[idx])
return lefts
def roulette(spieces):
idx = 0
total = 0
prob = []
for params in spieces:
p = fitness( params )
total = total + p
prob.append(p)
idx = idx + 1
idx = 0
for p in prob:
prob[idx] = p/total
idx = idx + 1
return prob
def mutate(spieces, count):
import copy
import random
s = copy.deepcopy(spieces)
i = 0
muts = []
while (i < count):
idx = int(random.random() * len(s))
m = s[idx]
cha = int(random.random() * len(m))
ratio = random.random() * 2
m[cha] = m[cha] * ratio
muts.append(m)
del s[idx]
i = i + 1
return muts
def crossover(spieces, count):
import copy
import random
s = copy.deepcopy(spieces)
i = 0
crs = []
while (i < count):
idx = int(random.random() * len(s))
a = s[idx]
del s[idx]
idx = int(random.random() * len(s))
b = s[idx]
del s[idx]
h = int(random.random() * len(a))
crs.append(a[:h] + b[h:])
crs.append(b[:h] + a[h:])
i = i + 2
return crs
"""main"""
i = 0
end = False
while (i < 10 and (not end)):
l = live(spieces)
nc = len(spieces) - len(l)
cc = int(nc/2)
mc = nc - cc
m = mutate(spieces, mc)
c = crossover(spieces, cc)
spieces = l + m + c
print('--------%d--------'%(i))
for s in spieces:
print(s)
for s in spieces:
if(fitness(s) > 9):
print('best: %r'%(s))
end = True
i = i + 1
对父代有记忆的GA代码:
t = 0
T = 10
spieces = [[1, 2, {'idx':0 ,'old': 1, 'fit': 0}],\
[2, 3, {'idx':0 ,'old': 2, 'fit': 0}],\
[3, 4, {'idx':0 ,'old': 3, 'fit': 0}],\
[4, 5, {'idx':0 ,'old': 4, 'fit': 0}],\
[5, 6, {'idx':0 ,'old': 5, 'fit': 0}]]
fitnesses = [0 for i in spieces]
def target(params):
return params[0] * params[0] + params[1] * params[1]
def fitness(params):
return 10 - target(params)
def live(spieces, fitnesses):
import random
probs = roulette(spieces, fitnesses)
lefts = []
idx = 0
for p in probs:
r = random.random()
if ( r < p ):
lefts.append(spieces[idx])
return lefts
def roulette(spieces, fitnesses):
idx = 0
total = 0
prob = []
del fitnesses[:]
for params in spieces:
p = fitness( params )
fitnesses.append(p)
total = total + p
prob.append(p)
idx = idx + 1
idx = 0
for p in prob:
prob[idx] = p/total
idx = idx + 1
return prob
def mutate(spieces, count):
import copy
import random
s = copy.deepcopy(spieces)
i = 0
muts = []
while (i < count):
idx = int(random.random() * len(s))
m = s[idx]
cha = int(random.random() * len(m))
ratio = random.random() * 2
m[cha] = m[cha] * ratio
muts.append(m)
del s[idx]
i = i + 1
return muts
def mutateWithMemory(spieces, count, fitnesses):
import copy
import random
s = copy.deepcopy(spieces)
i = 0
muts = []
while (i < count):
idx = int(random.random() * len(s))
m = s[idx]
cha = int(random.random() * (len(m) - 1))
fitness = fitnesses[idx]
threshold = 0.5
if (m[-1]['idx'] == cha):
memory = m[-1]
sign = 1
if (fitness > memory['fit'] and m[cha] < m[-1]['old']):
#last change is decrease and works well
sign = -1
elif (fitness < memory['fit'] and m[cha] > m[-1]['old']):
#last change is increase and works badly
sign = -1
threshold = 0.2 * sign + threshold
m[-1]['idx'] = cha
m[-1]['old'] = m[cha]
m[-1]['fit'] = fitness
direction = 1 if random.random() > threshold else -1
change = random.random() * m[cha]
m[cha] = m[cha] + direction * change
muts.append(m)
del s[idx]
i = i + 1
return muts
def crossover(spieces, count):
import copy
import random
s = copy.deepcopy(spieces)
i = 0
crs = []
while (i < count):
idx = int(random.random() * len(s))
a = s[idx]
del s[idx]
idx = int(random.random() * len(s))
b = s[idx]
del s[idx]
h = int(random.random() * len(a))
crs.append(a[:h] + b[h:])
crs.append(b[:h] + a[h:])
i = i + 2
return crs
"""main"""
i = 0
end = False
while (i < 10 and (not end)):
l = live(spieces, fitnesses)
nc = len(spieces) - len(l)
cc = int(nc/2)
mc = nc - cc
m = mutateWithMemory(spieces, mc, fitnesses)
c = crossover(spieces, cc)
spieces = l + m + c
print('--------%d--------'%(i))
for s in spieces:
print(s)
for s in spieces:
if(fitness(s) > 9):
print('best: %r'%(s))
end = True
i = i + 1