Algorithm Notes: Hungarian Algorithm

1 bipartite graph (bipartite graph)

  • A bipartite graph is a special kind of graph that can be divided into two parts, and the points in each part are not connected to each other.
    • The Hungarian algorithm is mainly used to solve two problems: finding the maximum number of matches and the minimum number of points covered in a bipartite graph .

2 Maximum matching problem

2.1 Problem description

  •  There are two point sets left and right, how many edges can we find at most without a common endpoint?

2.2 Example of Hungarian Algorithm

  • Starting from B1, traverse from G1~G4 one by one
    • First traverse to G2 that has an edge with B1
    • Temporarily connect B1 and G2
  • Then look at B2, and also traverse from G1~G4 one by one

    • First traverse to G2 that has an edge with B2
    • At this point G2 has been connected to B1 on the left
    • So go back and look at B1 to see if there are other options for connecting to B1
    • It is found that B1 can still connect to G4 after G2
    • ——> B2 temporarily connected to G2, B1 temporarily connected to G4
  • Then look at B3, first B3 will first traverse to G1
    • G no conflict
  • Last look at B4
    • B4 traverses to G4
    • G4 is now connected to B1
      • B1 has nothing else to connect to
    • ——>B4 cannot connect to G4

 2.3 Python implementation

2.3.1 Data and preparation section

# 左点-右点--邻接矩阵
ada_matrix=[[0,1,0,1],
           [0,1,0,0],
           [1,0,1,0],
           [0,0,0,1]]

num_left=len(ada_matrix)
num_right=len(ada_matrix[0])

right_pair=[-1]*num_right
#右点和哪个左点匹配了(一开始都是-1,表示没有匹配)

2.3.2 if_match function

  • Indicates that when the left point matches i, according to the situation of right_visited, whether the left point i will match a right point
  • right_visited indicates whether each right point has been considered in the process of matching the left point i
def if_match(i):
    global right_visited
    for j in range(num_right):
        if(ada_matrix[i][j]==1 and right_visited[j]==0):
            #如果右边的点和左边的点有连边;同时在考虑左点i的过程中,右点j没有被考虑过
            
            right_visited[j]=1
            
            if(right_pair[j]==-1):
                #如果左边的点现在还没有右边的点和他匹配,那么左点i和右点j连接
                right_pair[j]=i
                return True
                #左点遍历到i的时候,暂时可以匹配j(后续i点可能需要“改嫁”,但是如果只遍历到i,是不冲突的)
            elif(if_match(right_pair[j])):
                 right_pair[j]=i
                 #如果左边的点已经和别的点(right_pair[j])匹配了,那么看看(right_pair[j])能不能“改嫁”
                 #也就是看看不能选择j的情况下,(right_pair[j])能不能匹配到其他的右点
                    
                 #这是一个递归过程,进行if_match(right_pair[j])的时候,假设匹配到新的右点j'
                 #又需要判断j'是否有点和它匹配+如果匹配了,已经匹配的点能不能“改嫁”
                
                 return True
                 #左点遍历到i的时候,暂时可以匹配j(后续i点可能需要“改嫁”,但是如果只遍历到i,是不冲突的)
    return False                

2.3.3 Main function

for i in range(num_left):
    #每一个左边的点
    global right_visited
    right_visited=[0]*num_right
    #在考虑左边的点i的时候,右边的点有没有被考虑过
    print(right_pair)
    if_match(i)


'''
[-1, -1, -1, -1]
[-1, 0, -1, -1]
[-1, 1, -1, 0]
[2, 1, -1, 0]
'''

The result is the same as the previous manual derivation

3 Minimum point covering problem

  • Find the fewest points such that all edges of the bipartite graph have at least one endpoint among these points.
  • In other words, if you delete the edges containing these points, you can delete all the edges
  • König's theorem: The maximum number of matchings in a bipartite graph is equal to the minimum number of point covers in this graph

Reference content: Get you started with multi-target tracking (3) Hungarian algorithm & KM algorithm- Zhihu (zhihu.com)

Guess you like

Origin blog.csdn.net/qq_40206371/article/details/130019201