一、实验目的
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);
}