• 模拟退火算法


    算法简介

    模拟退火算法源于金属退火的原理。当固体温度很高时,内能较大,内部粒子进行快速的无序运动,当温度逐渐降低时,粒子运动速度逐渐下降,逐渐趋于有序,也基本趋于稳定。

    在搜索全局最优解时,我们也可以先设置一个高温,然后逐渐降低温度,直到温度趋近于0。在冷却过程中,对于每个温度,都去迭代多次,来寻找局部最优解:

    • 在当前位置进行一次扰动,模拟粒子从位置 x x x跳到位置 x ′ x' x
    • 对于新的函数值,若更优,则跳到新的位置
    • 若新的位置更劣,则有概率跳到新的位置

    温度趋近于0时,算法结束,即可得出最终的答案。


    算法原理

    为什么要有概率跳出而不是不跳出呢?因为如果现在找到了一个局部最优解,虽然它不是全局最优解,但如果在一定范围内没有比它更优的解,那最后的结果就是这个局部最优解了。如果有一定的概率能跳出,则就有可能找到另一个局部最优解。最后取所有局部最优解的最优解,得出的结果有更大概率是全局最优解。

    模拟退火算法是一个近似算法,它并不能保证找到的结果是全局最优解。

    其中跳出的概率 P P P满足以下公式(假设函数值最小为最优):

    P = { 1 f ( x ′ ) ≤ f ( x ) e f ( x ) − f ( x ′ ) k T   f ( x ′ ) > f ( x ) P=\left\{

    1f(x)f(x)ef(x)f(x)kT f(x)>f(x)" role="presentation">1f(x)f(x)ef(x)f(x)kT f(x)>f(x)
    \right. P= 1f(x)f(x)ekTf(x)f(x) f(x)>f(x)

    其中 T T T表示初始温度, k k k表示温度下降的速率。

    可以看出,当温度越⾼时,越有可能跳出局部最优解;当温度越⼩时,越趋向于稳定,越不容易跳出局部最优解。

    在温度固定的情况下,模拟退⽕算法需要迭代多次,迭代的次数越多,越容易找到局部最优解。这个迭代次数称为⻢尔科夫链。

    但⻢尔科夫链越⻓,所需要的时间也越多。


    例题

    【HDU - 2899】Strange fuction

    题目大意:定义函数 f ( x ) = 6 x 7 + 8 x 6 + 7 x 3 + 5 x 2 + a x f(x)=6x^7+8x^6+7x^3+5x^2+ax f(x)=6x7+8x6+7x3+5x2+ax a a a已知。求当 0 ≤ x ≤ 100 0\leq x\leq 100 0x100 f ( x ) f(x) f(x)的最小值。保留四位小数。有多组数据。

    模拟退火算法搜索 x x x。对于每个温度,求局部最优解。最后比较局部最优解,就能得出最后的结果。

    code

    #include
    #include
    #include
    #include
    #include
    using namespace std;
    int tt,T=50;
    double a,t0=100,t1,t2=1e-8,k=0.98;
    double f(double x){
    	return 6*x*x*x*x*x*x*x+8*x*x*x*x*x*x+7*x*x*x+5*x*x-a*x; 
    }
    double rd(double x){
    	return rand()*1.0/RAND_MAX*x;
    }
    int main()
    {
    	srand(time(NULL));
    	double x,y,tx,ty,px,py;
    	scanf("%d",&tt);
    	while(tt--){
    		scanf("%lf",&a);
    		t1=t0;
    		x=0;
    		px=0;py=f(0);
    		while(t1>t2){
    			y=f(x);
    			for(int i=1;i<=T;i++){
    				tx=x+(rand()%2*2-1)*t1;
    				if(tx<-0.01||tx>100.01) continue;
    				ty=f(tx);
    				if(ty<y){
    					x=tx;y=ty;
    				}
    				else{
    					if(rd(1)<exp((y-ty)/t1)){
    						x=tx;y=ty;
    					}
    				}
    				if(ty<py){
    					px=tx;py=ty;
    				}
    			}
    			t1=t1*k;
    		}
    		if(px<0.0) px=0.0;
    		if(px>100.0) px=100.0;
    		printf("%.4f\n",f(px));
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
  • 相关阅读:
    关于#python#的问题,请各位专家解答!(操作系统-linux)
    rmq事务消息
    mysql存储过程
    吉林教育杂志吉林教育杂志社吉林教育编辑部2022年第28期目录
    上线项目问题——无法加载响应数据
    Ruby 数据库访问 - DBI 教程
    Springboot2.1.1版本升级到2.3.10版本报错合集及解决办法
    首次做CMMI,如何选择适合的评估级别
    web3-引言之读取账户地址
    一文了解云计算
  • 原文地址:https://blog.csdn.net/tanjunming2020/article/details/127909973