模擬退火算法解決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);
}

實驗結果


有時候得出的答案


發佈了21 篇原創文章 · 獲贊 3 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章