模拟退火算法解决函数优化问题

一、实验目的

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

}



posted @ 2012-11-02 20:25  朱京辉  阅读(927)  评论(0编辑  收藏  举报