TSP问题(34个省会城市):遗传算法

# -*- encoding: utf-8 -*-
# 利用遗传算法求解TSP问题
import random
import math

SCORE_NONE = -1


class Life(object):
    """个体类"""

    def __init__(self, aGene=None):
        self.gene = aGene
        self.score = SCORE_NONE


class GA(object):
    """遗传算法类"""

    def __init__(self, aCrossRate, aMutationRage, aLifeCount, aGeneLenght, aMatchFun):
        # lambda作为一个表达式,定义了一个匿名函数
        self.croessRate = aCrossRate  # 交叉概率
        self.mutationRate = aMutationRage  # 突变概率
        self.lifeCount = aLifeCount  # 种群中个体数量
        self.geneLenght = aGeneLenght  # 基因长度
        self.matchFun = aMatchFun  # 适配函数
        self.lives = []  # 种群
        self.best = None  # 保存这一代中最好的个体
        self.generation = 1  # 第几代
        self.crossCount = 0  # 交叉计数
        self.mutationCount = 0  # 变异计数
        self.bounds = 0.0  # 适配值之和,用于选择是计算概率
        self.mean = 1.0  # 适配值平均值
        self.initPopulation()

    def initPopulation(self):
        """初始化种群"""
        self.lives = []
        for i in range(self.lifeCount):
            gene = [x for x in range(self.geneLenght)]
            random.shuffle(gene)  # 用来对一个元素序列进行重新随机排序
            life = Life(gene)
            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
            if self.best.score < life.score:
                self.best = life
        self.mean = self.bounds / self.lifeCount

    def cross(self, parent1, parent2):
        """交叉"""
        n = 0
        while 1:
            newGene = []
            index1 = random.randint(0, self.geneLenght - 1)  # 用于生成一个指定范围内的整数
            index2 = random.randint(index1, self.geneLenght - 1)
            tempGene = parent2.gene[index1:index2]  # 交叉的基因片段
            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
            if (self.matchFun(Life(newGene)) > max(self.matchFun(parent1), self.matchFun(parent2))):
                self.crossCount += 1
                return newGene
            # else:
            #       rate = random.random()
            #       if rate < math.exp(-100 / math.sqrt(self.generation)):
            #             self.crossCount += 1
            #             return newGene
            if (n > 100):
                self.crossCount += 1
                return newGene
            n += 1

    def mutation(self, egg):
        """突变"""
        index1 = random.randint(0, self.geneLenght - 1)
        index2 = random.randint(0, self.geneLenght - 1)
        newGene = egg.gene[:]  # 产生一个新的基因序列,以免变异的时候影响父种群
        newGene[index1], newGene[index2] = newGene[index2], newGene[index1]
        if self.matchFun(Life(newGene)) > self.matchFun(egg):
            self.mutationCount += 1
            return newGene
        else:
            rate = random.random()
            if rate < math.exp(-10 / math.sqrt(self.generation)):
                self.mutationCount += 1
                return newGene
            return egg.gene

    def getOne(self):
        """选择一个个体"""
        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.croessRate:
            # 交叉
            parent2 = self.getOne()
            gene = self.cross(parent1, parent2)
        else:
            gene = parent1.gene

        # 按概率突变
        rate = random.random()
        if rate < self.mutationRate:
            gene = self.mutation(Life(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


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

    def initCitys(self):
        self.citys = []

        # 中国34个省会城市的经纬度坐标
        self.citys.append((116.46, 39.92))
        self.citys.append((117.2, 39.13))
        self.citys.append((121.48, 31.22))
        self.citys.append((106.54, 29.59))
        self.citys.append((91.11, 29.97))
        self.citys.append((87.68, 43.77))
        self.citys.append((106.27, 38.47))
        self.citys.append((111.65, 40.82))
        self.citys.append((108.33, 22.84))
        self.citys.append((126.63, 45.75))
        self.citys.append((125.35, 43.88))
        self.citys.append((123.38, 41.8))
        self.citys.append((114.48, 38.03))
        self.citys.append((112.53, 37.87))
        self.citys.append((101.74, 36.56))
        self.citys.append((117, 36.65))
        self.citys.append((113.6, 34.76))
        self.citys.append((118.78, 32.04))
        self.citys.append((117.27, 31.86))
        self.citys.append((120.19, 30.26))
        self.citys.append((119.3, 26.08))
        self.citys.append((115.89, 28.68))
        self.citys.append((113, 28.21))
        self.citys.append((114.31, 30.52))
        self.citys.append((113.23, 23.16))
        self.citys.append((121.5, 25.05))
        self.citys.append((110.35, 20.02))
        self.citys.append((103.73, 36.03))
        self.citys.append((108.95, 34.27))
        self.citys.append((104.06, 30.67))
        self.citys.append((106.71, 26.57))
        self.citys.append((102.73, 25.04))
        self.citys.append((114.1, 22.2))
        self.citys.append((113.33, 22.13))

    def distance(self, order):
        distance = 0.0
        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

    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(("Generation: %4d \t\t Distance: %f") % (self.ga.generation-1, distance))  # 输出当前代数和路径长度
            self.ga.best.gene.append(self.ga.best.gene[0])
            print("Path: ", self.ga.best.gene)  # 输出当前最佳路径
            self.ga.best.gene.pop()
            n -= 1


if __name__ == '__main__':
    tsp = TSP()
    tsp.run(100)

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值