遗传算法解决TSP问答(C)
实验六:遗传算法求解TSP问题实验2篇

实验六:遗传算法求解TSP问题实验2篇第一篇:遗传算法的原理与实现1. 引言旅行商问题(TSP问题)是一个典型的组合优化问题,它要求在给定一组城市和每对城市之间的距离后,找到一条路径,使得旅行商能够在所有城市中恰好访问一次并回到起点,并且总旅行距离最短。
遗传算法作为一种生物启发式算法,在解决TSP问题中具有一定的优势。
本实验将运用遗传算法求解TSP问题,以此来探讨和研究遗传算法在优化问题上的应用。
2. 遗传算法的基本原理遗传算法是模拟自然界生物进化过程的一种优化算法。
其基本原理可以概括为:选择、交叉和变异。
(1)选择:根据问题的目标函数,以适应度函数来评估个体的优劣程度,并按照适应度值进行选择,优秀的个体被保留下来用于下一代。
(2)交叉:从选出的个体中随机选择两个个体,进行基因的交换,以产生新的个体。
交叉算子的选择及实现方式会对算法效果产生很大的影响。
(3)变异:对新生成的个体进行基因的变异操作,以保证算法的搜索能够足够广泛、全面。
通过选择、交叉和变异操作,不断迭代生成新一代的个体,遗传算法能够逐步优化解,并最终找到问题的全局最优解。
3. 实验设计与实施(1)问题定义:给定一组城市和每对城市之间的距离数据,要求找到一条路径,访问所有城市一次并回到起点,使得旅行距离最短。
(2)数据集准备:选择适当规模的城市数据集,包括城市坐标和每对城市之间的距离,用于验证遗传算法的性能。
(3)遗传算法的实现:根据遗传算法的基本原理,设计相应的选择、交叉和变异操作,确定适应度函数的定义,以及选择和优化参数的设置。
(4)实验流程:a. 初始化种群:随机生成初始种群,每个个体表示一种解(路径)。
b. 计算适应度:根据适应度函数,计算每个个体的适应度值。
c. 选择操作:根据适应度值选择一定数量的个体,作为下一代的父代。
d. 交叉操作:对父代进行交叉操作,生成新的个体。
e. 变异操作:对新生成的个体进行变异操作,以增加搜索的多样性。
利用遗传算法求解TSP问题

利⽤遗传算法求解TSP问题⼀、摘要TSP问题是指给定平⾯上N个点及每点的坐标,求⼀条路径,遍历所有的点并回到起点,使这条路径长度最⼩。
TSP问题是⼀个组合优化问题。
该问题可以被证明具有NPC计算复杂性。
因此,任何能使该问题的求解得以简化的⽅法,都将受到⾼度的评价和关注。
遗传算法是⼈⼯智能⽅法的⼀种,⽤于求解各种传统⽅法不⽅便求解或耗时很长的问题。
下⾯给出遗传算法求解TSP问题的步骤。
在传统遗传算法求解TSP的基础上,提出了⼀种新的编码⽅式,并且讨论了⼀种优化⽅法的可⾏性。
本次实验的程序⾸先在matlab上验证了基本的算法,然⽽由于matlab运⾏较慢,故⼜移植到C++平台上,经过测试,实验结果良好。
⼆、算法实现遗传算法的实现主要包括编码、选择、交叉、编译、将个体放⼊新种群这么⼏个步骤,经过很多代的编译求解,以逼近最优解。
下⾯讨论每⼀个步骤的实现,其中编码⽅式是我在考虑了传统编码⽅式不利于计算的缺点下,重新设计的⼀种全新的编码⽅式。
编码在传统TSP问题中,编码可以直接采⽤⼆进制编码或⾃然编码的形式,⽐如直接把城市转化成(2,5,4,1,3,6)的形式,表⽰从2到5到4到1到3到6最后回到起点。
但是在求解TSP问题时,如果直接采⽤此种编码⽅式,会导致在交叉或变异时出现冲突的情况。
如(2,5,4,1,3,6)和(3,5,6,1,2,4)交换后变成了(2,5,6,1,2,6)和(3,5,4,1,3,4),显然路径出现了冲突的现象,传统的解决⽅式是通过逐步调整的⽅法来消除冲突,但是这种⽅法增加了编码的复杂度,不利于问题的求解,根据问题的特点,提出了采⽤⼀种插⼊序号的编码⽅式。
假设6个城市(1,2,3,4,5,6)现在有编码(1,1,2,2,1,3),让第n个编码表⽰n放在第⼏个空格处。
那么⽣成路径的规则是⾸先取1放在第⼀个(1),然后取2放在第⼀个空格处(2,1),然后取3放在第⼆个空格处(2,3,1),然后取4放在第⼆个空格处(2,4,3,1)然后取5放在第⼀个空格处(5,2,4,3,1)最后取6放在第3个空格处(5,2,6,4,3,1)。
利用遗传算法解决TSP问题课件

