最短距离:遗传算法改进——python实现

本文介绍了如何使用遗传算法解决经典数学建模问题——旅行商问题。通过Python实现,优化了遍历大量可能路径的计算量,采用遗传算法进行路径优化,并展示了算法运行过程及最优解。在算法中,设置了种群大小、进化代数、交叉率和变异率等参数,以找到二十个位置之间的最短总距离。
摘要由CSDN通过智能技术生成

最短距离:遗传算法改进——python实现


针对上一篇文章,实现改进的部分


前言

在数学建模中经典的问题——最优距离,遍历可能是我们找到最优距离的最好办法。但是如果面对众多的需要优化的位置,那么计算量将会特别大,如有二十个位置,那么遍历需要的次数为20的阶乘次,计算量可想而知的恐怖,因此引入遗传算法

遗传算法实现

import numpy as np
import matplotlib.pyplot as plt

pop_size = 500     #每次计算的方案数量,也就是路径优化的方案数量
n_epoch = 800     #算法遗传的次数
dna_size = 20     #二十个位置
cross_rate = 0.8      #交配比例
mutate_rate = 0.1     #编译比例

class GA:
    def __init__(self,pop_size,n_poch,dna_size,cross_rate,mutate_rate):
        self.pop_size = pop_size
        self.n_epoch = n_epoch
        self.dna_size = dna_size
        self.cross_rate = cross_rate
        self.mutate_rate = mutate_rate

        self.pop = np.vstack([np.random.permutation(self.dna_size) for i in range(self.pop_size)])
        self.city = np.random.rand(self.dna_size,2)      #随机生成坐标点
        print(self.pop.shape)

    def get_fitness(self,parent_1,parent_2):

        way_1 = self.city[parent_1]
        way_2 = self.city[parent_2]
        # print(way_1.shape,way_2.shape)

        x_1 = sum(np.sqrt(np.square(np.diff(way_1[:,0]))+np.square(np.diff(way_1[:,1]))))
        x_2 = sum(np.sqrt(np.square(np.diff(way_2[:,0]))+np.square(np.diff(way_2[:,1]))))
        return x_1>x_2

    def cross(self,winner,loser):
        inx = []
        for i in range(0,self.dna_size):
            if np.random.rand()<cross_rate:
                inx.append(True)
            else:
                inx.append(False)
        child_1 = winner[:-1][inx]
        child_2 = winner[:-1][np.isin(winner[:-1],child_1,invert=True)]


        loser = np.append(child_1,child_2)
        loser = np.append(loser,loser[0])
        # print(loser)
        return loser

    def mutate(self,loser):
        for i in range(1,self.dna_size):
            if np.random.rand()<mutate_rate:
                idx = np.random.randint(1,self.dna_size,1)
                loser[i],loser[idx] = loser[idx],loser[i]
        return loser

    def get_best(self):
        x = np.empty(self.pop.shape, dtype=np.float64)
        y = np.empty(self.pop.shape, dtype=np.float64)
        for i, d in enumerate(self.pop):
            distance = self.city[d]
            x[i, :] = distance[:, 0]
            y[i, :] = distance[:, 1]
        x_, y_ = x[:, 0].reshape(-1, 1), y[:, 0].reshape(-1, 1)

        # 下面这两句是计算是否返回原来地方的最优路径
        x = np.concatenate((x, x_), axis=1)
        y = np.concatenate((y, y_), axis=1)
        total_distance = np.empty(len(x), dtype=np.float64)
        for i, (xs, ys) in enumerate(zip(x, y)):
            total_distance[i] = np.sum(np.sqrt(np.square(np.diff(xs)) + np.square(np.diff(ys))))
        fitness = np.exp(self.dna_size * 2 / total_distance)
        num = self.pop[np.argmax(fitness)]
        num = [str(i) for i in num]
        num = '>'.join(num) + '>' + num[0]

        # print(' '.join(self.pop[np.argmax(fitness)]))
        return x[np.argmax(fitness)], y[np.argmax(fitness)], total_distance[np.argmax(fitness)], num

    def evolve(self,n):
        plt.ion()
        for ii in range(self.n_epoch):
            x_,y_,total_dis,num = self.get_best()
            plt.cla()
            plt.scatter(self.city[:,0],self.city[:,1],c='r')
            plt.plot(x_,y_,c='b')
            plt.text(0.1,0.7,'{0}'.format(num))
            plt.text(0.8,0.8,'{0}'.format(str(total_dis)))
            plt.title('num_{0} figure'.format(str(ii)))
            plt.pause(0.05)
            print('num_{0} best distance:{1}'.format(ii,str(total_dis)))
            for _ in range(n):
                idx_1 = np.random.randint(0, self.pop_size, 2)
                parent_1, parent_2 = self.pop[idx_1[0]], self.pop[idx_1[1]]
                parent_1,parent_2 = np.append(parent_1,parent_1[0]),np.append(parent_2,parent_2[0])
                if self.get_fitness(parent_1, parent_2):
                    winner, loser = parent_2, parent_1
                else:
                    winner, loser = parent_1, parent_2
                loser = self.cross(winner, loser)
                loser = self.mutate(loser)
                self.pop[idx_1[0]], self.pop[idx_1[1]] = winner[:-1], loser[:-1]
        plt.ioff()
        plt.show()
ga = GA(pop_size=pop_size,n_poch=n_epoch,dna_size=dna_size,cross_rate=cross_rate,mutate_rate=mutate_rate)
ga.evolve(200)



下面为绘制的结果
在这里插入图片描述

总结

甘愿为理想“头破血流”

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值