matlab 遗传优化算法_转载 | 遗传算法解决TSP问题的MATLAB实现

问题定义:

巡回旅行商问题

给定一组n个城市和俩俩之间的直达距离,寻找一条闭合的旅程,使得每个城市刚好经过一次且总的旅行距离最短。

TSP问题也称为货郎担问题,是一个古老的问题。最早可以追溯到1759年Euler提出的骑士旅行的问题。1948年,由美国兰德公司推动,TSP成为近代组合优化领域的典型难题。

TSP是一个具有广泛的应用背景和重要理论价值的组合优化问题。近年来,有很多解决该问题的较为有效的算法不断被推出,例如Hopfield神经网络方法,模拟退火方法以及遗传算法方法等。

TSP搜索空间随着城市数n的增加而增大,所有的旅程路线组合数为(n-1)!/2。在如此庞大的搜索空间中寻求最优解,对于常规方法和现有的计算工具而言,存在着诸多计算困难。借助遗传算法的搜索能力解决TSP问题,是很自然的想法。

基本遗传算法可定义为一个8元组:

  • (SGA)=(C,E,P0,M,Φ,Г,Ψ,Τ)

  • C ——个体的编码方法,SGA使用固定长度二进制符号串编码方法;

  • E ——个体的适应度评价函数;

  • P0——初始群体;

  • M ——群体大小,一般取20—100;

  • Ф——选择算子,SGA使用比例算子;

  • Г——交叉算子,SGA使用单点交叉算子;

  • Ψ——变异算子,SGA使用基本位变异算子;

  • Т——算法终止条件,一般终止进化代数为100—500;

问题的表示

  • 对于一个实际的待优化问题,首先需要将其表示为适合于遗传算法操作的形式。用遗传算法解决TSP,一个旅程很自然的表示为n个城市的排列,但基于二进制编码的交叉和变异操作不能适用。

  • 路径表示是表示旅程对应的基因编码的最自然,最简单的表示方法。它在编码,解码,存储过程中相对容易理解和实现。例如:旅程(5-1-7-8-9-4-6-2-3)可以直接表示为(5 1 7 8 9 4 6 2 3)。

产生初始种群

  • 一是完全随机产生,它适合于对问题的解无任何先验知识的情况。随机性较强,因而也较公正。

  • 二是某些先验知识可转变为必须满足的一组要求,然后在满足这些要求的解中在随机地选取样本。这样选择初始种群可使遗传算法更快的达到最优解。种群有一定的目标性和代表性,但取例不如完全随机的广泛,而且先验知识是否可靠也是一个问题。

适应度函数

  • 遗传算法在进化搜索中基本不利用外部信息,仅以适应度函数为依据,利用种群中每个个体的适应度值来进行搜索。TSP的目标是路径总长度为最短,路径总长度的倒数就可以为TSP的适应度函数:

276026ec534eda4f352bb6ae43c2a1c5.png

选择

一般地说,选择将使适应度较大(优良)个体有较大的存在机会,而适应度较小(低劣)的个体继续存在的机会也较小。简单遗传算法采用赌轮选择机制,令Σfi表示群体的适应度值之总和,fi表示种群中第i个染色体的适应度值,它产生后代的能力正好为其适应度值所占份额fi/Σfi。

交叉

基于路径表示的编码方法,要求一个个体的染色体编码中不允许有重复的基因码,也就是说要满足任意一个城市必须而且只能访问一次的约束。基本遗传算法的交叉操作生成的个体一般不能满足这一约束条件。

部分匹配交叉操作要求随机选取两个交叉点,以便确定一个匹配段,根据两个父个体中两个交叉点之间的中间段给出的映射关系生成两个子个体。

5ca68953d35b39f389b7007817732f7e.png

变异

遗传算法解决TSP 问题基于二进值编码的变异操作不能适用,不能够由简单的变量的翻转来实现

在TSP问题中个体的编码是一批城市的序列,随机的在这个序列抽取两个城市,然后交换他们的位置。这样就实现了个体编码的变异,算法如下:

  1. 产生两个0到1之间的随机实数;

  2. 将这两个随机实数转化为0到n(城市数)-1之间的随机整数;

  3. 将这两个随机整数指代的城市进行交换;

流程图