给每个城市一个固定的基因编号,例如10个城市为 0 1 2 3 4 5 6 7 8 9 ,随机地组成一个染色体(以下所有情况都以10个城市为例说明)。 约定这10个城市之间的行走路线为: 0123456789 (其余基因序列的路线同样道理)
两个城市间的距离(用r[i][j]表示)
轮盘选择
for(mem=0;mem<PopSize;mem++) sum+=population[mem].fitness; for(mem=0;mem<PopSize;mem++) //使小的选中的可能性大 x[mem]=sum-population[mem].fitness; sum=0.0; for(mem=0;mem<PopSize;mem++) sum+=x[mem]; /* Calculate relative fitness */ for(mem=0;mem<PopSize;mem++) population[mem].rfitness=x[mem]/sum;
仿真结果
仿真结果
一个完整路线的长度
例如基因序列为:0 8 2 9 7 5 6 4 1 3,存放在gene[0]~gene[9]中。 表示行旅行路线为: 0829756413 总路程为: r[gene[0]][gene[1]]+r[gene[1]][gene[2]]~ +r[gene[9]gene[0]]
交叉
例如一个基因序列为: 0 2 5 6 9 8 1 3 4 7 产生两个0~9的int型随机数,如得到2和6,将gene[2]和gene[6]之间的基因反序,得到: 0 2 1 8 9 6 5 3 4 7
遗传算法解决TSP问题【精品毕业设计】(完整版)

GA(Fitness,Fitness_threshold,p,r,m)
Fitness:适应度评分函数,为给定假设赋予一个评估分数
Fitness_threshold:指定终止判据的阈值
p:群体中包含的假设数量
r:每一步中通过交叉取代群体成员的比例
m:变异率
初始化群体:P←随机产生的p个假设
在本程序的TSP问题中一共有20个城市,也就是在图模型中有20个顶点,因此一个染色体的长度为20。
3.3适应函数f(i)
对具有n个顶点的图,已知各顶点之间( , )的边长度d( , ),把 到 间的一条通路的路径长度定义为适应函数:
对该最优化问题,就是要寻找解 ,使f( )值最小。
3.4选择操作
选择作为交叉的双亲,是根据前代染色体的适应函数值所确定的,质量好的个体,即从起点到终点路径长度短的个体被选中的概率较大。
(2)交叉(Crossover):对于选中进行繁殖的两个染色体X,Y,以X,Y为双亲作交叉操作,从而产生两个后代X1,Y1.
(3)变异(Mutation):对于选中的群体中的个体(染色体),随机选取某一位进行取反运算,即将该染色体码翻转。
用遗传算法求解的过程是根据待解决问题的参数集进行编码,随机产生一个种群,计算适应函数和选择率,进行选择、交叉、变异操作。如果满足收敛条件,此种群为最好个体,否则,对产生的新一代群体重新进行选择、交叉、变异操作,循环往复直到满足条件。
3.变异:使用均匀的概率从Ps中选择m%的成员.对于选出的每个成员,在它表示中随机选择一个为取反
4.更新:P←Ps
5.评估:对于P中的每个h计算Fitness(h)
从P中返回适应度最高的假设
3.
3.1 TSP问题的图论描述
遗传算法的C语言实现(二)-----以求解TSP问题为例

