헝가리안 알고리즘
2023. 11. 17. 17:44ㆍpython
헝가리안 알고리즘은 일반적으로 이분 그래프에서 최대 가중 매칭을 찾는 문제로 표현되며, 이를 해결하기 위한 몇 가지 알고리즘이 있습니다. 그 중에서 대표적인 것은 Kuhn-Munkres 알고리즘이며, 이를 사용하여 헝가리안 알고리즘을 직접 구현할 수 있습니다.
아래는 Kuhn-Munkres 알고리즘을 사용하여 헝가리안 알고리즘을 직접 구현한 코드입니다. 이 코드에서는 최소 비용 매칭을 찾기 위해 최대 가중 매칭을 찾는 방식으로 구현되어 있습니다.
import numpy as np
def hungarian_algorithm(cost_matrix):
cost_matrix = np.array(cost_matrix)
num_rows, num_cols = cost_matrix.shape
# Step 1: Subtract the smallest entry in each row from all the other entries in that row.
cost_matrix -= cost_matrix.min(axis=1)[:, np.newaxis]
# Step 2: Subtract the smallest entry in each column from all the other entries in that column.
cost_matrix -= cost_matrix.min(axis=0)
# Step 3: Cover each column with the fewest possible lines.
covered_cols = set()
covered_rows = set()
while len(covered_rows) + len(covered_cols) < num_rows + num_cols:
# Find the minimum uncovered entry.
min_val = np.inf
for i in range(num_rows):
if i not in covered_rows:
for j in range(num_cols):
if j not in covered_cols:
min_val = min(min_val, cost_matrix[i, j])
# Subtract the minimum uncovered entry from all the uncovered entries.
for i in range(num_rows):
if i not in covered_rows:
for j in range(num_cols):
if j not in covered_cols:
cost_matrix[i, j] -= min_val
# Cover the rows and columns with the fewest uncovered entries.
min_uncovered_row = min(range(num_rows), key=lambda x: sum(1 if cost_matrix[x, j] == 0 else 0 for j in range(num_cols)))
min_uncovered_col = min(range(num_cols), key=lambda x: sum(1 if cost_matrix[i, x] == 0 else 0 for i in range(num_rows)))
if sum(1 if cost_matrix[min_uncovered_row, j] == 0 else 0 for j in range(num_cols)) <= sum(1 if cost_matrix[i, min_uncovered_col] == 0 else 0 for i in range(num_rows)):
covered_rows.add(min_uncovered_row)
else:
covered_cols.add(min_uncovered_col)
# Step 4: Find a zero in the cost matrix. If there is no starred zero in its row or column,
# star the zero. Repeat for each zero.
starred_zeros = set()
for i in range(num_rows):
for j in range(num_cols):
if cost_matrix[i, j] == 0 and i not in starred_zeros and j not in starred_zeros:
starred_zeros.add(i)
break
# Step 5: Cover each column containing a starred zero. If K columns are covered, the starred
# zeros describe a complete set of unique assignments.
covered_cols = set()
for i in starred_zeros:
for j in range(num_cols):
if cost_matrix[i, j] == 0 and j not in covered_cols:
covered_cols.add(j)
# Step 6: Use the smallest uncovered entry to modify the cost matrix.
min_val = min(cost_matrix[i, j] for i in range(num_rows) for j in range(num_cols) if i not in covered_rows and j not in covered_cols)
for i in range(num_rows):
for j in range(num_cols):
if i not in covered_rows and j in covered_cols:
cost_matrix[i, j] += min_val
elif i in covered_rows and j not in covered_cols:
cost_matrix[i, j] -= min_val
# Step 7: Erase all covered rows and columns. Repeat until all entries are covered.
while len(starred_zeros) < num_rows:
# Find a non-covered zero and prime it.
for i in range(num_rows):
if i not in covered_rows:
for j in range(num_cols):
if j not in covered_cols and cost_matrix[i, j] == 0:
cost_matrix[i, j] = -1
covered_rows.add(i)
covered_cols.add(j)
# Find the starred zero in the same column.
star_in_col = next((x for x in starred_zeros if x != i and cost_matrix[x, j] == 0), None)
if star_in_col is not None:
starred_zeros.remove(star_in_col)
covered_rows.remove(star_in_col)
covered_cols.remove(j)
break
# Return the assignment pairs.
assignment_pairs = [(i, j) for i in range(num_rows) for j in range(num_cols) if cost_matrix[i, j] == 0]
return assignment_pairs
# 예시 사용
cost_matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
assignment_pairs = hungarian_algorithm(cost_matrix)
print("Assignment Pairs:", assignment_pairs)
이 코드는 Kuhn-Munkres 알고리즘을 사용하여 헝가리안 알고리즘을 직접 구현한 예시입니다. 이 구현에서는 최소 비용 매칭을 찾기 위해 최대 가중 매칭을 찾는 방식으로 작성되어 있습니다. 비용 행렬 cost_matrix
를 입력으로 받아 최적의 할당 쌍을 찾아 반환합니다.
'python' 카테고리의 다른 글
Using Flask + s3 image viewer (1) | 2024.01.10 |
---|---|
다각형 겹친 부분의 넓이 구하기 (Python w/ shapely) (0) | 2024.01.08 |
cv2 bbox 그리기 (0) | 2023.11.16 |
python opencv 이미지 합치기 (1) | 2023.11.01 |
Python import 위치 알기 (0) | 2023.10.10 |