def find_min_cost(cost_matrix): assert ((cost_matrix >= 0).all()), matrix lin_assign = linear_assignment.LinearAssignment(cost_matrix) solution = lin_assign.solution association_list = zip([i for i in range(len(solution))], solution) minimum_cost = 0 for (row, col) in association_list: minimum_cost += np.asscalar(cost_matrix[row][col]) return (association_list, minimum_cost)
def find_max_cost(cost_matrix): ''' Solve the assignment problem for the specified cost_matrix Inputs: - cost_matrix: numpy.ndarray, cost matrix Outputs: - max_cost: float, the maximum cost - max_cost_assignments: list of pairs representing indices of 1's in max cost permutation matrix ''' size = cost_matrix.shape[0] lin_assign = linear_assignment.LinearAssignment( -1 * cost_matrix) #multiply by -1 to find max cost solution = lin_assign.solution max_cost_assignments = zip([i for i in range(len(solution))], solution) max_cost = 0.0 for (row, col) in max_cost_assignments: assert (row < size), (row, size, cost_matrix) assert (col < size), (col, size, cost_matrix) max_cost += cost_matrix[row][col] return (max_cost, max_cost_assignments)
def __init__(self, orig_cost_matrix, required_cells, excluded_cells, orig_cost_matrix_index, M, T, matrix_cost): ''' Following the terminology used by [1], a node is defined to be a nonempty subset of possible assignments to a cost matrix. Every assignment in node N is required to contain required_cells and exclude excluded_cells. Inputs: - orig_cost_matrix: (2d numpy array) the original cost matrix - required_cells: (list of pairs) where each pair represents a (zero indexed) location in the assignment matrix that must be a 1 - excluded_cells: list of pairs) where each pair represents a (zero indexed) location in the assignment matrix that must be a 0 - orig_cost_matrix_index: index of the cost matrix this Node is descended from, used when when finding the k lowest cost assignments among a group of assignment matrices (k_best_assign_mult_cost_matrices) - M: number of measurements - T: number of targets - matrix_cost: cost of this matrix, must be added to every assignment cost we compute orig_cost_matrix has dimensions (2*M + 2*T)x(2*M + 2*T) ''' self.orig_cost_matrix = np.array(orig_cost_matrix, copy=True) self.required_cells = required_cells[:] self.excluded_cells = excluded_cells[:] self.orig_cost_matrix_index = orig_cost_matrix_index self.M = M self.T = T if DEBUG: print "New Node:" print "self.required_cells:", self.required_cells print "self.excluded_cells:", self.excluded_cells self.matrix_cost = matrix_cost self.minimum_cost = matrix_cost if orig_cost_matrix.size > 0: #we will transform the cost matrix into the "remaining cost matrix" as described in [1] if REMAINING_COST_MATRIX_CONSTRUNCTION == 'fixed': self.remaining_cost_matrix = self.construct_fixed_size_remaining_cost_matrix() elif REMAINING_COST_MATRIX_CONSTRUNCTION == 'delete': self.remaining_cost_matrix = self.construct_remaining_cost_matrix() else: self.remaining_cost_matrix = self.construct_remaining_cost_matrix() assert((self.remaining_cost_matrix >= 0).all()), self.remaining_cost_matrix #solve the assignment problem for the remaining cost matrix if ASSIGNMENT_SOLVER == 'munkres': hm = Munkres() # we get a list of (row, col) associations, or 1's in the minimum assignment matrix association_list = hm.compute(self.remaining_cost_matrix.tolist()) elif ASSIGNMENT_SOLVER == 'scipy': row_ind, col_ind = linear_sum_assignment(self.remaining_cost_matrix) assert(len(row_ind) == len(col_ind)) association_list = zip(row_ind, col_ind) else: assert(ASSIGNMENT_SOLVER == 'pymatgen') lin_assign = linear_assignment.LinearAssignment(self.remaining_cost_matrix) solution = lin_assign.solution association_list = zip([i for i in range(len(solution))], solution) # association_list = [(i, i) for i in range(orig_cost_matrix.shape[0])] if DEBUG: print "remaining cost matrix:" print self.remaining_cost_matrix print "association_list" print association_list if REMAINING_COST_MATRIX_CONSTRUNCTION == 'fixed': for (row,col) in association_list: self.minimum_cost += np.asscalar(self.orig_cost_matrix[row][col]) elif REMAINING_COST_MATRIX_CONSTRUNCTION == 'delete': #compute the minimum cost assignment for the node for (row,col) in association_list: # print 'a', self.minimum_cost, type(self.minimum_cost) # print 'b', self.remaining_cost_matrix[row][col], type(self.remaining_cost_matrix[row][col]) # print 'c', self.minimum_cost +self.remaining_cost_matrix[row][col], type(self.minimum_cost +self.remaining_cost_matrix[row][col]) #np.asscalar important for avoiding overflow problems self.minimum_cost += np.asscalar(self.remaining_cost_matrix[row][col]) for (row, col) in self.required_cells: #np.asscalar important for avoiding overflow problems self.minimum_cost += np.asscalar(orig_cost_matrix[row][col]) else: implement_me = False #store the minimum cost associations with indices consistent with the original cost matrix if REMAINING_COST_MATRIX_CONSTRUNCTION == 'fixed': self.min_cost_associations = association_list else: self.min_cost_associations = self.get_orig_indices(association_list) else: self.min_cost_associations = [] if DEBUG: print "New Node:" print "self.required_cells:", self.required_cells print "self.excluded_cells:", self.excluded_cells print print
COUNT_CORRECT_matching = False if COUNT_CORRECT_matching: CORRECT_THRESHOLD = .15 all_pred_clusters = torch.stack(params, dim=1).squeeze()[:, :, :2] # print("len(params):", len(params)) # print("params[0].shape:", params[0].shape) # print("all_pred_clusters.shape:", all_pred_clusters.shape) # sleep(asldfhj) gt_objects = batch['gt_objects'].cuda() batch_size = all_pred_clusters.shape[0] for img_idx in range(batch_size): pairwise_distance = my_cdist(all_pred_clusters[img_idx], gt_objects[img_idx]) lin_assign = linear_assignment.LinearAssignment( pairwise_distance.cpu().detach()) solution = lin_assign.solution association_list = zip([i for i in range(len(solution))], solution) cur_img_loss = 0.0 correct_count = 0 for assoc in association_list: cur_assoc_distance = pairwise_distance[assoc[0], assoc[1]] all_distances.append(cur_assoc_distance.item()) if cur_assoc_distance <= CORRECT_THRESHOLD: correct_count += 1 all_correct_counts.append(correct_count) COUNT_CORRECT_greedy = True if COUNT_CORRECT_greedy: CORRECT_THRESHOLD = .15 all_pred_clusters = torch.stack(params, dim=1).squeeze()[:, :, :2]