遗传算法的C语⾔实现(⼆)-----以求解TSP问题为例上⼀次我们使⽤遗传算法求解了⼀个较为复杂的多元⾮线性函数的极值问题,也基本了解了遗传算法的实现基本步骤。
这⼀次,我再以经典的TSP问题为例,更加深⼊地说明遗传算法中选择、交叉、变异等核⼼步骤的实现。
⽽且这⼀次解决的是离散型问题,上⼀次解决的是连续型问题,刚好形成对照。
⾸先介绍⼀下TSP问题。
TSP(traveling salesman problem,旅⾏商问题)是典型的NP完全问题,即其最坏情况下的时间复杂度随着问题规模的增⼤按指数⽅式增长,到⽬前为⽌还没有找到⼀个多项式时间的有效算法。
TSP问题可以描述为:已知n个城市之间的相互距离,某⼀旅⾏商从某⼀个城市出发,访问每个城市⼀次且仅⼀次,最后回到出发的城市,如何安排才能使其所⾛的路线最短。
换⾔之,就是寻找⼀条遍历n个城市的路径,或者说搜索⾃然⼦集X={1,2,...,n}(X的元素表⽰对n个城市的编号)的⼀个排列P(X)={V1,V2,....,Vn},使得Td=∑d(V i,V i+1)+d(V n,V1)取最⼩值,其中,d(V i,V i+1)表⽰城市V i到V i+1的距离。
TSP问题不仅仅是旅⾏商问题,其他许多NP完全问题也可以归结为TSP问题,如邮路问题,装配线上的螺母问题和产品的⽣产安排问题等等,也使得TSP问题的求解具有更加⼴泛的实际意义。
再来说针对TSP问题使⽤遗传算法的步骤。
(1)编码问题:由于这是⼀个离散型的问题,我们采⽤整数编码的⽅式,⽤1~n来表⽰n个城市,1~n的任意⼀个排列就构成了问题的⼀个解。
可以知道,对于n个城市的TSP问题,⼀共有n!种不同的路线。
(2)种群初始化:对于N个个体的种群,随机给出N个问题的解(相当于是染⾊体)作为初始种群。
这⾥具体采⽤的⽅法是:1,2,...,n作为第⼀个个体,然后2,3,..n分别与1交换位置得到n-1个解,从2开始,3,4,...,n分别与2交换位置得到n-2个解,依次类推。
遗传算法解决TSP问题,C++版(带注释)

//遗传算法解决简单TSP问题,(VC6.0)//一、定义头文件(defines.h)#ifndef DEFINES_H#define DEFINES_H///////////////////////////////// DEFINES /////////////////////////////////////// //窗口定义大小#define WINDOW_WIDTH 500#define WINDOW_HEIGHT 500//城市数量及城市在窗口显示的大小#define NUM_CITIES 20#define CITY_SIZE 5//变异概率,交叉概率及种群数量#define MUTATION_RATE 0.2#define CROSSOVER_RATE 0.75#define POP_SIZE 40//倍数#define NUM_BEST_TO_ADD 2//最小容许误差#define EPSILON 0.000001#endif//二、一些用得到的小函数(utils.h)// utils.h: interface for the Cutils class.//头文件名//////////////////////////////////////////////////////////////////////#ifndef UTILS_H#define UTILS_H#include <stdlib.h>#include <math.h>#include <sstream>#include <string>#include <iostream>using namespace std;//--------定义一些随机函数--------//----定义随机整数,随机[x,y]之间的整数---inline int RandInt(int x, int y){return rand()%(y-x+1)+x;}//--------------随机产生0到1之间的小数----------inline float RandFloat(){return rand()/(RAND_MAX + 1.0);}//-----------------随机产生0和1-------------inline bool RandBool(){if (RandInt(0,1))return true;elsereturn false;}//-----定义一些方便的小功能包括:整形转字符型,浮点型转字符型--- string itos(int arg);//converts an float to a std::stringstring ftos (float arg);//限制大小void Clamp(double &arg, double min, double max);void Clamp(int &arg, int min, int max);#endif//三、地图头文件(CmapTSP)#ifndef CMAPTSP_H#define CMAPTSP_H//如果没有定义那么就定义////////////////////////////////////////////////////类名:CmapTSP.h////描述:封装地图数据、城市坐标以及适应度计算。
(完整)用遗传算法求解TSP问题

