def init(): with open("a280.tsp",'r') as f: lines = f.readlines() i=0 while "NODE_COORD_SECTION" not in lines[i]: i += 1 for j in range(280): c = lines[i+1+j].split() cities.append([int(c[1]),int(c[2])]) for i in range(len(cities)): distance.append([]) for j in range(len(cities)): if i<=j: distance[i].append(math.sqrt((cities[i][0]-cities[j][0])**2+(cities[i][1]-cities[j][1])**2)) else: distance[i].append(distance[j][i]) # 计算一个解的路径总长度 def totalDistance(arr): res = 0 for i in range(len(arr)-1): res += distance[arr[i]][arr[i+1]] res += distance[arr[-1]][arr[0]] return res
def GA(): startTime = time.time() history = [] groupSize = 1000 # 突变概率 mutation = 0.01 maxIter = 40000 currIter = 0 fatherGroup = [] sonGroup = [] fitness = [] minDistance = -1 minPath = [] # 初始化种群 totalDis = 0 for i in range(groupSize): arr = list(range(len(cities))) random.shuffle(arr) fatherGroup.append(arr) d = totalDistance(arr) fitness.append(d) totalDis += d # 计算适应度 fitness = [totalDis/i for i in fitness] totalFit = sum(fitness) fitness = [i/totalFit for i in fitness] while currIter<maxIter: if currIter==1: history.append([currIter,minDistance]) if currIter%400==0 and currIter>0: print("ga: "+str(currIter)) history.append([currIter,minDistance]) sonDis = [] # 杂交 for i in range(groupSize): # 轮盘赌选择父代 f1 = -1 r = random.random() p = 0 while r>p: f1 += 1 p += fitness[f1] f2 = f1 while f1==f2: f2 = -1 r = random.random() p = 0 while r>p: f2 += 1 p += fitness[f2] f1 = fatherGroup[f1] f2 = fatherGroup[f2] # 杂交生成两个子代 r = random.randint(0,len(cities)-2) s1 = f1[:i] s2 = f2[:i] for k in f1: if k not in s2: s2.append(k) for k in f2: if k not in s1: s1.append(k) r = random.random() if r<mutation: # 突变就是随机交换两个位置的值 change = random.sample(range(len(cities)),2) s1[change[0]],s1[change[1]] = s1[change[1]],s1[change[0]] s2[change[0]],s2[change[1]] = s2[change[1]],s2[change[0]] sonGroup.append(s1) sonGroup.append(s2) sonDis.append(totalDistance(s1)) sonDis.append(totalDistance(s2)) # 子代按路径长度排序 zipped=zip(sonGroup,sonDis) sort_zipped = sorted(zipped,key=lambda x:(x[1],x[0])) result = zip(*sort_zipped) sonGroup, sonDis = [list(x) for x in result] sonGroup = sonGroup[:groupSize] sonDis = sonDis[:groupSize] # 种群更新 minDistance = min(sonDis) minPath = sonGroup[sonDis.index(minDistance)] totalDis = sum(sonDis) fitness = [totalDis/i for i in sonDis] totalFit = sum(fitness) fitness = [i/totalFit for i in fitness] fatherGroup = sonGroup sonGroup = [] currIter += 1 history.append([maxIter,minDistance]) endTime = time.time() print("最短路程:"+str(minDistance)) print("运行时间:"+str(endTime-startTime)) print("最优路线:"+str([list(cities[i]) for i in minPath])) print("迭代历史:"+str(history))
1、ant cycle system 模型其中 $Q$ 为常数,表示蚂蚁循环一次所释放的信息素总量, $L_K$ 表示第 $k$ 只蚂蚁经过路径的长度
2、ant quantity system 模型
3、ant density system 模型在上述三种模型中,一般采用ant cycle system 模型,让信息素的浓度随蚂蚁迄今走过的总长度的增加而下降,使得路径上的信息素浓度更包含一种全局性的信息。
Python3实现如下,迭代次数设为一万次:
def ACO(): startTime = time.time() history = [] maxIter = 500 currIter = 0 minDistance = -1 minPath = [] # 初始化参数 antNum = len(cities) alpha = 1 beta = 5 rho = 0.1 Q = 1000 # 初始化信息素矩阵 pheromone = [[1 for i in range(len(cities))] for j in range(len(cities))] while currIter<maxIter: if currIter==1: history.append([currIter,minDistance]) if currIter%5==0 and currIter>0: print("aco: "+str(currIter)+" "+str(minDistance)) history.append([currIter,minDistance]) # 初始化行走的路径 path = [[] for j in range(antNum)] visit = [[0 for i in range(len(cities))] for j in range(antNum)] antDis = [] # 随机放置蚂蚁 arr = list(range(len(cities))) random.shuffle(arr) for i in range(antNum): path[i].append(arr[i]) visit[i][arr[i]] = 1 # 所有蚂蚁都走完一条完整路径时才算一次迭代 for i in range(antNum): while len(path[i])<len(cities): # 路径选择概率表 weight = [0 for k in range(len(cities))] for k in range(len(cities)): if visit[i][k]==0: weight[k] = (pheromone[path[i][-1]][k]**alpha)/(distance[path[i][-1]][k]**beta+0.0001) # 轮盘赌法选下个城市 totalWeight = sum(weight) p = [w/totalWeight for w in weight] r = random.random() sumP = 0 nextCity = -1 while r>sumP: nextCity += 1 sumP += p[nextCity] path[i].append(nextCity) visit[i][nextCity] = 1 for i in path: antDis.append(totalDistance(i)) minDistance = min(antDis) minPath = path[antDis.index(minDistance)] # 更新信息素 delta = [[0 for i in range(len(cities))] for j in range(len(cities))] for i in range(antNum): tau = Q/antDis[i] for j in range(1,len(cities)): fromCity = path[i][j-1] toCity = path[i][j] delta[fromCity][toCity] += tau delta[toCity][fromCity] += tau for i in range(len(cities)): for j in range(len(cities)): pheromone[i][j] = pheromone[i][j]*(1-rho)+delta[i][j] currIter += 1 history.append([maxIter,minDistance]) endTime = time.time() print("最短路程:"+str(minDistance)) print("运行时间:"+str(endTime-startTime)) print("最优路线:"+str([list(cities[i]) for i in minPath])) print("迭代历史:"+str(history))