目录
基本介绍
TSP问题
算法基本思想
路径选择
信息素更新
Python代码
初始化
遍历所有城市
信息素更新
绘制“迭代次数”与“路径和”图像
效果展示
基本介绍
TSP问题
旅行商问题,即TSP问题(Traveling Salesman Problem),给定一组城市和每对城市之间的距离,商家从其中一个城市出发,要求每个城市都要经过且每个城市经过一次,最后回到起点城市,求解商家访问这些城市的最短路径。
算法基本思想
(1)根据具体问题设置多只蚂蚁,分头并行搜索。
(2)每只蚂蚁完成一次周游后,在行进的路上释放信息素,信息素量与解的质量成正比。
(3)蚂蚁路径的选择根据信息素强度大小(初始信息素量设为相等),同时考虑两点之间的距离,采用随机的局部搜索策略。这使得距离较短的边,其上的信息素量较大,后来的蚂蚁选择该变的概率也较大。
(4)每只蚂蚁只能走合法路线(经过每个城市1次且仅1次),为此设置禁忌表来控制。
(5)所有蚂蚁都搜索完一次就是迭代一次,每迭代一次就对所有的边做一次信息素更新,原来的蚂蚁死掉,新的蚂蚁进行新一轮搜索。
(6)更新信息素包括原有信息素的蒸发和经过的路径上信息素的增加。
(7)达到预定的迭代步数,或出现停滞现象(所有蚂蚁都选择同样的路径,解不再变化),则算法结束,以当前最优解作为问题的最优解。
路径选择
蚂蚁在当前所在城市选择下一个城市时,转移概率 pij 是有两部分组成,一个是信息素浓度Tij,另一个是当前城市到下一城市的距离 ηij。α 是信息素重要程度因子,β 是启发式函数重要程度因子。其中 t 时刻,蚂蚁 k 从 i 城市到 j 城市的转移概率是按照下列公式来进行计算的:
α —— 信息素重要程度因子
β —— 启发式函数重要程度因子
启发式因子计算公式:ηij = 1 / dij
信息素更新
迭代过程中,问题空间中的所有路径上的信息素都会发生改变。其中第一部分是信息素的蒸发,ρ 是挥发因子,代表信息素的挥发速度。然后,所有的蚂蚁根据自己构建的路径长度在它们本轮经过的边上释放信息素,公式如下
ρ —— 挥发因子
等式右边第一部分代表了信息素自身挥发后剩余的信息素,第二部分是每只蚂蚁经过城市 i 到城市 j 留下的信息素。在一次迭代中,每只蚂蚁经过城市i到城市j都会留下信息素,在该次迭代结束后,所有蚂蚁留下的信息素总和即为该路径信息素的增量。注意,同一代的蚂蚁互相之间不会受到之前蚂蚁留下的信息素浓度的影响,计算到下一城市j的概率时所用到T是上一代所有蚂蚁留下的信息素。
Q —— 正常数
Lk —— 蚂蚁k本次周游中所走路径长度
Python代码
初始化
N = 5 # 城市数量
M = 5 # 蚂蚁数量
a = 2 # 信息素因子
b = 1 # 启发式因子
r = 0.3 # 信息素挥发因子
Q = 10 # 信息素常量
T = 4 # 最大迭代次数
path = [[0, 2, 10, 8, 3], [1, 0, 2, 5, 7], [9, 1, 0, 3, 6], [10, 4, 3, 0, 2], [2, 7, 5, 1, 0]] # 路径长度
ral = [[0, Q, Q, Q, Q], [Q, 0, Q, Q, Q],[Q, Q, 0, Q, Q], [Q, Q, Q, 0, Q], [Q, Q, Q, Q, 0]] # 信息素
result = [[] for c in range(T)] # 记录每轮迭代最优城市队列
minr = []
mint = 0
遍历所有城市
for t in range(T): # 迭代T次
arriving = [[] for c in range(M)] # 已访问的城市队列
for i in range(M): # 每轮都有M只蚂蚁寻找路径
city = [] # 候选可以下一跳的城市集合
for c in range(N):
city.append(c)
city.remove(i) # 从i开始选路,从剩下的N-1选择下一个城市
arriving[i].append(i) # i增加到已访问队列
s = i # s表示从i这个结点开始
while len(city) > 0: # 对city进行遍历,每次寻找下一个城市,直到city为空
p = [0 for c in range(N)]
sump = 0.0
for j in city:
p[j] = ((ral[s][j])**a)*((path[s][j])**b) # 概率分子
sump += p[j]
x = random.random() # 生成一个0-1间浮点数
lower = 0
for j in city:
p[j] = p[j]/sump
upper = lower + p[j]
if lower <= x < upper: # 说明j被选中
city.remove(j)
arriving[i].append(j)
s = j
break
lower = upper
arriving[i].append(i) # 表示回到原点
信息素更新
# 更新信息素
for i in range(N): # 挥发的信息素
for j in range(N):
ral[i][j] = (1-r)*ral[i][j]
minp = [0 for c in range(M)]
mini = 0
for i in range(M):
for j in range(len(arriving[i])-1):
x1 = arriving[i][j]
x2 = arriving[i][j+1]
ral[x1][x2] += Q/path[x1][x2] # 路径x1,x2信息素增加
minp[i] += path[x1][x2]
if minp[i] < minp[mini]:
mini = i # 最小值下标
minr.append(minp[mini]) # 记录第t轮最小的路径和
result[t] += arriving[mini] # 记录第t轮最优路径序列
if minr[t] < minr[mint]:
mint = t # 最小路径和的迭代轮数下标
print('输出路径选择结果')
print(result)
print('输出当前最优路径')
print(result[mint])
绘制“迭代次数”与“路径和”图像
x = range(T)
plt.plot(x, minr, label="蚁群算法", color="red", linestyle="--", marker="s", markersize=4)
xlabel = []
for x in range(T):
xlabel.append(x)
plt.xticks(xlabel)
plt.xlabel("迭代次数")
plt.ylabel("路径和")
plt.title("TSP")
plt.legend()
plt.show()