模擬退火算法

算法背景

退火是指將固體加熱到足夠高的溫度,使分子呈隨機排列狀態(tài)晰韵,然后逐步降溫使之冷卻惹挟,最后分子以低能狀態(tài)排列,固體達到某種穩(wěn)定狀態(tài)气筋。物理退火包括一下3個過程:

1.加溫過程——增強粒子的熱運動拆内,消除系統(tǒng)原先可能存在的非均勻態(tài);
2.等溫過程——對于與環(huán)境換熱而溫度不變的封閉系統(tǒng)宠默,系統(tǒng)狀態(tài)的自發(fā)變化總是朝自由能減少的方向進行麸恍,當自由能達到最小時,系統(tǒng)達到平衡態(tài)搀矫;
3.冷卻過程——使粒子熱運動減弱并漸趨有序抹沪,系統(tǒng)能量逐漸下降刻肄,從而得到低能的晶體結(jié)構(gòu)。

算法原理

基本原理

模擬退火算法分為三部分:初始解采够、解空間以及目標函數(shù)肄方,分別對應(yīng)物理退火過程中的初始溫度、降溫以及最終溫度蹬癌。

1.初始解:初始解釋算法迭代的起點权她,試驗表明,模擬退火算法是健壯的逝薪,即最終解的求得最優(yōu)解并不十分依賴初始解的選取隅要,從而可任意選擇一個初始解。當然董济,如果初始解選擇得當可以加快找到全局最優(yōu)解步清。
2.解空間:一般是離散的可行解的集合。
3.目標函數(shù):對優(yōu)化目標的量化描述虏肾,是解空間到某個數(shù)集的一個映射廓啊,通常表示為若干優(yōu)化目標的一個和式,應(yīng)正確體現(xiàn)問題的整體優(yōu)化要求且較易計算封豪,當解空間包含不可行解時還應(yīng)包括罰函數(shù)谴轮。
4.算法從初始解或稱為初始狀態(tài)開始,在解空間中進行啟發(fā)式搜索(通常是隨機搜索的方式)吹埠,最終搜索到最優(yōu)的目標值第步。

基本過程

初始化:設(shè)定初始溫度T,初始解狀態(tài)S缘琅,終止溫度T0粘都;
降溫過程:如果T>T0,則循環(huán)執(zhí)行3至6步刷袍;
在解空間中隨機搜索一個新解S’;
計算增量ΔE=E(S′)-E(S)翩隧,其中C(S)為解S對應(yīng)的目標函數(shù)值或稱為評價函數(shù);
若ΔE<0則接受S′作為新的當前解呻纹,否則以概率exp(-ΔE/T)接受S′作為新的當前解鸽心;
如果滿足終止條件則輸出當前解作為最優(yōu)解,結(jié)束程序居暖。終止條件可以有兩種情況顽频,一是溫度已經(jīng)達到了最低溫度T0;二是在連續(xù)的取若干個新解都沒有跳出當前最優(yōu)解太闺。

退火方式

模擬退火算法中糯景,退火方式對算法有很大影響。如果溫度下降過慢,算法的收斂速度會大大降低蟀淮。如果溫度下降過快最住,可能會丟失極值點。為了提高模擬退火算法的性能怠惶,許多學者提出了退火的各種方式涨缚,比較有代表性的有以下幾種:

  1. T(t) = T0/ln(1+t)

該方式的特點是溫度下降緩慢,算法收斂速度也較慢策治,但是最終達到全局最優(yōu)的可能性是最高的

  1. T(t) = T0/ln(1+at)

式中a為可調(diào)參數(shù)脓魏,可以改善退火曲線的形態(tài)。其特點是高溫區(qū)溫度下降比較快通惫,低溫區(qū)下降比較慢茂翔,這種退火方式主要期望在低溫區(qū)收斂到全局最優(yōu)。

  1. T(t) = T0a**t

式中a為可調(diào)參數(shù)履腋,其特點是溫度下降很快珊燎,算法的收斂速度快,但是帶來的損失是可能不能充分的收斂到全局最優(yōu)

以上三種退火方式各有優(yōu)缺點以及適用的場景遵湖,需針對具體的應(yīng)用進行選擇悔政。

算法框圖

模擬退火算法流程圖

源代碼

#!/usr/bin/env python 
# -*- coding: UTF-8 -*-

import matplotlib.pyplot as plt
import math
import numpy as np

