基于蚁群算法实现TSP问题

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

<Figure size 640x480 with 1 Axes>

<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

<Figure size 640x480 with 1 Axes>

<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

<Figure size 640x480 with 1 Axes>

<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

<Figure size 640x480 with 1 Axes>

<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

<Figure size 640x480 with 1 Axes>

<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

<Figure size 640x480 with 1 Axes>

<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

<Figure size 640x480 with 1 Axes>

<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

<Figure size 640x480 with 1 Axes>

<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

<Figure size 640x480 with 1 Axes>

<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

<Figure size 640x480 with 1 Axes>

<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

<Figure size 640x480 with 1 Axes>

<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

<Figure size 640x480 with 1 Axes>

<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

<Figure size 640x480 with 1 Axes>

<Figure size 640x480 with 1 Axes>
  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值