如何實(shí)現(xiàn)一個(gè)高效的啟發(fā)式算法轴捎?

一、前言

小伙伴們好军掂,說起來已經(jīng)好久好久好久沒見了呢轮蜕!之前一直忙著做其他事情去了(泛指學(xué)習(xí)一類),公眾號(hào)已經(jīng)落下好久好久了蝗锥。今天來寫點(diǎn)好玩的東西跃洛。

說起來,小編似乎就是做啟發(fā)式算法起家的终议。當(dāng)時(shí)記得老師是這么跟我說的汇竭,啟發(fā)式算法這東西很簡單,你不需要基礎(chǔ)穴张,有高中基礎(chǔ)就夠了(其實(shí)他想說的是初中……)细燎。后來小編一直在學(xué)這個(gè)東西,做了三四年了皂甘,用啟發(fā)式算法做過的大大小小的project已經(jīng)不記得有多少了玻驻,所以還算得上有一點(diǎn)點(diǎn)經(jīng)驗(yàn)。

因此今天就來寫寫偿枕,怎樣實(shí)現(xiàn)一個(gè)比較高效的啟發(fā)式算法吧~

二璧瞬、何為高效?

說到這個(gè)詞渐夸,相信大家一定不陌生嗤锉。高效意思就是達(dá)到相同效果或者更好的效果時(shí),使用的時(shí)間更短墓塌,所需要的資源更少瘟忱。就拿小編來說,由于小編特別笨苫幢,學(xué)一樣?xùn)|西需要花一周的時(shí)間访诱,而群里的小伙伴只需要一天的時(shí)間就能學(xué)會(huì)。那么這位小伙伴是要比我高效的韩肝。

同樣的對(duì)于一個(gè)啟發(fā)式算法而言触菜,不同人實(shí)現(xiàn)出來,即使是使用同一編程平臺(tái)達(dá)到同樣的效果伞梯,運(yùn)行時(shí)間也會(huì)千差萬別玫氢,相差幾倍甚至幾十倍帚屉。這樣說出來大家可能還沒啥感覺,那么放一下我們之前做過的一些數(shù)值實(shí)驗(yàn)大家直觀感受下吧~

這是某個(gè)Java實(shí)現(xiàn)的求解VRP類問題的算法代碼漾峡,兩個(gè)算法都達(dá)到了同樣的效果攻旦,只不過綠色曲線對(duì)應(yīng)的算法在計(jì)算過程中去除了相關(guān)冗余,可以看到運(yùn)行時(shí)間直線下降生逸。根據(jù)我們的統(tǒng)計(jì)牢屋,消除冗余計(jì)算后可使計(jì)算時(shí)間降低約83%,對(duì)于工業(yè)化生產(chǎn)而言槽袄,提升哪怕一個(gè)小數(shù)點(diǎn)都能帶來巨大的收益烙无,何止是83個(gè)百分點(diǎn)呢。怎么說呢遍尺,這簡直是A small step forward截酷,one step civiliazation

三乾戏、放碼過來迂苛?

不要一上來就是寫代碼,不加思考就上手寫代碼鼓择,你只會(huì)搓一坨屎山出來三幻,自己坑害自己。開始寫代碼之前一定要構(gòu)思好算法的整體架構(gòu)呐能,解的表示方式念搬,如何快速得到鄰居解等。建議是思考的時(shí)間一定要占總時(shí)間的一半以上摆出。

其實(shí)思路清晰寫代碼是非忱驶玻快的,比如每次在寫代碼的時(shí)候我都會(huì)先寫好注釋懊蒸,比如:

//1. 先獲取所有可行點(diǎn)的信息

//2. 對(duì)點(diǎn)按照成本進(jìn)行排序

//3. 貪心將各個(gè)點(diǎn)插入到解中

然后寫的時(shí)候我只需要按照這個(gè)思路往下走就可以了荣倾,這就跟你寫小學(xué)生作文一樣悯搔,起床刷牙到公園看鯨魚骑丸,一定要思路清晰。

四妒貌、鄰居解如何計(jì)算通危?

到了今天的核心問題,我們都知道灌曙,鄰域搜索過程中菊碟,鄰居解與當(dāng)前解相比往往只有細(xì)微的變化,因此迭代過程中絕大部分變量不需要重新計(jì)算在刺,消除了冗余計(jì)算逆害,可大大提高鄰域搜索效率头镊,降低運(yùn)行時(shí)間。聽不懂嗎魄幕?沒關(guān)系相艇,我舉例子,慢慢給你講解纯陨。

