模擬退火算法解決函數優化問題

一、實驗目的

1. 掌握模擬退火算法的基本原理和步驟。

2. 複習VBVC的基本概念、基本語法和編程方法,並熟練使用VBVC編寫模擬退火算法程序。

二、實驗設備

微機

三、實驗原理

模擬退火算法是基於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. 複習VBVC的基本概念、基本語法和編程方法。

2.標準模擬退火算法流程圖


代碼實現::::::::::::::::::::

#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);

}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章