一張圖說清匈牙利算法(Hungarian Algorithm)

做多目標跟蹤的時候會碰到這個算法筐钟,每個人都有自己的說法講清楚這個算法是干什么的?我的老師就跟我說過是什么給工人分配活干(即理解為指派問題)疹鳄,網(wǎng)上還看到有說紅娘盡可能匹配多的情侶等拧略,透過這些感性理解,基本上就能理解大概是最大匹配的問題了瘪弓。

然后加了限制:后來者優(yōu)先垫蛆。即后匹配的搶掉前人已匹配的對象,這個是有數(shù)學依據(jù)還是只是一種實現(xiàn)思路我就沒深究了腺怯。

我的理解不會比別人更高級袱饭,之所以能用一張圖說清楚,只不過是我作圖的時候發(fā)現(xiàn)可以把過程畫在一張圖里呛占,只需要把圖示標清楚就好了虑乖,這樣就不需要每一步畫一張圖了,一旦理解了晾虑,哪怕忘了疹味,一瞅這張圖也能立刻回憶起來仅叫。

先上數(shù)據(jù):

import numpy as np

relationship_matrix = np.array([
    [1,1,0,1,0,0,0],
    [0,1,0,0,1,0,0],
    [1,0,0,1,0,0,1],
    [0,0,1,0,0,1,0],
    [0,0,0,1,0,0,0],
    [0,0,0,1,0,0,0]
], dtype=bool)

你可以理解為6個工人,7個工作糙捺,6個男孩诫咱,7個女孩等,當然洪灯,6行7列坎缭,這么直觀理解也是一點問題都沒有的。

算法匹配過程如下:


hungarian_algorithm.png
  • 灰藍線就是被搶掉的
  • 綠線就是搶奪失敗的
  • 紫線是被搶了后找候選成功的
  • 紅線是一次性成功的

其中被搶的和搶奪失敗的還加了刪除線婴渡,這是為了強調(diào)幻锁。匹配成功的就是紅線紫線,也就是說边臼,我們匹配出來的是:

[0,1], [1,4], [2,0], [3,2], [4,3]

甚至可以這么表示這個過程:

x0,y0
x1,y1
x2,y0 -> x0,y1 -> x1->y4 (x2搶x0的,x0搶x1的)
x3,y2
x4,y3
x5,y3 -> x4匹配不到新的哄尔,搶奪失敗,-> x5,null

有沒有說清楚柠并?就兩步:

  1. 根據(jù)關聯(lián)表直接建立關系
  2. 如果當前C匹配的對象已經(jīng)被B匹配過了岭接,那么嘗試把它搶過來:
  • B去找別的匹配
    • 找到了(A)就建立新的匹配
      • 如果新的匹配(A)也已經(jīng)被別人(D)匹配了,那么那個“別人(D)”也放棄當前匹配去找別的(遞歸警告
    • 如果找不到新的匹配臼予,那么C搶奪失敗鸣戴,遞歸中的D也同理,失敗向上冒泡

注意遞歸怎么寫代碼就能寫出來了:

nx, ny = relationship_matrix.shape    # 6個x粘拾,7個y

# 如果x0與y0關聯(lián)窄锅,x3也與y0關聯(lián),那么x0去找新的匹配時缰雇,需要把y0過濾掉
# 同理x0如果找到下一個y2入偷,y2已被x2關聯(lián),那么x2找新的匹配時[y0, y2]都需要過濾掉
# 我們把這個數(shù)組存為y_used
y_used = np.zeros((ny,), dtype=bool)  # 存y是否連接上
path = np.full((ny,), -1, dtype=int)  # 存x連接的對象械哟,沒有為-1

def find_other_path_and_used(x):
    for y in range(ny):
        if relationship_matrix[x, y] and not y_used[y]:
            y_used[y] = True        # 處于爭奪中的y疏之,需要打標,在后續(xù)的遞歸時要過濾掉
            if path[y] == -1 or find_other_path_and_used(path[y]):
                path[y] = x         # 直接連接 和 搶奪成功
                return True
    return False                    # 搶奪失敗 和 默認失敗

for x in range(nx):
    y_used[:] = False  # empty
    find_other_path_and_used(x)

for y, x in enumerate(path):
    if x != -1:
        print(x, y)

真的寫代碼實現(xiàn)的時候暇咆,難點反而是y_used這個锋爪,第一遍代碼沒考慮這一點,導致遞歸的時候每次都從y_0開始而出現(xiàn)死循環(huán)爸业,意識到后把處于爭搶狀態(tài)中的y打個標就好了其骄。

scipy中有一個算法實現(xiàn)了Hungarian algorithm:

from scipy.optimize import linear_sum_assignment

# relationship_matrix是代價矩陣
# 所以我們要代價越小越好,就用1來減
rows, cols = linear_sum_assignment(1-relationship_matrix) 
list(zip(rows, cols))
[(0, 0), (1, 1), (2, 6), (3, 2), (4, 3), (5, 4)]

為什么與上面不一樣呢扯旷?

  1. (0年栓,0),(1薄霜,1)的匹配顯然不是我們實現(xiàn)的后來者優(yōu)先
  2. 他把行看成是工人某抓,列看成是任務纸兔,每個工人總要分配個任務,所以(5,4)這種代價矩陣里沒有的關聯(lián)它也做出來了否副,目的只是讓“總代價”最小
(1-relationship_matrix)[rows, cols]  # 總代價為1
array([0, 0, 0, 0, 0, 1])

從它的名字也能看出來汉矿,它是理解為指派問題的(assignment)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市备禀,隨后出現(xiàn)的幾起案子洲拇,更是在濱河造成了極大的恐慌,老刑警劉巖曲尸,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赋续,死亡現(xiàn)場離奇詭異,居然都是意外死亡另患,警方通過查閱死者的電腦和手機纽乱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昆箕,“玉大人鸦列,你說我怎么就攤上這事∨籼龋” “怎么了薯嗤?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長纤泵。 經(jīng)常有香客問我骆姐,道長,這世上最難降的妖魔是什么捏题? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任玻褪,我火速辦了婚禮,結(jié)果婚禮上涉馅,老公的妹妹穿的比我還像新娘。我一直安慰自己黄虱,他們只是感情好稚矿,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著捻浦,像睡著了一般晤揣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上朱灿,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天昧识,我揣著相機與錄音,去河邊找鬼盗扒。 笑死跪楞,一個胖子當著我的面吹牛缀去,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播甸祭,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼缕碎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了池户?” 一聲冷哼從身側(cè)響起咏雌,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎校焦,沒想到半個月后赊抖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡寨典,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年氛雪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凝赛。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡注暗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出墓猎,到底是詐尸還是另有隱情捆昏,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布毙沾,位于F島的核電站骗卜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏左胞。R本人自食惡果不足惜寇仓,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望烤宙。 院中可真熱鬧遍烦,春花似錦、人聲如沸躺枕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拐云。三九已至罢猪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間叉瘩,已是汗流浹背膳帕。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留薇缅,地道東北人危彩。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓攒磨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親恬砂。 傳聞我的和親對象是個殘疾皇子咧纠,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

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