import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import math
import random
import time
start = time.time()
matplotlib.rcParams['font.family'] = 'STSong'
np.set_printoptions(linewidth=400)
np.set_printoptions(threshold=np.inf)
"""
data.txt数据载入
"""
city_name = []
city_condition = []
with open('data.txt','r',encoding='UTF-8') as f:
lines = f.readlines()
for line in lines:
line = line.split('\n')[0]
line = line.split(',')
city_name.append(line[0])
city_condition.append([float(line[1]), float(line[2])])
city_condition = np.array(city_condition)
"""
地图展示
"""
def map_show():
fig = plt.figure()
ax1 = fig.add_subplot()
ax1.set_title('城市分布图')
for i in range(city_count):
plt.annotate(i+1,xy=(city_condition[i][0], city_condition[i][1]), xytext=(city_condition[i][0] + 0.3, city_condition[i][1] + 0.3))
plt.scatter(city_condition[:, 0], city_condition[:, 1])
plt.xlabel('经度')
plt.ylabel('纬度')
plt.show()
"""
距离矩阵和总距离的计算
"""
#距离矩阵
city_count = len(city_name)
Distance = np.zeros((city_count, city_count))
for i in range(city_count):
for j in range(city_count):
if i != j:
Distance[i][j] = math.sqrt((city_condition[i][0] - city_condition[j][0]) ** 2 + (city_condition[i][1] - city_condition[j][1]) ** 2)
else:
Distance[i][j] = 100000
# print(Distance[0][1])
# print(Distance)
#适应度计算
def get_total_distance(path_new):
distance = 0
for i in range(city_count-1):
#count为30,意味着回到了开始的点,此时的值应该为0.
distance += Distance[int(path_new[i])][int(path_new[i+1])]
distance += Distance[int(path_new[-1])][int(path_new[0])]
return distance
"""
两个难点
1.城市的选择:初始城市选择和下一个城市的选择设计
2.信息素的更新
"""
def main(cant=10,calpha=1,cbeta=5,crho=0.1,citer=0,citeration=200,cq=1):
##参数设计
# 蚂蚁数量
AntCount = cant
# 城市数量
city_count = len(city_name)
# 信息素
alpha = calpha # 信息素重要程度因子
beta = cbeta # 启发函数重要程度因子
rho = crho #挥发速度
iter = citer # 迭代初始值
iteration = citeration # 最大迭代值
Q = cq
# 初始信息素矩阵,全是为1组成的矩阵
pheromonetable = np.ones((city_count, city_count))
# print(pheromonetable)
# 候选集列表
candidate = np.zeros((AntCount, city_count)).astype(int) # 存放100只蚂蚁的路径(一只蚂蚁一个路径),一共就Antcount个路径,一共是蚂蚁数量*31个城市数量
path_best = np.zeros((iteration, city_count)) # path_best存放的是相应的,每次迭代后的最优路径,每次迭代只有一个值
# 存放每次迭代的最优距离
distance_best = np.zeros(iteration)
#怎么处理对角线的元素是0的情况
etable = 1.0 / Distance # 倒数矩阵
while iter < iteration:
"""
路径创建
"""
## first:蚂蚁初始点选择
if AntCount <= city_count:
candidate[:, 0] = np.random.permutation(range(city_count))[:AntCount]
else:
candidate[:city_count, 0] = np.random.permutation(range(city_count))[:]
candidate[city_count:, 0] = np.random.permutation(range(city_count))[:AntCount - city_count]
length = np.zeros(AntCount)#每次迭代的N个蚂蚁的距离值
## second:选择下一个城市选择
for i in range(AntCount):
# 移除已经访问的第一个元素
unvisit = list(range(city_count)) # 列表形式存储没有访问的城市编号
visit = candidate[i, 0] # 当前所在点,第i个蚂蚁在第一个城市
unvisit.remove(visit) # 在未访问的城市中移除当前开始的点
for j in range(1, city_count):#访问剩下的city_count个城市,city_count次访问
protrans = np.zeros(len(unvisit))#每次循环都更改当前没有访问的城市的转移概率矩阵1*30,1*29,1*28...
# 下一城市的概率函数
for k in range(len(unvisit)):
# 计算当前城市到剩余城市的(信息素浓度^alpha)*(城市适应度的倒数)^beta
# etable[visit][unvisit[k]],(alpha+1)是倒数分之一,pheromonetable[visit][unvisit[k]]是从本城市到k城市的信息素
protrans[k] = np.power(pheromonetable[visit][unvisit[k]], alpha) * np.power(
etable[visit][unvisit[k]], (alpha + 1))
# 累计概率,轮盘赌选择
cumsumprobtrans = (protrans / sum(protrans)).cumsum()
cumsumprobtrans -= np.random.rand()
# 求出离随机数产生最近的索引值
k = unvisit[list(cumsumprobtrans > 0).index(True)]
# 下一个访问城市的索引值
candidate[i, j] = k
unvisit.remove(k)
length[i] += Distance[visit][k]
visit = k # 更改出发点,继续选择下一个到达点
length[i] += Distance[visit][candidate[i, 0]]#最后一个城市和第一个城市的距离值也要加进去
"""
更新路径等参数
"""
# 如果迭代次数为一次,那么无条件让初始值代替path_best,distance_best.
if iter == 0:
distance_best[iter] = length.min()
path_best[iter] = candidate[length.argmin()].copy()
else:
# 如果当前的解没有之前的解好,那么当前最优还是为之前的那个值;并且用前一个路径替换为当前的最优路径
if length.min() > distance_best[iter - 1]:
distance_best[iter] = distance_best[iter - 1]
path_best[iter] = path_best[iter - 1].copy()
else: # 当前解比之前的要好,替换当前解和路径
distance_best[iter] = length.min()
path_best[iter] = candidate[length.argmin()].copy()
"""
信息素的更新
"""
#信息素的增加量矩阵
changepheromonetable = np.zeros((city_count, city_count))
for i in range(AntCount):
for j in range(city_count - 1):
# 当前路径比如城市23之间的信息素的增量:1/当前蚂蚁行走的总距离的信息素
changepheromonetable[candidate[i, j]][candidate[i][j + 1]] += Q / length[i]
#Distance[candidate[i, j]][candidate[i, j + 1]]
#最后一个城市和第一个城市的信息素增加量
changepheromonetable[candidate[i, j + 1]][candidate[i, 0]] += Q / length[i]
#信息素更新的公式:
pheromonetable = (1 - rho) * pheromonetable + changepheromonetable
iter += 1
return distance_best,path_best,iteration
def draw(distance_best,path_best,iteration):
end = time.time()
print("Time used:", end - start)
print("蚁群算法的最优路径",path_best[-1]+1)
print("迭代",iteration,"次后","蚁群算法求得最优解",distance_best[-1])
# # 路线图绘制
fig = plt.figure()
ax2 = fig.add_subplot(111)
ax2.set_title('BestPath')
x = []
y = []
path = []
for i in range(len(path_best[-1])):
x.append(city_condition[int(path_best[-1][i])][0])
y.append(city_condition[int(path_best[-1][i])][1])
path.append(int(path_best[-1][i])+1)
x.append(x[0])
y.append(y[0])
path.append(path[0])
for i in range(len(x)):
plt.annotate(path[i], xy=(x[i], y[i]), xytext=(x[i] + 0.3, y[i] + 0.3))
plt.plot(x, y,'-o')
# 距离迭代图
fig = plt.figure()
ax3 = fig.add_subplot(111)
ax3.set_title('Distance iter')
plt.plot(range(1, len(distance_best) + 1), distance_best)
plt.xlabel('Iter')
plt.ylabel('Distance')
plt.show()
if __name__ == '__main__':
#初始
distance_best, path_best, iteration = main(cant=20,calpha=1,cbeta=5,crho=0.1,citer=0,citeration=200,cq=1)
draw(distance_best, path_best, iteration)
Time used: 11.88286280632019
蚁群算法的最优路径 [16. 15. 17. 18. 23. 19. 21. 20. 22. 30. 31. 24. 6. 28. 1. 27. 29. 2. 3. 12. 25. 4. 26. 14. 10. 11. 5. 9. 8. 7. 13.]
迭代 200 次后 蚁群算法求得最优解 153.3356634220494
![](https://i-blog.csdnimg.cn/blog_migrate/136cf62ecbc8e7cd45ee87d21cc74852.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/abe5a1fa4557c03af86536efca28ed22.png)
<Figure size 640x480 with 1 Axes>
#蚂蚁数量过大
#随机每个路径都有蚂蚁,导致路径上信息素趋于平均,正反馈作用减弱,收敛速度减慢,Time used: 280.8177342414856
if __name__ == '__main__':
distance_best, path_best, iteration = main(cant=60,calpha=1,cbeta=5,crho=0.1,citer=0,citeration=200,cq=1)
draw(distance_best, path_best, iteration)
Time used: 280.8177342414856
蚁群算法的最优路径 [16. 15. 17. 18. 23. 19. 21. 20. 22. 31. 30. 24. 6. 28. 1. 27. 29. 2. 3. 12. 25. 4. 26. 14. 11. 5. 10. 13. 9. 8. 7.]
迭代 200 次后 蚁群算法求得最优解 153.6850658334985
![](https://i-blog.csdnimg.cn/blog_migrate/9e87f7ac59f28c0db602906933223af7.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/8d09598d88491e15bf3f353c02045f86.png)
<Figure size 640x480 with 1 Axes>
#蚂蚁数量少
#存在一些路径信息素减少为0,导致过早收敛,解的全局最优性降低,蚁群算法求得最优解 160.16264772856997
if __name__ == '__main__':
distance_best, path_best, iteration = main(cant=5,calpha=1,cbeta=5,crho=0.1,citer=0,citeration=200,cq=1)
draw(distance_best, path_best, iteration)
Time used: 177.81868410110474
蚁群算法的最优路径 [27. 1. 28. 29. 6. 24. 31. 30. 22. 20. 19. 21. 16. 15. 17. 18. 23. 7. 8. 9. 13. 10. 5. 11. 14. 26. 4. 25. 12. 2. 3.]
迭代 200 次后 蚁群算法求得最优解 160.16264772856997
![](https://i-blog.csdnimg.cn/blog_migrate/9b042bf5154be95462d6f8973711620b.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/939cf6f0b379556b85f3e172f673d4e1.png)
<Figure size 640x480 with 1 Axes>
#信息素常量过小
#信息含量差别较小,容易陷入混沌状态
if __name__ == '__main__':
distance_best, path_best, iteration = main(cant=20,calpha=1,cbeta=5,crho=0.1,citer=0,citeration=200,cq=0.001)
draw(distance_best, path_best, iteration)
Time used: 330.68768310546875
蚁群算法的最优路径 [ 2. 29. 27. 1. 28. 6. 24. 31. 30. 22. 20. 19. 21. 16. 15. 17. 18. 23. 9. 8. 7. 13. 10. 11. 5. 14. 26. 4. 25. 12. 3.]
迭代 200 次后 蚁群算法求得最优解 156.314719942114
![](https://i-blog.csdnimg.cn/blog_migrate/47d48566550627c43c495f4ea4fb8624.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/0c3b515d193a025d8c8c1847aa30fe72.png)
<Figure size 640x480 with 1 Axes>
#信息素常量过大
#容易陷入局部最优,导致无法到达全局最优
if __name__ == '__main__':
distance_best, path_best, iteration = main(cant=20,calpha=1,cbeta=5,crho=0.1,citer=0,citeration=200,cq=100)
draw(distance_best, path_best, iteration)
Time used: 588.0640876293182
蚁群算法的最优路径 [21. 19. 16. 15. 17. 18. 23. 30. 22. 31. 24. 6. 28. 1. 27. 29. 2. 3. 12. 25. 4. 5. 11. 10. 13. 9. 8. 7. 14. 26. 20.]
迭代 200 次后 蚁群算法求得最优解 156.34783475204844
![](https://i-blog.csdnimg.cn/blog_migrate/83bd2de651e71e55ab93582c4cac5188.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/08b00c60d29812b998ec8864009d87f4.png)
<Figure size 640x480 with 1 Axes>
#迭代次数少
#可选路径较少,使种群陷入局部最优
if __name__ == '__main__':
distance_best, path_best, iteration = main(cant=20,calpha=1,cbeta=5,crho=0.1,citer=0,citeration=20,cq=1)
draw(distance_best, path_best, iteration)
Time used: 712.2953383922577
蚁群算法的最优路径 [15. 16. 1. 28. 27. 29. 24. 31. 30. 22. 6. 19. 20. 21. 26. 14. 10. 11. 4. 25. 12. 2. 3. 5. 9. 8. 7. 13. 18. 23. 17.]
迭代 20 次后 蚁群算法求得最优解 191.42062332702517
![](https://i-blog.csdnimg.cn/blog_migrate/30c1b23c1c11bae88b68c656ee3e3b5e.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/a8c8fd3aa42f639bec11d91735c12cc3.png)
<Figure size 640x480 with 1 Axes>
#迭代次数多
#运行时间长
if __name__ == '__main__':
distance_best, path_best, iteration = main(cant=20,calpha=1,cbeta=5,crho=0.1,citer=0,citeration=500,cq=1)
draw(distance_best, path_best, iteration)
Time used: 782.4452455043793
蚁群算法的最优路径 [16. 15. 17. 18. 23. 19. 21. 20. 22. 31. 30. 24. 6. 28. 1. 27. 29. 2. 3. 12. 25. 4. 26. 14. 10. 11. 5. 8. 7. 9. 13.]
迭代 500 次后 蚁群算法求得最优解 153.22801835361074
![](https://i-blog.csdnimg.cn/blog_migrate/2bceaca6e134222c817b13fe9471949e.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/6427cd2e792eb8c6ecc18fab233cf902.png)
<Figure size 640x480 with 1 Axes>
#信息素因子过大
#蚂蚁选择以前已经走过的路可能性较大,容易使随机搜索性减弱
if __name__ == '__main__':
distance_best, path_best, iteration = main(cant=20,calpha=100,cbeta=5,crho=0.1,citer=0,citeration=200,cq=1)
draw(distance_best, path_best, iteration)
Time used: 886.269362449646
蚁群算法的最优路径 [ 3. 2. 29. 28. 1. 27. 25. 12. 4. 26. 14. 11. 10. 13. 15. 16. 21. 19. 20. 22. 31. 30. 24. 6. 18. 23. 17. 9. 8. 7. 5.]
迭代 200 次后 蚁群算法求得最优解 172.95773937274245
![](https://i-blog.csdnimg.cn/blog_migrate/a6a3562b080918f5cdcc0d9369da5144.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/1f67a3939f23450c749b5a33fc830972.png)
<Figure size 640x480 with 1 Axes>
#信息素因子过小
#使蚁群的搜索范围减小容易过早收敛,陷入局部最优
if __name__ == '__main__':
distance_best, path_best, iteration = main(cant=20,calpha=0.01,cbeta=5,crho=0.1,citer=0,citeration=200,cq=1)
draw(distance_best, path_best, iteration)
Time used: 914.863662481308
蚁群算法的最优路径 [21. 15. 17. 18. 19. 16. 13. 9. 8. 7. 5. 12. 25. 29. 10. 20. 23. 22. 30. 31. 11. 14. 26. 6. 24. 1. 28. 2. 3. 4. 27.]
迭代 200 次后 蚁群算法求得最优解 243.7082251628025
![](https://i-blog.csdnimg.cn/blog_migrate/2ca0f904a2f2fa4efc63bdff95cefd22.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/959860062d73324cf82ceb4bda9f8060.png)
<Figure size 640x480 with 1 Axes>
#启发函数因子过大
#收敛速度加快,容易陷入局部最优
if __name__ == '__main__':
distance_best, path_best, iteration = main(cant=20,calpha=1,cbeta=500,crho=0.1,citer=0,citeration=200,cq=1)
draw(distance_best, path_best, iteration)
Time used: 974.3684582710266
蚁群算法的最优路径 [ 3. 2. 29. 27. 1. 28. 6. 24. 31. 30. 22. 20. 21. 19. 16. 15. 17. 18. 23. 9. 8. 7. 5. 11. 10. 13. 14. 26. 4. 25. 12.]
迭代 200 次后 蚁群算法求得最优解 156.30466087815466
![](https://i-blog.csdnimg.cn/blog_migrate/33f4b38521de09f3df1cd62cb85176a6.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/fb3e284189a4bba9f15c87e1ca82c611.png)
<Figure size 640x480 with 1 Axes>
#启发函数因子过小
#蚁群易陷入纯粹的随机搜索,很难找到最优解
if __name__ == '__main__':
distance_best, path_best, iteration = main(cant=20,calpha=1,cbeta=0.05,crho=0.1,citer=0,citeration=200,cq=1)
draw(distance_best, path_best, iteration)
Time used: 1054.1947333812714
蚁群算法的最优路径 [14. 26. 21. 20. 19. 16. 15. 17. 18. 23. 30. 22. 31. 24. 6. 28. 1. 27. 29. 2. 3. 12. 25. 4. 5. 11. 10. 13. 9. 8. 7.]
迭代 200 次后 蚁群算法求得最优解 156.10332160552423
![](https://i-blog.csdnimg.cn/blog_migrate/d31bf65ae1e6b4c19b3e022f4b2db253.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/0fe0e63201156f87e6ab58b0745296eb.png)
<Figure size 640x480 with 1 Axes>
#信息素挥发因子过大
#信息素挥发较快,容易导致较优路径被排除
if __name__ == '__main__':
distance_best, path_best, iteration = main(cant=20,calpha=1,cbeta=5,crho=10,citer=0,citeration=200,cq=1)
draw(distance_best, path_best, iteration)
Time used: 1089.608152627945
蚁群算法的最优路径 [11. 5. 13. 10. 14. 20. 21. 19. 17. 15. 16. 18. 30. 31. 22. 23. 24. 6. 28. 1. 27. 25. 12. 4. 26. 29. 2. 3. 8. 7. 9.]
迭代 200 次后 蚁群算法求得最优解 196.44642363321697
![](https://i-blog.csdnimg.cn/blog_migrate/5fe841c2373925e134bac0114f8e0d2d.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/5e8e93a2dbc30b8889b64648926e1f08.png)
<Figure size 640x480 with 1 Axes>
#信息素挥发因子过小
# 各路径上信息素含量差别较小,收敛速度降低
if __name__ == '__main__':
distance_best, path_best, iteration = main(cant=20,calpha=1,cbeta=5,crho=0.001,citer=0,citeration=200,cq=1)
draw(distance_best, path_best, iteration)
Time used: 1124.0912442207336
蚁群算法的最优路径 [ 8. 7. 9. 13. 5. 11. 10. 20. 19. 21. 16. 15. 17. 18. 23. 22. 31. 30. 24. 6. 28. 1. 27. 4. 25. 12. 3. 2. 29. 14. 26.]
迭代 200 次后 蚁群算法求得最优解 178.91821605715512
![](https://i-blog.csdnimg.cn/blog_migrate/22b4bf72ffad696dd2db9b9cb28f3e1f.png)
<Figure size 640x480 with 1 Axes>
![](https://i-blog.csdnimg.cn/blog_migrate/7b6e1ea8face6b4295d8a246a46be9db.png)
<Figure size 640x480 with 1 Axes>