1. 程式人生 > >蟻群演算法的原始碼 .

蟻群演算法的原始碼 .

不知道現在是否還有人在研究蟻群演算法?應該有吧。當初為了找C或C++原始碼而不可得,在閱讀了多份"雜七雜八"的程式碼的基礎,總算寫出來了。運行了三個TSP經典用例,基本符合要求。2008年3月份寫的,現在貼出來大家共享一下,註釋加的應該算齊全。僅僅是一份按照蟻群演算法的原理寫的程式碼,沒有做任何優化。至於我做優化後的程式碼,就不發出來了吧,呵呵。環境為:Windows XP SP2 + VC 6.0.

/*********************************
*作者:陳杰
*單位:四川大學計算機學院
*郵件地址:[email protected]
*完成時間:2008年3月
*********************************/

#include<iostream>
#include<math.h>
#include<time.h>
using namespace std;

//該程式是以蟻群系統為模型寫的蟻群演算法程式(強調:非螞蟻周模型),以三個著名的TSP問題為測試物件
//通過微調引數,都可以獲得較好的解

/*
//----------(1)問題一:Oliver 30 城市 TSP 問題 best_length = 423.7406; ------------------------
//該程式最好的結果是423.741,可執行多次獲得
//城市節點數目
#define N 30
//城市座標
double C[N][2]={
	{2,99},{4,50},{7,64},{13,40},{18,54},{18,40},{22,60},{24,42},{25,62},{25,38},
	{37,84},{41,94},{41,26},{44,35},{45,21},{54,67},{54,62},{58,35},{58,69},{62,32},
	{64,60},{68,58},{71,44},{71,71},{74,78},{82,7},{83,46},{83,69},{87,76},{91,38}
};
//----------上面引數是固定的,下面的引數是可變的-----------
//螞蟻數量
#define M 30
//最大迴圈次數NcMax
int NcMax = 500;
//資訊啟發因子,期望啟發式因子,全域性資訊素揮發引數,區域性資訊素揮發引數, 狀態轉移公式中的q0
double alpha = 2, beta = 3, rou = 0.1, alpha1 = 0.1,  qzero = 0.01;
//-----------問題一結束------------------------------------------------------------------------
*/

/*
//----------(2)問題二:Elion50 城市 TSP 問題 best_length = 427.96; ----------------------------
//該程式最好的結果是428.468,可執行多次獲得
//城市節點數目
#define N 50
//城市座標
double C[N][2]={
	{5,64}, {5,25}, {5,6}, {7,38}, {8,52}, {10,17},
	{12,42}, {13,13}, {16,57}, {17,33}, {17,63},
	{20,26}, {21,47}, {21,10}, {25,32}, {25,55},
	{27,68}, {27,23}, {30,48}, {30,15}, {31,62},
	{31,32}, {32,22}, {32,39}, {36,16}, {37,69},
	{37,52}, {38,46}, {39,10}, {40,30}, {42,57},
	{42,41}, {43,67}, {45,35}, {46,10}, {48,28},
	{49,49}, {51,21}, {52,33}, {52,41}, {52,64},
	{56,37}, {57,58}, {58,27}, {58,48}, {59,15},
	{61,33}, {62,42}, {62,63}, {63,69}
};
//----------上面引數是固定的,下面的引數是可變的-----------
//螞蟻數量
#define M 50
//最大迴圈次數NcMax
int NcMax = 1000;
//資訊啟發因子,期望啟發式因子,全域性資訊素揮發引數,區域性資訊素揮發引數, 狀態轉移公式中的q0
double alpha = 2, beta = 4, rou = 0.1, alpha1 = 0.1,  qzero = 0.01;
//-----------問題二結束------------------------------------------------------------------------
*/

