遗传算法解决TSP问题,C 版(带注释)

合集下载

利用遗传算法求解TSP问题

利用遗传算法求解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问题课件

利用遗传算法解决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

遗传算法(GA)解决TSP问题

遗传算法(GA)解决TSP问题

遗传算法(GA)解决TSP问题 遗传算法解决TSP问题遗传算法遗传算法的基本原理是通过作⽤于染⾊体上的基因寻找好的染⾊体来求解问题,它需要对算法所产⽣的每个染⾊体进⾏评价,并基于适应度值来选择染⾊体,使适应性好的染⾊体有更多的繁殖机会,在遗传算法中,通过随机⽅式产⽣若⼲个所求解问题的数字编码,即染⾊体,形成初始种群;通过适应度函数给每个个体⼀个数值评价,淘汰低适应度的个体,选择⾼适应度的个体参加遗传操作,经过遗产操作后的个体集合形成下⼀代新的种群,对这个新的种群进⾏下⼀轮的进化。

TSP问题TSP问题即旅⾏商问题,经典的TSP可以描述为:⼀个商品推销员要去若⼲个城市推销商品,该推销员从⼀个城市出发,需要经过所有城市后,回到出发地。

应如何选择⾏进路线,以使总的⾏程最短。

从图论的⾓度来看,该问题实质是在⼀个带权完全⽆向图中,找⼀个权值最⼩的哈密尔顿回路。

遗传算法解决TSP问题概念介绍:种群 ==> 可⾏解集个体 ==> 可⾏解染⾊体 ==> 可⾏解的编码基因 ==> 可⾏解编码的分量基因形式 ==> 遗传编码适应度 ==> 评价的函数值(适应度函数)选择 ==> 选择操作交叉 ==> 编码的交叉操作变异 ==> 可⾏解编码的变异遗传操作:就包括优选适应性强的个体的“选择”;个体间交换基因产⽣新个体的“交叉”;个体间的基因突变⽽产⽣新个体的“变异”。

其中遗传算法是运⽤遗传算⼦来进⾏遗传操作的。

即:选择算⼦、变异算⼦、交叉算⼦。

遗传算法的基本运算过程(1)种群初始化:个体编码⽅法有⼆进制编码和实数编码,在解决TSP问题过程中个体编码⽅法为实数编码。

对于TSP问题,实数编码为1-n的实数的随机排列,初始化的参数有种群个数M、染⾊体基因个数N(即城市的个数)、迭代次数C、交叉概率Pc、变异概率Pmutation。

(2)适应度函数:在TSP问题中,对于任意两个城市之间的距离D(i,j)已知,每个染⾊体(即n个城市的随机排列)可计算出总距离,因此可将⼀个随机全排列的总距离的倒数作为适应度函数,即距离越短,适应度函数越好,满⾜TSP要求。

遗传算法解决TSP问题【精品毕业设计】(完整版)

遗传算法解决TSP问题【精品毕业设计】(完整版)
2.2遗传算法原型:
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问题的图论描述

用遗传算法求解中国34个省会TSP的问题

用遗传算法求解中国34个省会TSP的问题

用遗传算法求解中国34个省会TSP的问题题目:用遗传算法求解中国34 个省会TSP 问题源代码分享在本人博客:2012-1-17智能控制技术及其应用大作业专业: 控制工程学号:XXXXXX姓名:XXX用遗传算法求解中国34 个省会TSP 问题一、TSP 问题的描述旅行商问题(TSP)可以具体描述为:已知n 个城市之间的相互距离,现有一个推销员从某一个城市出发,必须遍访这n 个城市,并且每个城市只能访问一次,最后又必须返回到出发城市,如何安排他对这些城市的访问次序,可使其旅行路线的总长度最短。

现给出中国34 个省会数据,要求基于此数据使用遗传算法解决该TSP 问题。