下面是一個(gè)VRP問題(沒有TW哦)的一個(gè)初始解

S_1
:

為了方便表示我們用

C(x)
表示x的cost吧坛芽,其中x可以為一個(gè)解、解中的一條路徑翼抠。
c_{ij}
表示邊<i,j>的距離咙轩。對(duì)于初始解,計(jì)算它的cost阴颖,只能是從頭到尾挨個(gè)遍歷一下了活喊。因此:

C(S_1) = C(r_1) + C(r_2) + C(r_3) + C(r_4)

其中各條路徑的cost又可以表示為:

C(r_1) = c_{0,6} +c_{6,4}+ ... + c_{8,0} \\ ......\\ C(r_4) = c_{0,14} +c_{14,18}+ ... + c_{25,0}

因此最后解的計(jì)算方式為:

C(S_1) = c_{0,6} +c_{6,4}+ ... +c_{25,0}

為了方便比較我們將這種計(jì)算解cost的方式稱為Algorithm1

算一下量愧,Algorithm1在計(jì)算時(shí)遍歷了所有的客戶點(diǎn)胧弛,對(duì)于N個(gè)客戶點(diǎn)的解而已,算法的復(fù)雜度為O(N)侠畔,嗯结缚!還不賴。

好了現(xiàn)在解

S_1
通過一個(gè)move软棺,生成了一個(gè)鄰居解
S_2

image

可以看到該move就是將客戶19從路徑

r_2
中移除红竭,并重新relocate到路徑
r_3
中客戶1后面。

現(xiàn)在生成了一個(gè)鄰居解喘落,得知道這個(gè)鄰居解是好還是壞對(duì)吧茵宪,那么我們得比較

C(S_1)
C(S_2)
的大小吧。前面我們通過Algorithm1算出了
C(S_1)
的大小瘦棋,那么現(xiàn)在的問題就是
C(S_2)
怎么計(jì)算了稀火。敲黑板的重點(diǎn)來了。

利用Algorithm1對(duì)

S_2
重新進(jìn)行計(jì)算赌朋,時(shí)間復(fù)雜度前面分析過了凰狞,為
O(n)

優(yōu)化一下

觀察上面的解

S_1
S_2
沛慢,可以發(fā)現(xiàn)一個(gè)鄰域搜索算法非常顯著的特點(diǎn):鄰居解
S_2
相比較當(dāng)前解
S_1
而言赡若,只發(fā)生了微小的改變,整個(gè)解中有4條路徑团甲,只有兩條路徑發(fā)生了改變逾冬,因此
S_2
的cost可以由原來計(jì)算好的一些結(jié)果進(jìn)行換算:

C(S_2) = C(S_1) - C(r_2) - C(r_3) + C(r'_2) + C(r'_3)

在上面的式子中,只有