//----------(3)問題三:Elion75 城市 TSP 問題 best_length = 542.31;
//該程式最好的結果是542.309,可執行多次獲得 
//城市節點數目
#define N 75
//城市座標
double C[N][2]={
{6,25}, {7,43}, {9,56}, {10,70}, {11,28},
{12,17}, {12,38}, {15,5}, {15,14}, {15,56},
{16,19}, {17,64}, {20,30}, {21,48}, {21,45},
{21,36}, {22,53}, {22,22}, {26,29}, {26,13},
{26,59}, {27,24}, {29,39}, {30,50}, {30,20},
{30,60}, {31,76}, {33,34}, {33,44}, {35,51},
{35,16}, {35,60}, {36,6}, {36,26}, {38,33},
{40,37}, {40,66}, {40,60}, {40,20}, {41,46},
{43,26}, {44,13}, {45,42}, {45,35}, {47,66},
{48,21}, {50,30}, {50,40}, {50,50}, {50,70},
{50,4}, {50,15}, {51,42}, {52,26}, {54,38},
{54,10}, {55,34}, {55,45}, {55,50}, {55,65},
{55,57}, {55,20}, {57,72}, {59,5}, {60,15},
{62,57}, {62,48}, {62,35}, {62,24}, {64,4},
{65,27}, {66,14}, {66,8}, {67,41}, {70,64}
};
//----------上面引數是固定的,下面的引數是可變的-----------
//螞蟻數量
#define M 75
//最大迴圈次數NcMax
int NcMax =1000;
//資訊啟發因子,期望啟發式因子,全域性資訊素揮發引數,區域性資訊素揮發引數, 狀態轉移公式中的q0
double alpha = 2, beta = 5, rou = 0.1, alpha1 = 0.1,  qzero = 0.1;
//-----------問題三結束------------------------------------------------------------------------


//===========================================================================================================
//區域性更新時候使用的的常量,它是由最近鄰方法得到的一個長度
//什麼是最近鄰方法?:)就是從源節點出發,每次選擇一個距離最短的點來遍歷所有的節點得到的路徑
//每個節點都可能作為源節點來遍歷
double Lnn;
//矩陣表示兩兩城市之間的距離
double allDistance[N][N];

//計算兩個城市之間的距離
double calculateDistance(int i, int j)
{
	return sqrt(pow((C[i][0]-C[j][0]),2.0) + pow((C[i][1]-C[j][1]),2.0));
}

//由矩陣表示兩兩城市之間的距離
void calculateAllDistance()
{
	for(int i = 0; i < N; i++)
	{
		for(int j = 0; j < N; j++)
		{
			if (i != j)
			{
				allDistance[i][j] = calculateDistance(i, j);
				allDistance[j][i] = allDistance[i][j];
			}
		}
	}
}

//獲得經過n個城市的路徑長度
double calculateSumOfDistance(int* tour)
{
	double sum = 0;
	for(int i = 0; i< N ;i++)
	{
		int row = *(tour + 2 * i);
		int col = *(tour + 2* i + 1);
		sum += allDistance[row][col];
	}
	return sum;
}

class ACSAnt;

class AntColonySystem
{
private:	
	double info[N][N], visible[N][N];//節點之間的資訊素強度,節點之間的能見度
public:	
	AntColonySystem()
	{
	}
	//計算當前節點到下一節點轉移的概率
	double Transition(int i, int j);	
	//區域性更新規則
	void UpdateLocalPathRule(int i, int j);	
	//初始化
	void InitParameter(double value);	
	//全域性資訊素更新
	void UpdateGlobalPathRule(int* bestTour, int globalBestLength);
};

//計算當前節點到下一節點轉移的概率
double AntColonySystem::Transition(int i, int j)
{
	if (i != j)
	{
		return (pow(info[i][j],alpha) * pow(visible[i][j], beta));
	}
	else
	{
		return 0.0;
	}	
}
//區域性更新規則
void AntColonySystem::UpdateLocalPathRule(int i, int j)
{
	info[i][j] = (1.0 - alpha1) * info[i][j] + alpha1 * (1.0 / (N * Lnn));
	info[j][i] = info[i][j];
}
//初始化
void AntColonySystem::InitParameter(double value)
{
	//初始化路徑上的資訊素強度tao0
	for(int i = 0; i < N; i++)
	{
		for(int j = 0; j < N; j++)
		{				
			info[i][j] = value;
			info[j][i] = value;
			if (i != j)
			{
				visible[i][j] = 1.0 / allDistance[i][j];
				visible[j][i] = visible[i][j];
			}
		}
	}	
}