图1 中国34 省会位置city =1.西藏2.云南3.四川4.青海5.宁夏6.甘肃7.内蒙古8.黑龙江9.吉林10.辽宁11.北京12 天津13.河北14.山东15.河南16.山西17. 陕西18.安徽19.江苏20.上海21.浙江22.江西23.湖北24.湖南25,贵州26. 广西27.广东28.福建29.海南30.澳门31.香港32.台湾33.重庆34.新疆像素坐标如下:Columns 1 through 11100 187 201 187 221 202 258 352 346 336 290211 265 214 158 142 165 121 66 85 106 127Columns 12 through 22297 278 296 274 265 239 302 316 334 325 293135 147 158 177 148 182 203 199 206 215 233Columns 23 through 33280 271 221 233 275 322 250 277 286 342 220216 238 253 287 285 254 315 293 290 263 226Column 3410477二、遗传算法的介绍2.1 遗传算法遗传算法的基本原理是通过作用于染色体上的基因寻找好的染色体来求解问题,它需要对算法所产生的每个染色体进行评价,并基于适应度值来选择染色体,使适应性好的染色体有更多的繁殖机会,在遗传算法中,通过随机方式产生若干个所求解问题的数字编码,即染色体,形成初始种群;通过适应度函数给每个个体一个数值评价,淘汰低适应度的个体,选择高适应度的个体参加遗传操作,经过遗产操作后的个体集合形成下一代新的种群,对这个新的种群进行下一轮的进化。

遗传算法的C语言实现(二)-----以求解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问题,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问题

用遗传算法求解TSP问题遗传算法(Genetic Algorithm——GA),是模拟达尔文的遗传选择和自然淘汰的生物进化过程的计算模型,它是由美国Michigan大学的J。

Holland教授于1975年首先提出的。

J.Holland 教授和它的研究小组围绕遗传算法进行研究的宗旨有两个:抽取和解释自然系统的自适应过程以及设计具有自然系统机理的人工系统。

遗传算法的大致过程是这样的:将每个可能的解看作是群体中的一个个体或染色体,并将每个个体编码成字符串的形式,根据预定的目标函数对每个个体进行评价,即给出一个适应度值。

开始时,总是随机的产生一些个体,根据这些个体的适应度,利用遗传算子-—选择(Selection)、交叉(Crossover)、变异(Mutation)对它们重新组合,得到一群新的个体.这一群新的个体由于继承了上一代的一些优良特性,明显优于上一代,以逐步向着更优解的方向进化.遗传算法主要的特点在于:简单、通用、鲁棒性强。

经过二十多年的发展,遗传算法已经在旅行商问题、生产调度、函数优化、机器学习等领域得到成功的应用。

遗传算法是一类可用于复杂系统优化的具有鲁棒性的搜索算法,与传统的优化算法相比,主要有以下特点:1、遗传算法以决策变量的编码作为运算对象.传统的优化算法往往直接决策变量的实际植本身,而遗传算法处理决策变量的某种编码形式,使得我们可以借鉴生物学中的染色体和基因的概念,可以模仿自然界生物的遗传和进化机理,也使得我们能够方便的应用遗传操作算子.2、遗传算法直接以适应度作为搜索信息,无需导数等其它辅助信息。

3、遗传算法使用多个点的搜索信息,具有隐含并行性。

4、遗传算法使用概率搜索技术,而非确定性规则。

遗传算法是基于生物学的,理解或编程都不太难。

下面是遗传算法的一般算法步骤:1、创建一个随机的初始状态初始种群是从解中随机选择出来的,将这些解比喻为染色体或基因,该种群被称为第一代,这和符号人工智能系统的情况不一样;在那里,问题的初始状态已经给定了。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

