1. 程式人生 > >模擬退火演算法例項分析--Matlab演算法

模擬退火演算法例項分析--Matlab演算法

模擬退火演算法(例項分析)–Matlab演算法

此篇文章為我一學長(Hong Yilin)所作,我又進行了一些加工,在此只為學習使用。

此篇為模擬退火演算法的例項分析,模擬退火演算法的理論講解見上一篇。

題目:我方有一個基地,經度和緯度為(70,40)。假設我方飛機的速度為 1000 公里/小時。

我方派一架飛機從基地出發,偵察完敵方所有目標,再返回原來的基地。在敵方每一目標點的偵察時間不計,

求該架飛機所花費的時間(假設我方飛機巡航時間可以充分長)。

敵方經度緯度如下:

[html] view plain copy print?
  1. 表1 敵方100城市經緯度  
  2. 經度  緯度  經度  緯度  經度  緯度  經度  緯度  
  3. 53.7121 15.3046 51.1758 0.0322  46.3253 28.2753 30.3313 6.9348  
  4. 56.5432 21.4188 10.8198 16.2529 22.7891 23.1045 10.1584 12.4819  
  5. 20.1050 15.4562 1.9451  0.2057  26.4951 22.1221 31.4847 8.9640  
  6. 26.2418 18.1760 44.0356 13.5401 28.9836 25.9879 38.4722 20.1731  
  7. 28.2694 29.0011 32.1910 5.8699  36.4863 29.7284 0.9718  28.1477  
  8. 8.9586  24.6635 16.5618 23.6143 10.5597 15.1178 50.2111 10.2944  
  9. 8.1519  9.5325  22.1075 18.5569 0.1215  18.8726 48.2077 16.8889  
  10. 31.9499 17.6309 0.7732  0.4656  47.4134 23.7783 41.8671 3.5667  
  11. 43.5474 3.9061  53.3524 26.7256 30.8165 13.4595 27.7133 5.0706  
  12. 23.9222 7.6306  51.9612 22.8511 12.7938 15.7307 4.9568  8.3669  
  13. 21.5051 24.0909 15.2548 27.2111 6.2070  5.1442  49.2430 16.7044  
  14. 17.1168 20.0354 34.1688 22.7571 9.4402  3.9200  11.5812 14.5677  
  15. 52.1181 0.4088  9.5559  11.4219 24.4509 6.5634  26.7213 28.5667  
  16. 37.5848 16.8474 35.6619 9.9333  24.4654 3.1644  0.7775  6.9576  
  17. 14.4703 13.6368 19.8660 15.1224 3.1616  4.2428  18.5245 14.3598  
  18. 58.6849 27.1485 39.5168 16.9371 56.5089 13.7090 52.5211 15.7957  
  19. 38.4300 8.4648  51.8181 23.0159 8.9983  23.6440 50.1156 23.7816  
  20. 13.7909 1.9510  34.0574 23.3960 23.0624 8.4319  19.9857 5.7902  
  21. 40.8801 14.2978 58.8289 14.5229 18.6635 6.7436  52.8423 27.2880  
  22. 39.9494 29.5114 47.5099 24.0664 10.1121 27.2662 28.7812 27.6659  
  23. 8.0831  27.6705 9.1556  14.1304 53.7989 0.2199  33.6490 0.3980  
  24. 1.3496  16.8359 49.9816 6.0828  19.3635 17.6622 36.9545 23.0265  
  25. 15.7320 19.5697 11.5118 17.3884 44.0398 16.2635 39.7139 28.4203  
  26. 6.9909  23.1804 38.3392 19.9950 24.6543 19.6057 36.9980 24.3992  
  27. 4.1591  3.1853  40.1400 20.3030 23.9876 9.4030  41.1084 27.7149  
表1 敵方100城市經緯度

經度  緯度  經度  緯度  經度  緯度  經度  緯度
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.7149

分析:

1.實際距離的求解:
設A, B兩點的地理座標分別為(x1,y1), (x2,y2),過 A, B兩點的大圓的劣弧長即為兩點的實際距離。

以地心為座標原點o,以赤道平面為XOY平面,以0度經線圈所在的平面為XOZ平面建立三維直角座標系。

地球半徑為R=6370km。則 A, B兩點的直角座標分別為:

A( R*cos(x1)*cos(y1), R*sin(x1)*cos(y1), R*sin(y1) )     B( R*cos(x2)*cos(y2), R*sin(x2)*cos(y2), R*sin(y2) )

A、B兩點實際距離:
d=Rarccos[ cos(x1-x2)*cos(y1)*cos(y2) + sin(y1)*sin(y2) ]。
建立矩陣D,將所有點之間的距離存放進去。

問題轉化為從(70,40)出發,走遍所有點,並返回出發點。

2.關於Monte Carlo方法

本文中使用Monte Carlo方法先得到一個較小的sum,和一組S0。

3.演算法原理:

設S={s1,s2,…,sn}為所有可能的狀態所構成的集合, f:S—R為非負代價函式,

即優化問題抽象如下:尋找s*∈S,使得f(s*)=min f(si) 任意si∈S 

具體步驟:
(1)給定一較高初始溫度T,隨機產生初始狀態S
(2)按一定方式,對當前狀態作隨機擾動,產生一個新的狀態S’
              S’=S+sign(η).δ (其中δ為給定的步長, η為[-1,1]的隨機數 )
     計算Δ=f(S’)-f(S)
(3)若Δ<0,則令S=S’,轉第(5)步
(4)若Δ≤0,則以概率exp(-Δ/T)接受S’,即S=S’
    具體操作:產生一個在[0,1]上服從均勻分佈的隨機數x,若x<exp(-Δ/T),則S=S;否則S保持不變
(5)按一定方式降溫,使T≤Ti, 如: =αTi,習慣上取α∈(0.8,0.9999)
(6)檢查退火是否結束
     是——轉向第(7)步
     否——轉向第(2)步
(7)以當前Si作為最優解輸出

注:1、結束標誌:溫度是否小於某一閥值(迴圈次數)f的值變化是否明顯
        2、初始溫度的高低:下降是否充分慢對結果有影響

4.演算法詳述:

首先給定一個初始溫度TO 和該優化問題的一個初始解 x(0),並由 x(0)生成下一個解 x’∈ N(x(0)),是否接受x’作為一個新解x(1)依賴於下面概率:
                                 
換句話說,如果生成的解 的函式值比前一個解的函式值更小,則接受x(1)=x ‘作為一個新解。否則以概率作為一個新解。

以此類推,在溫度T_i下,經過很多次的轉移之後,降低溫度T_i,得到T(i+1)<T(i)。在T(i+1)下重複上述過程。因此整個優化過程就是不斷尋找新解和緩慢降溫的交替過程。最終的解是對該問題尋優的結果。

在得到初始解之後,可以用2變換法,即交換兩個點之間的路線。設定T0為1,以0.001為降溫幅度,選擇終止溫度為e=10-30。執行程式碼,得到可行解,時間為43小時左右

演算法:

[plain] view plain copy print?
  1. function Simulated_AnneALIng()  
  2. %演算法:模擬退火演算法(Simulated AnneALIng)  
  3. %敵方經度緯度資料見 sj.txt  
  4. %% 清空  
  5. clc,clear;  
  6. %% 座標轉換,計算距離  
  7. load sj.txt %載入敵方100個目標的資料,資料按照表格中的位置儲存在純文字檔案 sj.txt 中  
  8. x=sj(:,1:2:8) ; x=x(:);%將4列變成1列  
  9. y=sj(:,2:2:8) ; y=y(:);  
  10. sj=[x y];  
  11. d1=[70,40] ; sj=[d1;sj;d1] ;   
  12. sj1=sj;  
  13. sj=sj*pi/180;   
  14. n=length(sj);  
  15. d=zeros(n);   %距離矩陣 d  
  16. for i=1:n-1  %座標轉換為距離  
  17.      for j=i+1:n  
  18.           temp=cos(sj(i,1)-sj(j,1))*cos(sj(i,2))*cos(sj(j,2))+sin(sj(i,2))*sin(sj(j,2));  
  19.           d(i,j)=6370*acos(temp);  
  20.      end  
  21. end  
  22. d=d+d’ ; S0=[] ; Sum=inf;  
  23. %% 設定初始解(MonteCarlo法)  
  24. for j=1:1000    
  25.      S=[1,1+randperm(n-2),n]; temp=0;    %用randperm函式隨機打亂2到(n-2)之間的數  
  26.      for i=1:n-1  
  27.           temp=temp+d(S(i),S(i+1));  
  28.      end  
  29.      if temp<Sum  
  30.           S0=S; Sum=temp;  
  31.      end  
  32. end  
  33. e=0.1^30; L=20000; at=0.999; T=1;%引數設定  
  34. %% 退火過程  
  35. for k=1:L  %產生新解  
  36.     %隨機找兩個點來交換路線  
  37.      c=2+floor((n-2)*rand(1,2)); c=sort(c);   
  38.      c1=c(1);c2=c(2);  
  39.      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));%計算代價函式值  
  40.      %接受準則  
  41.      if df<0 %路徑更短,接受新解  
  42.          S0=[S0(1:c1-1),S0(c2:-1:c1),S0(c2+1:n)];  
  43.          Sum=Sum+df ; T=T*at;%接受並降溫  
  44.      elseif exp(-df/T)>rand(1)  %路徑沒變短,以一定概率接受新解  
  45.          S0=[S0(1:c1-1),S0(c2:-1:c1),S0(c2+1:n)];  
  46.          Sum=Sum+df ; T=T*at;  
  47.      end  
  48.      if T<e  
  49.          break;  
  50.      end  
  51. end  
  52. disp([‘最短巡航路徑長度:’,num2str(Sum),’km’]);  
  53. disp([‘最短巡航路徑時耗:’,num2str(Sum/1000),’h’]);  
  54. %% 畫圖  
  55. hold on  
  56. plot(sj1(1:101,1), sj1(1:101,2), ‘ko’);  
  57. for i=1:101  
  58.     temp=[‘  ’,int2str(i)];  
  59.     text(sj1(i,1), sj1(i,2),temp);  
  60. end  
  61. for i=1:101  
  62.     plot(sj1(S0(i:i+1),1)’, sj1(S0(i:i+1),2)’,’k-‘);  
  63. end  
  64. title([‘近似路徑如下,巡航路徑長度:’,num2str(Sum),’km,’,’時耗:’,num2str(Sum/1000),’h’]);  
  65. hold off  
function Simulated_AnneALIng()
%演算法:模擬退火演算法(Simulated AnneALIng)

%敵方經度緯度資料見 sj.txt

%% 清空
clc,clear;
%% 座標轉換,計算距離
load sj.txt %載入敵方100個目標的資料,資料按照表格中的位置儲存在純文字檔案 sj.txt 中
x=sj(:,1:2:8) ; x=x(:);%將4列變成1列
y=sj(:,2:2:8) ; y=y(:);
sj=[x y];
d1=[70,40] ; sj=[d1;sj;d1] ; 
sj1=sj;
sj=sj*pi/180; 
n=length(sj);
d=zeros(n);   %距離矩陣 d
for i=1:n-1  %座標轉換為距離
     for j=i+1:n
          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;
%% 設定初始解(MonteCarlo法)
for j=1:1000  
     S=[1,1+randperm(n-2),n]; temp=0;    %用randperm函式隨機打亂2到(n-2)之間的數
     for i=1:n-1
          temp=temp+d(S(i),S(i+1));
     end
     if temp<Sum
          S0=S; Sum=temp;
     end
end
e=0.1^30; L=20000; at=0.999; T=1;%引數設定
%% 退火過程
for k=1:L  %產生新解
    %隨機找兩個點來交換路線
     c=2+floor((n-2)*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:n)];
         Sum=Sum+df ; T=T*at;%接受並降溫
     elseif exp(-df/T)>rand(1)  %路徑沒變短,以一定概率接受新解
         S0=[S0(1:c1-1),S0(c2:-1:c1),S0(c2+1:n)];
         Sum=Sum+df ; T=T*at;
     end
     if T<e
         break;
     end
end
disp(['最短巡航路徑長度:',num2str(Sum),'km']);
disp(['最短巡航路徑時耗:',num2str(Sum/1000),'h']);

%% 畫圖
hold on
plot(sj1(1:101,1), sj1(1:101,2), 'ko');
for i=1:101
    temp=['  ',int2str(i)];
    text(sj1(i,1), sj1(i,2),temp);
end
for i=1:101
    plot(sj1(S0(i:i+1),1)', sj1(S0(i:i+1),2)','k-');
end
title(['近似路徑如下,巡航路徑長度:',num2str(Sum),'km,','時耗:',num2str(Sum/1000),'h']);
hold off