//全域性資訊素更新
void AntColonySystem::UpdateGlobalPathRule(int* bestTour, int globalBestLength)
{
	for(int i = 0; i < N; i++)
	{
		int row = *(bestTour + 2 * i);
		int col = *(bestTour + 2* i + 1);
		info[row][col] = (1.0 - rou) * info[row][col] + rou * (1.0 / globalBestLength);
		info[col][row] =info[row][col];
	}
}

class ACSAnt
{
private:
	AntColonySystem* antColony;
protected:
	int startCity, cururentCity;//初始城市編號,當前城市編號
	int allowed[N];//禁忌表	
	int Tour[N][2];//當前路徑
	int currentTourIndex;//當前路徑索引,從0開始,儲存螞蟻經過城市的編號
public:	
	ACSAnt(AntColonySystem* acs, int start)
	{
		antColony = acs; 
		startCity = start;
	}	
	//開始搜尋
	int* Search();
	//選擇下一節點
	int Choose();
	//移動到下一節點
	void MoveToNextCity(int nextCity);

};

//開始搜尋
int* ACSAnt::Search()
{
	cururentCity = startCity;
	int toCity;
	currentTourIndex = 0;
	for(int i  = 0; i < N; i++)
	{
		allowed[i] = 1;
	}
	allowed[cururentCity] = 0;
	int endCity;
	int count = 0;
	do
	{
		count++;
		endCity = cururentCity;
		toCity = Choose();		
		if (toCity >= 0)
		{			
			MoveToNextCity(toCity);
			antColony->UpdateLocalPathRule(endCity, toCity);
			cururentCity = toCity;
		}		
	}while(toCity >= 0);
	MoveToNextCity(startCity);
	antColony->UpdateLocalPathRule(endCity, startCity);

	return *Tour;
}

//選擇下一節點
int ACSAnt::Choose()
{
	int nextCity = -1;		
	double q = rand()/(double)RAND_MAX;
	//如果 q <= q0,按先驗知識,否則則按概率轉移,
	if (q <= qzero)
	{
		double probability = -1.0;//轉移到下一節點的概率
		for(int i = 0; i < N; i++)
		{
			//去掉禁忌表中已走過的節點,從剩下節點中選擇最大概率的可行節點
			if (1 == allowed[i])
			{
				double prob = antColony->Transition(cururentCity, i);
				if (prob  > probability)
				{
					nextCity = i;
					probability = prob;
				}
			}
		}
	}
	else
	{
		//按概率轉移			
		double p = rand()/(double)RAND_MAX;//生成一個隨機數,用來判斷落在哪個區間段
		double sum = 0.0;			
		double probability = 0.0;//概率的區間點,p 落在哪個區間段,則該點是轉移的方向
		//計算概率公式的分母的值
		for(int i = 0; i < N; i++)
		{
			if (1 == allowed[i])
			{
				sum += antColony->Transition(cururentCity, i);
			}
		}
		for(int j = 0; j < N; j++)
		{
			if (1 == allowed[j] && sum > 0)
			{
				probability += antColony->Transition(cururentCity, j)/sum;
				if (probability >= p || (p > 0.9999 && probability > 0.9999))
				{
					nextCity = j;
					break;
				}
			}
		}	
	}	
	return nextCity;
}

//移動到下一節點
void ACSAnt::MoveToNextCity(int nextCity)
{
	allowed[nextCity]=0;
	Tour[currentTourIndex][0] = cururentCity;
	Tour[currentTourIndex][1] = nextCity;
	currentTourIndex++;
	cururentCity = nextCity;
}

