Пример #1
0
def edit_distance(board: Board) -> int:
    # Determines the edit distance between the board positions and the stalemate positions
    # input: board positions
    # return: edit distance value

    tigers = board.get_all_tiger_positions()
    numGoats = len(board.get_all_goat_positions())

    _, stalemate_board = optimal_stalemate(tigers[0].address,
                                           tigers[1].address,
                                           tigers[2].address)
    # _, stalematePositions = stalemate(tigers[0], tigers[1], tigers[2])
    possible_pos = board.get_all_addresses()
    # Initializing Bipartite graph
    B = nx.Graph()
    B.add_nodes_from(list(range(23)), bipartite=0)
    B.add_nodes_from(possible_pos, bipartite=1)

    # Populate graph
    for i, pos in enumerate(possible_pos):
        for stalematePos in stalemate_board.get_all_positions():

            # print('DEBUG: pos ', pos, ' stalematePos ',stalematePos)
            # print('DEBUG: possible_pos[pos] ', boardPosition[possible_pos[pos]], ' stalematePositions[stalematePos] ', stalematePositions[stalematePos])
            # print('DEBUG: pos ', possible_pos[pos], ' stalematePos ',stalematePos)
            # print(10 - num_moves(pos,stalematePos))
            if (board.get_pos(stalematePos.address).is_goat()
                    and stalematePos.is_goat()):

                # print('stalematePos',stalematePos, 'weight',10 - num_moves(possible_pos[pos],stalematePos))
                B.add_edge(
                    i,
                    stalematePos,
                    weight=-10 + num_moves(pos, stalematePos.address),
                )
            # elif boardPosition[possible_pos[pos]] == stalematePositions[stalematePos] and possible_pos[pos] == stalematePos:
            #     B.add_edge(pos,stalematePos, weight = -1e20)
            else:
                B.add_edge(i, stalematePos.address, weight=1e20)

    # Bipartite Max Matching
    # print(B.edges(data=True))

    maxMatching = bipartite.minimum_weight_full_matching(B)
    # print(maxMatching)
    Sum = 0
    # Collect sum of weights
    n = 0
    for key, item in maxMatching.items():
        if n == 23:
            break
        # # print(B.get_edge_data(key,item)['weight'])
        if board.get_pos(possible_pos[key]).is_goat():
            Sum = Sum + num_moves(possible_pos[key], item)
        # print(Sum)
        n = n + 1

    return Sum
Пример #2
0
def edit_distance(boardPosition):
    # Determines the edit distance between the board positions and the stalemate positions
    # input: board positions
    # return: edit distance value

    tigers = tigerPositions(boardPosition)
    numGoats = len(goatPositions(boardPosition))
    _, stalematePositions = stalemate(tigers[0], tigers[1], tigers[2])
    positions = list(boardPosition.keys())
    possiblePos = list(Board().boardPositions.keys())
    # Initializing Bipartite graph
    B = nx.Graph()
    B.add_nodes_from(list(range(23)), bipartite=0)
    B.add_nodes_from(positions, bipartite=1)

    # Populate graph
    for pos in list(range(23)):
        for stalematePos in positions:

            # print('DEBUG: pos ', pos, ' stalematePos ',stalematePos)
            # print('DEBUG: possiblePos[pos] ', boardPosition[possiblePos[pos]], ' stalematePositions[stalematePos] ', stalematePositions[stalematePos])
            # print('DEBUG: pos ', possiblePos[pos], ' stalematePos ',stalematePos)
            # print(10 - num_moves(pos,stalematePos))
            if boardPosition[possiblePos[pos]] == "O" and stalematePositions[
                    stalematePos] == "O":

                # print('stalematePos',stalematePos, 'weight',10 - num_moves(possiblePos[pos],stalematePos))
                B.add_edge(pos,
                           stalematePos,
                           weight=-10 +
                           num_moves(possiblePos[pos], stalematePos))
            # elif boardPosition[possiblePos[pos]] == stalematePositions[stalematePos] and possiblePos[pos] == stalematePos:
            #     B.add_edge(pos,stalematePos, weight = -1e20)
            else:
                B.add_edge(pos, stalematePos, weight=1e20)

    # Bipartite Max Matching
    # print(B.edges(data=True))

    maxMatching = bipartite.minimum_weight_full_matching(B)
    # print(maxMatching)
    Sum = 0
    # Collect sum of weights
    n = 0
    for key, item in maxMatching.items():
        if n == 23:
            break
        # # print(B.get_edge_data(key,item)['weight'])
        if boardPosition[possiblePos[key]] == 'O':
            Sum = Sum + num_moves(possiblePos[key], item)
        # print(Sum)
        n = n + 1

    return Sum