用遗传算法求解TSP问题遗传算法(Genetic Algorithm——GA),是模拟达尔文的遗传选择和自然淘汰的生物进化过程的计算模型,它是由美国Michigan大学的J。
Holland教授于1975年首先提出的。
J.Holland 教授和它的研究小组围绕遗传算法进行研究的宗旨有两个:抽取和解释自然系统的自适应过程以及设计具有自然系统机理的人工系统。
遗传算法的大致过程是这样的:将每个可能的解看作是群体中的一个个体或染色体,并将每个个体编码成字符串的形式,根据预定的目标函数对每个个体进行评价,即给出一个适应度值。
开始时,总是随机的产生一些个体,根据这些个体的适应度,利用遗传算子-—选择(Selection)、交叉(Crossover)、变异(Mutation)对它们重新组合,得到一群新的个体.这一群新的个体由于继承了上一代的一些优良特性,明显优于上一代,以逐步向着更优解的方向进化.遗传算法主要的特点在于:简单、通用、鲁棒性强。
经过二十多年的发展,遗传算法已经在旅行商问题、生产调度、函数优化、机器学习等领域得到成功的应用。
遗传算法是一类可用于复杂系统优化的具有鲁棒性的搜索算法,与传统的优化算法相比,主要有以下特点:1、遗传算法以决策变量的编码作为运算对象.传统的优化算法往往直接决策变量的实际植本身,而遗传算法处理决策变量的某种编码形式,使得我们可以借鉴生物学中的染色体和基因的概念,可以模仿自然界生物的遗传和进化机理,也使得我们能够方便的应用遗传操作算子.2、遗传算法直接以适应度作为搜索信息,无需导数等其它辅助信息。
3、遗传算法使用多个点的搜索信息,具有隐含并行性。
4、遗传算法使用概率搜索技术,而非确定性规则。
遗传算法是基于生物学的,理解或编程都不太难。
下面是遗传算法的一般算法步骤:1、创建一个随机的初始状态初始种群是从解中随机选择出来的,将这些解比喻为染色体或基因,该种群被称为第一代,这和符号人工智能系统的情况不一样;在那里,问题的初始状态已经给定了。
遗传算法求解TSP问题