//------------------------------------------
//選擇下一個節點,配合下面的函式來計算的長度
int ChooseNextNode(int currentNode, int visitedNode[])
{
	int nextNode = -1;		
	double shortDistance = 0.0;
	for(int i = 0; i < N; i++)
	{
		//去掉已走過的節點,從剩下節點中選擇距離最近的節點
		if (1 == visitedNode[i])
		{			
			if (shortDistance == 0.0)
			{
				shortDistance = allDistance[currentNode][i];
				nextNode = i;
			}
			if(shortDistance < allDistance[currentNode][i])
			{
				nextNode = i;
			}
		}
	}
	return nextNode;
}

//給一個節點由最近鄰距離方法計算長度
double CalAdjacentDistance(int node)
{
	double sum = 0.0;
	int visitedNode[N];
	for(int j = 0; j < N; j++)
	{
		visitedNode[j] = 1; 
	}
	visitedNode[node] = 0;
	int currentNode = node;
	int nextNode;
	do
	{
		nextNode = ChooseNextNode(currentNode, visitedNode);
		if (nextNode >= 0)
		{
			sum += allDistance[currentNode][nextNode];
			currentNode= nextNode;
			visitedNode[currentNode] = 0;
		}		
	}while(nextNode >= 0);
	sum += allDistance[currentNode][node];
	return sum;
}

//---------------------------------結束---------------------------------------------

//--------------------------主函式--------------------------------------------------
int main()
{
	time_t timer,timerl;

	time(&timer);
	unsigned long seed = timer;
	seed %= 56000;
	srand((unsigned int)seed);

	//由矩陣表示兩兩城市之間的距離
	calculateAllDistance();
	//蟻群系統物件
	AntColonySystem* acs = new AntColonySystem();
	ACSAnt* ants[M];
	//螞蟻均勻分佈在城市上
	for(int k = 0; k < M; k++)
	{
		ants[k] = new ACSAnt(acs, (int)(k%N));
	}
	calculateAllDistance();
	//隨機選擇一個節點計算由最近鄰方法得到的一個長度
	int node = rand() % N;
	Lnn = CalAdjacentDistance(node);
	
	//各條路徑上初始化的資訊素強度
	double initInfo = 1 / (N * Lnn);
	acs->InitParameter(initInfo);	
	
	//全域性最優路徑
	int globalTour[N][2];
	//全域性最優長度
	double globalBestLength = 0.0;	
	for(int i = 0; i < NcMax; i++)
	{
		//區域性最優路徑
		int localTour[N][2];
		//區域性最優長度
		double localBestLength = 0.0;
		//當前路徑長度
		double tourLength;
		for(int j = 0; j < M; j++)
		{
			int* tourPath = ants[j]->Search();
			tourLength = calculateSumOfDistance(tourPath);				
			//區域性比較,並記錄路徑和長度
			if(tourLength < localBestLength || abs(localBestLength - 0.0) < 0.000001)
			{				
				for(int m = 0; m< N; m++)
				{
					int row = *(tourPath + 2 * m);
					int col = *(tourPath + 2* m + 1);
					localTour[m][0] = row;
					localTour[m][1] = col;
				}
				localBestLength = tourLength;			
			}
		}
		//全域性比較,並記錄路徑和長度
		if(localBestLength < globalBestLength || abs(globalBestLength - 0.0) < 0.000001)
		{				
			for(int m = 0; m< N; m++)
			{
				globalTour[m][0] = localTour[m][0];
				globalTour[m][1] = localTour[m][1];
			}
			globalBestLength = localBestLength;	
		}
		acs->UpdateGlobalPathRule(*globalTour, globalBestLength);
		//輸出所有螞蟻迴圈一次後的迭代最優路徑
		cout<<"第 "<<i + 1<<" 迭代最優路徑:"<<localBestLength<<"."<<endl;
		for(int m = 0; m< N; m++)
		{
			cout<<localTour[m][0]<<".";
		}
		cout<<endl;		
	}	
	//輸出全域性最優路徑
	cout<<"全域性最優路徑長度:"<<globalBestLength<<endl;	
	cout<<"全域性最優路徑:";
	for(int m = 0; m< N; m++)
	{
		cout<<globalTour[m][0]<<".";
	}
	cout<<endl;
	time(&timerl);
	int t = timerl - timer;
	return 0;
}
//--------------------------主函式結束--------------------------------------------------

