一、實驗目的
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);
}
實驗結果
有時候得出的答案