模拟退火算法及其代码

模拟退火算法作为较为简单的智能算法,具有极大的参考意义。

以求解较为简单的y=(x-1)^2的最小值为例(智能算法是数值型解法,虽然我们预先知道其精确值为x=1,y=0)

clear
clc
tic
%y=x^2+1-2*x;%求-10到10的最小值
e=0.1^30;L=200000;at=0.99999;T=1;
%一般来说循环次数越多越精确。循环次数与e,L,at都有关系。有时候e很大(下降更慢),解却更粗糙,那是因为接近L值了,L的次数限制了它,提高L往往就可以
%得到更精确地结果了。
%退火过程
dmin=20;%设置初值,即y的最小值
for k=1:L
%产生新解
c=-10+rand()*20;
df=c^2+1-2*c-dmin
if df<0
    xbest=c;
    dmin=c^2+1-2*c;
elseif exp(-df/T)>rand(1)
    xbest=c;
    dmin=c^2+1-2*c;
    dd(k)=dmin;
end
T=T*at;
if T<e
break;
end
end
xbest
dmin
plot(dd)
toc

后面附录上,经典的TSP模型的代码(参考别人的)

clc,clear
load sj.txt %加载敌方 100 个目标的数据,数据按照表格中的位置保存在纯文本文件 sj.txt 中
x=sj(:,1:2:8);x=x(:);
y=sj(:,2:2:8);y=y(:);
sj=[x y];
d1=[70,40];%我方基地位置
sj=[d1;sj;d1];%首尾为基地位置,构成102行,实现闭环
sj=sj*pi/180;
%距离矩阵 d
d=zeros(102);
for i=1:101
for j=i+1:102
temp=cos(sj(i,1)-sj(j,1))*cos(sj(i,2))*cos(sj(j,2))+sin(sj(i,2))*sin(sj(j,2));
d(i,j)=6370*acos(temp);
end
end
d=d+d';
S0=[];Sum=inf;
rand('state',sum(clock));
for j=1:1000
S=[1 1+randperm(100),102];
temp=0;
for i=1:101
temp=temp+d(S(i),S(i+1));
end
if temp<Sum
S0=S;Sum=temp;
end
end
e=0.1^3000;L=20000;at=0.999;T=1;
%退火过程
for k=1:L
%产生新解
c=2+floor(100*rand(1,2));
c=sort(c);
c1=c(1);c2=c(2);
%计算代价函数值
df=d(S0(c1-1),S0(c2))+d(S0(c1),S0(c2+1))-d(S0(c1-1),S0(c1))-d(S0(c2),S0(c2+1));
%接受准则
if df<0
S0=[S0(1:c1-1),S0(c2:-1:c1),S0(c2+1:102)];
Sum=Sum+df;
elseif exp(-df/T)>rand(1)
S0=[S0(1:c1-1),S0(c2:-1:c1),S0(c2+1:102)];
Sum=Sum+df;
end
T=T*at;
if T<e
break;
end
end
% 输出巡航路径及路径长度
S0,Sum
for i=1:102
xx(i)=sj((S0(i)),1)*180/pi;
yy(i)=sj((S0(i)),2)*180/pi;
end
plot(xx,yy,'-o')
hold on
x=70,y=40;
plot(x,y,'r*')
53.7121 15.3046  51.1758 0.0322  46.3253 28.2753  30.3313 6.9348
56.5432 21.4188  10.8198 16.2529  22.7891 23.1045  10.1584 12.4819
20.1050 15.4562  1.9451 0.2057  26.4951 22.1221  31.4847 8.9640
26.2418 18.1760  44.0356 13.5401  28.9836 25.9879  38.4722 20.1731
28.2694 29.0011  32.1910 5.8699  36.4863 29.7284  0.9718 28.1477
8.9586 24.6635  16.5618 23.6143  10.5597 15.1178  50.2111 10.2944
8.1519 9.5325  22.1075 18.5569  0.1215 18.8726  48.2077 16.8889
31.9499 17.6309  0.7732 0.4656  47.4134 23.7783  41.8671 3.5667
43.5474 3.9061  53.3524 26.7256  30.8165 13.4595  27.7133 5.0706
23.9222 7.6306  51.9612 22.8511  12.7938 15.7307  4.9568 8.3669
21.5051 24.0909  15.2548 27.2111  6.2070 5.1442  49.2430 16.7044
17.1168 20.0354  34.1688 22.7571  9.4402 3.9200  11.5812 14.5677
52.1181 0.4088  9.5559 11.4219  24.4509 6.5634  26.7213 28.5667
37.5848 16.8474  35.6619 9.9333  24.4654 3.1644  0.7775 6.9576
14.4703 13.6368  19.8660 15.1224  3.1616 4.2428  18.5245 14.3598
58.6849 27.1485  39.5168 16.9371  56.5089 13.7090  52.5211 15.7957
38.4300 8.4648  51.8181 23.0159  8.9983 23.6440  50.1156 23.7816
13.7909 1.9510  34.0574 23.3960  23.0624 8.4319  19.9857 5.7902
40.8801 14.2978  58.8289 14.5229  18.6635 6.7436  52.8423 27.2880
39.9494 29.5114  47.5099 24.0664  10.1121 27.2662  28.7812 27.6659
8.0831 27.6705  9.1556 14.1304  53.7989 0.2199  33.6490 0.3980
1.3496 16.8359  49.9816 6.0828  19.3635 17.6622  36.9545 23.0265
15.7320 19.5697  11.5118 17.3884  44.0398 16.2635  39.7139 28.4203
6.9909 23.1804  38.3392 19.9950  24.6543 19.6057  36.9980 24.3992
4.1591 3.1853  40.1400 20.3030  23.9876 9.4030  41.1084 27.714	

sj.txt文件如上

模拟退火算法的性能评价:

   一般认为,下降温度足够慢,可以找到全局最优解,但是寻找时间延长。所以,在时间有限情况下,全局最优的性能评价,SA算法不占优势,但是由于其编程较为简单,具有模块化特征。

将其模板化如下:

伪代码:

产生数值   %可以用蒙特卡洛或者爬山算法产生较好初值,不过随意选取也行
e=0.1^3000;L=20000;at=0.999;T=1;
%设置温度阈值e,低于这个温度就停止循环,即停止降温;L是循环次数阈值,就算温度没有降到
%温度阈值,但是仍然会停止;at是降温速率,一般取0.999,认为越接近于1越好,但是速率慢,T是初始温度
%退火过程
for k=1:L   %开始循环
%产生新解
c=2+floor(100*rand(1,2));
c=sort(c);
c1=c(1);c2=c(2);
%计算代价函数值
df=d(S0(c1-1),S0(c2))+d(S0(c1),S0(c2+1))-d(S0(c1-1),S0(c1))-d(S0(c2),S0(c2+1));
%接受准则
if df<0
   S0=[S0(1:c1-1),S0(c2:-1:c1),S0(c2+1:102)];  %这里是求最小值,所以df<0,接受新解
Sum=Sum+df;
elseif exp(-df/T)>rand(1)
   S0=[S0(1:c1-1),S0(c2:-1:c1),S0(c2+1:102)];  
%%尽管df<0,也以较小概率接受新解,这是比爬山算法优越的地方,同时得注意T值在不断变小,这正是模拟退火的精髓,如果T固定为20000不变,则很难找到较好的解,或者说收敛很慢
Sum=Sum+df;

end
T=T*at;
if T<e
break;
end
end   %这是模板化的,降温过程与退出机制

% 输出巡航路径及路径长度
S0,Sum

猜你喜欢

转载自blog.csdn.net/bufengzj/article/details/82593332
今日推荐