相關推薦

演算法簡介及matlab原始碼

1 蟻群演算法原理  自1991年由義大利學者 M. Dorigo,V. Maniezzo 和 A. Colorni 通過模擬蟻群覓食行為提出了一種基於種群的模擬進化演算法——蟻群優化。該演算法的出現引起了學者們的極大關注,蟻群演算法的特點:     ① 其原理是一種正

演算法原始碼 .

不知道現在是否還有人在研究蟻群演算法?應該有吧。當初為了找C或C++原始碼而不可得,在閱讀了多份"雜七雜八"的程式碼的基礎,總算寫出來了。運行了三個TSP經典用例,基本符合要求。2008年3月份寫的,現在貼出來大家共享一下,註釋加的應該算齊全。僅僅是一份按照蟻群演算法的

演算法學習

** 蟻群演算法的基本原理(簡單概括): ** 剛開始螞蟻按照同等概率選擇各條路徑。 螞蟻在經過的路徑下留下資訊素。 短的路徑螞蟻會率先找到食物源,因此資訊素濃度偏大。 由於資訊素的揮發,較長路徑上的資訊素逐漸消失 特點:正反饋;不容易陷入區域

C++:演算法解決TSP(C++多執行緒版)

TSP問題:旅行商問題,最短迴路。 這裡採用att48資料,鄰接矩陣全部取整數,原資料放在文後。 解決程式碼如下: //#define TEST_INPUT //#define TEST_T //#define TEST_ANT //#define TEST_VALUE #

【機器學習筆記35】演算法

【參考資料】 【1】《蟻群演算法原理及其應用》 【2】測試資料: https://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/tsp/att48.tsp.gz 演算法原理(以TSP問題為例) (1)引數初始化。令時間t=0和迴圈次數

演算法matlab

(一)蟻群演算法的由來 蟻群演算法最早是由Marco Dorigo等人在1991年提出,他們在研究新型演算法的過程中,發現蟻群在尋找食物時,通過分泌一種稱為資訊素的生物激素交流覓食資訊從而能快速的找到目標,據此提出了基於資訊正反饋原理的蟻群演算法。 蟻群演算法的基本思想來源於自然界螞

簡單易懂,演算法解決旅行商問題

轉載宣告: 原文把蟻群解決旅行商問題寫的很清楚,只不過本人認為原文中有一些小錯誤,特此更改(文中紅色加粗字型為改正處),程式碼中出現的一些演算法的小問題也進行了更正(比如程式碼中的貪心演算法),程式碼也附在下面,謝謝博主的分享。 1.關於旅行商(TSP)問題及衍化

智慧演算法---演算法

  1 蟻群演算法及其基本思想 蟻群演算法是一種智慧優化演算法,通過蟻群優化求解複雜問題,ACO在離散優化問題方面有比較好的優越性。     基本思想(以旅行商問題為例)       &nbs

基於基本演算法解決連續優化問題

基於基本蟻群演算法解決連續優化問題 相關連結 TSP_旅行商問題-基本蟻群演算法 基本蟻群演算法解決連續優化問題基本流程 用一個螞蟻代表一個可行解,一個螞蟻含有的資訊包括各變數值; 1、確定迭代週期; 2、確定螞蟻數;

TSP_旅行商問題-基本演算法

TSP_旅行商問題-基本蟻群演算法 旅行商系列演算法 TSP_旅行商問題-貪心演算法 TSP_旅行商問題-模擬退火演算法 TSP_旅行商問題-遺傳演算法 TSP_旅行商問題-基本蟻群演算法 基於基本蟻群演算法解決連續優化

何為啟發式演算法——退火演算法演算法,遺傳演算法