C(r'_2)
C(r'_3)
是需要重新算的:
C(r'_2) = c_{0,15} +c_{15,12}+ ... + c_{7,0}\\ C(r'_3) = c_{0,32} +c_{32,13}+ ... + c_{5,0}

這樣一來,只需要計(jì)算變動(dòng)的路徑即可身腻,就不用重新計(jì)算所有路徑了产还。大大降低了鄰居解的計(jì)算時(shí)間復(fù)雜度。

進(jìn)一步優(yōu)化

細(xì)細(xì)觀察一下

r'_2
r'_3
我們發(fā)現(xiàn)嘀趟,路徑中發(fā)生變動(dòng)的邊似乎也不是很多啊雕沉。我給大家標(biāo)一下:

image

S_1
中發(fā)生變動(dòng)的邊我已經(jīng)用紅色實(shí)線標(biāo)出來了,
S_2
中發(fā)生變動(dòng)的邊我用紅色虛線標(biāo)出來去件,那么
C(r'_2)
C(r'_3)
是不是可以用之前計(jì)算好的
C(r_2)
C(r_3)
得出來呢坡椒?當(dāng)然可以啦,我們只需減去原來的邊尤溜,再加上新的邊就可以了倔叼。

C(r'_2) = C(r_2) - c_{11,19}-c_{19,17}+c_{11,17}\\ C(r'_3) = C(r_3) - c_{1,2}+c_{1,19}+c_{19, 2}

我們將這兩條式子帶入下面的式子:

C(S_2) = C(S_1) - C(r_2) - C(r_3) + C(r'_2) + C(r'_3)

即可得到:

C(S_2) = C(S_1) - c_{11,19}-c_{19,17}+c_{11,17} - c_{1,2}+c_{1,19}+c_{19, 2}

這個(gè)時(shí)間復(fù)雜度為

O(1)
,OK宫莱。經(jīng)過重重優(yōu)化丈攒,將時(shí)間復(fù)雜度從原來的
O(n)
成功降到了
O(1)

可能大家對(duì)這個(gè)

O(n)
降到
O(1)
沒什么感覺授霸。我來給大家分析一下巡验,在小規(guī)模問題,比如10個(gè)碘耳、20個(gè)節(jié)點(diǎn)這樣可能還真沒啥區(qū)別显设。但是別忘記了啟發(fā)式算法是針對(duì)大規(guī)模的優(yōu)化問題的,鄰域搜索類算法的鄰域規(guī)模往往是隨著問題規(guī)模的增長而呈爆炸式增長的辛辨。比如說在一個(gè)100個(gè)節(jié)點(diǎn)的VRP算例中捕捂,對(duì)于exchange算子,交換任意兩個(gè)客戶斗搞,那么一個(gè)解所能形成的鄰居解就有
C_{100}^{2}=4950
指攒,大約為5000個(gè)鄰居解。

  • 如果每個(gè)鄰居解你都使用Algorithm1重新算一遍僻焚,那么大概要算5000*100=50萬次允悦。
  • 如果你用優(yōu)化過的計(jì)算方法,只需要算5000*1=5000次虑啤。

這個(gè)差距有多大隙弛,大家動(dòng)動(dòng)屁股都知道了。當(dāng)然了咐旧,這只是理論上的分析驶鹉。實(shí)際上的差距和編程環(huán)境以及實(shí)現(xiàn)方式等都有很大關(guān)系绩蜻,但是只要差距超過10倍以上铣墨,都是能很明顯的感覺出來的。

五办绝、小結(jié)

關(guān)于如果去除冗余伊约,不是說一套方法通用的姚淆,需要根據(jù)算法工程師根據(jù)問題的特性,設(shè)計(jì)合適的解結(jié)構(gòu)屡律,再對(duì)鄰域算子進(jìn)行降冗余的思考與實(shí)現(xiàn)腌逢。降冗余的操作比較適合鄰域搜索類的啟發(fā)式算法,因?yàn)檫@類算法顯著特點(diǎn)就是鄰居解相比較當(dāng)前解而言超埋,變化非常細(xì)微搏讶。

當(dāng)然了,這需要豐富的編程經(jīng)驗(yàn)霍殴,所以大家有時(shí)間還是好好磨練下吧媒惕,相應(yīng)的學(xué)習(xí)代碼請(qǐng)點(diǎn)擊頭像獲取哦。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末来庭,一起剝皮案震驚了整個(gè)濱河市妒蔚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌月弛,老刑警劉巖肴盏,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異帽衙,居然都是意外死亡菜皂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門厉萝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來幌墓,“玉大人,你說我怎么就攤上這事冀泻〕B拢” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵弹渔,是天一觀的道長胳施。 經(jīng)常有香客問我,道長肢专,這世上最難降的妖魔是什么舞肆? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮博杖,結(jié)果婚禮上椿胯,老公的妹妹穿的比我還像新娘。我一直安慰自己剃根,他們只是感情好哩盲,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般廉油。 火紅的嫁衣襯著肌膚如雪惠险。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天抒线,我揣著相機(jī)與錄音班巩,去河邊找鬼。 笑死嘶炭,一個(gè)胖子當(dāng)著我的面吹牛抱慌,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播眨猎,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼遥缕,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了宵呛?” 一聲冷哼從身側(cè)響起单匣,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎宝穗,沒想到半個(gè)月后户秤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡逮矛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年鸡号,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片须鼎。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鲸伴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出晋控,到底是詐尸還是另有隱情汞窗,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布赡译,位于F島的核電站仲吏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蝌焚。R本人自食惡果不足惜裹唆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望只洒。 院中可真熱鬧许帐,春花似錦、人聲如沸毕谴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至羡鸥,卻和暖如春蔑穴,著一層夾襖步出監(jiān)牢的瞬間忠寻,已是汗流浹背惧浴。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留奕剃,地道東北人衷旅。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像纵朋,于是被迫代替她去往敵國和親柿顶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345