贪心算法求解 TSP 旅行商问题及其实现
文章目錄
- 一、TSP 概述
- 1. TSP
- 2. 數學模型
- 3. TSP分類
- 二、貪心算法
- 1. 算法思路
- 2. 算法框架
- 3. 問題
- 三、貪心算法求解 TSP
一、TSP 概述
1. TSP
旅行商問題即 TSP(Traveling Salesman Problem),又稱為貨郎擔問題,是數學領域中著名問題之一。假設有一個旅行商人要拜訪n個城市,他必須選擇所要走的路徑,路徑的限制是每個城市只能拜訪一次,而且最后要回到原來出發的城市。路徑的選擇目標是要求得的路徑路程為所有路徑之中的最小值。
TSP問題是一個組合優化問題,該問題可以被證明具有NPC計算復雜性。從圖論的角度來看,該問題實質是給定一個帶權完全無向圖(頂點表示城市,邊表示道路,權重是道路的成本或距離),找一個權值最小的 Hamilton 回路。
2. 數學模型
記 G = (V, E) 為賦權圖,V = {1, 2 , ……,n} 為頂點集,E 為邊集,各頂點間距離為 Cij,已知(Cij > 0,Cij = +∞,i,j ∈ V),并設
xij={1,邊(i,j)在最優路線上0,其他x~ij~= \begin{cases} 1,邊(i, j)在最優路線上 \\ 0,其他 \end{cases}x?ij?={1,邊(i,j)在最優路線上0,其他?
則旅行商問題的數學模型可寫成如下的線性規劃形式:
p=∑i≠jcijxijp = \sum_{i ≠ j} c_{ij}x_{ij}p=i?=j∑?cij?xij?
s.t.={∑j≠icij=1,i∈V∑i≠jcij=1,j∈V∑i,j∈Sxij≤∣K∣?1,K?Vxij∈{0,1}i,j∈Vs.t.=\begin{cases} \sum_{j ≠ i} c_{ij} = 1 ,& i∈V \\ \sum_{i ≠ j} c_{ij} = 1 ,& j∈V \\ \sum_{i,j∈S} x_{ij} ≤|K|-1 ,& K ?V \\ x_{ij}∈\{0, 1\} & i,j∈V\\ \end{cases}s.t.=??????????∑j?=i?cij?=1,∑i?=j?cij?=1,∑i,j∈S?xij?≤∣K∣?1,xij?∈{0,1}?i∈Vj∈VK?Vi,j∈V?
K 為 V 的所有非空子集,|K| 為集合 K 中所含圖 G 的頂點個數。前兩個余數意味著對每個頂點而言,出度和入度都為1,后一約束則保證沒有任何子回路解的產生,于是滿足上述約束的解構成了一條 Hamilton 回路。
3. TSP分類
旅行商問題按把不同的分類方法可以分為不同的種類,這里只介紹距離矩陣劃分: 當 cij = cji,(i, j ∈ V)時,問題被稱為對稱型旅行商問題,反之稱為非對稱型旅行商問題,非對稱旅行商問題可以化為對稱型旅行商問題,用對稱型的方法求解。當對所有的 i, j, k ∈[1, n],有不等式 cij + cjk ≥ cik,問題滿足三角形不等式的,也稱三角型旅行商問題。
旅行售貨商問題(TSP)是組合優化領域的經典問題之一,而其中考慮多個旅行商的多旅行商問題(MTSP)是經典的旅行商問題的擴展,多種擴展形式1如下:
二、貪心算法
貪心算法,又名貪婪算法,是一種常用的求解最優化問題的簡單、迅速的算法。貪心算法總是做出在當前看來最好的選擇,它所做的每一個在當前狀態下某種意義上是最好的選擇即貪心選擇,并希望通過每次所作的貪心選擇導致最終得到問題最優解。必須注意的是,貪心算法不是對所有問題都能得到整體最優解,選擇的貪心策略必須具備無后效性,即某個狀態以后的過程不會影響以前的狀態,只與當前狀態有關。
1. 算法思路
貪心算法以當前情況為基礎根據某個優化測度作最優選擇,而不考慮各種可能的整體情況,省去了為找最優解要窮盡所有可能而必須耗費的大量時間。貪心算法采用自頂向下,以迭代的方法做出相繼的貪心選擇,每做一次貪心選擇,就將所求問題簡化為一個規模更小的子問題,通過每一步貪心選擇,可得到問題的一個最優解。雖然每一步上都要保證能獲得局部最優解,但由此產生的全局解有時不一定是最優的,所以貪心算法不要回溯。
貪心算法求解具有以下性質2:
2. 算法框架
貪心算法沒有固定的算法框架,算法設計的關鍵是貪心策略的選擇,而貪心策略適用的前提是:局部最優策略能導致產生全局最優解。
//問題隨機初始解 while(能向總目標前進一步) {//利用可行的決策,從候選集合中求出可行解的一個解元素; }3. 問題
貪心算法也存在如下問題3:
- 不能保證求得的最后解是最佳的;
- 不能用來求最大最小解問題;
- 只能在某些特定條件約束的情況下使用,例如貪心策略必須具備無后效性等。
三、貪心算法求解 TSP
貪心策略基本思路:從一節點出發遍歷所有能到達的下一節點,選擇距離最近的節點作為下一節點,然后把當前節點標記已走過,下一節點作為當前節點,重復貪心策略,以此類推直至所有節點都標記為已走節點結束。
TSP 數據集來自于 TSPLIB 上的 att48.tsp,這是一個對稱 TSP 問題,城市規模為48,其最優值為10628。其距離計算方法如下:
The edge weight type ATT corresponds to a special “pseudo-Euclidean” distance function. Let x[ i ] and y[ i ] be the coordinates of node i. The distance between two points i and j is computed as follows:
double dis = sqrt((pow((double)x[i] - x[j], 2) / 10 + pow((double)y[i] - y[j], 2) / 10 ));
int disInt = (int)dis;
if(disInt < dis) dis = disInt + 1;
else dis = disInt;
具體代碼如下:
/********************************************************************************************************************** TSP 算例來自TSPLIB,att48.tsp 數據集,其中有 48 個城市,距離為偽歐式距離* TSPLIB is a library of sample instances for the TSP (and related problems)from various sources and of various types.* 目前最佳解總距離為 10628,其中距離的計算方式為 sqrt((x*x + y*y)/10)* 使用貪心策略求解,解集總距離為 12861,可見貪心策略只是局部最優解 **********************************************************************************************************************/ #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<math.h> #include<stdlib.h> #include<time.h>// 城市數量 N #define N 48 // 城市距離矩陣 int distance[N][N];/************************************************************************ Function :init()* Description:從文件中讀取城市坐標,并計算城市之間的距離 distance[N][N] * Input :void* Output :void* Return :void***********************************************************************/ void init() {//城市的 x 和 y 坐標int x[N] = { 0 };int y[N] = { 0 };//從 data.txt 文件讀取數據FILE* fp;if ((fp = fopen("..//att48.txt", "r")) == NULL)//if ((fp = fopen("..//kroB100.txt", "r")) == NULL){printf("can not open the file!");exit(0);}while (!feof(fp)){int count;fscanf(fp, "%d", &count);fscanf(fp, "%d%d", &x[count - 1], &y[count - 1]);}fclose(fp);//計算城市之間距離for (int i = 0; i < N - 1; i++){distance[i][i] = 0; // 對角線為0for (int j = i + 1; j < N; j++){double dis = sqrt((pow((double)x[i] - x[j], 2) / 10 + pow((double)y[i] - y[j], 2) / 10));int disInt = (int)dis;distance[i][j] = dis == disInt ? disInt : disInt + 1;distance[j][i] = distance[i][j];}}distance[N - 1][N - 1] = 0; }/************************************************************************ Function :TSPGreedyAlgorithm()* Description:貪心策略求解 TSP 問題* Input :void* Output :TSP 路徑和對應的總距離* Return :void***********************************************************************/ void TSPGreedyAlgorithm() {//總路程int totalDistance = 0; //默認從 0 開始遍歷int current = 0; //標識城市是否被訪問,訪問過置為 1bool visit[N] = { false };visit[0] = 1;printf("TSP 路徑為:%d ->", 1);//遍歷 N - 1 次for (int i = 1; i < N; i++){//設置較大的距離初始值用來選取最近鄰int min_distance = 0x7fffffff;//保存當前最近鄰城市int temp;//循環選取城市for (int j = 1; j < N; j++){if (!visit[j] && distance[current][j] < min_distance){min_distance = distance[current][j];temp = j;}}visit[temp] = 1;current = temp;totalDistance += min_distance;printf(" %d ->", temp + 1);}totalDistance += distance[current][0];printf(" %d\n", 1);printf("TSP 總距離為:%d\n", totalDistance); }int main() {init();TSPGreedyAlgorithm();return 0; }結果如下:
可見,貪心算法求解 TSP 問題只能得到局部最優解,如果需要得到最優解,需要采用局部搜索算法等非精確性算法,作者將在后文中繼續介紹其他方法求解 TSP 問題。
The multiple traveling salesman problem: an overview of formulations and solution procedures. ??
計算機算法設計與分析研究,新華出版社,2015.09. ??
計算機算法基礎,西南交通大學出版社,2015.02. ??
總結
以上是生活随笔為你收集整理的贪心算法求解 TSP 旅行商问题及其实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Web前端第二季(CSS):十:第5章:
- 下一篇: IEEE PHM 2012竞赛数据集