模拟退火算法解决TSP问题

一、实验目的

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

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

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

二、实验设备

微机

三、实验原理

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

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

四、预习要求

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

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

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

五、实验内容及步骤

1. 上机编写程序,利用退火算法和遗传算法解决27城市TSP问题。27城市的坐标为:41 9437 8453 6725 627 642 9968 5871 4454 6283 6964 6018 5422 6083 4691 38

25 3824 4258 6971 7174 7887 7618 4013 4082 762 3258 3545 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);
}

实验结果


有时候得出的答案


posted @ 2012-11-02 21:35  朱京辉  阅读(680)  评论(0编辑  收藏  举报