模擬退火詳解

2022-09-19 15:09:07 字數 3377 閱讀 9623

很多人都學過貪心,但是貪心在一些情況並不適用,比如:

已知我們從黃色出發,找最小值。

貪心策略當然是一直往函式大小減小的地方偏移——但是,萬一不是單谷呢?我們會陷入如圖的藍色中無法自拔。

肯能你會想到:隨機找乙個點出發,然後貪心找最小值?多隨機幾遍,然後求全域性最小值?

你會發現複雜度暴增!!!!!!!!——所以如何處理這種問題呢?

模擬退火:啊,對對對~

是的!模擬退火就是一種類似於隨機化貪心的乙個演算法,在oi界也小有名氣(冥器)!(如題[noip2021] 方差 )

原理圖:

如圖:在物理應用中分子排布可能是紊亂的,如果我們將它公升溫然後緩慢降溫,就可以生成完美的晶形!

而對於我們求解的:

怎麼形象描述它呢?

乙個有自己一定卡路里的人爬山,他想翻山找遠方的草藥給自己心愛的妻子,但是他並不知道山的那頭是什麼。所以他會在卡路里多的時候盡量去遠方探險,但是每次會花費他的卡路里以至於他後面不能翻過太高的山丘,而且他的揹包蠻大的,裝填著無數愛的草藥芳香四溢。

所以我們立刻(啊,對對對~)能設定模擬退火的引數:

1.初始溫度 t (1000-7000)

2.末尾溫度 p(1e-5~1e-15)

3.降溫係數 k (0.91~0.9975)

4.狀態空間(被降溫物體) s

5.當前能量 e ( new )

6.全域性能量 e ( old )

一:metropolis準則- 以概率接受新狀態:

這就是物理(化學)方面類似的推論——一定概率的更新。

什麼意思呢?

我們已知:當前能量 e ( new ) , 全域性能量 e ( old ),那麼我們的目標是什麼,不就是減少目前的能量嗎?

所以:當當前能量少於全域性能量(即更新前的能量),那麼我們有概率為 1 的更新概率;

當當前能量大於全域性能量(即更新前的能量),那麼我們有概率為 exp( - (e( new )-e( old ))/t) 的更新概率 ( t為當前溫度) [exp(x)函式:e的x次方的函式  如 exp(1)表示e的1次方=e=2.718281828…  exp(0)表示e的0次方=1  exp(2)表示e的平方=7.3890561…  e是乙個常數,等於2.718281828…];

注意:有時候也不一定以以上方式更新,這只是比較妥的做法,概率方面是可以自己定的,但是一定以當前能量與全域性能量的關係來設定的。(除非直接暴力的隨機演算法)

二:

那麼怎麼生成新的當前溫度呢?,以生成小數為例:

當前將更新溫度=全域性溫度+(rand()*2-rand_max)*t;

if(不在狀態空間內)

即:在當前狀態的鄰域結構內以一定概率方式(均勻分布、正態分佈、指數分布等)產生。

三:溫度更新函式

若固定每一溫度,演算法均計算至平穩分布,然後下降溫度,則稱為時齊演算法;

若無需各溫度下演算法均達到平穩分布,但溫度需按一定速率下降,則稱為非時齊演算法。

本人用的:

t*=k;
四:內迴圈終止準則 

本人使用的:

(t>1e-15)//可以改大一點
其他常用方法:

(1)設定終止溫度的閾值。

(2)設定外迴圈迭代次數。

(3)演算法搜尋到的最優值連續若干步保持不變。

(4)概率分析方法。

五:實現流程圖:

注意:以下是我自己總結的退火口訣:

初始溫度小心設(1000-3000),又粗又大wa一臉

多次sa更保險,忘了卡時直接t[if((double)clock()/clocks_per_sec>=0.993)]

退火係數大膽設,不過0.9975會很厄

全域性、狀態不一樣,全域性必須菊部優

百年騙分一場空,不開srand見祖宗

退火需謹慎,退火不規範,靈封兩行淚

然後是[noip2021]方差的實現(玄學萬歲):

#include using

namespace

std;

#define ll long long

const

int n=1e5+10

;const

double dw=0.9975

;int

a[n],n,c[n];

long

long

ans;

bool cmp(int a,int

b)ll en()

for(int i=1;i<=n;i++)em=(long

long)em*n;

for(int i=1;i<=n;i++)ranss=(long

long)ranss*ranss;

return (long

long)(em-ranss);

}void

sa()

int x=rand()%(n-1)+2,y=rand()%(n-1)+2

;

while(x==y)x=rand()%(n-1)+2

; swap(c[x],c[y]);

ll m=en(),dt=ans-m;

if(dt>0

)else

if((double)rand()>=(double)rand_max*(double)exp((double)dt/t))

t*=dw;

}}int

main()

sort(c+2,c+n/2+1

,cmp);

sort(c+n/2+1,c+n+1

); ans=en();

while(1

)sa();

}

模擬退火演算法

w 模擬退火演算法的基本思想 將乙個優化問題比擬成乙個金屬物體,將優化問題的目標函式比擬成物體的能量,問題的解比擬成物體的狀態,問題的最優解比擬成能量最低的狀態,然後模擬金屬物體的退火過程,從乙個足夠高的溫度開始,逐漸降低溫度,使物體分子從高能量狀態緩慢的過渡到低能量狀態,直至獲得能量最小的理想狀態...

模擬退火合集

首次接觸模擬退火 看來還是挺神奇的。主要參考這篇博文 題意判斷多邊形內部能否容納乙個半徑為r的圓,即在有限的平面內找最優範圍。遺傳演算法的結果難以掌控,爬山演算法又沒法保證跳出區域性最優,所以基於貪心原則的模擬退火演算法還是值得考慮的。然後就是設定每次變化的步長和演化方式。該題可以從每條邊的中點開始...

模擬退火演算法

一些求解極值的問題不能通過函式特性直接求解,只能暴力列舉,但是單純的列舉效率不高,通過模擬退火演算法可以高效的找到答案。學習好博文 最小圓覆蓋 hdu 3007 buried memory 大意 給出一些點,求出能覆蓋他們的最小的圓。輸出圓心和半徑 include include include i...