一、退火演算法 模擬退火演算法來源於固體退火原理,將固體加溫至充分高,再讓其徐徐冷卻,加溫時,固體內部粒子隨溫升變為無序狀,內能增大,而徐徐冷卻時粒子漸趨有序,在每個溫度都達到平衡態,最後在常溫時達到基態,內能減為最小。 模擬退火演算法新解的產生和接受

記一次演算法解決TSP問題

演算法規則 1)範圍 螞蟻觀察到的範圍是一個方格世界,螞蟻有一個引數為速度半徑(一般是3),那麼它能觀察到的範圍就是3*3個方格世界,並且能移動的距離也在這個範圍之內。 2)摺疊環境 螞蟻所在的環境是一個虛擬的世界,其中有障礙物,有別的螞蟻,還有資訊素,資訊素有兩種,一種是找到食物的

2018-4-8演算法---包子陽《智慧優化演算法以及Matlab實現》第五章

資料來源:《智慧優化演算法以及matlab實現》包子陽  餘繼周 編著第五章-----蟻群演算法是一種元啟發式優化演算法(自己理解:就是作為群體的單位個體也就是元,在裡面充當著隨機的選擇搜尋的方向,有助於全域性勘探)啟發:自然界的螞蟻有能力在沒有然和提示的情況下找到從巢穴矩離

演算法原理詳解和matlab程式碼

1原理: 螞蟻在尋找食物源的時候,能在其走過的路徑上釋放一種叫資訊素的激素,使一定範圍內的其他螞蟻能夠察覺到。當一些路徑上通過的螞蟻越來越多時,資訊素也就越來越多,螞蟻們選擇這條路徑的概率也就越高,結果導致這條路徑上的資訊素又增多,螞蟻走這條路的概率又增加,生生

旅行商問題TSP(演算法Java)

旅行商問題,即TSP問題(Traveling Salesman Problem)是數學領域中著名問題之一。假設有一個旅行商人要拜訪N個城市,他必須選擇所要走的路徑,路徑的限制是每個城市只能拜訪一次,而且最後要 回到原來出發的城市。路徑的選擇目標是要求得的路徑路程為所有路徑之中

演算法解決tsp問題

控制蟻群演算法走向的關鍵是資訊素,資訊素類似遺傳演算法的適應性函式,類似退火演算法的評價函式,影響著其中一隻螞蟻的下一步的選擇。 螞蟻:類似遺傳演算法的染色體,就是一條解,在tsp問題中螞蟻的路徑就是tsp的解。 資訊素:評價函式,與路徑成反比 螞蟻數量:一次迭代有多少隻螞

有限級資訊素演算法

有限級資訊素蟻群演算法使用路徑等級作為資訊素更新的依據,相比於傳統的蟻群演算法,捨棄了目標函式作為資訊素更新的依據這一方法。在TSP問題中,目標函式實際就是路徑長度,在傳統的蟻群演算法中資訊素更新量為Q/f(x),其中Q為某一常數,而f(x)就是目標函式值,即路徑長度。而在有限級資訊素蟻群演算法中在

【機器學習】利用演算法求解旅行商(TSP)問題

如果喜歡這裡的內容,你能夠給我最大的幫助就是轉發,告訴你的朋友,鼓勵他們一起來學習。 If you like the content here, you can give me the greatest help is forwarding, tell you

演算法調參記錄

蟻群演算法主要有5個引數a資訊素重要程度,b啟發式因子重要程度,c資訊素蒸發係數,ant螞蟻數量,iter迭代次數製作了一個50個節點的地圖,用交叉對比的方法尋找最佳引數首先調b螞蟻數100,迭代數100.很明顯b越小距離和平均值越大,標準差也越大,b=14的時候距離的平均值

演算法解TSP問題

添加了部分註釋,幾乎沒有改動(引數和城市格式略做改動),原博主的程式碼寫的很容易理解,也是我找到的最短的程式碼了,在此感謝。 程式碼如下: //蟻群演算法關於簡單的TSP問題求解// #include<stdio.h> #include<std