遗传算法求解TSP问题实验六遗传算法求解TSP问题⼀、实验⽬的熟悉和掌握遗传算法的原理、流程和编码策略,并利⽤遗传求解函数优化问题,理解求解TSP问题的流程并测试主要参数对结果的影响。
⼆、实验内容1、参考实验系统给出的遗传算法核⼼代码,⽤遗传算法求解TSP的优化问题,分析遗传算法求解不同规模TSP问题的算法性能。
2、对于同⼀个TSP问题,分析种群规模、交叉概率和变异概率对算法结果的影响。
3、增加1种变异策略和1种个体选择概率分配策略,⽐较求解同⼀TSP问题时不同变异策略及不同个体选择分配策略对算法结果的影响。
4、上交源代码。
三、遗传算法求解TSP问题的流程图四、遗传算法求解不同规模的TSP问题的算法性能(1)遗传算法执⾏⽅式说明:适应度值计算⽅法:当前路线的路径长度●个体选择概率分配⽅法:适应度⽐例⽅法●选择个体⽅法:轮盘赌选择●交叉类型:PMX交叉●变异类型: 两点互换变异(2)实验模拟结果:图1-1(3)分析由图1-1可知,遗传算法执⾏时间随着TSP问题规模的增⼤⽽增⼤,并且⼤致为线性增长。
五、不同参数下的计算结果对⽐最⼤迭代步数:100交叉概率:0.85变异概率:0.15如表1-1或3-1-0-9-2-4-8-5-7-6,注意到这是⼀圈,顺时针或者逆时针都可以。
当种群规模为10,20时,并没有找到最优解。
(2)交叉概率对算法结果的影响实验次数:15种群规模:25最⼤迭代步数:100变异概率:0.15实验结果:在该情况下,交叉概率过低将使搜索陷⼊迟钝状态,得不到最优解。
种群规模:25最⼤迭代步数:100交叉概率:0.85实验结果:⼜表1-3可知,当变异概率过⼤或过低都将导致⽆法得到最优解。
注:(2)(3)的实验数据与(1)的实验数据不同,详见附录。
六、不同变异策略和个体选择概率分配策略对算法结果的影响(1)两点互换变异与插⼊变异的⽐较:●试验次数(CASNUM):10●城市数(POINTCNT):10●种群规模(POPSIZE):100●最⼤迭代步数(GENERATIONS):100●交叉概率(PC):0.85●变异概率(PM):0.15●选择个体⽅法:轮盘赌选择●交叉类型:PMX交叉●个体选择概率分配⽅法:适应度⽐例⽅法a.变异类型: 两点互换变异b.变异类型: 插⼊变异分析:两点互换变异20次模拟中,4次得到⾮最优解;⽽插⼊变异只有2次;插⼊变异的最好适应度平均值⽐两点互换变异⼩0.14755,最差适应度平均值和总的适应度平均值都⽐两点互换下,并且在Release下,运⾏时间前者⽐后者快218.3ms。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
遗传算法解决TSP问题(C++版)遗传算法流程:交叉,编译,计算适应度,保存最优个体。
其中交叉过程是选择最优的两个染色体进行交叉操作,本文采用的是轮盘赌算法。
#include<iostream>#include<cstdlib>#include<ctime>using namespace std;#define population 200//种群数量#define pc 0.9//交叉的概率#define pm 0.1//变异的概率#define count 200//迭代的次数#define num 10//城市的数量int** city;//存放每个个体的访问顺序int path[10][10] = {//0, 1, 2, 3, 4, 5, 6, 7, 8, 9{ 0, 23, 93, 18, 40, 34, 13, 75, 50, 35 },//0{ 23, 0, 75, 4, 72, 74, 36, 57, 36, 22 },//1{ 93, 75, 0, 64, 21, 73, 51, 25, 74, 89 },//2{ 18, 4, 64, 0, 55, 52, 8, 10, 67, 1 }, //3{ 40, 72, 21, 55, 0, 43, 64, 6, 99, 74 }, //4{ 34, 74, 73, 52, 43, 0, 43, 66, 52, 39 },//5{ 13, 36, 51, 8, 64, 43, 0, 16, 57, 94 },//6{ 75, 57, 25, 10, 6, 66, 16, 0, 23, 11 }, //7{ 50, 36, 74, 67, 99, 52, 57, 23, 0, 42 },//8{ 35, 22, 89, 1, 74, 39, 94, 11, 42, 0 }//9};int* dis;//存放每个个体的访问顺序下的路径长度double* fitness;//存放灭个个体的适应度int min_dis = 1000000;int min_index = -1;int* min_path;//初始化种群void init(){int *a = new int[num];for (int i = 0; i<num; i++){a[i] = i;}city = new int*[population];for (int i = 0; i<population; i++){city[i] = new int[num];}for (int i = 0; i<population; i++){for (int j = num - 1; j >= 0; j--){int n = rand() % (j + 1);//产出的数是0-j,保证交换的后面的数不会再被交换swap(a[j], a[n]);//保证a里面全是0-(num-1)的数,无重复的数,只是顺序颠倒city[i][j] = a[j];}}delete[]a;dis = new int[population];fitness = new double[population];min_path = new int[num];}//计算适应度void compute(){//cout << "do compute now. " << endl;double total = 0;for (int i = 0; i<population; i++){//计算每种情况下,路径的长度dis[i] = 0;int a = city[i][0], b;for (int j = 1; j<num; j++){b = city[i][j];dis[i] += path[a][b];a = b;}dis[i] += path[b][city[i][0]];fitness[i] = 1.0 / dis[i];//以距离的倒数作为适应度函数值total += fitness[i];}}//选择适应度高的物种,采用轮盘赌算法int select(){double total = 0;for (int i = 0; i<population; i++){total += fitness[i];}double size = rand() / (double)RAND_MAX * total;//保证不产生0//cout << "size " << size << endl;double sum = 0;int i = 0;while (sum <= size&&i<population){sum += fitness[++i];}return --i;//返回被选中的个体}int getMinDis(){int result = dis[0];int index = 0;for (int i = 1; i<population; i++){if (result > dis[i]){result = dis[i];index = i;}}return index;}int getMaxDis(){int result = dis[0];int index = 0;for (int i = 1; i<population; i++){if (result < dis[i]){result = dis[i];index = i;}}return index;}void save(){int current_min_index = getMinDis();int current_max_index = getMaxDis();if (dis[current_min_index] < min_dis){min_dis = dis[current_min_index];for (int i = 0; i < num; i++){min_path[i] =city[current_min_index][i];}//cout << "current min dis is: " << min_dis << endl;}else{for (int i = 0; i<num; i++){city[current_max_index][i] = min_path[i];}dis[current_max_index] = min_dis;fitness[current_max_index] = 1.0 / min_dis;}}//最优保存算法bool isExist(int value, int* array, int len){for (int i = 0; i<len; i++){if (value == array[i])return true;}return false;}void convert(int p1, int p2, int* src, int* dst){int len = p2 - p1 + 1;int* temp = new int[len];for (int i = p1; i <= p2; i++){temp[i - p1] = src[i];}int j = (p2 + 1) % num;for (int i = 1; i <= num; i++){int index = (i + p2) % num;if (!isExist(dst[index], temp, len)){dst[j] = dst[index];j = (j + 1) % num;}}for (int i = p1; i <= p2; i++){dst[i] = src[i];}delete[]temp;}//交叉,采用次序交叉算法void cross(){//cout << "do cross now. " << endl;for (int k = 0; k<population; k += 2){int a = select();int b = select();while (a == b){b = select();//保证被选中的个体不是一样的//cout << "same " << b << endl;}//cout << "choose popuilation" << a << " " << b << endl;double p = rand() / double(RAND_MAX);//cout << "cross rate is " << p << endl;int* a1 = new int[num];int* a2 = new int[num];int* b1 = new int[num];int* b2 = new int[num];for (int i = 0; i<num; i++){a1[i] = city[a][i];a2[i] = city[b][i];b1[i] = a2[i];b2[i] = a1[i];}if (p<pc)//满足交叉条件{//选择交叉的两点,并保证p1<p2int p1 = -1;int p2 = -1;while (p1 == p2){p1 = rand() % num;p2 = rand() % num;if (p1>p2){swap(p1, p2);}}//cout << "choose pos " << p1 << " " << p2 << endl;//开始交叉convert(p1, p2, a1, b1);convert(p1, p2, a2, b2);for (int i = 0; i<num; i++){city[k][i] = b1[i];city[k + 1][i] = b2[i];}}else{for (int i = 0; i<num; i++){city[k][i] = a1[i];city[k + 1][i] = a2[i];}}delete[]a1;delete[]a2;delete[]b1;delete[]b2;}}//变异,采用对换操作进行变异void morphis(){//cout << "do morphis now. " << endl;for (int i = 0; i<population; i++){double p = rand() / double(RAND_MAX);//cout << "morphis rate is " << p << endl;if (p<pm)//执行变异{int a = -1, b = -1;while (a == b){a = rand() % num;b = rand() % num;}swap(city[i][a], city[i][b]);}}}int getdis(){//compute();int result = dis[0];int index = 0;for (int i = 1; i<population; i++){if (result > dis[i]){result = dis[i];index = i;}}return result;}//释放申请的数组的空间void dispose(){for (int i = 0; i<population; i++){delete[]city[i];}delete[]city;delete[]dis;delete[]fitness;}int main(){init();//初始化种群int i = 0;srand(time(0));compute();while (i<count){cross();//交叉morphis();//变异compute();//计算适应度save();//保存当前最优的个体//cout << "count " << i++ << endl;cout << getdis() << " ";//输出结果//cout << min_index << " ";if (++i % 10 == 0)cout << endl;}compute();cout << "min distance is: " << min_dis << endl;for (int i = 0; i<num; i++)cout << min_path[i] << " ";cout << endl;dispose();//释放空间return 0;}。