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
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
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
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