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