6f381a666721f8e81e306bdb26a394c2.png

代码

主函数代码:

clear;

clc;

tStart= tic;% 算法计时器

%%%%%%%%%%%%自定义参数%%%%%%%%%%%%%

[cityNum,cities]= Read('dsj1000.tsp');

cities= cities';

%cityNum=100;

maxGEN = 1000;

popSize = 100; % 遗传算法种群大小

crossoverProbabilty = 0.9; %交叉概率

mutationProbabilty = 0.1; %变异概率

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

gbest = Inf;

%随机生成城市位置

%cities=rand(2,cityNum)*100;%100是最远距离

%计算上述生成的城市距离

distances = calculateDistance(cities);

%生成种群,每个个体代表一个路径

pop = zeros(popSize, cityNum);

for i=1:popSize

    pop(i,:) = randperm(cityNum);

end

offspring = zeros(popSize,cityNum);

%保存每代的最小路劲便于画图

minPathes = zeros(maxGEN,1);

%GA算法

for  gen=1:maxGEN

    % 计算适应度的值,即路径总距离

    [fval, sumDistance, minPath, maxPath] = fitness(distances, pop);

    % 轮盘赌选择

    tournamentSize=4; %设置大小

    for k=1:popSize

        % 选择父代进行交叉

        tourPopDistances=zeros( tournamentSize,1);

        for i=1:tournamentSize

            randomRow = randi(popSize);

            tourPopDistances(i,1) = sumDistance(randomRow,1);

        end

        % 选择最好的,即距离最小的

        parent1  = min(tourPopDistances);

        [parent1X,parent1Y] = find(sumDistance==parent1,1, 'first');

        parent1Path = pop(parent1X(1,1),:);

        for i=1:tournamentSize

            randomRow = randi(popSize);

            tourPopDistances(i,1) = sumDistance(randomRow,1);

        end

        parent2  = min(tourPopDistances);

        [parent2X,parent2Y] = find(sumDistance==parent2,1, 'first');

        parent2Path = pop(parent2X(1,1),:);

        subPath = crossover(parent1Path, parent2Path, crossoverProbabilty);%交叉

        subPath = mutate(subPath, mutationProbabilty);%变异

        offspring(k,:) = subPath(1,:);

        minPathes(gen,1) = minPath;

    end

    fprintf('代数:%d   最短路径:%.2fKM \n', gen,minPath);

    % 更新

    pop= offspring;

    % 画出当前状态下的最短路径

    ifminPath< gbest

        gbest= minPath;

        paint(cities,pop,gbest,sumDistance,gen);

    end

end

figure

plot(minPathes,'MarkerFaceColor','red','LineWidth',1);

title('收敛曲线图(每一代的最短路径)');

set(gca,'ytick',500:100:5000);

ylabel('路径长度');

xlabel('迭代次数');

gridon

tEnd= toc(tStart);

fprintf('时间:%d 分  %f 秒.\n',floor(tEnd/60),rem(tEnd,60));

function[distances]= calculateDistance(city)

%计算距离

    [~,col]= size(city);

    distances= zeros(col);

    fori=1:col

        forj=1:col

            distances(i,j)= distances(i,j)+ sqrt((city(1,i)-city(1,j))^2+ (city(2,i)-city(2,j))^2  );          

        end

    end

end

function[childPath]= crossover(parent1Path,parent2Path,prob)

%交叉

    random= rand();

    ifprob>= random

        [l,length]= size(parent1Path);

        childPath= zeros(l,length);

        setSize= floor(length/2)-1;

        offset= randi(setSize);

        fori=offset:setSize+offset-1

            childPath(1,i)= parent1Path(1,i);

        end

        iterator= i+1;

        j= iterator;

        whileany(childPath== 0)

            ifj> length

                j= 1;

            end

            ifiterator> length

                iterator= 1;

            end

            if~any(childPath== parent2Path(1,j))

                childPath(1,iterator)= parent2Path(1,j);

               iterator= iterator+ 1;

            end

            j= j+ 1;

        end

    else

        childPath= parent1Path;

    end

end

function[fitnessvar,sumDistances,minPath,maxPath]= fitness(distances,pop)

