python实现遗传算法求解TSP旅行商问题(详细解释)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Chrome_matrix_68/article/details/53770132

课设需要做这个题目,看了http://www.tuicool.com/articles/Fb2YjeF之后下了他在github上的代码https://github.com/zchlong/tsp,发现一些错别字这份代码里改正了。

三个文件:

1.GA.py遗传算法类

2.Life.py基因序列类

3.TSP_GA.py 旅行商算法类,届时直接运行这个代码文件即可

4.34所城市经纬度distanceMatrix.txt

格式:

城市名 经度 纬度


1.GA.py遗传算法类

# -*- coding: utf-8 -*-

import random
from Life import Life

class GA(object):
      """遗传算法类"""
      def __init__(self, aCrossRate, aMutationRate, aLifeCount, aGeneLength, aMatchFun = lambda life : 1):
            self.crossRate = aCrossRate               #交叉概率
            self.mutationRate = aMutationRate         #突变概率
            self.lifeCount = aLifeCount               #种群数量,就是每次我们在多少个城市序列里筛选,这里初始化为100
            self.geneLength = aGeneLength             #其实就是城市数量
            self.matchFun = aMatchFun                 #适配函数
            self.lives = []                           #种群
            self.best = None                          #保存这一代中最好的个体
            self.generation = 1                       #一开始的是第一代
            self.crossCount = 0                       #一开始还没交叉过,所以交叉次数是0
            self.mutationCount = 0                    #一开始还没变异过,所以变异次数是0
            self.bounds = 0.0                         #适配值之和,用于选择时计算概率

            self.initPopulation()                     #初始化种群


      def initPopulation(self):
            """初始化种群"""
            self.lives = []
            for i in range(self.lifeCount):
                  #gene = [0,1,…… ,self.geneLength-1]
                  #事实就是0到33
                  gene = range(self.geneLength)
                  #将0到33序列的所有元素随机排序得到一个新的序列
                  random.shuffle(gene)
                  #Life这个类就是一个基因序列,初始化life的时候,两个参数,一个是序列gene,一个是这个序列的初始适应度值
                  # 因为适应度值越大,越可能被选择,所以一开始种群里的所有基因都被初始化为-1
                  life = Life(gene)
                  #把生成的这个基因序列life填进种群集合里
                  self.lives.append(life)


      def judge(self):
            """评估,计算每一个个体的适配值"""
            # 适配值之和,用于选择时计算概率
            self.bounds = 0.0
            #假设种群中的第一个基因被选中
            self.best = self.lives[0]
            for life in self.lives:
                  life.score = self.matchFun(life)
                  self.bounds += life.score
                  #如果新基因的适配值大于原先的best基因,就更新best基因
                  if self.best.score < life.score:
                        self.best = life


      def cross(self, parent1, parent2):
            """交叉"""
            index1 = random.randint(0, self.geneLength - 1)
            index2 = random.randint(index1, self.geneLength - 1)
            tempGene = parent2.gene[index1:index2]                      #交叉的基因片段
            newGene = []
            p1len = 0
            for g in parent1.gene:
                  if p1len == index1:
                        newGene.extend(tempGene)                               #插入基因片段
                        p1len += 1
                  if g not in tempGene:
                        newGene.append(g)
                        p1len += 1
            self.crossCount += 1
            return newGene


      def  mutation(self, gene):
            """突变"""
            #相当于取得0到self.geneLength - 1之间的一个数,包括0和self.geneLength - 1
            index1 = random.randint(0, self.geneLength - 1)
            index2 = random.randint(0, self.geneLength - 1)
            #把这两个位置的城市互换
            gene[index1], gene[index2] = gene[index2], gene[index1]
            #突变次数加1
            self.mutationCount += 1
            return gene


      def getOne(self):
            """选择一个个体"""
            #产生0到(适配值之和)之间的任何一个实数
            r = random.uniform(0, self.bounds)
            for life in self.lives:
                  r -= life.score
                  if r <= 0:
                        return life

            raise Exception("选择错误", self.bounds)


      def newChild(self):
            """产生新后的"""
            parent1 = self.getOne()
            rate = random.random()

            #按概率交叉
            if rate < self.crossRate:
                  #交叉
                  parent2 = self.getOne()
                  gene = self.cross(parent1, parent2)
            else:
                  gene = parent1.gene

            #按概率突变
            rate = random.random()
            if rate < self.mutationRate:
                  gene = self.mutation(gene)

            return Life(gene)


      def next(self):
            """产生下一代"""
            self.judge()#评估,计算每一个个体的适配值
            newLives = []
            newLives.append(self.best)#把最好的个体加入下一代
            while len(newLives) < self.lifeCount:
                  newLives.append(self.newChild())
            self.lives = newLives
            self.generation += 1

