蚁群算法求解TSP
__author__:cheng
__date__:2022.5.7
__version__: V1.0.0
__description__:
要求用Python写出蚁群算法求解TSP问题的代码
要求对每一轮迭代的结果用曲线图的形式表现出来

"""
蚁群算法求解TSP
__author__:cheng
__date__:2022.5.7
__version__: V1.0.0
__description__:
要求用Python写出蚁群算法求解TSP问题的代码
要求对每一轮迭代的结果用曲线图的形式表现出来

"""
import random
from pathlib import Path
import matplotlib.pyplot as plt
from matplotlib.pyplot import MultipleLocator#设置刻度间隔
plt.rcParams['font.sans-serif'] = ['SimSun']#设置字体
#1.初始化(各个参数)
N = 4#城市数量
M = 4#蚂蚁数量
Q = 10#信息素浓度常量
T = 3#迭代次数
a = 2#信息素启发因子
b = 1#启发因子
r = 0.3#信息素挥发因子
path = [[0,3,6,7],[5,0,2,3],[6,4,0,2],[3,7,5,0]]#路径向量
tal = [[0,Q,Q,Q],[Q,0,Q,Q,],[Q,Q,0,Q],[Q,Q,Q,0]]#信息素浓度
result = [[] for c in range(T)]#记录每一轮迭代的最优爬行路径
mint = 0#记录最优路径的那一次迭代下标
minr = [0 for c in range(T)]#记录每一轮迭代的最优路径和
y = [[] for c in range(T)]#记录每一次迭代M只蚂蚁的爬行路径长度
#2.构建解空间
for t in range(T):#迭代T次
    arriving = [[] for c in range(M)]#构建包含M只蚂蚁的初始化路径空列表
    for i in range(M):#M只蚂蚁开始寻路
        city = []
        for c in range(N):#初始化候选城市集合
            city.append(c)
        city.remove(i)#将出发城市i从下一跳城市列表中删除
        arriving[i].append(i)#第i个城市加入到访问队列中
        s =i#s表示每一次出发的城市,从i开始第一次搜索
        while len(city) > 0:#要求对city中的所有城市都遍历完
            p = [0 for c in range(N)]
            sump = 0.0
            for j in city:#计算每个候选城市被选择的概率
                p[j] = ((tal[s][j])**a)*((1/path[s][j])**b)#分子
                sump += ((tal[s][j])**a)*((1/path[s][j])**b)#循环结束后得到分母
            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被选中
                    arriving[i].append(j)#j加入到访问队列中
                    city.remove(j)#从候选城市中删除
                    s = j#从j出发
                    break
                lower = upper
        arriving[i].append(i)#结尾增加一个i,表示回到原点
    #该轮迭代所有蚂蚁完成后,进行信息素更新
    for i in range(N):#更新挥发后的信息素
        for j in range(N):
            tal[i][j] = tal[i][j]*(1-r)
    minp = [0 for i in range(M)]#M只蚂蚁爬行的路径
    mini = 0#该轮迭代中爬行的最短路径的蚂蚁(下标)
    for i in range(M):
        for j in range(len(arriving[i])-1):#后续需要用到j+1,因此len-1
            x1 = arriving[i][j]
            x2 = arriving[i][j+1]
            tal[x1][x2] += Q/path[x1][x2]
            minp[i] += path[x1][x2]#记录路径长度
        if minp[i] < minp[mini]:
            mini = i#记录该轮迭代中爬行路径最短的那只蚂蚁的下标
        y[t].append(minp[i])#记录第t+1轮迭代第i只蚂蚁的爬行路径长度,t从0开始
    print(arriving)#首尾数字必相等,最后回到起始点
    result[t] = arriving[mini]#记录每一轮迭代最好的那只蚂蚁的路径
    minr[t] = minp[mini]#记录每一轮迭代最好的那只蚂蚁的路径长度
    if minr[t] < minr[mint]:
        mint = t#下标
print(result[mint])

#print(minr[mint])
#print(y)#输出每一次迭代M只蚂蚁的爬行路径长度

x = range(1,M+1)
plt.plot(x,y[0],label="第一次迭代每只蚂蚁爬行路径长度",color="green",linestyle="-",marker="s",markersize=4)
plt.plot(x,y[1],label="第二次迭代每只蚂蚁爬行路径长度",color="blue",linestyle="--",marker="^",markersize=4)
plt.plot(x,y[2],label="第三次迭代每只蚂蚁爬行路径长度",color="red",linestyle=":",marker="*",markersize=4)

xlabel = []
for i in range(1,M+1):
    xlabel.append(i)
plt.xticks(xlabel)  # 设定x轴刻度显示为文本
plt.ylim(0,25) #设定y轴显示的区间
plt.xlabel("蚂蚁编号")#x轴的文本说明
plt.ylabel("路径长度")#y轴的文本说明
plt.title("191491531-蚁群算法求解TSP问题")#图标题
plt.gca().yaxis.set_major_locator(MultipleLocator(2))#设置y轴间隔为1
plt.legend()#加载图例
plt.savefig("191491531-蚁群算法求解TSP问题.pdf")#保存图片
plt.show()#显示图片