Guest User

Untitled

a guest
Jan 23rd, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.04 KB | None | 0 0
  1. #!/usr/bin/env python2
  2.  
  3. # I'm going to stick this in a class at some point because passing all the shit between the functions is fugly
  4. # Also: IT FUCKING WORKS!
  5.  
  6. """original_matrix = [
  7.    [17, 20, 13, 10],
  8.    [ 6, 18,  7, 17],
  9.    [11,  3,  2, 10],
  10.    [ 4,  5, 11, 17]
  11. ]"""
  12.  
  13. """original_matrix = [
  14.    [17, 10, 12],
  15.    [ 9,  8, 10],
  16.    [14,  4,  7]
  17. ]"""
  18.  
  19. """original_matrix = [
  20.    [25,  4, 15,  7],
  21.    [ 6,  3,  8, 18],
  22.    [13,  2,  2,  4],
  23.    [ 1,  1,  2,  1]
  24. ]"""
  25.  
  26. original_matrix = [
  27.     [10,5,18,11],
  28.     [3,2,4,5],
  29.     [18,9,17,15],
  30.     [11,6,19,10]
  31. ]
  32.  
  33. matrix = [l[:] for l in original_matrix]
  34.  
  35. def reduction(matrix):
  36.     # Rows
  37.     for key, row in enumerate(matrix):
  38.         row_min = min(row)
  39.         if row_min == 0:
  40.             continue
  41.         matrix[key] = [n - row_min for n in row]
  42.  
  43.     # Columns
  44.     for i in range(len(matrix[0])):
  45.         col = []
  46.         for j in range(len(matrix)):
  47.             col.append(matrix[j][i])
  48.         col_min = min(col)
  49.         if col_min == 0:
  50.             continue
  51.         for j in range(len(matrix)):
  52.             matrix[j][i] -= col_min
  53.     return matrix
  54.  
  55. def path_decision(matrix, assignments_overlay, total_assignments, assigned_cols, assigned_rows):
  56.     # Given a bipartite graph matrix and a partial matching consisting only of necessary pairs, find a maximal matching.
  57.     for j in range(len(matrix)):
  58.         if j in assigned_rows:
  59.             continue
  60.         for i in range(len(matrix[0])):
  61.             if i in assigned_cols:
  62.                 continue
  63.             if matrix[j][i] == 0:
  64.                 my_overlay = [row[:] for row in assignments_overlay]
  65.                 my_overlay[j][i] = 1
  66.                 new_overlay, my_total_assignments, my_assigned_cols, my_assigned_rows = path_decision(matrix, my_overlay, total_assignments + 1, assigned_cols + [i], assigned_rows + [j])
  67.                 if not my_total_assignments == len(matrix):
  68.                     continue
  69.                 assignments_overlay = new_overlay
  70.                 total_assignments = my_total_assignments
  71.                 assigned_cols = my_assigned_cols
  72.                 assigned_rows = my_assigned_rows
  73.     return assignments_overlay, total_assignments, assigned_cols, assigned_rows
  74.  
  75. def assignments(matrix):
  76.     assignments_overlay = [[0 for n in row] for row in matrix]
  77.     total_assignments = 0
  78.     assigned_cols = []
  79.     assigned_rows = []
  80.     keep_going = True
  81.     while keep_going:
  82.         keep_going = False
  83.         # Rows
  84.         for key, row in enumerate(matrix):
  85.             if key in assigned_rows:
  86.                 continue
  87.             temp_row = row[:]
  88.             for col in assigned_cols:
  89.                 temp_row[col] = -1
  90.             if temp_row.count(0) == 1:
  91.                 zeroindex = temp_row.index(0)
  92.                 assignments_overlay[key][zeroindex] = 1
  93.                 assigned_cols.append(zeroindex)
  94.                 assigned_rows.append(key)
  95.                 keep_going = True
  96.                 total_assignments += 1
  97.         # Cols
  98.         for i in range(len(matrix[0])):
  99.             if i in assigned_cols:
  100.                 continue
  101.             zeroes = 0
  102.             for j in range(len(matrix)):
  103.                 if j in assigned_rows:
  104.                     continue
  105.                 if matrix[j][i] == 0:
  106.                     zeroes += 1
  107.                     if zeroes > 1:
  108.                         break
  109.                     zero_index = j
  110.             if not zeroes == 1:
  111.                 continue
  112.             assignments_overlay[zero_index][i] = 1
  113.             assigned_cols.append(i)
  114.             assigned_rows.append(zero_index)
  115.             keep_going = True
  116.             total_assignments += 1
  117.         if not keep_going and total_assignments < len(matrix):
  118.             # We must decide which path to take. MAN THE HARPOONS!
  119.             assignments_overlay, total_assignments, assigned_cols, assigned_rows = path_decision(matrix, assignments_overlay, total_assignments, assigned_cols, assigned_rows)
  120.     return assignments_overlay, total_assignments, assigned_cols, assigned_rows
  121.  
  122. def ohgodtheresmore(matrix, assignments_overlay, total_assignments, assigned_cols, assigned_rows):
  123.     marked_rows = []
  124.     marked_cols = []
  125.     for key, row in enumerate(matrix):
  126.         if not key in assigned_rows:
  127.             marked_rows.append(key)
  128.     marked = True
  129.     while marked:
  130.         marked = False
  131.         for row_key in marked_rows:
  132.             for col_key, n in enumerate(matrix[row_key]):
  133.                 if col_key in marked_cols:
  134.                     continue
  135.                 if n == 0:
  136.                     marked_cols.append(col_key)
  137.                     marked = True
  138.         for i in marked_cols:
  139.             for j in range(len(matrix)):
  140.                 if j in marked_rows:
  141.                     continue
  142.                 if assignments_overlay[j][i] == 1:
  143.                     marked_rows.append(j)
  144.                     marked = True
  145.     remaining_elements = []
  146.     for i in range(len(matrix[0])):
  147.         for j in range(len(matrix)):
  148.             if (not i in marked_cols) and (j in marked_rows):
  149.                 remaining_elements.append(matrix[j][i])
  150.     min_remaining = min(remaining_elements)
  151.     for i in range(len(matrix[0])):
  152.         for j in range(len(matrix)):
  153.             if (i in marked_cols) and (not j in marked_rows):
  154.                 matrix[j][i] += min_remaining
  155.             elif (not i in marked_cols) and (j in marked_rows):
  156.                 matrix[j][i] -= min_remaining
  157.     assignments_overlay, total_assignments, assigned_cols, assigned_rows = assignments(matrix)
  158.     return matrix, assignments_overlay, total_assignments, assigned_cols, assigned_rows
  159.  
  160. matrix = reduction(matrix)
  161. assignments_overlay, total_assignments, assigned_cols, assigned_rows = assignments(matrix)
  162.  
  163. while total_assignments < len(matrix):
  164.     matrix, assignments_overlay, total_assignments, assigned_cols, assigned_rows = ohgodtheresmore(matrix, assignments_overlay, total_assignments, assigned_cols, assigned_rows)
  165.  
  166. print assignments_overlay
  167. print matrix
  168. print original_matrix
Add Comment
Please, Sign In to add comment