{ CreateCitiesCircular();
CalculateBestPossibleRoute(); } //改变窗口坐标时 void Resize(const int new_width, const int new_Height);
//给一个有效的周游路径,返回该路径长度 double GetTourLength(const vector<int> &route);
//窗口定义大小
#define WINDOW_WIDTH 500
#define WINDOW_HEIGHT 500
//城市数量及城市在窗口显示的大小
#define NUM_CITIES
20
#define CITY_SIZE
5
//变异概率,交叉概率及种群数量
#define MUTATION_RATE 0.2
};
#endif
//五、一个其实没有用的头文件(StdAfx.h) #if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000_ _INCLUDED_) #define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDE D_
m_pMap = new CmapTSP(map_width, map_height, NumCities); CreateStartingPopulation();
} //析构函数 ~CgaTSP(){delete m_pMap;}
void Run(HWND hwnd);
void
Epoch();
//他的适应度分数 double dFitness;
//构造函数 SGenome ():dFitness(0){}
SGenome(int nc):dFitness(0) {
vecCities = GrabPermutation(nc); } //随机创建一个周游路径 vector<int> GrabPermutation (int &limit);
//限制大小 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 // //描述:封装地图数据、城市坐标以及适应度计算。 ///////////////////////////////////////////////// #include <vector>
#include "mapTSP.h" #include "defines.h"
using namespace std;
//----------基因组结构体(包含旅行路径和其适应度函数)---------struct SGenome {
//周游城市路径,(基因组) vector<int> vecCities;
//把所有城市组成一个环形 void CreateCitiesCircular();
//用勾股定理计算两个城市 A 和 B 之间的距离 double CalculateA_to_B(const CoOrd &city1, const CoOrd &city2);
//该函数计算出排列成环形后的最佳路径,答案是显而易见的(环形多边形 周长)
//在此之前找到的最长周游路径 double m_dLongestRoute;
//种群中基因组的数目 int m_iPopSize;
//染色体长度 int m_iChromoLength;
//新一代中适应度分数最高的成员
int m_iFittestGenome;
//表明已经到了那一代 int m_iGeneration;
//在 GrabPermutation 中使用 bool TestNumber(const vector<int> &vec, const int &number);
};
//--------CgaTSP 类---------------
class CgaTSP { private:
//声明基因组实例 vector<SGenome> m_vecPopulation;
void CalculateBestPossibleRoute();
public: //城市坐标 vector<CoOrd> m_vecCityCoOrds;
//构造函数,当创建一个实例时,城市坐标即被创建,并计算出可能的最佳 路径
CmapTSP(int w, int h, int nc):m_MapWidth(w), m_MapHeight(h),m_NumCities(nc)
inline bool RandBool() {
if (RandInt(0,1)) return true;
else return false;
}
//-----定义一些方便的小功能包括:整形转字符型,浮点型转字符型--string itos(int arg); //converts an float to a std::string string ftos (float arg);
//------CmapTSP 类,封装地图数据,城市坐标,以及适应度计算---class CmapTSP { private:
//城市数目 int m_NumCities;
//地图长度和宽度 int m_MapWidth; int m_MapHeight;
//可能最好路径 double m_dBestPossibleRoute;
#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
//帮助了解长须当前是否进入绘图阶段 bool m_bStarted;
//交换变异(Exchange Mutation) void MutateEM(vector<int> &chromo);
//部分匹配杂交 void CrossoverPMX(const vector<int> &mum,
const vector<int> &dad, vector<int> &baby1, vector<int> &baby2);
//地图类的实例 CmapTSP* m_pMap;
//交叉及变异概率 double m_dMutationRate; double m_dCrossoverRate;
//整个种群的总适应度分数 double m_dTotalFitness;
//在此之前找到的最短路径 double m_dShortestRoute;
#endif
//////////////////////////////----------------源文件---------------///////////////////////////////-
//一、utils.cpp // utils.cpp: implementation of the Cutils class. // //////////////////////////////////////////////////////////////////////
SGenome& RouletteWheelSelection();
//适应度函数中用到的函数 void CalculatePopulationsFitness(); void CalculateBestWorstAvtot(); void Reset(); void CreateStartingPopulation();
#include <stdlib.h> #include <math.h> #include <sstream> #include <string> #include <iostream>
using namespace std; //--------定义一些随机函数--------
//----定义随机整数,随机[x,y]之间的整数--inline int RandInt(int x, int y) {
double BestPossibleRoute()const{return m_dBestPossibleRoute;} };
#endif
//四、遗传算法头文件(CgaTSP)
#ifndef CGATSP_H #define CGATSP_H
#include <vector> #include <windows.h> #include <fstream> #include <algorithm> #include <iostream>
相关文档
最新文档