遗传算法解决商旅问题

《人工智能导论》实验报告之二遗传算法解决商旅问题

专业班级:计0901

姓名:薛彬

学号:200907010106

电子信箱:598432534@https://www.360docs.net/doc/4f542187.html, 手机号码:152********

提交日期:2012年6月04日

指导老师:程国建

实验成绩:

一.问题描述:

TSP是一个具有广泛应用背景和重要理论价值的组合优化难题,TSP问题可以简单的描述为:已知N个城市之间的相互距离.现有一个旅行商必须遍历这N 个城市,并且每个城市只能访一次,最后必须返回出发城市。如何安排他对这些城市的访问次序,可使旅行路线的总长度最短?

二.需求分析:

TSP已经被证明是一个NP—Hard问题,即找不到一种算法能在多项式时间内求得问题的最优解。利用遗传算法,在一定时间内求得近似最优解的可能性比较大。实验目标是:

1)设计用遗传算法解决TSP问题的程序;

2)求出该TSP问题的(近似)最短路程;

3)求得相应的城市遍历序列;

4)检查算法收敛性,求解决该问题的(近似)最优遗传参数。

三.算法分析:

1.算法描述与基本流程

(1) 编码

遗传算法先将解空间的解数据表示成遗传空间的基因型串结构数据,他们的不同组合就构成了不同的点。

(2) 生成初始种群

采用随机的方法产生若干个初始串结构数据,每个串结构数据代表一个个体,全体初始串结构数据构了初始种群。种群的大小一般是20~100,这样既可以提高遗传算法的稳定型,又能够保证种群的多样性,容易获得全局最优解。

(3) 适应度评估

对于不同的优化问题,采用不同的适应度函数来评价个体的优劣性。通常有一些常用的带欺骗性的函数用于测试。

(4) 选择

按照适者生存的目的,从当前的种群中选择出适应度强的优良个体,使它们有机会作为父代产生下一代,适应度强的个体被选择的概率大。

(5) 交叉

交叉算子根据交叉率将种群中两个个体随机的交换某些基因,从而产生新一代个体。新个体组合了父辈个体的特性。交叉率根据具体问题确定,一般取0.25~0.75,这样既可以得到高适应度的结构,又可以保证搜索效率。

(6) 变异

变异算子根据交叉率随机地在当前种群中选择一个个体,对其以一定的概率

随机地改变串结构数据中的某个串的数值,从而产生新一代个体。变异率不宜取得过高,一般取0.005~0.20。

2. 编码策略与初始群体设定

TSP 的一般编码策略主要有二进制表示、次序表示、路径表示、矩阵表示和边表示等。而路径编码是最直观的方式,以城市序号作为遗传基因。在本实验中,我们用一个N 维向量来表示一个个体,N 是城市总数,元素表示城市遍历顺序,以最后一个到达的城市为结束。则群体用一个N * POP 的矩阵表示,POP 为群体中的人口(个体数)。初始群体在空间中自动生成。

3. 适应度函数及结束条件

适应度函数采用题目的目标函数——路径的总路程(包括回到出发点)。适应度越低,个体越优秀。由于暂时无法先验估计收敛性和目标结果,所以以一个参数,最大遗传代数MAXGEN 作为程序结束控制。

4. 遗传算子设计

遗传算子的设计方法主要有两大类:自然算法和贪心算法。自然算法是以大自然的进化规律为依据,大体采用“优胜劣汰”的机制来进行遗传;贪心算法则是以迅速收敛为目标,对个体进行更严格的选择和遗传处理。

本实验中,为了更好地研究遗传算法的内部原理和收敛性质,我们偏向采用自然算法设计算子。以下是各算子的设计:

选择

交叉

变异

群体适应度计算

结束

输出结果 Y

N 计算适应度并输出

初始群体生成

在遗传个体的选择上,我们先人工保留最优种子,再采用轮盘赌法选择保留一部分个体,用轮盘赌法的理由是在“择优录取”的原则上增加选择的随机性。在轮盘赌过程中,如果按适应度来划分,将导致适应度高的劣质个体被选择的概率更大,于是我们设计了一个变换,用最坏适应度减去该个体的适应度,再进行轮盘赌选择。

另外,为了保持群体的“生命力”,我们在选择的同时又引入随机的新个体,与保留的个体进行“杂交”,产生下一代。

交叉算子

我们采用的是Davis等提出顺序交叉、双亲双子遗传的算法。随机选择两个交叉点A、B(0

变异算子

个体发生变异的概率为参数PMUTATION。当一个个体发生变异时,随机选择序列中一个基因与其相邻基因交换。

其他部分

数据输入为直接读取城市距离矩阵文本,本例中为ctsp.txt;

数据输出格式为:每代的最佳适应度,平均适应度和标准差,最终结果序列和相关参数。文件名galog.txt。

四.程序源代码及运行结果

#include

#include

#include

struct node//建立结点结构体

{

int label;

int former;

int access[100];

int weight[100];

int c_p;

};

node* f[100];

int flag[100];

int scount;

//int length=0;

int parent=-10;

int answer[100][101];

int an_p=0;

void convert(int a[100],char b[100])//转变算法

{

for(int i=0;i<100;i++)

{

a[i]=b[i]-48;

b[i]='\0';

}

}

void init()

{

node* temp;

int count=0;

char t_a[100];

char t_w[100];

for(int i=0;i<100;i++)

{

flag[i]=-5;

for(int j=0;j<100;j++)

{

answer[i][j]=-5;

}

answer[i][100]=9999;

}

do

{

printf("please input a new node:\n");//建立一个新的节点

printf("label: %d\n",count);//节点数目

printf("access:\n");//进入节点的许可

scanf("%s",t_a);

printf("weight:\n");//输入路径长度

scanf("%s",t_w);

if(strcmp(t_a,"end"))//输入结束语

{

temp=(node *)malloc(sizeof(node));

(*temp).label=count;

相关文档
最新文档