模拟退火_matlab

退火是一种金属热处理工艺,指的是将金属缓慢加热到一定温度,保持足够时间,然后以适宜速度冷却。在温度较高时,固体内部的粒子热运动较为激烈,随着温度的降低,固体内能减少,粒子的运动也渐渐减缓。这个过程和我们求函数最小值有什么共同点呢,看下面这个图,如果初始点在红色位置,按照梯度搜索,是不可能找到全局最小值的。但是模仿退火过程,如果下一步的位置对应的值更小,就保存下来,如果变大了,以一定的概率来选择是不是保留。在温度很高的时候,这个概率是比较大的,这就能够实现跳出局部最优,而随着温度越来越低,这个概率会变低,而且温度也不是匀速降低的,而是以一个越来越慢的速度降低,这就保证了在全局最优附近能够搜索得更仔细。

下面给出两个很经典的例子:

1.商旅问题

2.0-1背包问题

1.商旅问题:一个商人要从自己的国家出发去n个国家走一遍售卖商品,最终回到自己的国家。问他应该如何规划自己访问国家的顺序,才能走最少的路程呢?

解题思路:一开始看到这个问题,可能会想到前面学过的Floyed或者Dijkstra算法,但是他们都是计算两点之间最短路问题的,而不是吧所有的点全走一遍。所以就不能用了。面对这样的组合规划问题,模拟退火就能派上用场了。

(1)设置模拟退火初参数

(2)随机生成一个访问序列[1,2,3...n],记作sol

(3)在当前温度高于终温情况下循环,生成对sol的扰动,形式是随机的两个国家顺序互换或者三个国家之间的国家位置互换

(4)计算新的sol的距离,如果距离比sol_best(最好的顺序)对应的距离e_best(最短的距离)还小,那么更新sol_best和e_best,如果不是,则按一定几率接受这个顺序,把他当做新的顺序进行下一次循环

(5)当温度达到终温是跳出循环,出书结果和访问顺序

clear;
clc;
b=0.99;
t0=97;
tf=3;
t=t0;
Markov_length=100;
a=[1 3 2;
   2 0 0;
   3 5 5
   4 3 1];
a(:,1) =[];
amount=size(a,1)
dist_matrix=zeros(amount,amount);
disp(dist_matrix);
plot(a(:,1),a(:,2),'*');
coor_x_tmp1=a(:,1)*ones(1,amount);
disp(coor_x_tmp1);
coor_x_tmp2=coor_x_tmp1';
disp(coor_x_tmp2);
coor_y_tmp1=a(:,2)*ones(1,amount);
coor_y_tmp2=coor_y_tmp1';
dist_matrix=sqrt((coor_x_tmp1-coor_x_tmp2).^2+(coor_y_tmp1-coor_y_tmp2).^2);
disp(dist_matrix);
sol_new=1:amount;
e_current=inf;
e_best=inf;
sol_current=sol_new;
sol_best=sol_new;
p=1;
while t>tf
    for r=1:Markov_length
        if rand<0.5
            ind1=0;
            ind2=0;
            while ind1==ind2
                ind1=ceil(rand.*amount);
                ind2=ceil(rand.*amount);
            end
            tmp1=sol_new(ind1);
            sol_new(ind1)=sol_new(ind2);
            sol_new(ind2)=tmp1;
        else
            ind1=0;ind2=0;ind3=0;
            while(ind1==ind2)||(ind1==ind3)||(ind2==ind3)||(abs(ind1-ind2)==1)
                ind1=ceil(rand.*amount);
                ind2=ceil(rand.*amount);
                ind3=ceil(rand.*amount);
            end
            arr=[ind1 ind2 ind3]
            
            for i=1:3
                for j=1:2
                    if arr(j)>arr(j+1)
                        tmp=arr(j);
                        arr(j)=arr(j+1);
                        arr(j+1)=tmp;
                    end
                end
            end
            ind1=arr(1);ind2=arr(2);ind3=arr(3);
            tmplist1=sol_new((ind1+1):(ind2-1));
            sol_new((ind1+1):(ind1+ind3-ind2+1))=sol_new((ind2):ind3);
            sol_new((ind1+ind3-ind2+2):ind3)=tmplist1;
        end
        e_new=0;
        for i=1:(amount-1)
            e_new=e_new+dist_matrix(sol_new(i),sol_new(i+1));
        end
        e_new=e_new+dist_matrix(sol_new(amount),sol_new(1));
        if e_new<e_current
            e_current=e_new;
            sol_current=sol_new;
            if e_new<e_best
                e_best=e_new;
                sol_best=sol_new;
            end
        else
            if rand<exp(-(e_new-e_current)./t)
                e_current=e_new;
                sol_current=sol_new;
            else
                sol_new=sol_current;
            end
        end
    end
    t=t.*b;
end
disp(sol_best);

猜你喜欢

转载自www.cnblogs.com/javaStudy947/p/9274577.html