模擬退火算法簡介
模擬退火是一種通用概率算法,可來在固定時間內尋求在一個大的搜尋空間內找到的最優解,也可以用來求解函數最優解。模擬退火是S. Kirkpatrick, C. D. Gelatt和M. P. Vecchi在1983年所發明。而V. Černý在1985年也獨立發明此算法。
在這裏不講解模擬退火算法的基礎知識,重點對模擬退火算法的兩種應用程序做解析,需要了解基礎知識的可以參考文章最後的參考資料。
模擬退火算法流程圖
模擬退火算法流程圖
模擬退火算法Matlab程序
求解函數最優解
變量聲明初始化
clear
clc
%生成初始解
sol_new2=1;%(1)解空間(初始解)
sol_new1=2-sol_new2^2;
sol_current1 = sol_new1;
sol_best1 = sol_new1;
sol_current2 = sol_new2;
sol_best2 = sol_new2;
E_current = inf;
E_best = inf;
退火算法參數設置
rand('state',sum(clock)); %初始化隨機數發生器
t=90; %初始溫度
tf=89.9; %結束溫度
a = 0.99; %溫度下降比例
主循環
while t>=tf%(7)結束條件
for r=1:100 %退火次數
%產生隨機擾動(3)新解的產生
sol_new2=sol_new2+rand*0.2;
sol_new1=2-sol_new2^2;
%檢查是否滿足約束
if sol_new1^2-sol_new2>=0 && -sol_new1-sol_new2^2+2==0 && sol_new1>=0 &&sol_new2>=0
else
sol_new2=rand*2;
sol_new1=2-sol_new2^2;
continue;
end
%退火過程
E_new=sol_new1^2+sol_new2^2+8;%(2)目標函數
if E_new<E_current%(5)接受準則
E_current=E_new;
sol_current1=sol_new1;
sol_current2=sol_new2;
if E_new<E_best
%把冷卻過程中最好的解保存下來
E_best=E_new;
sol_best1=sol_new1;
sol_best2=sol_new2;
end
else
if rand<exp(-(E_new-E_current)/t)%(4)代價函數差
E_current=E_new;
sol_current1=sol_new1;
sol_current2=sol_new2;
else
sol_new1=sol_current1;
sol_new2=sol_current2;
end
end
plot(r,E_best,'.')
hold on
end
t=t*a;%(6)降溫
end
顯示結果
disp('最優解爲:')
disp(sol_best1)
disp(sol_best2)
disp('目標表達式的最小值等於:')
disp(E_best)
運行結果如圖
通過運行結果可以直觀的看出最後程序的結果趨近於最優解,在這裏最多退火100次,多次迭代後結果會更好。
求解二維空間最優路徑
程序初始化,設置50個需要訪問的點
clc, clear
% 設置處理點的數量
N = 50;
M = zeros(N, 2);
% 產生100個位置不同的點
M(:, 1) = randperm(N);
M(:, 2) = randperm(N);
計算兩點之間的距離
% 初始化距離矩陣
d = zeros(N);
% 統計每兩個點之間的距離
for i=1:N-1
for j=i+1:N
d(i, j) = sqrt((M(i,1)-M(j,1))*(M(i,1)-M(j,1)) + (M(i,2)-M(j,2))*(M(i,2)-M(j,2)));
end
end
for循環生成的兩點之間的距離思路爲
- 先計算(1,2),(1,3),(1,4)……(1,N)的距離存在二維數組d中。
- 計算(2,3),(2,4)(2,5)……(2,N)的距離存在二維數組d中。
- 計算(3,4)(3,5),(3,6)……(3,N)的距離存在二維數組d中。
- ……
- 計算(N-1,N)的距離存在二維數組d中,結束。
此時d中存的數據爲上三角矩陣,因爲(1,2)和(2,1)的距離是一樣的,因此將d中的數據擴充。
d = d + d';
通過打亂50個座標點的鏈接順序,多次計算其總路線長度,得出近似最優解。目的是爲了和退火算法比較。
% 初始化路徑及路線長度
path = zeros(1, N);
length = inf;
% 先確定一個比較好的初始解
for i=1:1000
path0 = randperm(N); % randperm 1-N 亂序排列
temp = 0;
for j=1:N-1
temp = temp + d(path0(j) , path0(j+1));
end
if temp < length
length = temp;
path = path0;
end
end
length
subplot(1, 2, 1)
plot(M(path, 1), M(path, 2), '-o');
title("Initial Solution");
退火算法求解50個座標點的最優路徑
初始化參數
% 設置模擬退火的參數
e = 0.1^30; % 結束溫度
L = 20000; % 退火次數
at = 0.999; % 溫度下降比例
T = 1; % 初始溫度
主循環
for k = 1:L
% 產生新解
c = floor(rand(1, 2)*(N-2)) + 2; % floor 比它小的最大整數
c = sort(c);
c1 = c(1);
c2 = c(2);
change = d(path(c1-1), path(c2)) + d(path(c1), path(c2+1)) - d(path(c1-1), path(c1)) - d(path(c2), path(c2+1));
if change < 0
path = [path(1:c1-1), path(c2:-1:c1), path(c2+1: N)];
length = length + change;
elseif exp(-change/T) >= rand % 接受條件
path = [path(1:c1-1), path(c2:-1:c1), path(c2+1: N)];
length = length + change;
end
T = T * at;
if T < e
break;
end
end
輸出結果對比
length
subplot(1, 2, 2)
plot(M(path, 1), M(path, 2), '-*');
title("Simulte Anneal Solution");
hold off
產生新解的思路
- 隨機生成兩個數,A,B。
- 將A,B之間的序列調換。
- 計算變化量。
- 總路長比之前解短的話保留結果,總路長比之前解長的話按接受條件
exp(-change/T) >= rand
接收。 - 滿足終止條件後推出循環。
運行結果
從上圖可以很明顯的看出模擬退火算法比初始的最優解效果好,通過最後輸出的總路徑長度也可以看出模擬退火算法比初始的最優解效果好N倍~
Marlab 完整代碼
兩個代碼在一起放着哦,大家注意看下哦
模擬退火算法Matlab程序二合一下載鏈接