一.问题描述

假设有一个旅行商人要拜访n(研究n=10)个城市,他必须选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。路径的选择目标是要求得的路径路程为所有路径之中的最小值。

二.遗传算法(GA)概述 

遗传算法(Genetic Algorithm)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法,它最初由美国Michigan大学J.Holland教授于1975年首先提出来的,并出版了颇有影响的专著《Adaptation in Natural and Artificial Systems》,GA这个名称才逐渐为人所知,J.Holland教授所提出的GA通常为简单遗传算法(SGA)。

三.问题分析 

TSP问题就是寻找一条最短的遍历n 个城市的最短路径, 即搜索自然数子集W= { 1 ,2 , ⋯, n} ( W的元素表示对n 个城市的编号) 的一个排列  π( W) = { V1 , V2 , ⋯, Vn} , 使len = ∑ d ( Vi , Vi+1) + d ( V1 , Vn)取最小值, 式中的d ( Vi , Vi+1) 表示城市Vi 到城市Vi + 1的距离。

遗传算法是具有“生成+检测”的迭代过程的搜索算法。遗传算法是一种群体型操作,该操作以群体中的所有个体为对象。选择、交叉和变异是遗传算法的3个主要操作算子,它们构成了所谓的遗传操作,使遗传算法具有了其它传统方法所没有的特性。遗传算子包含如下6个基本因素:

1.参数编码:由于遗传算法不能直接处理解空间的解数据,因此必须通过编码将它们表示成遗传空间的基因型串结构数据。 我们采用整数编码的方式,用0-9来表示10个城市。

2.种群初始化:由于遗传算法的群体型操作需要,所以必须为遗传操作准备一个由若干初始解组成的初始种群。初始种群的每个个体都是通过随机方法产生。

3. 适应度函数:遗传算法在搜索进化过程中一般不需要其他外部信息,仅用适应度值来评估个体或解的优劣,并作为以后遗传操作的依据。 设一个解遍历初始行走的总距离为D,N=1000(根据具体路径而变化),则适应度fitness=pow(2,N/D)。即总距离越高,适应度越低,总距离越低(解越好),适应度越高。

4.选择操作:选择或复制操作是为了从当前群体中选出优良的个体,使它们有机会作为父代为下一代繁殖子孙。个体适应度越高,其被选择的机会就越多。此处采用与适应度成比例的概率方法进行选择。具体地说,就是首先计算群体中所有个体适应度的总和,再计算每个个体的适应度所占的比例,并以此作为相应的选择概率。采用轮盘赌方法。

5. 交配操作:交配操作是遗传算法中最主要的遗传操作。常用的交配规则如下:常规交配法、基于次序的交配法、基于位置的交配法、基于部分映射的交配法。这里采用基于部分映射的交配法。例如:

父代路径1:  0 6 8 5 1 3 2 9 7 4 0

父代路径2:  0 9 7 8 5 2 3 6 1 4 0

产生一个随机数,假设a = 4,设定交配4位,上面标红的位置,进行交换并放在首位(0之后),然后再从各自的路径中按顺序填充未出现过的数字。如下:

子代路径1:  0 5 2 3 6 8 1 9 7 4 0

子代路径2:  0 1 3 2 9 7 8 5 6 4 0

6.变异操作:变异操作是按位进行的,即把某一位的内容进行变异。变异操作同样也是随机进行的。一般而言,变异概率都取得较小。一般采取对于一个染色体(即个体)随机选取两个基因进行交换的策略。如下:

父代路径:  0 6 8 5 1 3 2 9 7 4 0

子代路径:  0 6 8 9 1 3 2 5 7 4 0

交换后计算两次的城市距离,如若变异后距离变大,则重新变异。

四.具体实现

首先,建立城市位置结构体和功能结构体:

typedef struct CityPosition{int x;int y;}CityPosition;typedef struct {int colony[POPSIZE][CITY_NUM + 1];  //城市种群double fitness[POPSIZE];           // 路径适应值double Distance[POPSIZE];         //路径实际长度int BestRooting[CITY_NUM + 1];     //最优城市路径序列double BestFitness;               //最优路径适应值double BestValue;                //最优路径长度}TSP;

然后,定义实现功能函数:

void CalculatDist() //计算每两个城市之间的距离void InitColony(TSP &city) //初始化种群void CalFitness(TSP &city) //计算适应值void Select(TSP &city) //选择操作void Cross(TSP &city, double pc) //交叉操作void Mutation(TSP &city, double pm) //变异操作void OutPut(TSP &city) //输出函数

最后定义实现主函数:

main(){CalculatDist();InitColony(city);CalFitness(city);for (i = 0; i < MaxEpoc; i++){Select(city);//选择Cross(city, pcross);//交叉Mutation(city, pmutation);//变异CalFitness(city);//计算适应值                 }OutPut(city);//输出}

五.运行结果

六.总结

通过遗传算法对10城市的求解,可以看出,用遗传算法来求解TSP问题是可行的。用遗传算法求解时,增加迭代次数,可以得到更加优良的结果,但是会需要更长的时间,即一个优良的结果往往是以时间为代价的,这种情况要依据具体问题具体分析,平衡两者在问题求解时的比重。另外,对选择算法进行优化,会提高遗传算法的性能,这些都需要在实践中不断积累和广泛涉猎优良算法。最后,遗传算法得到的未必是最优解,我们可以根据需要进行多次求解,从而比较得出符合要求的结果。

七.源代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "math.h"
#include "time.h"
#define CITY_NUM 10     //城市编号是0-9
#define POPSIZE 20
#define MAXVALUE 100   //路径值
#define N 1000            //需要根据实际求得的路径值修正
int Hash[CITY_NUM + 1];
typedef struct CityPosition
{int x;int y;
}CityPosition;
CityPosition CityPos[10] = { {1,1},{1,4},{1,6},{1,8},{3,8},{5,1},{8,1},{8,2},{8,4},{8,8} };
double CityDistance[CITY_NUM][CITY_NUM];
typedef struct {int colony[POPSIZE][CITY_NUM + 1];  //城市种群double fitness[POPSIZE];          // 路径适应值double Distance[POPSIZE];         //路径实际长度int BestRooting[CITY_NUM + 1];      //最优城市路径序列double BestFitness;               //最优路径适应值double BestValue;                 //最优路径长度
}TSP, *PTSP;void CalculatDist()
{//计算每两个城市之间的距离int i, j;int temp1, temp2;for (i = 0; i < CITY_NUM; i++) {for (j = 0; j <= CITY_NUM; j++) {       temp1 = CityPos[j].x - CityPos[i].x;temp2 = CityPos[j].y - CityPos[i].y;CityDistance[i][j] = sqrt(temp1*temp1 + temp2 * temp2);}}
}void copy(int a[], int b[])
{//复制int i = 0;for (i = 0; i < CITY_NUM + 1; i++){a[i] = b[i];}
}bool check(TSP &city, int pop, int num, int k)
{//用来检查新生成的节点是否在当前群体中,0号节点是默认出发节点和终止节点int i;for (i = 0; i <= num; i++) {if (k == city.colony[pop][i])return true;//新生成节点存在于已经生成的路径中}return false;//新生成节点没有存在于已经生成的路径中
}void InitColony(TSP &city)
{//初始化种群int i, j, r;for (i = 0; i < POPSIZE; i++) {city.colony[i][0] = 0;city.colony[i][CITY_NUM] = 0;city.BestValue = MAXVALUE;city.BestFitness = 0;//适应值越大越好}for (i = 0; i < POPSIZE; i++){for (j = 1; j < CITY_NUM; j++){r = rand() % (CITY_NUM - 1) + 1;//产生1~CITY_NUM-1之间的随机数while (check(city, i, j, r)){r = rand() % (CITY_NUM - 1) + 1;}city.colony[i][j] = r;}}
}void CalFitness(TSP &city)
{//计算适应值int i, j, start, end;int Best = 0;for (i = 0; i < POPSIZE; i++) {//求适应值city.Distance[i] = 0;for (j = 1; j <= CITY_NUM; j++){start = city.colony[i][j - 1]; end = city.colony[i][j];city.Distance[i] = city.Distance[i] + CityDistance[start][end];}city.fitness[i] = pow(2, N / (city.Distance[i]));if (city.fitness[i] > city.fitness[Best])Best = i;}copy(city.BestRooting, city.colony[Best]);city.BestFitness = city.fitness[Best];city.BestValue = city.Distance[Best];
}void Select(TSP &city)
{//选择算子int TempColony[POPSIZE][CITY_NUM + 1];int i, j, s, t;double GaiLv[POPSIZE];int SelectP[POPSIZE + 1];double avg;double sum = 0;for (i = 0; i < POPSIZE; i++){sum += city.fitness[i];}for (i = 0; i < POPSIZE; i++){GaiLv[i] = city.fitness[i] / sum;}SelectP[0] = 0;for (i = 0; i < POPSIZE; i++){SelectP[i + 1] = SelectP[i] + GaiLv[i] * RAND_MAX;}for (t = 0; t < POPSIZE; t++){//轮盘赌s = rand() % RAND_MAX;for (i = 1; i < POPSIZE; i++){if (SelectP[i] >= s)break;}copy(TempColony[t], city.colony[i - 1]);}for (i = 0; i < POPSIZE; i++){copy(city.colony[i], TempColony[i]);}
}void Cross(TSP &city, double pc)
{//交叉算子int i, j, t;int a, b;int Temp1[CITY_NUM + 1], Temp2[CITY_NUM + 1];for (i = 0; i < POPSIZE - 1; i++){double s = ((double)(rand() % RAND_MAX)) / RAND_MAX;if (s < pc){a = rand() % (CITY_NUM - 4) + 1;memset(Hash, 0, sizeof(Hash));//内存空间初始化Temp1[0] = Temp1[CITY_NUM] = 0;for (j = 1; j < 5; j++){Temp1[j] = city.colony[i + 1][a + j - 1];Hash[Temp1[j]] = 1;}for (t = 1; t < CITY_NUM; t++){if (Hash[city.colony[i][t]] == 0){Temp1[j++] = city.colony[i][t];Hash[city.colony[i][t]] = 1;}}memset(Hash, 0, sizeof(Hash));Temp2[0] = Temp2[CITY_NUM] = 0;for (j = 1; j < 5; j++){Temp2[j] = city.colony[i][a + j - 1];Hash[Temp2[j]] = 1;}for (t = 1; t < CITY_NUM; t++){if (Hash[city.colony[i + 1][t]] == 0){Temp2[j++] = city.colony[i + 1][t];Hash[city.colony[i + 1][t]] = 1;}}copy(city.colony[i], Temp1);copy(city.colony[i + 1], Temp2);}}}double GetDistance(int a[CITY_NUM + 1])
{int i, start, end;double Distance = 0;for (i = 0; i < CITY_NUM; i++){start = a[i];   end = a[i + 1];Distance += CityDistance[start][end];}return Distance;
}void Mutation(TSP &city, double pm)
{//变异算子int i;int Temp[CITY_NUM + 1];for (i = 0; i < POPSIZE; i++){double s = ((double)(rand() % RAND_MAX)) / RAND_MAX;if (s < pm){int a, b, t;a = (rand() % (CITY_NUM - 1)) + 1;b = (rand() % (CITY_NUM - 1)) + 1;copy(Temp, city.colony[i]);t = Temp[a];Temp[a] = Temp[b];Temp[b] = t;if (GetDistance(Temp) > GetDistance(city.colony[i])){a = (rand() % (CITY_NUM - 1)) + 1;b = (rand() % (CITY_NUM - 1)) + 1;copy(Temp, city.colony[i]);t = Temp[a];Temp[a] = Temp[b];Temp[b] = t;}copy(city.colony[i], Temp);}}
}void OutPut(TSP &city)
{int i, j;printf("The population is:\n");for (i = 0; i < POPSIZE; i++){for (j = 0; j <= CITY_NUM; j++){printf("%5d", city.colony[i][j]);}printf("    %f\n", city.Distance[i]);}printf("The best rooting is:\n");for (i = 0; i <= CITY_NUM; i++)printf("%5d", city.BestRooting[i]);printf("\nIt's cost value is %f\n", (city.BestValue));printf("\n\n\n\n");
}int main()
{TSP city;double pcross = 0.5, pmutation = 0.1;//交叉概率和变异概率int MaxEpoc = 200;//最大迭代次数int i;srand((unsigned)time(0));//随机数发生器的初始化CalculatDist();//求城市间两两之间的距离InitColony(city);//生成初始种群CalFitness(city);//计算适应值,考虑应该在这里面把最优选出来for (i = 0; i < MaxEpoc; i++){Select(city);//选择(复制)Cross(city, pcross);//交叉Mutation(city, pmutation);//变异CalFitness(city);//计算适应值       }OutPut(city);//输出return 0;
}

旅行商问题(遗传算法)相关推荐

  1. 旅行商问题(动态规划_爬山算法_遗传算法)

    问题描述 ​ 旅行商问题(Travelling Salesman Problem, 简记TSP,亦称货郎担问题):设有n个城市和距离矩阵D=[dij],其中dij表示城市i到城市j的距离,i,j=1, ...

  2. TSP_旅行商问题 - 模拟退火算法(三)

    一.前言 [旅行商问题]旅行商问题(TravelingSalesmanProblem,TSP)是一个经典的组合优化问题.经典的TSP可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市 ...

  3. 解决旅行商问题的方法

    旅行商问题 旅行商问题 定义: 简介: 智能优化算法解决旅行商问题 遗传算法 TSP问题基本概念 遗传算法的基本原理 1.设计算法的编码方式 2.设计遗传算法的适应度函数 3.设计遗传算法的选择操作 ...

  4. 旅行商问题(TSP)简介

    什么是旅行商问题 旅行商问题(TravelingSalesmanProblem,TSP)是一个经典的组合优化问题.经典的TSP可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发, ...

  5. TSP_旅行商问题-基本蚁群算法

    TSP_旅行商问题-基本蚁群算法 旅行商系列算法 TSP_旅行商问题-贪心算法 TSP_旅行商问题-模拟退火算法 TSP_旅行商问题-遗传算法 TSP_旅行商问题-基本蚁群算法 基于基本蚁群算法解决连 ...

  6. TSP_旅行商问题 - 贪心算法

    TSP_旅行商问题 - 贪心算法 TSP_旅行商问题-贪心算法 TSP_旅行商问题-模拟退火算法 TSP_旅行商问题-遗传算法 TSP_旅行商问题-基本蚁群算法 问题描述 寻找最短路径使得其经过所有城 ...

  7. A tutorial on Principal Components Analysis - 主成分分析(PCA)教程

    A tutorial on Principal Components Analysis 原著:Lindsay I Smith, A tutorial on Principal Components A ...

  8. 遗传算法解决旅行商问题(TSP)

    遗传算法解决旅行商问题(TSP) 参考文章: (1)遗传算法解决旅行商问题(TSP) (2)https://www.cnblogs.com/studylyn/p/5097238.html 备忘一下.

  9. 人工智能--遗传算法(旅行商问题)

    人工智能是研究使计算机来模拟人的某些思维过程和智能行为(如学习.推理.思考.规划等)的学科,主要包括计算机实现智能的原理.制造类似于人脑智能的计算机,使计算机能实现更高层次的应用.人工智能将涉及到计算 ...

  10. MAT之GA:遗传算法(GA)解决M-TSP多旅行商问题

    MAT之GA:遗传算法(GA)解决M-TSP多旅行商问题 导读       MTSP_GA Multiple Traveling Salesmen Problem (M-TSP) Genetic Al ...

最新文章

  1. php error_reporting 详解
  2. ROS初级教程1---官方ROS文件系统导览
  3. 简单粗暴地理解js原型链–js面向对象编程
  4. kaggle奖牌发放体系(转)
  5. 转: Linux下单网卡多vlan多虚拟机
  6. 全球计算机用户人数,NIC2019年11月:全球IPv6 用户数占比中国居43位
  7. SpringBoot + Vue 开发前后端分离的旅游管理系统
  8. \t\t使用Google APP Engine 完成个人代理服务器架设
  9. 安装CentOS 7.4 操作系统
  10. 蓝桥杯 省赛 杨辉三角形 python组(转)
  11. 利用维基百科挖掘概念之间的先决条件关系(初探)
  12. RNA 23. SCI文章中表达基因Cox模型的风险因子关联图(ggrisk)
  13. amigo幸运字符什么意思_机器视觉之halcon入门(4)-字符识别
  14. 瀑布流网站数据如何采集解决思路方法
  15. python基础以及面向对象
  16. CSS Font-awesome字体图标库文件
  17. 七、ROS-CAN通信
  18. 【Python】pathlib 模块的用法(Path)
  19. JPA常用的SQL语法操作---官方操作
  20. 2-SII--应用本包下文件写入和读取

热门文章

  1. edgy trees_将Ubuntu从Edgy升级到Feisty(6.10至7.04)
  2. 05-现代威胁环境下的10个SIEM用例
  3. Ae 入门系列之二:素材的导入与管理
  4. 解决Android调试微信页面,chrome的inspect弹出空白
  5. 如何解决“MSCOMCTL.ocx を読み込めません” 即 MSCOMCTL.ocx加载失败?
  6. 2003服务器怎么安装系统,工控机安装WindowsServer2003系统步骤
  7. 虚幻4 游戏引擎(二):蓝图教学
  8. 量子计算机是否存在相对论,从量子到宇宙——颠覆人类认知的科学之旅
  9. 大数据就业前景如何?大数据时代,马云这样说...
  10. 大数据学习路线思维导图