class SA():
    def __init__ (self, max_steps):
        self.T_max = 100 #最高溫度
        self.T_min = 1 #最小溫度
        self.T = self.T_max #溫度初始化
        self.t=1 #初始化時間
        self.max_steps = max_steps  # 同一溫度下迭代次數(shù)
        self.dim = 9  # 搜索空間的維度
        self.x_bound_low = np.full(shape = self.dim, fill_value = -10)  #變量取值下邊界
        self.x_bound_high = np.full(shape = self.dim, fill_value = 10)  #變量取值上邊界

    def function_fitness (self, x):
        return np.sum(np.square(x))
    
    def update_value (self, x, y, new_x, new_y,best_x, best_y, flag):
        """要接受這個y_new為當前溫度下的理想值,要滿足y_new>y_old 或 math.exp(-(y - new_y) / self.T)>random.random()"""

        if (new_y < y) or (math.exp(-(new_y - y) / self.T) > np.random.random()):
            x = new_x.copy()
            y = new_y
        if new_y < best_y:
            flag = 1
            best_x = new_x.copy()
            best_y = new_y

        return x, y, new_x, new_y,best_x, best_y, flag

    def solve (self):
        x = np.random.uniform(self.x_bound_low, self.x_bound_high,size=(self.dim))   #  初始化自變量位置
        y = self.function_fitness(x)
        best_x = x.copy()  #矩陣之間相互賦值需要特別注意延旧,賦值后兩者對應(yīng)的地址還是一樣的
        best_y = y
        new_x = x.copy()
        new_y = y

        while self.T > self.T_min:

            flag = 0 #用以判斷有無新值被接受
            for step in range(self.max_steps):

                delta_x = np.random.uniform(low=-0.055,high=0.055,size=(self.dim))*self.T
                middle_value = x+delta_x
                for i in range(self.dim):
                    if (self.x_bound_low[i] <= middle_value[i]) and (middle_value[i] <= self.x_bound_high[i]):
                        new_x[i] = x[i] + delta_x[i]
                new_y = self.function_fitness(new_x)

                x, y, new_x, new_y, best_x, best_y, flag = self.update_value ( x, y, new_x, new_y, best_x, best_y, flag)

            if flag == 1:
                x = best_x
                y = best_y
            self.t += 1
            self.T = self.T_max/(50+self.t)
        print(best_x, best_y)

sa = SA(100)
sa.solve()

python tips

當對數(shù)組進行運算和操作時谋国,其數(shù)據(jù)有時會被拷貝到一個新的數(shù)組而有時又不會拷貝。對應(yīng)有三種情況:完全不拷貝(b=a垄潮,兩者對應(yīng)內(nèi)存地址相同)烹卒、視圖或淺拷貝(c = a.view()闷盔,c隨著a變弯洗,c不擁有數(shù)據(jù),但改變其中任意一個值逢勾,兩者都會變牡整,矩陣切片是淺拷貝)、深拷貝(d=a.copy()溺拱,d和a已經(jīng)沒有任何關(guān)系了)逃贝!

本程序中的退火方式為T = T0/(a+t),與隨機梯度下降法的學習率取相同的變化規(guī)律,仍有比較好的效果迫摔。

python中支持函數(shù)中嵌套函數(shù)沐扳,此時嵌套函數(shù)在函數(shù)體外不能使用,即歸函數(shù)私有句占。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沪摄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌杨拐,老刑警劉巖祈餐,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哄陶,居然都是意外死亡帆阳,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進店門屋吨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜒谤,“玉大人,你說我怎么就攤上這事离赫“攀牛” “怎么了?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵渊胸,是天一觀的道長旬盯。 經(jīng)常有香客問我,道長翎猛,這世上最難降的妖魔是什么胖翰? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮切厘,結(jié)果婚禮上萨咳,老公的妹妹穿的比我還像新娘。我一直安慰自己疫稿,他們只是感情好培他,可當我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著遗座,像睡著了一般舀凛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上途蒋,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天猛遍,我揣著相機與錄音,去河邊找鬼号坡。 笑死懊烤,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的宽堆。 我是一名探鬼主播腌紧,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼畜隶!你這毒婦竟也來了壁肋?” 一聲冷哼從身側(cè)響起逮光,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎墩划,沒想到半個月后涕刚,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡乙帮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年杜漠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片察净。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡驾茴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出氢卡,到底是詐尸還是另有隱情锈至,我是刑警寧澤,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布译秦,位于F島的核電站峡捡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏筑悴。R本人自食惡果不足惜们拙,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阁吝。 院中可真熱鬧砚婆,春花似錦、人聲如沸突勇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甲馋。三九已至埂奈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間摔刁,已是汗流浹背挥转。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工海蔽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留共屈,地道東北人。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓党窜,卻偏偏與公主長得像拗引,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子幌衣,可洞房花燭夜當晚...
    茶點故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容