一、实验目的

1. 了解TSP问题的基本概念,解决TSP问题的难点是什么?

2. 掌握模拟退火算法、遗传算法的基本原理和步骤。

3. 复习VB、VC的基本概念、基本语法和编程方法,并熟练使用VB、VC编写程序。

二、实验设备

微机

三、实验原理

TSP问题即旅行商问题(Traveling Salesperson Problem)。该问题给定n个城市和两两城市之间的距离,要求确定一条经过各城市当且仅当一次的最短路线。其图论描述为:给定图G=(V, A),其中V为顶点集,A为各顶点相互连接组成的边集,已知各顶点间的连接距离,要求确定一条长度最短的Hamilton回路,即遍历所有顶点当且仅当一次的最短回路。

其他详见《智能信息处理及应用实验讲义--智能优化算法解决TSP问题--模拟退火算法》和《智能信息处理及应用实验讲义--智能优化算法解决TSP问题—遗传算法》。

四、预习要求

1. 认真阅读教材中模拟退火算法和遗传算法的基本原理与步骤。

2. 分析用模拟退火算法和遗传算法解决TSP问题时的编码方式、新解产生的方法等内容。

3. 复习VB、VC的基本概念、基本语法和编程方法。

五、实验内容及步骤

1. 上机编写程序,利用退火算法和遗传算法解决27城市TSP问题。27城市的坐标为:41 94;37 84;53 67;25 62;7 64;2 99;68 58;71 44;54 62;83 69;64 60;18 54;22 60;83 46;91 38;

25 38;24 42;58 69;71 71;74 78;87 76;18 40;13 40;82 7;62 32;58 35;45 21。

2. 调试程序。

3. 根据实验结果,写实验报告。



实验代码::::

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

const int MAXN = 27; //城市数量
const double MAX = 27.0; //城市数量
const double INIT_T = 3000; //初始温度
const double RATE = 0.95; //温度衰减率
const double FINNAL_T = 1E-10; //终止温度
const int IN_LOOP = 15000; //内循环次数
const int LIMIT = 10000; //概率选择上限
const int FINL_LOOP = 1000; //外层循环
double DD=0;
double D_Length[MAXN][MAXN]={0};

struct path
{//定义路线结构
	int citys[MAXN];
	double length;
}D_BestPath;

struct point
{//定义点结构
	double x;
	double y;
}D_Point[MAXN];


//计算点和点之间的距离
void point_dist()
{
	int i, j;
	double x;
	for(i=0; i<MAXN; i++)
	{
		for(j=i+1; j<MAXN; j++)
		{
			x = (D_Point[i].x-D_Point[j].x)*(D_Point[i].x-D_Point[j].x);
			x += (D_Point[i].y-D_Point[j].y)*(D_Point[i].y-D_Point[j].y);
			D_Length[i][j] = sqrt(x);
			D_Length[j][i] = D_Length[i][j];
		}	
	}
}
//初始化
void init()
{
	int i;
	printf("初始状态路径:");
	D_BestPath.length = 0;
	for(i=0; i<MAXN; i++)
	{//初始顺序经过路径
		D_BestPath.citys[i] = i;
		printf("%d--", i);
	}
	for(i=0; i<MAXN-1; i++)
	{//计算路径长度
		D_BestPath.length += D_Length[i][i+1];
	}
	printf("\n路径长度为:%.3lf\n\n", D_BestPath.length);
			
}
void Dprintf(path p)
{//用于显示过程变化情况,打印
	int i;
	printf("路径是:");
	for(i=0; i<MAXN; i++)
	{
		printf("%d--", p.citys[i]);
	}
	printf("\n路径长度为:%.3lf\n\n", p.length);
}
void initi()
{ //测试
	int i;
	D_BestPath.length = 0;
	D_BestPath.citys[0] = 0;
	D_BestPath.citys[1] = 1;
	D_BestPath.citys[2] = 5;
	D_BestPath.citys[3] = 4;
	D_BestPath.citys[4] = 11;
	D_BestPath.citys[5] = 12;
	D_BestPath.citys[6] = 3;
	D_BestPath.citys[7] = 17;
	D_BestPath.citys[8] = 18;
	D_BestPath.citys[9] = 19;
	D_BestPath.citys[10] = 20;
	D_BestPath.citys[11] = 9;
	D_BestPath.citys[12] = 13;
	D_BestPath.citys[13] = 14;
	D_BestPath.citys[14] = 7;
	D_BestPath.citys[15] = 6;
	D_BestPath.citys[16] = 10;
	D_BestPath.citys[17] = 8;
	D_BestPath.citys[18] = 2;
	D_BestPath.citys[19] = 16;
	D_BestPath.citys[20] = 22;
	D_BestPath.citys[21] = 21;
	D_BestPath.citys[22] = 15;
	D_BestPath.citys[23] = 26;
	D_BestPath.citys[24] = 25;
	D_BestPath.citys[25] = 24;
	D_BestPath.citys[26] = 23;
	for(i=0; i<MAXN-1; i++)
	{//计算路径长度
		D_BestPath.length += D_Length[D_BestPath.citys[i]][D_BestPath.citys[i+1]];
	}
	Dprintf(D_BestPath);
}


//输入城市坐标信息
void input()
{
	int i;
	for(i=0; i<MAXN; i++)
		scanf("%lf%lf", &D_Point[i].x, &D_Point[i].y);
}

path getnext(path p)
{
	path ret;
	int i,  x, y;
	int te;
	ret = p;
	do
	{
		x = (int)(MAX*rand()/(RAND_MAX + 1.0));
		y = (int)(MAX*rand()/(RAND_MAX + 1.0));
	}
	while(x == y);
	te = ret.citys[x];
	ret.citys[x] = ret.citys[y];
	ret.citys[y] = te;
	ret.length = 0;
	for(i=0; i<MAXN-1; i++)
	{//计算路径长度
		ret.length += D_Length[ret.citys[i]][ret.citys[i+1]];
	}
	Dprintf(ret);
	DD++;
	return ret;
}

void sa()
{
	int i, P_L=0, P_F=0;;
	path curPath, newPath;
	double T = INIT_T;
	double p, delta;
	srand((int)time(0));
	curPath = D_BestPath;
	while(true)
	{
		for(i=0; i<IN_LOOP; i++)
		{
			newPath = getnext(curPath);
			delta = newPath.length - curPath.length;
			if(delta < 0)
			{//更新长度
				curPath = newPath;
				P_L = 0;
				P_F = 0;
			}
			else
			{
				p = (double)(1.0*rand()/(RAND_MAX+1.0));
				if(exp(delta/T) < 1 && exp(delta/T) > p)
				{
					curPath = newPath;
				}
				P_L ++;
			}
			if(P_L > LIMIT)
			{
				P_F ++;
				break;
			}
		}
		if(curPath.length < newPath.length)
		{
			D_BestPath = curPath;
		}
		if(P_F > FINL_LOOP || T<FINNAL_T)
			break;
		T = T * RATE;
	}

}

void main()
{
	input();
	point_dist();
	init();
	sa();
	Dprintf(D_BestPath);
	printf("\n共测试%.0lf次\n", DD);
}


实验结果

有时候得出的答案