模擬退火(SA)
物理過程由以下三個部分組成
1.加溫過程 問題的初始解
2.等溫過程 對應算法的Metropolis抽樣的過程
3.冷卻過程 控制參數的下降
默認的模擬退火是一個求最小值的過程,其中Metropolis准則是SA算法收斂於全局最優解的關鍵所在,Metropolis准則以一定的概率接受惡化解,這樣就使算法跳離局部最優的陷進
1.模擬退火算法求解一元函數最值問題
使用simulannealbnd - Simulated annealing algorithm工具箱
求y=sin(10*pi*x)./x;在[1,2]的最值
下圖是用畫圖法求出最值的
x=1:0.01:2; y=sin(10*pi*x)./x; figure hold on plot(x,y,'linewidth',1.5); ylim([-1.5,1.5]); xlabel('x'); ylabel('y'); title('y=sin(10*\pi*x)/x'); [maxVal,maxIndex]=max(y); plot(x(maxIndex),maxVal,'r*'); text(x(maxIndex),maxVal,{['x:' num2str(x(maxIndex))],['y:' num2str(maxVal)]}); [minVal,minIndex]=min(y); plot(x(minIndex),minVal,'ro'); text(x(minIndex),minVal,{['x:' num2str(x(minIndex))],['y:' num2str(minVal)]}); hold off;
用模擬退火工具箱來找最值
求最小值
function fitness=fitnessfun(x) fitness=sin(10*pi*x)./x; end
求最大值
function fitness=fitnessfun(x) fitness=-sin(10*pi*x)./x; end
Optimization running.
Objective function value: -0.9527670052175917
Maximum number of iterations exceeded: increase options.MaxIterations.
用工具箱求得的最大值為0.9527670052175917
2.二元函數優化
[x,y]=meshgrid(-5:0.1:5,-5:0.1:5); z=x.^2+y.^2-10*cos(2*pi*x)-10*cos(2*pi*y)+20; figure mesh(x,y,z); hold on xlabel('x'); ylabel('y'); zlabel('z'); title('z=x^2+y^2-10*cos(2*\pi*x)-10*cos(2*\pi*y)+20'); maxVal=max(z(:)); [maxIndexX,maxIndexY]=find(z==maxVal);%返回z==maxVal時,x和y的索引 for i=1:length(maxIndexX) plot3(x(maxIndexX(i),maxIndexY(i)),y(maxIndexX(i),maxIndexY(i)),maxVal,'r*'); text(x(maxIndexX(i),maxIndexY(i)),y(maxIndexX(i),maxIndexY(i)),maxVal,{['x:' num2str(x(maxIndexX(i)))] ['y:' num2str(y(maxIndexY(i)))] ['z:' num2str(maxVal)] }); end hold off;
function fitness=fitnessfun(x) fitness=-(x(1).^2+x(2).^2-10*cos(2*pi*x(1))-10*cos(2*pi*x(2))+20); end
Optimization running.
Objective function value: -80.50038894455415
Maximum number of iterations exceeded: increase options.MaxIterations.
找到的最大值:80.50038894455415
3.解TSP問題
(用的數據和前幾天用遺傳算法寫TSP問題的數據一致,但是結果比遺傳算法算出來效果差很多,不知道是不是我寫錯了,懷疑人生_(:з」∠)_中。。。
x=[41 94;37 84;54 67;25 62;7 64;2 99;68 58;71 44;54 62;83 69;64 60;18 54;22 60; 83 46;91 38;25 38;24 42;58 69;71 71;74 78;87 76;18 40;13 40;82 7;62 32;58 35;45 21;41 26;44 35;4 50]; d=distance(x);%計算距離矩陣 n=size(d,1);%城市的個數 T0=1e50;%初始溫度 Tend=1e-30;%終止溫度 L=2;%各溫度下的迭代次數 q=0.95; %計算迭代的次數 T0 * (0.95)^x = Tf time=ceil(double(solve([num2str(T0) '*(0.9)^x=' num2str(Tend)])));%計算迭代的參數 count=0; obj=zeros(time,1); path=zeros(time,n); %隨機產生一條初始路線 journey=randperm(n); rlength=pathlength(d,journey); drawpath(journey,x,rlength); disp('初始種群中的一個隨機值:'); outputpath(journey); disp(['初始路徑總距離:',num2str(rlength)]); index=0; %迭代優化 while T0>Tend count=count+1; %產生新解 newjourney=NewAnswer(journey); [journey,r]=Metropolis(journey,newjourney,d,T0); %記錄每次迭代的最優路線 if count==1||r<obj(count-1) obj(count)=r; index=count; else obj(count)=obj(count-1); end path(count,:)=journey; T0=T0*q; disp(['第' num2str(count) '代最優解' num2str(path(count,:))] ); disp(['總距離:',num2str(obj(count))]); end figure plot(1:count,obj); xlabel('迭代次數'); ylabel('距離'); title('優化過程'); grid on; s=path(index,:); a=pathlength(d,s); drawpath(path(index,:),x,a); disp('最優解'); p=outputpath(s); disp(['總距離:',num2str(a)]);
function d=distance(citys) %輸入 各城市的位置坐標 %輸出 兩兩城市之間的距離 n=size(citys,1); d=zeros(n,n); for i=1:n for j=1:n d(i,j)=((citys(i,1)-citys(j,1))^2+(citys(i,2)-citys(j,2))^2)^0.5; d(j,i)=d(i,j); end end
function [s,r]=Metropolis(s1,s2,d,t) %s1 當前解 %s2 新解 %d 距離矩陣 %t 溫度 %s 下一個當前解 %r 下一個當前解的路線距離 r1=pathlength(d,s1);%計算s1路線長度 n=size(d(2));%城市的個數 r2=pathlength(d,s2);%計算s2路線長度 dc=r2-r1;%計算能力之差 %比前一個解更優接受新解,沒有前一個解以一定概率接受新解 if dc<0 s=s2; r=r2; elseif exp(-dc/t)>0 % 以exp(-dC/T)概率接受新路線 a=exp(-dc/t)*100; test(1:100)=0; test(1:a)=1; r=round(99*rand+1); pcc=test(r); if pcc==1 s=s2; r=r2; else s=s1; r=r1; end else s=s1; r=r1; end end
function s2=NewAnswer(s1) %隨機產生新的解 %s1 當前解 %s2 新解 n=length(s1); s2=s1; a=round(rand(1,2)*(n-1)+1); s2(a(2))=s1(a(1)); w=s1(a(2)); s2(a(1))=w;
function p=outputpath(route) %給R末端添加起點R(1) route=[route,route(1)]; n=length(route); p=num2str(route(1)); for i=2:n p=[p,'->',num2str(route(i))]; end disp(p);
function dis=pathlength(d,route) %計算起點與終點之間的距離 %d 城市間距離 %route 路線 dis=0; n=length(d); for i=1:n-1 j=route(i); k=route(i+1); dis=dis+d(route(j),route(k)); end j=route(n); dis=dis+d(route(1),route(j));
function drawpath(route,citys,s) %傳入參數 路線 城市坐標 figure plot([citys(route, 1); citys(route(1), 1)], [citys(route, 2); citys(route(1), 2)], 'o-'); grid on %給每個地點標上序號 for i = 1: size(citys, 1) text(citys(i, 1), citys(i, 2), [' ' num2str(i)]); end text(citys(route(1), 1), citys(route(1), 2), ' 起點'); text(citys(route(end), 1), citys(route(end), 2), ' 終點'); text(10,20,['距離長度:' num2str(s) 'km']); xlabel('x/km'); ylabel('y/km');