def matching(idxA, idxB):
    labelsA = np.unique(idxA)
    m = len(labelsA)
    labelsB = np.unique(idxB)
    n = len(labelsB)
    W = np.zeros((m, n))
    for j in range(n):
        for i in range(m):
            W[i, j] = -sum(idxA[idxB == labelsB[j]] == labelsA[i])
    G = bipartite.from_biadjacency_matrix(scipy.sparse.coo_matrix(W))
    top_nodes = {n for n, d in G.nodes(data=True) if d["bipartite"] == 0}
    match = bipartite.minimum_weight_full_matching(G, top_nodes)
    new_labels = dict()
    for i in range(n):
        new_labels[labelsB[i]] = labelsA[match[i+n]]
    matched = np.array([new_labels[idxB[i]] for i in range(len(idxB))])
    return matched
Пример #4
0
    def compute_graph_similarity(self):
        match = bipartite.minimum_weight_full_matching(self.G)
        score = 0
        for x in range(self.nx):
            score += self.weiht[x, match[x] - 10000]
        ## there are three graph similarity compute method,please choose one

        ### the fisrt :author's paper's formula
        # similarity = 1 - score/max(self.nx,self.ny)

        ### the second: fix the max to min

        similarity = 1 - score / min(self.nx, self.ny)

        ### the third: improved second'formula by normalize node's effective
        # similarity = 1 - score / min(self.nx, self.ny)
        # similarity = similarity * self.nx / self.ny
        del self.G
        del self.weiht
        return similarity
Пример #5
0
def match(tutors, tutees):
    tutDict = {}
    for tutor in tutors:
        print(tutor.subjects)
        tutDict[tutor.tutorID] = tutor
    for tutee in tutees:
        print(tutee.subjects)
        tutDict[tutee.tuteeID] = tutee

    tutorIDIndex = len(tutors) * [0]
    tuteeIDIndex = len(tutees) * [0]
    scoreMat = len(tutors) * [
        len(tutees) * [0]
    ]  #scoreMat[tutorIndex][tuteeIndex] returns the score for this pair and the label explaining the score - is stored as a tuple (score, label)
    for tutor in range(len(tutors)):
        tutorIDIndex[tutor] = tutors[tutor].tutorID
        for tutee in range(len(tutees)):
            tuteeIDIndex[tutee] = tutees[tutee].tuteeID
            scoreMat[tutor][tutee] = s(tutors[tutor], tutees[tutee])

    # convert matrix to a complete bipartite graph
    G = nx.Graph()
    # add nodes - tutors and tutees
    G.add_nodes_from([tutor.tutorID for tutor in tutors], bipartite=0)
    G.add_nodes_from([tutee.tuteeID for tutee in tutees], bipartite=1)
    # add edges - copy across from matrix
    for tutori in range(len(tutorIDIndex)):
        for tuteej in range(len(tuteeIDIndex)):
            G.add_edge(tuteeIDIndex[tuteej],
                       tutorIDIndex[tutori],
                       weight=scoreMat[tutori][tuteej][0],
                       label=scoreMat[tutori][tuteej][1])

    M = bipartite.minimum_weight_full_matching(G)

    #remove duplicate dict data
    for tutee in tutees:
        M.pop(tutee.tuteeID, None)
    #remove any infinite edges
    ok = True
    for key in M:
        if G.get_edge_data(key, M[key])['weight'] == math.inf:
            ok = False
            M.pop(key)

    matchableTutors = [tutor for tutor in tutors if tutor.tutorID in M]
    matchableTutees = [
        tutee for tutee in tutees if tutee.tuteeID in M.values()
    ]

    # if not ok we need to call repeat on a subset of tutors and tutees
    if not ok:
        return match(matchableTutors, matchableTutees)

    tts = []  #tutor, tutee, subject
    print("")
    for key in M:
        subject = G.get_edge_data(key, M[key])['label']
        print(subject)
        print(tutDict[M[key]].tuteeID)
        print(tutDict[M[key]].subjects)
        tts.append([tutDict[key], tutDict[M[key]], subject])

    days = {'misc': 0}
    table = []

    # if only one day is an option then trivially assign pair to that time slot - we then balance the rest accordingly
    i = 0
    while i < len(tts):
        pairDays = []
        for d in tts[i][0].days:
            if d in tts[i][1].days:
                pairDays.append(d)
        if len(pairDays) == 1:
            day = pairDays[0]
            if day in days:
                days[day] += 1
            else:
                days[day] = 1
            tts[i].append(d)
            table.append(tts.pop(i))
        else:
            tts[i].append(pairDays)
            i += 1

    overlap = lambda xs, ys: [x for x in xs if x in ys]
    pick = lambda xs: random.choice(xs)

    # if any remaining pairs can be grouped with the trivial groupings then do so
    i = 0
    while i < len(tts):
        pair = tts[i]
        pair.append(overlap(pair[3], days))
        if len(pair[4]) == 0:
            pair[4] = 'misc'
            i += 1
        else:
            pair[3] = pick(pair[4])
            table.append(tts.pop(i)[:4])

    # deal with outliers
    i = 0
    while i < len(tts):
        pair = tts[i]
        pair[3] = pick(pair[3])
        table.append(tts.pop(i)[:4])

    return table