%计算整个种群的适应度值

    [popSize,col]= size(pop);

    sumDistances= zeros(popSize,1);

    fitnessvar= zeros(popSize,1);

    fori=1:popSize

       forj=1:col-1

          sumDistances(i)= sumDistances(i)+ distances(pop(i,j),pop(i,j+1));

       end

    end

    minPath= min(sumDistances);

    maxPath= max(sumDistances);

    fori=1:length(sumDistances)

        fitnessvar(i,1)=(maxPath- sumDistances(i,1)+0.000001)/ (maxPath-minPath+0.00000001);

    end

end

function[mutatedPath]= mutate(path,prob)

%对指定的路径利用指定的概率进行更新

    random= rand();

    ifrandom<= prob

        [l,length]= size(path);

        index1= randi(length);

        index2= randi(length);

        %交换

        temp= path(l,index1);

        path(l,index1)= path(l,index2);

        path(l,index2)=temp;

    end

        mutatedPath= path;

end

function[output_args]= paint(cities,pop,minPath, totalDistances, gen)

    gNumber=gen;

    [~,length]= size(cities);

    xDots= cities(1,:);

    yDots= cities(2,:);

    %figure(1);

    title('GA TSP');

    plot(xDots,yDots,'p','MarkerSize',14,'MarkerFaceColor','blue');

    xlabel('经度');

    ylabel('纬度');

    axisequal

    holdon

    [minPathX,~]= find(totalDistances==minPath,1,'first');

    bestPopPath= pop(minPathX,:);

    bestX= zeros(1,length);

    bestY= zeros(1,length);

    forj=1:length

       bestX(1,j)= cities(1,bestPopPath(1,j));

       bestY(1,j)= cities(2,bestPopPath(1,j));

    end

    title('GA TSP');

    plot(bestX(1,:),bestY(1,:),'red','LineWidth',1.25);

    legend('城市','路径');

    axisequal

    gridon

    %text(5,0,sprintf('迭代次数: %d 总路径长度: %.2f',gNumber, minPath),'FontSize',10);

    drawnow

    holdoff

end

function[n_citys,city_position]= Read(filename)

fid= fopen(filename,'rt');

location=[];

A= [12];

tline= fgetl(fid);

