摸擬退火演算法 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.