蚁群算法(ant system,AS)

蚁群算法

  蚂蚁系统(ant system,AS)由Dorigo于1996年发表,文章题目为[《The Ant System : optimization by a colony of cooperating agents》](https://www.docin.com/p-1565494487.html)。在耳熟能详的TSP旅行商问题上AS算法有着不错的效果,这也是被大多数人认可的一种随机演化算法。

蚁群算法的思想来源于蚂蚁觅食的过程:

  • 单个蚂蚁的行为比较简单
  • 但蚁群在不同的环境下,能寻找到达食物源的最短路径
  • 蚂蚁在其经过的路径上释放“信息素”
  • 蚁群内的蚂蚁会沿着“信息素”浓度较高的路径行走,形成正反馈
  • 人工蚂蚁可以超越真实蚂蚁,如具有有限记忆存储能力

   一般而言机器智慧都是产生于多个个体之间的“交流”,如当下比较火的深度学习,层与层之间链接方式是尤为关键的,后续的传播方向就是由这些链接来决定的,又比如传统的群体智能优化算法PSO,一个种群之中个体和最优个体之间有一种交流,就是个体向最优个体学习,而蚁群算法中的个体交流像是人类阅读图书跟前人交流,蚂蚁通过“阅读”前人留下的“信息素”来更好的判断下一步要怎么走,人类社会中也有老话:不听老人言吃亏在眼前,所以蚂蚁跟着“信息素”走能够极大地保证单只蚂蚁的行为是普遍正确的。
  如果蚁群中只有一只蚂蚁,这显然是不行的,单只蚂蚁的智慧能力比较局限,它只能和上一个自己进行“交流”并且效率十分低,所以一般认为单只蚂蚁是很难产生智慧的。一个蚁群就像是一个人类社会,无论在长江黄河流域还是在黄土高原地区,当地的人们总能找到一种适合自己生存的方式,而蚂蚁觅食也是如此,在一定时间的演化下,蚂蚁的“信息素”就如同人类社会的书籍一般宝贵。另外,人工蚂蚁相较于真实的蚂蚁具有很多优势,例如,只要计算机的内存足够大,那么蚂蚁的记忆是无限的,对于真实的生物来说,这显然是不能达到的,毕竟总要遗忘。
蚁群算法的过程:

  • 初始化:城市数n、距离矩阵d、蚂蚁数量、沉积常数、挥发率、每条边的初始信息素。
  • while 条件不满足
  • 构建每个蚂蚁的路径(随机比例+轮盘赌)
  • 计算每个蚂蚁的路劲总长度
  • 更新每条边的信息素(全局信息素更新:沉积+挥发)
  • end
    构建蚂蚁路径:
  • 第k只蚂蚁,已访问城市集合 C k C_{k} Ck
  • 对每一个未访问的城市j,计算随机比例: p i j ( k ) = τ i j α / d i j β ∑ m ∉ C k τ i m α / d i m β p^{(k)}_{ij}=\frac{τ^{α}_{ij}/d^{β}_{ij}}{\sum_{m\notin{C_{k}}}τ^{α}_{im}/d^{β}_{im}} pij(k)=m/Ckτimα/dimβτijα/dijβ
  • 让蚂蚁k以上述随机比例(轮盘赌)到达城市j
    信息素更新
  • 所有蚂蚁的路径构建完毕后,进行信息素的更新
    τ i j = ( 1 − ρ ) τ i j + ∑ k = 1 N Δ τ i j ( k ) τ_{ij}=(1-ρ)τ_{ij}+\sum^{N}_{k=1}{\Delta \tau^{(k)}_{ij}} τij=(1ρ)τij+k=1NΔτij(k)
    Δ τ i j ( k ) = { Q / L k , 边 ( i , j ) 在 蚂 蚁 k 的 路 径 上 0 , 其 他 \Delta τ^{(k)}_{ij} =\left\{\begin{aligned} Q/L_{k} ,& 边(i,j)在蚂蚁k的路径上\\ 0,其他\end{aligned}\right. Δτij(k)={Q/Lk,0,(i,j)k
    典型的TSP问题:
      一个典型的TSP问题就是中国31个省会都走一次的最短路径。本文就以这个问题为例实现AS算法。
    城市信息:
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()

结果:
蚁群算法(ant system,AS)_第1张图片
总结:
  目前这个问题通过CTSP求得的最优解是15378km,我调了一些参数,始终未能达到其最优的结果,以后有时间再做调整!

你可能感兴趣的:(算法,人工智能,python)