一、實驗目的
1. 掌握模擬退火算法的基本原理和步驟。
2. 複習VB、VC的基本概念、基本語法和編程方法,並熟練使用VB、VC編寫模擬退火算法程序。
二、實驗設備
微機
三、實驗原理
模擬退火算法是基於Monte Carlo迭代求解策略的一種隨機尋優算法,其出發點是基於物理退火過程與組合優化之間的相似性,模擬退火算法由某一較高初溫開始,利用具有概率突跳特性的Metropolis抽樣策略在解空間中進行隨機搜索,伴隨溫度的不斷下降重複抽樣過程,最終得到問題的全局最優解。
標準模擬退火算法的一般步驟可描述如下:
(1)令m=0,給定初溫tm,隨機產生初始狀態sm;
(2)Repeat;
sold=sm;
(2.1)Repeat;
(2.1.1)產生新狀態:snew=Generate(sold);
(2.1.2)若min{1, exp[(C(sold)-C(snew))/tm]}³random[0, 1],則sold=snew;
(2.1.3)Until抽樣穩定準則滿足;
(2.2)退溫:tm+1=update(tm),sm+1=sold,m=m+1;
(3)Until算法終止準則滿足;
(4)輸出算法搜索結果:sm。
四、預習要求
1. 認真閱讀教材中模擬退火算法的基本原理與步驟。
2. 複習VB、VC的基本概念、基本語法和編程方法。
圖2.1 標準模擬退火算法流程圖
代碼實現::::::::::::::::::::
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <math.h>
#define MAXN 10 //個數
const double MIN = 100.00; //數據範圍
const double INIT_T = 300; //初始溫度
const double RATE = 0.95; //溫度衰減率
const double FINAL_T = 0.1; //凝固溫度
const int IN_LOOP = 130; //內層循環次數
const int OUT_LOOP = 100; //外層循環次數
const int P_LIMIT = 10000; //概率選擇次數
double cost = 0; //用於記錄次數
struct path //數據類型存儲
{
double NUM[MAXN];
double sum;
};
path bestpath; //最優解
path getnext(path p) //得到下一組數據的函數
{
int x, i;
double y;
path ret;
ret = p;
cost ++;
printf("第%.0lf次改變數字:\n", cost);
x = (int)(10.0*rand()/(RAND_MAX+1.0)); //隨機產生一個0-9的數更換
printf("更換的是%d:%lf", x, ret.NUM[x]);
ret.sum -= ret.NUM[x]*ret.NUM[x];
y = 2*MIN*rand()/(RAND_MAX+1.0)-MIN;//更換後的數據
printf("變成:%lf\n", y);
ret.NUM[x] = y; //覆蓋
ret.sum += y*y; //更新總和
for(i=0; i<MAXN; i++)
{
printf("%lf__", bestpath.NUM[i]);
}
printf("總和:%lf\n\n\n", ret.sum);
return ret;
}
void init()
{//初始化
int i;
char ss[66];
bestpath.sum = 0;
srand((int)(time(0)));
printf("初始狀態:");
for(i=0; i<MAXN; i++)
{//隨機產生10個-100到100的數
bestpath.NUM[i] = 2*MIN*rand()/(RAND_MAX+1.0)-MIN;
bestpath.sum += bestpath.NUM[i]*bestpath.NUM[i];
printf("!!!%lf", bestpath.NUM[i]);
}
printf("$$$%lf\n", bestpath.sum);
gets(ss); //用於記錄初始狀態
}
void sa()
{
double T;
double rnd = rand()%10000 /10000.0;
path curpath, newpath;
int i, P_t=0, A_t=0;
double delta; //差
T = INIT_T;
curpath = bestpath;
while(true)
{
for (i=1; i<=IN_LOOP; i++)
{
newpath = getnext(curpath);//產生新數據
delta = newpath.sum - curpath.sum;
if(delta < 0.0)
{//符合局部優化條件,更新
curpath = newpath;
P_t = 0;
A_t = 0;
}
else
{//跳變
rnd = rand()%10000 /10000.0;
double p = exp(-delta/T);
if (p > rnd) //符合概率,更新
curpath = newpath;
P_t++;
}
if (P_t >=P_LIMIT)
{//概率上限限制
A_t++;
break;
}
}
if (curpath.sum<bestpath.sum)
{//當前數據較優,更新最佳答案
bestpath = curpath;
}
if ( A_t >= OUT_LOOP || T < FINAL_T) break;
T = T * RATE;//溫度衰減
}
}
void main()
{
int i;
init();
sa();
printf("Best number is: ");
for(i=0; i<MAXN; i++)
{
printf("%lf__", bestpath.NUM[i]);
}
printf("/nThe result is: %lf\n", bestpath.sum);
}