1. 程式人生 > >摸擬退火演算法 Simualtea Annealing AIirthm(SAA)

摸擬退火演算法 Simualtea Annealing AIirthm(SAA)

1:固體退火過程

       固體退火是將固體加熱到熔化,在冷卻使之凝固成規整晶體的熱力學過程。

文獻原文描述:

        固體加熱時, 固體粒子的熱運動不斷增強,隨著溫度的升高 , 粒子與其平衡位置的偏離越來越大 , 固體的規則性逐漸被破 壞 . 當粒子排列從較有序的結晶態變為無序的液態時便完成熔解過程 . 熔解過程的目的是消出系統中原先可能存在的非均勻狀態 , 該過程中系統的能量隨著溫度的升高而增大 .

         冷卻時, 液體粒子的熱運動漸漸減弱 , 隨著溫度的徐徐降低, 粒子運動漸趨規則 (有 序 ) , 當溫度降至結晶溫度後 ,粒子運動變為圍繞晶體格點的微小振動 . 當液體凝固成固體的晶態時完成退火過程. 退火過程中系統的能量隨著溫度的降低趨於最小值 .

2:Metropolis準則

     初始狀態i,其能量是Ei;新狀態為j,其能量是Ej。

                     當Ej<Ei時,則接受它。

                     當Ei<Ej時,根據概率來判斷是否接受,p=exp((Ej-Ei)/kT)。在[0,1)之間產生隨機數m,如果p>m,則接受。否 則不接受。(k是波爾茲曼常數,T是當前溫度。)

3:演算法描述

1:退火與最優解聯絡

      狀態i對應組合解i,能量Ei對應目標函式f(x),能量最小值對應最優解。

2:演算法步驟

    重複一下步驟,知道停止準則。

          隨機產生新解;

          計算f(x);

          比較與上一次的解的大小,根據Metropolis準則進行取捨。

取一張他人部落格的圖片:

 

. 通常SAA可用於多種組合優化問題及相關問題 , 它不會因為問題例項的不同而使實驗效能脫變, 從而具有較好的穩健性 .

C語言程式碼實現:

#include <stdio.h>
#include <math.h>
#include <time.h>
#include<stdlib.h>
#define num 30000 //迭代次數

double k=0.1;
double r=0.9; //用於控制降溫的快慢
double T=2000; //系統的溫度,系統初始應該要處於一個高溫的狀態
double T_min =10;//溫度的下限,若溫度T達到T_min,則停止搜尋

//返回指定範圍內的隨機浮點數
double rnd(double dbLow,double dbUpper)
{
    double dbTemp=rand()/((double)RAND_MAX+1.0);
    return dbLow+dbTemp*(dbUpper-dbLow);
}

double func(double x)//目標函式
{
	return x*(x-1)+1;
}
int main()
{
	double best=func(rnd(0.0,10));
	double dE,current;
	int i;
	while( T > T_min )
    {
		for(i=0;i<num;i++)
		{
		//用當前時間點初始化隨機種子,防止每次執行的結果都相同
		time_t tm;
		time(&tm);
		unsigned int nSeed=(unsigned int)tm;
		srand(nSeed);

		current=func(rnd(0.0,10));
		dE = current - best ;

		if ( dE < 0 ) //表達移動後得到更優解,則總是接受移動
			best = current ;
		else
		{
			// 函式exp( dE/T )的取值範圍是(0,1) ,dE/T越大,則exp( dE/T )也越大
			if ( exp( dE/(T*k) ) > rnd( 0.0 , 1.0 ) )
				best = current ;
		}
		}
		T = r * T ;//降溫退火 ,0<r<1 。r越大,降溫越慢;r越小,降溫越快
    }
	printf("最小值是 %f\n",best);
	return 0;
}

【參考文獻】:魏延,謝開貴.模擬退火演算法[J].蒙自師範高等專科學校學報,1999(04):7-11.