140 lines
4.1 KiB
Python
Executable File
140 lines
4.1 KiB
Python
Executable File
import numpy as np
|
|
|
|
|
|
def min_zero_row(zero_mat, mark_zero):
|
|
min_row = [99999, -1]
|
|
|
|
for row_num in range(zero_mat.shape[0]):
|
|
if np.sum(zero_mat[row_num] == True) > 0 and min_row[0] > np.sum(zero_mat[row_num] == True):
|
|
min_row = [np.sum(zero_mat[row_num] == True), row_num]
|
|
|
|
zero_index = np.where(zero_mat[min_row[1]] == True)[0][0]
|
|
mark_zero.append((min_row[1], zero_index))
|
|
zero_mat[min_row[1], :] = False
|
|
zero_mat[:, zero_index] = False
|
|
|
|
|
|
def mark_matrix(mat):
|
|
cur_mat = mat
|
|
zero_bool_mat = (cur_mat == 0)
|
|
zero_bool_mat_copy = zero_bool_mat.copy()
|
|
|
|
marked_zero = []
|
|
while (True in zero_bool_mat_copy):
|
|
min_zero_row(zero_bool_mat_copy, marked_zero)
|
|
|
|
marked_zero_row = []
|
|
marked_zero_col = []
|
|
for i in range(len(marked_zero)):
|
|
marked_zero_row.append(marked_zero[i][0])
|
|
marked_zero_col.append(marked_zero[i][1])
|
|
|
|
non_marked_row = list(set(range(cur_mat.shape[0])) - set(marked_zero_row))
|
|
|
|
marked_cols = []
|
|
check_switch = True
|
|
while check_switch:
|
|
check_switch = False
|
|
for i in range(len(non_marked_row)):
|
|
row_array = zero_bool_mat[non_marked_row[i], :]
|
|
for j in range(row_array.shape[0]):
|
|
if row_array[j] == True and j not in marked_cols:
|
|
marked_cols.append(j)
|
|
check_switch = True
|
|
|
|
for row_num, col_num in marked_zero:
|
|
if row_num not in non_marked_row and col_num in marked_cols:
|
|
non_marked_row.append(row_num)
|
|
check_switch = True
|
|
|
|
marked_rows = list(set(range(mat.shape[0])) - set(non_marked_row))
|
|
|
|
return (marked_zero, marked_rows, marked_cols)
|
|
|
|
|
|
def adjust_matrix(mat, cover_rows, cover_cols):
|
|
cur_mat = mat
|
|
non_zero_element = []
|
|
|
|
for row in range(len(cur_mat)):
|
|
if row not in cover_rows:
|
|
for i in range(len(cur_mat[row])):
|
|
if i not in cover_cols:
|
|
non_zero_element.append(cur_mat[row][i])
|
|
min_num = min(non_zero_element)
|
|
|
|
for row in range(len(cur_mat)):
|
|
if row not in cover_rows:
|
|
for i in range(len(cur_mat[row])):
|
|
if i not in cover_cols:
|
|
cur_mat[row, i] = cur_mat[row, i] - min_num
|
|
|
|
for row in range(len(cover_rows)):
|
|
for col in range(len(cover_cols)):
|
|
cur_mat[cover_rows[row], cover_cols[col]] = cur_mat[cover_rows[row], cover_cols[col]] + min_num
|
|
|
|
return cur_mat
|
|
|
|
|
|
def hungarian_algorithm(mat):
|
|
dim = mat.shape[0]
|
|
cur_mat = mat
|
|
|
|
for row_num in range(mat.shape[0]):
|
|
cur_mat[row_num] = cur_mat[row_num] - np.min(cur_mat[row_num])
|
|
|
|
for col_num in range(mat.shape[1]):
|
|
cur_mat[:, col_num] = cur_mat[:, col_num] - np.min(cur_mat[:, col_num])
|
|
|
|
zero_count = 0
|
|
while zero_count < dim:
|
|
ans_pos, marked_rows, marked_cols = mark_matrix(cur_mat)
|
|
zero_count = len(marked_rows) + len(marked_cols)
|
|
|
|
if zero_count < dim:
|
|
cur_mat = adjust_matrix(cur_mat, marked_rows, marked_cols)
|
|
|
|
return ans_pos
|
|
|
|
|
|
def ans_calculation(mat, ans_pos):
|
|
total = 0
|
|
ans_mat = np.zeros((mat.shape[0], mat.shape[1]))
|
|
for i in range(len(ans_pos)):
|
|
total += mat[ans_pos[i][0], ans_pos[i][1]]
|
|
ans_mat[ans_pos[i][0], ans_pos[i][1]] = mat[ans_pos[i][0], ans_pos[i][1]]
|
|
|
|
return total, ans_mat
|
|
|
|
|
|
def main():
|
|
cost_matrix = np.array([
|
|
[7, 3, 6, 9, 5],
|
|
[7, 5, 7, 5, 6],
|
|
[7, 6, 8, 8, 9],
|
|
[3, 1, 6, 5, 7],
|
|
[2, 4, 9, 9, 5]
|
|
])
|
|
|
|
ans_pos = hungarian_algorithm(cost_matrix.copy())
|
|
ans, ans_mat = ans_calculation(cost_matrix, ans_pos)
|
|
print(f"Result min: {ans:.0f}\n{ans_mat}")
|
|
|
|
profit_matrix = np.array([
|
|
[7, 3, 6, 9, 5],
|
|
[7, 5, 7, 5, 6],
|
|
[7, 6, 8, 8, 9],
|
|
[3, 1, 6, 5, 7],
|
|
[2, 4, 9, 9, 5]
|
|
])
|
|
max_value = np.max(profit_matrix)
|
|
cost_matrix = max_value - profit_matrix
|
|
|
|
ans_pos = hungarian_algorithm(cost_matrix.copy())
|
|
ans, ans_mat = ans_calculation(profit_matrix, ans_pos)
|
|
print(f"Result max: {ans:.0f}\n{ans_mat}")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|