TSP的人工智能求解问题Word文档格式.docx
- 文档编号:20302960
- 上传时间:2023-01-21
- 格式:DOCX
- 页数:14
- 大小:22.29KB
TSP的人工智能求解问题Word文档格式.docx
《TSP的人工智能求解问题Word文档格式.docx》由会员分享,可在线阅读,更多相关《TSP的人工智能求解问题Word文档格式.docx(14页珍藏版)》请在冰豆网上搜索。
2符号说明
V顶点的集合
C过所有定点且最后回到起点的圈(不重复)
vi第i个城市的标号,i=1,2,…10
E所有边的集合
eijvi到vj的边
wijvi到vj距离
Tx巡回路线
G巡回路线城市列表
gi在访问中第n个被访问的城市
W圈C的权值
Pm变异概率
F适应度函数
3模型假设
1假设n取10已经足够大
2假设变异概率以及适应度函数准确
3在交叉运算和变异运算中没有产生不满足约束条件或无实际意义的巡回路线
4设随机选取的r准确
4问题分析
这可以归结为一个图论问题:
给出一个图G=(V,E),每个边eij∈E,且每一个边e上都有非负权值w(e),寻找一个G的一个回路C,使得C不重复过定点vi(i=1,2,…n),使C的总权W(C)=∑w(e)(其中e∈E)最小。
可以知道,总的旅程路线为组合数(n-1)!
/2,TSP搜索空间随着城市数n的增加而增大,一般很难精确地求出其精确的最优解,因此利用遗传算法的思想对旅行商所经过的城市进行编码,将问题空间的数据映射成遗传空间的基因串结构数据。
用遗传算法解决TSP,一个旅程很自然地表示为n个城市的排列,但基于二进制编码的交叉和变异操作不能适用,因此利用Grefenstette方法对其进行编码,对这些已经编码的数据,再利用遗传算法常用的单点交叉对路径进行交叉变换,并且利用变异概率对路径进行进一步修正,从而得到接近的解。
5模型建立
5.1交叉模型的建立
5.1.1城市编码的设计
常规的交叉运算和变异运算使群体中产生一些不满足问题约束条件或者无实际意义的巡回录像,为了克服这种编码方法的缺点,基于对各个城市的访问顺序,采用由Grefenstette等提出的一种新的巡回路线编码方法,该方法可以使得任意的基因型个体都能够对应一条具有实际意义的巡回路线,下面对这种新的编码方法进行介绍:
对于一个旅行商问题的城市列表M,假定各个城市的一个访问顺序为T:
T=(t1,t2,t3,…,ti,…tn)
规定每访问完一个城市,就从城市列表M中将该城市删除,则用第i个访问的城市ti在所有未访问的城市列表M-{t1,t2,…ti-1}中对应位置序号gi就可以表示具体访问哪个城市,如此处理玩M中的所有的城市。
将所有的gi排列在一起得到一个列表:
G=(g1,g2,…gn)
就可以表示成一条巡回路线,它即为遗传算法的一个个体的基因型。
为了方便运算,取10个城市:
M=(ABCDEFGHIJ)
现在有两条巡回旅行路线:
Tx=(ADBHFIJGEC)
Ty=(BCADEJHIFG)
按照上述Grefenstette所提出的编码方法,这两条巡回旅行路线可以编码为
Gx=(1315344321)
Gy=(2211153311)
5.2.2单点交叉方法
旅行商问题对于交叉算子的设计要求是:
对于任意两条巡回路线进行交叉操作之后,都能得到另外两条新的并且具有实际意义的巡回路线。
下面介绍本文即将使用的单点交叉:
对于旅行商问题,使用Grefenstette等所提出的编码方法来表示个体时,个体基因和个体表现型之间具有一一对应的关系,特别是它使得经过遗传运算后得到的任意一个基因型个体都能够对应一条具有实际意义的巡回路线。
这样,就可以用基本遗传算法来求解旅行商问题,而无需重新去开发一些位置重排序的遗传算子。
这时,交叉运算可以使用通常的单点交叉算子。
所谓单点交叉可以理解为下:
仍然以取前十个城市,以所给出的两条巡回路线Gx和Gy为例,取单点交叉操作的交叉点在第6个和第7个基因座之间,则对Gx和Gy进行进行交叉操作后可以得到两个新的个体Gx1和Gy1:
Gx=(131534|4321)
Gy=(221115|3311)
单点交叉后:
Gx1=(131534|3311)
Gy1=(221115|4321)
此时,对其进行解码处理后,可以得到两条新的巡回路线
Tx1=(ADBHFIGJCE)
Tx2=(BCADEJIHGF)
就以这种方法对题目所给的十个城市进行编码和解码。
5.2变异模型的建立
遗传算法中的所谓的变异运算,是指将个体染色体编码串中的某些基因值用该基因座的其他等位基因来替换,从而形成一个新的个体。
遗传算法使用交叉算子已经接近或者有助于接近问题的最优解,但是仅仅使用交叉算子无法对搜索空间的细节进行局部搜索,使用变异算子来调整个体编码串中的部分基因值,就可以提高遗传算法的局部搜索能力。
本文采用的是基础位变异(SimpleMutation)中的均匀变异(UniformMutation),使用的是均匀变异算子,类似交叉操作中选择父代的过程,在r<
pm的标准下选择多个染色体vi作为父代。
对每一个选择的父代,随机选择多个位置,使其在每位置按均匀变异[0,1]中随机数r,(该变异点xk的取值范围为[u^kmin,u^kmax]该点变异为x’k=ukmin+r(ukmax-ukmin))操作。
如:
81421386325
7
变异后:
8142131063227
交叉和变异都是在Grefenstette编码之后进行的,为了循环操作和返回最终结果,必须逆Grefenstette编码过程,将编码恢复到自然编码。
本文利用这种变异方法,对十个城市进行变异求的最接近的解。
这里取r=0.1。
6、模型求解和分析
6.1根据建立的模型的模型,用C语言变成进行求解。
(详见附录A)
6.2结果分析
对于本题目中10个城市TSP坐标信息,应用C语言进行求解,可以达到最优旅程为ACBIFEGJHD旅行长度为24.38。
采用遗传算法方法,种群大小为50,交叉概率为0.9,终止代数为15,总共运行200次。
7模型评价
借助遗传算法的搜索能力解决TSP问题,是一个很自然的想法。
于此同时,单点交叉和均匀变异通俗易懂。
但是,均匀变异操作改变的知识个体编码串中的个别基因座中基因值,并且变异发生的概率比较小,所以其发挥的作用比较慢,作用的效果也不是很明显。
此外,对于旅行商问题,使用Grefentette等所提出的编码方法来表示个体时,染色体编码串中位于前面的一些基因座上的基因值的改变,会对位于后面的基因座上的基因值有不同的解释,所以这里使用的单点交叉算子,个体在交叉点之前的性状能够被完全继承下来,在交叉之后的性状就改变的相当的大。
8参考文献
AnsariN,HouE.用于最优化的计算智能.李军,边肇祺译.北京:
清华大学出版社,2009年。
【1】附录A
【2】#include"
stdio.h"
【3】#include"
string.h"
【4】#include"
stdlib.h"
【5】#definecity_num10//城市个数
【6】#defineunit_num50//群体规模为50
【7】#definepc0.9//交叉概率为0.9
【8】#definepv0.1//变异概率为10%
【9】#defineps0.6//进行选择时保留的比例
【10】#definegenmax15//最大代数15
【11】/*定义个体信息*/
【12】typedefstructunit
【13】{
【14】intpath[city_num];
//个体的路径信息
【15】intlength;
//个体代价值
【16】}Unit;
【17】typedefstructnode
【18】{
【19】intcity;
【20】structnode*next;
【21】}Node;
【22】Unitgroup[unit_num];
//种群变量group
【23】Unitbestone;
//记录最短路径
【24】
【25】intgeneration_num=0;
//记录当前达到第几代
【26】/*检查k是否在son[city_num]中已出现过*/
【27】Node*search_son(Node*p,intk)
【28】while(p->
next->
city!
=k)
【29】p=p->
next;
【30】returnp;
【31】/*将种群中个体按代价从小到大排序*/
【32】
【33】voidSort(Unitgroup[unit_num])
【34】{inti,j;
【35】Unittemp,*p1,*p2;
【36】for(j=1;
j<
=unit_num-1;
j++)//排序总共需进行N-1轮
【37】{
【38】for(i=1;
i<
i++)
【39】{
【40】p1=&
group[i-1];
【41】p2=&
group[i];
【42】if(p1->
length>
p2->
length)//总长度大的往后排
【43】{
【44】memcpy(&
temp,p1,sizeof(Unit));
【45】memcpy(p1,p2,sizeof(Unit));
【46】memcpy(p2,&
temp,sizeof(Unit));
【47】}//endif
【48】}//end一轮排序
【49】}//end排序
【50】if(group[0].length<
bestone.length)//记录最优个体
【51】memcpy(&
bestone,&
group[0],sizeof(Unit));
【52】}
【53】/*计算某个路径的总长度*/
【54】voidCalculate_length(Unit*p)
【55】{
【56】intj;
【57】p->
length=0;
【58】for(j=1;
=city_num-1;
j++)
【59】{
【60】p->
length+=length_table[p->
path[j-1]][p->
path[j]];
【61】}
【62】p->
path[city_num-1]][p->
path[0]];
【63】}
【64】/*生成一个介于两整型数之间的随机整数*/
【65】
【66】intRandomInteger(intlow,inthigh)
【67】
【68】{
【69】intrand_num;
【70】doubled;
【71】d=(double)(rand()%100)/100.0;
//d>
0&
&
d<
1
【72】rand_num=(int)(d*(high-low+1))+low;
【73】returnrand_num;
【74】}
【75】/*输出当代种群中的每个个体*/
【76】voidPrint_optimum(Unitgroup[unit_num],intk)
【77】{
【78】inti,j;
【79】Unit*p;
【80】printf("
当前第%d代:
\n"
k);
【81】for(i=0;
【82】{
【83】printf("
第%2d代,个体%2d:
"
k,i);
【84】p=&
【85】for(j=0;
【86】printf("
%d"
p->
path[j]);
【87】printf("
总路径长度为:
%d\n"
length);
【88】}
【89】}
【90】/*输出最优个体*/
【91】voidPrint_bestone(Unit*bestone)
【92】{
【93】inti;
【94】Unit*p=bestone;
【95】printf("
\n\n最优路径为:
);
【96】for(i=0;
【97】printf("
%d-->
path[i]);
【98】printf("
%d总路径长度为:
path[0],p->
【99】/*交叉*/
【100】voidCross_group(Unit*p1,Unit*p2,Unit*p3){
【101】inti,j,k,Cross_group_point;
【102】inta,b,c;
【103】intson[city_num];
【104】Node*current1,*current2,*current3;
【105】Node*top1,*top2,*top3;
【106】Node*p;
【107】//将三个父代路径改为单循环链表
【108】top1=current1=(Node*)malloc(sizeof(Node));
//为第一个父代路径生成头一个結点
【109】top1->
city=p1->
path[0];
【110】top2=current2=(Node*)malloc(sizeof(Node));
//为第二个父代路径生成头一个結点
【111】top2->
city=p2->
【112】top3=current3=(Node*)malloc(sizeof(Node));
//为第三个父代路径生成头一个結点
【113】top3->
city=p3->
【114】for(i=1;
city_num;
i++)//生成三个父代路径的其他結点
【115】{
【116】current1->
next=(Node*)malloc(sizeof(Node));
【117】
【118】current1=current1->
【119】current1->
path[i];
【120】current2->
【121】current2=current2->
【122】current2->
【123】current3->
【124】current3=current3->
【125】current3->
【126】}
【127】current1->
next=top1;
//链接第一个父代路径头尾结点
【128】current2->
next=top2;
//链接第二个父代路径头尾结点
【129】current3->
next=top3;
//链接第三个父代路径头尾结点
【130】Cross_group_point=RandomInteger(0,city_num-1);
//三交换启发交叉
【131】while(Cross_group_point--)
【132】current1=current1->
【133】current2=search_son(top2,current1->
city);
【134】current3=search_son(top3,current1->
【135】for(i=0;
【136】{
【137】son[i]=current1->
city;
//将最优点存入son
【138】p=current1->
//从第一个父代路径链表中删除该最优点
【139】current1->
next=p->
【140】free(p);
【141】p=current2->
//从第二个父代路径链表中删除该最优点
【142】current2->
【143】free(p);
【144】p=current3->
//从第三个父代路径链表中删除该最优点
【145】current3->
【146】free(p);
【147】if(i==9)break;
【148】a=length_table[son[i]][current1->
city];
【149】b=length_table[son[i]][current2->
【150】c=length_table[son[i]][current3->
【151】if(a<
=b&
a<
=c){//比较最短踞离后,将三条父代路径链表定位于最优点的前一个节点
【152】current2=search_son(current2,current1->
【153】current3=search_son(current3,current1->
【154】}
【155】elseif(b<
=a&
b<
=c){
【156】current1=search_son(current1,current2->
【157】current3=search_son(current3,current2->
【158】}
【159】elseif(c<
c<
=b){
【160】current1=search_son(current1,current3->
【161】current2=search_son(current2,current3->
【162】}
【163】memcpy(p1->
path,son,sizeof(p1->
path));
//生成第一个子代路径
【164】Cross_group_point=RandomInteger(0,city_num-1);
//生成第二个子代路径
【165】for(k=0,i=Cross_group_point;
【166】p2->
path[k++]=son[i];
【167】for(i=0;
Cross_group_point;
【168】p2->
【169】Cross_group_point=RandomInteger(0,city_num-1);
//生成第三个子代路径
【170】for(k=0,i=Cross_group_point;
【171】p3->
【172】for(i=0;
【173】p3->
、
【174】Calculate_length(p1);
//计算子代p1路径的总长度
【175】Calculate_length(p2);
//计算子代p2路径的总长度
【176】Calculate_length(p3);
//计算子代p3路径的总长度
【177】}
【178】/*变异*/
【179】voidVaration_group(Unit*group,intgen_num)
【180】{
【181】intflag,i,j,k,temp;
【182】Unit*p;
【183】flag=(gen_num>
50)?
(3*100*pv):
(100*pv);
//在进化后期,增大变异概率
【184】while(flag--)
【185】{
【186】i=RandomInteger(0,unit_num-1);
//确定发生变异的个体
【187】j=RandomInteger(0,city_num-1);
//确定发生变异的位
【188】k=RandomInteger(0,city_num-1);
【189】p=&
//变异
【190】temp=p->
path[j];
【191】p->
path[j]=p->
path[k];
【192】p->
path[k]=temp;
【193】Calculate_length(p);
//重新计算变异后路径的总长度
【194】}
【195】}
【196】/*初始化最优值*/
【197】voidInitial_bestone(Unit*bestone)
【1
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- TSP 人工智能 求解 问题