mirea-projects/Second term/Discrete math/Задание_12.py

140 lines
4.1 KiB
Python
Raw Permalink Normal View History

2024-09-23 23:22:33 +00:00
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()