蚁群算法解TSP问题

蚁群算法解TSP问题

    TSP问题(Travelling Salesman Problem),可译为旅行商问题、货郎担问题。其问题描述简单,却具有输入规模的指数函数的计算复杂性,属于NP完全问题。

问题可描述为:

有一位商人,他想访问中国的某些城市,要求:
1. 所走路程最近
2. 每个城市只能访问一次
3. 从某城市出发,最后回到该城市

本文所解的TSP问题与上述第3条不同,只处理了走完所有城市,没有回到出发的城市。

code:

#coding:utf-8

import random

class ACOtspSolution:
    maxgen=2500     #循环次数
    pop_size=380    #蚂蚁个数
    alpha=3         #信息启发式因子
    beta=4          #期望启发式因子
    q=100           #信息素强度
    phinit=20       #初始信息素浓度
    rou=0.3         #信息挥发系数
    def __init__(self,plist):#传入点列表(坐标元组表示)
        self.g=[]  #邻接矩阵,每两个点间的距离
        self.n=len(plist)    #问题规模(点的个数)
        self.pheromone=[[self.phinit]*self.n for i in range(self.n)]
        #信息素list,记载每两点间直接路径上的信息素量
        for i in range(len(plist)):
            self.g.append([])
            for j in range(len(plist)):
                if i==j :self.g[i].append(0)
                else :
                    dis=(plist[i][0]-plist[j][0])**2
                    dis+=(plist[i][1]-plist[j][1])**2
                    dis=dis**0.5#欧氏距离
                    self.g[i].append(dis)
                    pass
                pass
            pass
        #print self.g
        pass

    def run(self):
        for t in range(self.n-1):
            self.taboo=[[False]*self.n for i in range(self.pop_size)]
            #每一只蚂蚁维护一个taboo list,记载到每一个点的taboo值
            self.position=[random.randint(0,self.n-1)for i in range(self.pop_size)]
            #蚂蚁的当前位置
            #每次循环前,随机散布所有蚂蚁到随机城市
            self.path=[[]for i in range(self.pop_size)]
            #路径
            self.l=[0 for i in range(self.pop_size)]
            #总长,计delta pheromone用
            for i in range(self.pop_size):
                self.taboo[i][self.position[i]]=True
                self.path[i].append(self.position[i])
                pass
            #所有蚂蚁不能走当前所在点
            for k in range(self.n):#走完n个城市
                for i in range(self.pop_size):#第i只蚂蚁
                    #此处用的是《蚁群算法原理及应用-段海滨》p35公式(2.4.3)
                    prob=[]
                    allow=[]
                    #allow中元素与prob中元素一一对应,表示去某个可达城市的概率
                    divsum=0
                    for j in range(self.n):#计一遍所有城市的选择概率
                        if not self.taboo[i][j]:
                            allow.append(j)
                            prb=self.pheromone[self.position[i]][j]**self.alpha
                            if self.g[self.position[i]][j]==0:print self.position[i],j
                            prb*=self.g[self.position[i]][j]**(-1*self.beta)
                            divsum+=prb
                            prob.append(prb)
                            pass
                        pass
                    for j in range(len(prob)):prob[j]/=divsum
                    #公式用完
                    #if i==3 and t==2:print prob
                    p=random.uniform(0,1)
                    for j in range(len(allow)):
                        p-=prob[j]
                        if p<=0:#就要走此点
                            self.l[i]+=self.g[self.position[i]][allow[j]]#加距离
                            self.position[i]=allow[j]#更新位置
                            self.taboo[i][self.position[i]]=True#标taboo
                            self.path[i].append(self.position[i])#记路径
                            #if i==3 and t==2:print 'choose=',j
                            break
                        pass
                    pass
                pass
            #开始更新信息素
            #更新信息素需要总路程,可以记下当前最短路程,每轮更新
            for i in range(self.pop_size):#每一只蚂蚁
                for j in range(len(self.path[i])-1):#路径上每一段
                    self.pheromone[self.path[i][j]][self.path[i][j+1]]*=(1-self.rou)
                    self.pheromone[self.path[i][j]][self.path[i][j+1]]+=self.q/self.l[i]
            pass
        #for i in self.pheromone:
            #print i
        pass

if __name__=='__main__':
    #a=[(random.randint(0,50),random.randint(0,50))for i in range(10)]
    #a=[(0,0),(3,4),(7,7),(10,11),(14,14)]

    fr=open('tspdata.txt')
    a=[]
    for line in fr.readlines():
        line=line.strip()
        line=line.split(' ')
        while '' in line:
            line.remove('')
            #print line
        a.append((int(line[0]),int(line[1])))
        pass
    #print a
    n=ACOtspSolution(a)
    n.run()
    #print n.path
    order=n.path[n.l.index(min(n.l))]
    print min(n.l),n.path[n.l.index(min(n.l))]
    s=0
    for i in range(1,len(order)):
        s+=n.g[order[i-1]][order[i]]
        pass
    print 's=',s
    raw_input('Press  to quit.')

代码写得有点烂,全堆在run()里面了……


算法思想就不写了,我是学的论文《蚁群算法原理及应用--段海滨》。很好,讲的很明白。


测试数据下载地址:

http://download.csdn.net/detail/fghdvbgt/9524375

论文下载地址:

http://download.csdn.net/detail/fghdvbgt/9524403



你可能感兴趣的:(蚁群算法)