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)
예제 #2
0
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)
예제 #3
0
    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
예제 #4
0
    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]