whileischar(tline)

    if(strcmp(tline,'NODE_COORD_SECTION'))

        while~isempty(A)

            A=fscanf(fid,'%f',[3,1]);

            ifisempty(A)

                break;

            end

            location=[location;A(2:3)'];

        end

    end

    tline = fgetl(fid);

    if strcmp(tline,'EOF')

        break;

    end

end

[m,n]=size(location);

n_citys= m;

city_position=location;

fclose(fid);

end

结果

测试数据:

adaa0b2e40c4f34d9f584ea88ced2662.png

初始态:

d81d79502fd4dfb49115ea6a10fd6dab.png

终态:

8f2e85873daf369e2e61d28c0352380b.png

收敛曲线:

53736b3841829a10e9cb332ff9d1da01.png

可以看到,当城市数量适中时,迭代500次最短路径长度有收敛的趋势。

当城市数目较多时

a061e85952f1527fe33d146d5934c6cc.png

迭代500次,仍然不收敛,可能的问题是陷入了局部最优解。

总结与观点

难点是交叉算法的设计,由于TSP问题和一般的NP问题不一样,每个个体的每个维度具有唯一性,因此在交叉的时候要注意不能有重复的值。本次实验采用的是部分匹配交叉,先从第一个父代选出一个偏移量,从偏移量后的部分点加入到子代,接下来从第二个父代选择第一代没有选择的部分点移到子代中。

当城市数量较多时,大于50个城市,迭代多次,GA仍然不收敛,可能的问题是陷入了局部最优解,因此对GA算法进行改进怡跳出局部最优解,可以采用类似于PSO或者蚁群算法的思想。

数据集下载

https://github.com/xyjigsaw/Dataset

转载自:

https://www.omegaxyz.com/2019/01/21/matlab-tsp-all/

作者:OmegaXYZ

https://www.omegaxyz.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/527588.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php 如何配置 redis,php 如何设置redis

php设置redis的方法&#xff1a;首先安装redis服务及PHP redis驱动&#xff1b;然后打开php.ini文件&#xff1b;接着增加内容为“extensionredis.so”&#xff1b;最后重启php-fpm或apache即可。PHP 设置使用 Redis安装开始在 PHP 中使用 Redis 前&#xff0c; 我们需要确保已…

java数组有跨类建立对象_Java性能优化的45个细节(珍藏版)

点击上面 蓝色字体关注我们技术 / 架构 / 职场 / 面试 关注即送&#xff1a;4000G 架构师视频来源&#xff1a;http://t.cn/EiP42VF在JAVA程序中&#xff0c;性能问题的大部分原因并不在于JAVA语言&#xff0c;而是程序本身。养成良好的编码习惯非常重要&#xff0c;能够显著地…

java 数据纠错,纠错码简介

纠错码是个什么东西引出网络中的通信基于TCP和UDP两个通信协议, 这大家都知道的, 什么TCP的三次握手等等, 面试经常被问到. 三次握手是为了保证连接的正确建立. 但是, 在通信的时候, 你如何保证你的消息正确送达了呢? 有人说了, 有收到请求的响应包. 但我说的不是这个,比如说,…

dataframe修改数据_数据处理进阶pandas入门(一)

前言NumPy作为数据处理的利器&#xff0c;在对数据进行科学计算、存储处理大型矩阵等方面为我们带来了极大的方便&#xff0c;但对于更进一步的数据分析任务&#xff0c;文件操作等方面显得有些吃力。于是&#xff0c;作为NumPy的进阶库pandas应运而生&#xff0c;在实际应用中…

java6个人抽奖抽三个人,基于Java的抽奖逻辑

小组在做一个抽奖系统&#xff0c;现在给我分配到了抽奖逻辑这方面的实现。EMMM&#xff0c;拿到分配的时候是懵B的。老大给的需求图给的关键表结构DROP TABLE IF EXISTS dd_annual_meeting_check;CREATE TABLE dd_annual_meeting_check (check_id int(255) NOT NULL AUTO_INCR…

python自动化教程_Python 任务自动化工具 tox 教程

1、tox 能做什么&#xff1f; 细分的用途包括&#xff1a; 创建开发环境 运行静态代码分析与测试工具 自动化构建包 针对 tox 构建的软件包运行测试 检查软件包是否能在不同的 Python 版本/解释器中顺利安装 统一持续集成&#xff08;CI&#xff09;和基于命令行的测试 创建和部…

php 添加inotify扩展,php inotify 扩展的安装

一、安装1) 从内核和目录里面查看是否支持inotify[rootnfs01 ~]# uname -r2.6.32-573.el6.x86_64[rootnfs01 ~]#** ls -l /proc/sys/fs/inotify/** -→主要查看下面有没有三个目录总用量 0-rw-r--r-- 1 root root 0 1月 21 13:03 max_queued_events-rw-r--r-- 1 root root…

简述python执行原理_Python程序的执行原理(1)(2)

Python程序的执行原理(1)&#xff08;2&#xff09; 1. 过程概述 Python先把代码&#xff08;.py文件&#xff09;编译成字节码&#xff0c;交给字节码虚拟机&#xff0c;然后虚拟机一条一条执行字节码指令&#xff0c;从而完成程序的执行。 2. 字节码 字节码在Python虚拟机程序…

python文本特征选择,机器学习--特征选择(Python实现)

特征选择就是从原始特征中选取一些最有效的特征来降低维度,&#xff0c;提高模型泛化能力减低过拟合的过程&#xff0c;主要目的是剔除掉无关特征和冗余特征&#xff0c;选出最优特征子集&#xff1b;常见的特征选择方法可以分为3类&#xff1a;过滤式(filter)、包裹式(wrapper…

用python画风车_python接口自动化()一)(实现一款简单的接口自动化框架)

python接口自动化一&#xff08;设计一款自己的接口自动化框架&#xff09; 一、起因&#xff1a; 前面学习过了python接口requests来进行接口测试&#xff0c;但是在框架选择上还是选择的unittest。当接口数量不怎么多时还好&#xff0c;但是当接口的量上去了&#xff0c;一切…

系统新模块增加需要哪些步骤_防锈高效型干式地暖模块解决了装修施工配合的哪些难点?...