2.Life.py基因序列类

# -*- encoding: utf-8 -*-


SCORE_NONE = -1

class Life(object):
      """个体类"""
      def __init__(self, aGene = None):
            self.gene = aGene
            self.score = SCORE_NONE

3.TSP_GA.py 旅行商算法类,届时直接运行这个代码文件即可

# -*- encoding: utf-8 -*-

import random
import math
import Tkinter
from GA import GA

class TSP(object):
      def __init__(self, aLifeCount = 100,):
            self.initCitys()
            self.lifeCount = aLifeCount
            self.ga = GA(aCrossRate = 0.7, 
                  aMutationRate = 0.02,
                  aLifeCount = self.lifeCount, 
                  aGeneLength = len(self.citys),
                  aMatchFun = self.matchFun())


      def initCitys(self):
            self.citys = []
            #这个文件里是34个城市的经纬度
            f=open("distanceMatrix.txt","r")
            while True:
                  #一行一行读取
                  loci = str(f.readline())
                  if loci:
                        pass  # do something here
                  else:
                        break
                  #用readline读取末尾总会有一个回车,用replace函数删除这个回车
                  loci = loci.replace("\n", "")
                  #按照tab键分割
                  loci=loci.split("\t")
                  # 中国34城市经纬度读入citys
                  self.citys.append((float(loci[1]),float(loci[2]),loci[0]))

      #order是遍历所有城市的一组序列,如[1,2,3,7,6,5,4,8……]
      #distance就是计算这样走要走多长的路
      def distance(self, order):
            distance = 0.0
            #i从-1到32,-1是倒数第一个
            for i in range(-1, len(self.citys) - 1):
                  index1, index2 = order[i], order[i + 1]
                  city1, city2 = self.citys[index1], self.citys[index2]
                  distance += math.sqrt((city1[0] - city2[0]) ** 2 + (city1[1] - city2[1]) ** 2)

            return distance

      #适应度函数,因为我们要从种群中挑选距离最短的,作为最优解,所以(1/距离)最长的就是我们要求的
      def matchFun(self):
            return lambda life: 1.0 / self.distance(life.gene)


      def run(self, n = 0):
            while n > 0:
                  self.ga.next()
                  distance = self.distance(self.ga.best.gene)
                  print (("%d : %f") % (self.ga.generation, distance))
                  print self.ga.best.gene
                  n -= 1
            print "经过%d次迭代,最优解距离为:%f"%(self.ga.generation, distance)
            print "遍历城市顺序为:",
            # print "遍历城市顺序为:", self.ga.best.gene
            #打印出我们挑选出的这个序列中
            for i in self.ga.best.gene:
                  print self.citys[i][2],

def main():
      tsp = TSP()
      tsp.run(100)


if __name__ == '__main__':
      main()

4.34所城市经纬度distanceMatrix.txt

北京	116.46	39.92
天津	117.2	39.13
上海	121.48	31.22
重庆	106.54	29.59
拉萨	91.11	29.97
乌鲁木齐	87.68	43.77
银川	106.27	38.47
呼和浩特	111.65	40.82
南宁	108.33	22.84
哈尔滨	126.63	45.75
长春	125.35	43.88
沈阳	123.38	41.8
石家庄	114.48	38.03
太原	112.53	37.87
西宁	101.74	36.56
济南	117	36.65
郑州	113.6	34.76
南京	118.78	32.04
合肥	117.27	31.86
杭州	120.19	30.26
福州	119.3	26.08
南昌	115.89	28.68
长沙	113	28.21
武汉	114.31	30.52
广州	113.23	23.16
台北	121.5	25.05
海口	110.35	20.02
兰州	103.73	36.03
西安	108.95	34.27
成都	104.06	30.67
贵阳	106.71	26.57
昆明	102.73	25.04
香港	114.1	22.2
澳门	113.33	22.13

参考文献

https://blog.oldj.net/2010/05/22/ga-tsp/

http://www.tuicool.com/articles/Fb2YjeF


展开阅读全文

没有更多推荐了,返回首页