蚁群算法的思想来源于蚂蚁觅食的过程:
一般而言机器智慧都是产生于多个个体之间的“交流”,如当下比较火的深度学习,层与层之间链接方式是尤为关键的,后续的传播方向就是由这些链接来决定的,又比如传统的群体智能优化算法PSO,一个种群之中个体和最优个体之间有一种交流,就是个体向最优个体学习,而蚁群算法中的个体交流像是人类阅读图书跟前人交流,蚂蚁通过“阅读”前人留下的“信息素”来更好的判断下一步要怎么走,人类社会中也有老话:不听老人言吃亏在眼前,所以蚂蚁跟着“信息素”走能够极大地保证单只蚂蚁的行为是普遍正确的。
如果蚁群中只有一只蚂蚁,这显然是不行的,单只蚂蚁的智慧能力比较局限,它只能和上一个自己进行“交流”并且效率十分低,所以一般认为单只蚂蚁是很难产生智慧的。一个蚁群就像是一个人类社会,无论在长江黄河流域还是在黄土高原地区,当地的人们总能找到一种适合自己生存的方式,而蚂蚁觅食也是如此,在一定时间的演化下,蚂蚁的“信息素”就如同人类社会的书籍一般宝贵。另外,人工蚂蚁相较于真实的蚂蚁具有很多优势,例如,只要计算机的内存足够大,那么蚂蚁的记忆是无限的,对于真实的生物来说,这显然是不能达到的,毕竟总要遗忘。
蚁群算法的过程:
from matplotlib import pyplot as plt
import numpy as np
import random
locations={
'拉萨':(1304,2312),
'北京':(3639,1315),
'上海':(4177,2244),
'天津':(3712,1399),
'石家庄':(3488,1535),
'太原':(3326,1556),
'呼和浩特':(3238,1229),
'沈阳':(4196,1004),
'长春':(4312,790),
'哈尔滨':(4386,570),
'西安':(3007,1970),
'兰州':(2562,1756),
'银川':(2788,1491),
'西宁':(2381,1676),
'乌鲁木齐':(1332,695),
'济南':(3715,1678),
'南京':(3918,2179),
'杭州':(4061,2370),
'合肥':(3780,2212),
'南昌':(3676,2578),
'福州':(4029,2838),
'台北':(4263,2931),
'郑州':(3429,1908),
'武汉':(3507,2367),
'长沙':(3394,2643),
'广州':(3439,3201),
'南宁':(2935,3240),
'海口':(3140,3550),
'成都':(2545,2357),
'贵阳':(2778,2826),
'昆明':(2370,2975)
}
初始化:
n=len(locations) #城市数量
dis=np.zeros((n,n)) # 距离矩阵
τ=np.ones((n,n))*1e-6 # 初始信息素
position=list(locations.values())
# 计算城市之间距离
for i in range(n):
for j in range(i+1,n):
dis[i,j]=np.linalg.norm(np.array(position[i])-np.array(position[j]))
dis[j,i]=dis[i,j]
# parameter`在这里插入代码片`
N=n # 蚂蚁数量
Q=20 # 沉积常数
ρ=0.618 #挥发率
α=1
β=6
city=set(range(n)) #城市标记0-30
# C=[[set([i]),[i],set(),0] for i in range(N)] # 已访问城市集合 Ck为第k个蚂蚁访问的轨迹
def generate_ants():
C=[]
for _ in range(N):
point=random.choice(range(n))
C.append([set([point]),[point],set(),0])
return C
C=generate_ants() #生成蚁群,其中每个蚂蚁用[走过的城市,按顺序走过的城市,路径,距离]来表示
构建蚁群路径:
def build_path():
for ant in range(N):
no_visit=city-C[ant][0]
p=np.zeros((n))
while no_visit:
denominator=sum(map(lambda x:τ[C[ant][1][-1],x]**α/dis[C[ant][1][-1],x]**β,no_visit))
for j in no_visit:
p[j]=(τ[C[ant][1][-1],j]**α/dis[C[ant][1][-1],j]**β)/denominator
for j in range(1,n):
p[j]=p[j]+p[j-1]
q=random.random()
for j in range(n):
if q<p[j]:
break
C[ant][0].add(j)
C[ant][2].add((C[ant][1][-1],j))
C[ant][3]+=dis[C[ant][1][-1],j]
C[ant][1].append(j)
no_visit=city-C[ant][0]
p=np.zeros((n))
C[ant][3]+=dis[C[ant][1][-1],C[ant][1][0]]
C[ant][2].add((C[ant][1][-1],C[ant][1][0]))
更新信息素:
def update_pheromone():
for i in range(n):
for j in range(i+1,n):
τ[i][j]=(1-ρ)*τ[i][j]+sum(map(lambda x:Q/x[3] if (i,j) in x[2] or (j,i) in x[2] else 0,C))
τ[j][i]=τ[i][j]
测试:
build_path()
update_pheromone()
best=min(C,key=lambda x:x[-1]) #获取当前蚁群的最优蚂蚁
C=generate_ants()
# C=[[set([i]),[i],set(),0] for i in range(N)]
dis_record=[best[-1]] #最优距离记录
epoch=1000 #迭代1000次
for e in range(epoch):
build_path()
update_pheromone()
temp=min(C,key=lambda x:x[-1])
if temp[-1]<best[-1]:
best=temp
dis_record.append(best[-1])
# C=[[set([i]),[i],set(),0] for i in range(N)]
C=generate_ants()
# 绘图
plt.scatter([i[0] for i in position],[i[1] for i in position])
for k,v in locations.items():
plt.text(v[0],v[1],k,fontproperties="simhei")
for i in best[2]:
plt.plot([position[i[0]][0],position[i[1]][0]],[position[i[0]][1],position[i[1]][1]],color='g')
plt.title('min_dis={}'.format(best[-1]))
plt.show()
结果:
总结:
目前这个问题通过CTSP求得的最优解是15378km,我调了一些参数,始终未能达到其最优的结果,以后有时间再做调整!