通过前面的讲解&#xff0c;我们知道铝板干式地暖末端应用于地暖、辐射冷暖等系统的技术优势非常明显&#xff0c;即省层高、省费用、效果好、空调舒适、业主使用满意度高等&#xff0c;随着水泥黄沙的大幅涨价&#xff0c;其成本优势也突显出来&#xff0c;越来越多的暖通公司…

python爬取网站数据步骤_python怎么爬取数据

在学习python的过程中&#xff0c;学会获取网站的内容是我们必须要掌握的知识和技能&#xff0c;今天就分享一下爬虫的基本流程&#xff0c;只有了解了过程&#xff0c;我们再慢慢一步步的去掌握它所包含的知识Python网络爬虫大概需要以下几个步骤&#xff1a; 一、获取网站的地…

matlab chan算法定位,MATLAB实现基于Chan氏算法的三维TDOA定位

% 功能&#xff1a;基于chan算法的TDOA三维定位function [zp] Chan_3(Noise,MS)%基站数目BSN 7;%基站位置,每一列为一个基站位置BS [0, 2*sqrt(3), -2*sqrt(3), sqrt(3), -sqrt(3), -sqrt(3), sqrt(3);0, 0, 0, 3, 3, -3, -3;0, 0, 0, 0, 2, 2, 0];%无噪声情况下BS到MS的距离…

Redis源码精读:字符串

文章目录 前言代码位置核心类型SDS结构获取sds字符串的元数据的宏获取字符串长度重新设置sds长度创建字符串感悟最后 前言 Redis中实现了sds&#xff08;simple dynamic string&#xff09;这种字符串&#xff0c;它比c语言标准库的char*字符串更加实用 代码位置 src/sdc.h …

python自动化测试脚本可以测php吗_python unittest实现api自动化测试_python

这篇文章主要为大家详细介绍了python unittest实现api自动化测试的方法&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可以参考一下 项目测试对于一个项目的重要性&#xff0c;大家应该都知道吧&#xff0c;写python的朋友&#xff0c;应该都写过自动化测试脚本。…

Linux服务器版本鼠标,安装GPM给Linux虚拟控制台提供配置鼠标支持

给你的 Linux 系统安装 GPM&#xff0c;这样我们就可以在虚拟控制台中配置鼠标&#xff0c;比如进行复制与粘贴操作。GPM 是一个守护程序&#xff0c;是通用鼠标的首字母的缩写&#xff0c;它可以帮助你配置 Linux 虚拟控制台的鼠标支持。GPM 在以下场景中特别有用&#xff1a;…

valgrind 内存泄漏_应用 AddressSanitizer 发现程序内存错误

应用 AddressSanitizer 发现程序内存错误作为 C/ C 工程师&#xff0c;在开发过程中会遇到各类问题&#xff0c;最常见便是内存使用问题&#xff0c;比如&#xff0c;越界&#xff0c;泄漏。过去常用的工具是 Valgrind&#xff0c;但使用 Valgrind 最大问题是它会极大地降低程序…

配置文件存int类型_Redis详解(五)------ redis的五大数据类型实现原理

> 本系列教程持续更新&#xff0c;可以微信搜索「 IT可乐 」第一时间阅读。回复《电子书》有我为大家特别筛选的书籍资料前面两篇博客&#xff0c;第一篇介绍了五大数据类型的基本用法&#xff0c;第二篇介绍了Redis底层的六种数据结构。在Redis中&#xff0c;并没有直接使用…

java list 占用内存不释放_性能不打折,内存占用减少90%,Facebook提出极致模型压缩方法Quant-Noise...

对于动辄上百 M 大小的神经网络来说&#xff0c;模型压缩能够减少它们的内存占用、通信带宽和计算复杂度等&#xff0c;以便更好地进行应用部署。最近&#xff0c;来自 Facebook AI 的研究者提出了一种新的模型量化压缩技术 Quant-Noise&#xff0c;让神经网络在不降低性能的前…

苹果系统安装python环境_如何在mac下配置python虚拟环境

安装python虚拟环境核心目的就是为了复制一个python环境,这样新项目下载的所有包,都会存放在虚拟环境下的python site-package 中 首先安装 1. sudo pip install virtualenv # 安装虚拟环境 2. sudo pip install virtualenvwrapper # 安装虚拟环境扩展包 3. vim .bash_profile …