tsp问题——遗传算法解决
TSP问题最简单的求解方法是枚举法。
它的解是多维的、多局部极值的、趋于无穷大的复杂解的空间。搜索空间是n个点的全部排列的集合。大小为(n-1)!
。能够形象地把解空间看成是一个无穷大的丘陵地带,各山峰或山谷的高度即是问题的极值。求解TSP,则是在此不能穷尽的丘陵地带中攀登以达到山顶或谷底的过程。
这一篇将用遗传算法解决TSP问题。
1)评价。
这个评价算法应该比較简单了,就是找计算总距离,小的为优。目标函数转化为适应度函数能够取倒数。
2)突变。为了防止反复訪问,不能随机的进行突变。由于每一个城市仅仅能訪问一次。我们仅仅须要随意的交换两个城市就可以。
上一行是突变之前。以下一行是突变之后的。
3)交叉。这个操作是个比較关键的步骤。如何交叉才干才干父母的优秀基因呢?对于TSP问题,我们要找的是一个最优的排列。当中排列的顺序应该是最重要的。
因此在交叉的时候。分别随机的取 父母的部分序列,要保持原有的顺序。
Parents
先随机的选取 Parent1 的 一部分。比如 678 部分,。然后把剩下的城市 安装 Parent2 中的顺序,遗传下去。
Chlid
其他基本依照遗传算法的框架来即可了
// TSP.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include<iostream>
//#include <stdio.h>
#include <time.h>
//#include <stdlib.h> using namespace std;
#define POPSIZE 200 //种群总数
#define rdint(i)(rand()%(int)(i))
#define rdft()((float)rdint(16384)/(16383.0))
typedef unsigned char BYTE; //31个城市的坐标
int city[31][2] = { { 1304, 2312 }, 3639, 1315, 4177, 2244, 3712, 1399, 3488, 1535, 3326, 1556, 3238, 1229,
4196, 1004, 4312, 790, 4386, 570, 3007, 1970, 2562, 1756, 2788, 1491, 2381, 1676, 1332, 695, 3715, 1678,
3918, 2179, 4061, 2370, 3780, 2212, 3676, 2578, 4029, 2838, 4263, 2931, 3429, 1908, 3507, 2367, 3394, 2643,
3439, 3201, 2935, 3240, 3140, 3550, 2545, 2357, 2778, 2826, 2370, 2975 }; int* my_unrepeat_rand(int L, int H)
{
const int LEN = H - L + 1;
//int n[LEN];
int *n = new int[LEN];
for (int i = 0; i < LEN; ++i)
{
n[i] = L + i;
} for (int j = LEN; j > 0; --j)
{
int m = j*rand() /(RAND_MAX + 1.0);
int temp = n[m];
n[m] = n[j - 1];
n[j - 1] = temp;
}
return n;
} class Chromosome
{
friend class Population;
public:
static const int length = 31; private:
BYTE gene[length];
double fitness;
double distance;
public:
void initial_chromosome()//初始化染色体
{
distance = 0;
fitness = 0;
int*b = my_unrepeat_rand(0, length - 1);
for (int i = 0; i < length; i++)
gene[i] = b[i];
delete[]b;
}
BYTE*get_gene()
{
return this->gene;
}
double get_distance()
{
return distance;
}
void calculate_distance()//计算适应度。这里直接取总距离,越小越好
{
distance = 0;
for (int i = 0; i < length - 1; i++)
{
distance += sqrt(pow(double(city[gene[i]][0] - city[gene[i + 1]][0]), double(2)) +
pow(double(city[gene[i]][1] - city[gene[i + 1]][1]), double(2)));
}
distance += sqrt(pow(double(city[gene[0]][0] - city[gene[length - 1]][0]), double(2)) + pow(double(city[gene[0]][1] - city[gene[length - 1]][1]), double(2)));
} pair<Chromosome, Chromosome> cross(Chromosome p1)//交叉操作,选中区间的基因不改变。孩子基因的其它位置的基因从配偶处获得,要保持顺序
{
pair<Chromosome, Chromosome>child;
//srand(time(0));
int m = rand() % length ;
int n = rand() % length;
if (m > n)
{
int temp = m;
m = n;
n = temp;
}
int j = 0,p=0;
for (int i = 0; i < length; i++)
{
if (i >= m&&n >= i)
{
child.first.gene[i] = gene[i];
child.second.gene[i] = p1.gene[i];
continue;
}
bool flag = true;
while (flag)
{
flag = false;
for (int k = m; k <= n; k++)
if (p1.gene[j] == gene[k])
{
flag = true;
break;
}
if (flag)
j++;
}
child.first.gene[i] = p1.gene[j];
j++;
flag = true;
while (flag)
{
flag = false;
for (int k = m; k <= n; k++)
if (gene[p] == p1.gene[k])
{
flag = true;
break;
}
if (flag)
p++;
}
child.second.gene[i] = gene[p];
p++;
} return child;
} Chromosome mutation()//变异。选择两个位置交换基因
{
int m = rand() % (length - 1);
int n = rand() % (length - 1);
while (n == m)
{
n = rand() % (length - 1);
}
int temp = gene[m];
gene[m] = gene[n];
gene[n] = temp;
return *this;
} }; class Population
{
private:
Chromosome pop[POPSIZE];
Chromosome best;
Chromosome worst;
unsigned int Generation;
unsigned int maxgeneration;
double m_dCrossoverRate;//交叉率0.6
double m_dMutationRate;//变异率0.01
bool elitism;//是否在新一代中保存前一代的最优个体
double m_dTotalFitnessScore;
void initial_pop()
{
for (int i = 0; i < POPSIZE; i++)
pop[i].initial_chromosome();
};
public:
Population(double pc, double pM, bool ISelitism, unsigned int maxgen) :m_dCrossoverRate(pc), m_dMutationRate(pM), elitism(ISelitism), maxgeneration(maxgen)//构造函数
{
Generation = 1;
initial_pop();
}
void Calcu_fit()//计算适应值
{
m_dTotalFitnessScore = 0;
for (int i = 0; i < POPSIZE; i++)
{
pop[i].calculate_distance();
}
find_best_worst();
//sort_by_distance(POPSIZE);
double mindis = best.distance;
double maxdis = worst.distance;
for (int i = 0; i < POPSIZE; i++)
{
pop[i].fitness = 1 - (pop[i].distance - mindis) / (maxdis - mindis + 0.0001);//double(1000) / pop[i].distance;//
m_dTotalFitnessScore += pop[i].fitness;
} }
//fitness(i,1)=(1-((len(i,1)-minlen)/(maxlen-minlen+0.0001)))
void sort_by_distance(int k)
{
if (k == 1)
return;
for (int i = 0; i < k-1; i++)
{
if (pop[i].distance < pop[i + 1].distance)
{
double temp = pop[i].distance;
pop[i].distance = pop[i + 1].distance;
pop[i + 1].distance = temp;
}
}
sort_by_distance(k - 1);
}
void find_best_worst()
{
double mindis = 100000000;
double maxdis = 0;
for (int i = 0; i < POPSIZE; i++)
{
if (pop[i].distance > maxdis)
{
maxdis = pop[i].distance;
worst = pop[i];
}
if (pop[i].distance < mindis)
{
mindis = pop[i].distance;
best = pop[i];
}
}
} int RouletteWheelSelection()
{
double fSlice = rdft() * m_dTotalFitnessScore;
double cfTotal = 0.0; for (int i = 0; i<POPSIZE; ++i)
{
cfTotal += pop[i].fitness;
if (cfTotal > fSlice)
{
return i;
}
}
}
void Epoch()
{
Calcu_fit();
Chromosome new_pop[POPSIZE+1];
int NewBabies = 0;
if (elitism)
{
NewBabies = 1;
new_pop[0] = best;
} while (NewBabies < POPSIZE)
{
//select 2 parents
int mum = RouletteWheelSelection();
int dad = RouletteWheelSelection();
while (dad == mum)
{
dad = RouletteWheelSelection();
}pair<Chromosome, Chromosome>child;
if (rdft() < m_dCrossoverRate)
{
child = pop[mum].cross(pop[dad]);
}
else
{
child.first = pop[mum];
child.second = pop[dad];
}
if (rdft() < m_dMutationRate)
{
child.first.mutation();
}
if (rdft() < m_dMutationRate)
{
child.second.mutation();
}
new_pop[NewBabies]=child.first;
new_pop[NewBabies+1] = child.second;
NewBabies += 2;
} for (int i = 0; i < POPSIZE; i++)
pop[i] = new_pop[i];
++Generation;
} Chromosome get_best()
{
return best;
}
void run()
{
while (Generation < maxgeneration)
{
Epoch();
}
} }; int _tmain(int argc, _TCHAR* argv[])
{
time_t t;
srand((unsigned)time(&t)); Population tsp(0.6,0.1,true,1000);
tsp.run(); cout << tsp.get_best().get_distance()<<endl;
system("pause");
return 0;
}
tsp问题——遗传算法解决的更多相关文章
- 遗传算法解决旅行商问题(TSP)
这次的文章是以一份报告的形式贴上来,代码只是简单实现,难免有漏洞,比如循环输入的控制条件,说是要求输入1,只要输入非0就行.希望会帮到以后的同学(*^-^*) 一.问题描述 旅行商问题(Traveli ...
- 遗传算法解决寻路问题——Python描述
概要 我的上一篇写遗传算法解决排序问题,当中思想借鉴了遗传算法解决TSP问题,本质上可以认为这是一类问题,就是这样认为:寻找到一个序列X,使F(X)最大. 详解介绍 排序问题:寻找一个序列,使得这个序 ...
- 【高级算法】遗传算法解决3SAT问题(C++实现)
转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46910079 1 SAT问题描写叙述 命题逻辑中合取范式 (CNF) 的可满足性问 ...
- 遗传算法解决TSP问题实现以及与最小生成树的对比
摘要: 本实验采用遗传算法实现了旅行商问题的模拟求解,并在同等规模问题上用最小生成树算法做了一定的对比工作.遗传算法在计算时间和占用内存上,都远远优于最小生成树算法. 程序采用Microsoft vi ...
- 遗传算法解决TSP问题
1实验环境 实验环境:CPU i5-2450M@2.50GHz,内存6G,windows7 64位操作系统 实现语言:java (JDK1.8) 实验数据:TSPLIB,TSP采样实例库中的att48 ...
- 转:遗传算法解决TSP问题
1.编码 这篇文章中遗传算法对TSP问题的解空间编码是十进制编码.如果有十个城市,编码可以如下: 0 1 2 3 4 5 6 7 8 9 这条编码代表着一条路径,先经过0,再经过1,依次下去. 2.选 ...
- 用遗传算法解决TSP问题
浅谈遗传算法:https://www.cnblogs.com/AKMer/p/9479890.html Description \(小m\)在踏上寻找\(小o\)的路程之后不小心碰到了大魔王\(fat ...
- [POJ 3311]Hie with the Pie——谈论TSP难题DP解决方法
主题连接: id=3311">http://poj.org/problem?id=3311 题目大意:有n+1个点,给出点0~n的每两个点之间的距离,求这个图上TSP问题的最小解 ...
- TSP问题 遗传算法 智能优化算法
写了半天,效率还是有点低的,以后有空再优化下: //用次序表示法来表示个体编码 #include<iostream> #include<fstream> #include< ...
随机推荐
- JS学习笔记-数据类型
最初的JS学习已经过去大半年的时间了,至此感觉对JS的使用与理解并非非常深入,因此在近期的工作之余也開始了新一轮的JS学习. 几天时间过去了,对于一些基础内容的学习还是非常有必要的,就从今天的又一次整 ...
- POJ 2528 Mayor's posters 离散化和线段树题解
本题就是要往墙上贴海报,问最后有多少可见的海报. 事实上本题的难点并非线段树,而是离散化. 由于数据非常大,直接按原始数据计算那么就会爆内存和时间的. 故此须要把数据离散化. 比方有海报1 6 7 ...
- hpuoj--校赛--2015年的第一场雪(暴力)
问题 D: 感恩节KK专场--2015年的第一场雪 时间限制: 1 Sec 内存限制: 128 MB 提交: 865 解决: 76 [提交][状态][讨论版] 题目描述 下雪了,KK学长站在三教门 ...
- [HNOI2008] GT考试(DP+矩阵快速幂+KMP)
题目链接:https://www.luogu.org/problemnew/show/P3193#sub 题目描述 阿申准备报名参加 GT 考试,准考证号为 N 位数 X1,X2…Xn(0 <= ...
- 关于md解析器
不得不说,博客园的 md 解析器真的不够好.和 csdn 以及 sf 社区的比起来,差太多了.以后,博客园就老老实实写随笔了,文章类的还是用 csdn 吧.
- c# IndexOf()用法
IndexOf()用法 查找字符串中字符或者字符串首次出现的位置,返回的是索引值; str1.indexOf('字');//查找“字”在字符串中首次出现的索引值 str1.indexOf(" ...
- hadoop ha
https://blog.csdn.net/daydayup_668819/article/details/70815335 https://www.jianshu.com/p/8a6cc2d7206 ...
- 在windows下如何新建爬虫虚拟环境和进行scrapy安装
Scrapy是Python开发的一个快速.高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据.Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改.Sc ...
- python虚拟环境virtualenv、virtualenv下运行IDLE、powershell 运行脚本由执行策略引起的问题
一.为什么要创建虚拟环境: 应为在开发中会有同时对一个包不同版本的需求,创建多个开发环境就能解决这个问题.或许也会有对python不同版本的需求,这就需要使用程序来管理不同的版本,virtualenv ...
- 中国象棋程序的设计与实现(十一)--第2次回答CSDN读者的一些问题
最近一段时间,有不少CSDN读者朋友看了我写的中国象棋文章.其中,不少爱好者下载了中国象棋程序的初级版和高级版源码. 由于水平有限,不少同学遇到了若干问题,向我咨询,寻找解决办法. 我的处境1.如果我 ...