def find_matching(self): u"""Finds a matching in the bipartite graph. This is done using the Hopcroft-Karp algorithm with an implementation from the `hopcroftkarp` package. Returns: A dictionary where each edge of the matching is represented by a key-value pair with the key being from the left part of the graph and the value from te right part. """ # The directed graph is represented as a dictionary of edges # The key is the tail of all edges which are represented by the value # The value is a set of heads for the all edges originating from the tail (key) # In addition, the graph stores which part of the bipartite graph a node originated from # to avoid problems when a value exists in both halfs. # Only one direction of the undirected edge is needed for the HopcroftKarp class directed_graph = {} # type: Dict[Tuple[int, TLeft], Set[Tuple[int, TRight]]] for (left, right) in self._edges: tail = (LEFT, left) head = (RIGHT, right) if tail not in directed_graph: directed_graph[tail] = set([head]) else: directed_graph[tail].add(head) matching = HopcroftKarp(directed_graph).maximum_matching() # Filter out the partitions (LEFT and RIGHT) and only return the matching edges # that go from LEFT to RIGHT return dict((tail[1], head[1]) for tail, head in matching.items() if tail[0] == LEFT)
def compute_maximum_matching(): class_size = int(input("Enter Class Size: ")) associate_dict = example_creator.associate_preferences(class_size) manager_dict = example_creator.manager_preferences(class_size) amicable_preference_dict = create_amicable_preference( associate_dict, manager_dict) # converted_amicable_dict = amicable_dict_converter(amicable_preference_dict) """ print_dictionary(associate_dict) print_dictionary(manager_dict) print_dictionary(amicable_preference_dict) print_dictionary(converted_amicable_dict) """ duplicate_dict = copy.deepcopy(amicable_preference_dict) amicable_match = HopcroftKarp(amicable_preference_dict).maximum_matching() print(amicable_match) print( "Total number of managers and associates matched where both listed each other is: " + str(len(amicable_match))) return class_size, associate_dict, manager_dict, amicable_match
def solver(file): graph = {} allLefts = set() allRights = set() total = 0 numlines = int(file.readline()) total = numlines for x in range(numlines): words = file.readline().lower().strip().split() num = words[1] + "XXX" if words[0] in graph: graph[words[0]].add(num) else: graph[words[0]] = {num} allLefts.add(words[0]) allRights.add(num) hk = HopcroftKarp(graph) max_matching = hk.maximum_matching() caught = 0 caught += len(max_matching.keys()) // 2 caught += len([x for x in allLefts if x not in max_matching]) caught += len([x for x in allRights if x not in max_matching]) print(caught) print(max_matching) return(total - caught)
def run(data): c1 = [] c2 = [] for t in data: if t[1] == 1: c1.append(t[0]) else: c2.append(t[0]) c1.sort() c2.sort() c1 += [float('inf')] * max(len(c2) - len(c1), 0) c2 += [float('inf')] * max(len(c1) - len(c2), 0) n = len(c1) # print(c1, c2) graph = dict() c1h = list() for i, c in enumerate(c1): graph[(1, i, c)] = {(2, j, d) for j, d in enumerate(c2) if c != d} c1h.append((1, i, c)) mm = HopcroftKarp(graph).maximum_matching() # print(mm) # print(c1h) diff = [c[2] for c in c1h if c not in mm] cars = diff.count(1) prom = len(diff) - cars return str(n + cars) + ' ' + str(prom)
def hopkroft(graph, structure): transformed_graph = {} supervisors = graph.getEdges() students = graph.getStuEdges() correspondence = {} sup_name = 0 list_supervisors = [supervisor for supervisor in supervisors] list_students = [student for student in students] random.shuffle(list_supervisors) random.shuffle(list_students) a_to_b = {} for i in range(len(list_students)): a_to_b[list_students[i]] = 'stu' + str(i) for supervisor in list_supervisors: cardinality = structure[supervisor] for i in range(cardinality): for stu in supervisors[supervisor]: transformed_graph.setdefault(sup_name, set()).add(a_to_b[stu]) correspondence[sup_name] = supervisor sup_name = sup_name + 1 m = HopcroftKarp(transformed_graph).maximum_matching() result = BipartiteGraph() for student in students: sup_code = m[a_to_b[student]] result.addEdge(correspondence[sup_code], student) return result
def gluten_morgen(filename="data/day21.dat"): food = [] total_food = [] allergens = {} with open(filename) as fdata: for i, line in enumerate(fdata): f, a = line.strip().split(" (contains ") total_food.extend(f.split(" ")) food.append(f.split(" ")) allgs = a[:-1].split(", ") for a in allgs: if a in allergens: allergens[a].append(i) else: allergens[a] = [i] def intersection(*food_chains): master_set = set(food[food_chains[0]]) for f in food_chains: master_set &= set(food[f]) return master_set ing = set() final_dict = {} for a in allergens: inter = intersection(*allergens[a]) final_dict[a] = list(inter) ing = ing.union(inter) print(final_dict) matching = HopcroftKarp(final_dict).maximum_matching(keys_only=True) alph = ",".join(matching[a] for a in sorted(matching)) return len([f for f in total_food if f not in ing]), alph
def FindBipartitePerfectMatching(matrix): ''' Leveraged Hopcroft-Karp to find the maximal matching in a bipartite graph. ''' # Input: Bipartite Matrix # Output: Perfect Matching of Bipartite Matrix from hopcroftkarp import HopcroftKarp import string bipartiteGraph = {} for rowNum in xrange(0, len(matrix)): key = string.lowercase bipartiteGraph[key[rowNum]] = set( np.where(matrix[rowNum] == 1)[0]) perfectMatching = HopcroftKarp(bipartiteGraph).maximum_matching() matrix[:] = 0 for key in perfectMatching: val = perfectMatching[key] if type(val) == type('a'): matrix[string.lowercase.index(val), key] = 1 return matrix
def run(data): graph = dict() # build graph for bipartite maximum-matching for a, b in data: a = 'A_' + a b = 'B_' + b if a not in graph: graph[a] = set([b]) else: graph[a] |= set([b]) # if b not in graph: # graph[b] = set([a]) # else: # graph[b] |= set([a]) # number of edges in left / right half of graph left = set() right = set() for a, b in data: left |= set([a]) right |= set([b]) x = HopcroftKarp(graph).maximum_matching() num_optimal = round(len(x) / 2) num_real_topics = num_optimal + (len(left) - num_optimal) + (len(right) - num_optimal) return len(data) - num_real_topics
def test_keys_only(self): graph = {'a': {1, 3}, 'c': {1, 3}, 'd': {3, 6}, 'h': {8}} hk = HopcroftKarp(graph) max_matching = hk.maximum_matching(keys_only=True) self.assertTrue( max_matching == { 'a': 1, 'c': 3, 'd': 6, 'h': 8 } or max_matching == { 'a': 3, 'c': 1, 'd': 6, 'h': 8 }, 'maximum matching is incorrect')
def getBottleneckDist(S, T): """ Perform the Bottleneck distance matching between persistence diagrams. Assumes first two columns of S and T are the coordinates of the persistence points, but allows for other coordinate columns (which are ignored in diagonal matching) :param S: Mx(>=2) array of birth/death pairs for PD 1 :param T: Nx(>=2) array of birth/death paris for PD 2 :returns (tuples of matched indices, total cost, (N+M)x(N+M) cross-similarity) """ from bisect import bisect_left from hopcroftkarp import HopcroftKarp N = S.shape[0] M = T.shape[0] # Step 1: Compute CSM between S and T, including points on diagonal # L Infinity distance Sb, Sd = S[:, 0], S[:, 1] Tb, Td = T[:, 0], T[:, 1] D1 = np.abs(Sb[:, None] - Tb[None, :]) D2 = np.abs(Sd[:, None] - Td[None, :]) DUL = np.maximum(D1, D2) # Put diagonal elements into the matrix, being mindful that Linfinity # balls meet the diagonal line at a diamond vertex D = np.zeros((N + M, N + M)) D[0:N, 0:M] = DUL UR = np.max(D) * np.ones((N, N)) np.fill_diagonal(UR, 0.5 * (S[:, 1] - S[:, 0])) D[0:N, M::] = UR UL = np.max(D) * np.ones((M, M)) np.fill_diagonal(UL, 0.5 * (T[:, 1] - T[:, 0])) D[N::, 0:M] = UL # Step 2: Perform a binary search + Hopcroft Karp to find the # bottleneck distance N = D.shape[0] ds = np.unique(D.flatten()) ds = ds[ds > 0] ds = np.sort(ds) bdist = ds[-1] matching = {} while len(ds) >= 1: idx = 0 if len(ds) > 1: idx = bisect_left(range(ds.size), int(ds.size / 2)) d = ds[idx] graph = {} for i in range(N): graph['%s' % i] = {j for j in range(N) if D[i, j] <= d} res = HopcroftKarp(graph).maximum_matching() if len(res) == 2 * N and d < bdist: bdist = d matching = res ds = ds[0:idx] else: ds = ds[idx + 1::] matchidx = [(i, matching['%i' % i]) for i in range(N)] return (matchidx, bdist, D)
def main(args): """ """ with open(args.input, 'r') as fh: data = fh.read().split('\n') allergens_map = defaultdict(list) all_ingred = list() for d in data: res = re.match('(.+)\(contains(.+)\)', d) if res: ingredients = res.group(1).rstrip().lstrip().split(' ') allergens = res.group(2).rstrip().lstrip().split(', ') for a in allergens: allergens_map[a].append(set(ingredients)) all_ingred.append(ingredients) poison = list() graph = {} for a in allergens_map: i = set.intersection(*allergens_map[a]) graph[a] = i for entry in i: if entry not in poison: poison.append(entry) # print(all_ingred) c = 0 for a in all_ingred: for i in a: if i not in poison: c += 1 print(c) # https://en.wikipedia.org/wiki/Hopcroft%E2%80%93Karp_algorithm matcb = HopcroftKarp(graph).maximum_matching(keys_only=True) l = sorted(matcb.keys()) part2 = [] for key in l: part2.append(matcb[key]) print(",".join(part2))
def get_departure_keys_product(rules=RULES, tickets=TICKETS, my_ticket=MY_TICKET): tickets_to_remove = set(i for i, ticket in enumerate(tickets) if invalid(ticket, rules)) n = len(tickets[0]) rule_columns = {r: set(range(n)) for r in rules} for i, ticket in enumerate(tickets): if i in set(tickets_to_remove): continue for rule in rules: for j, v in enumerate(ticket): if not is_valid(v, rules[rule]): rule_columns[rule].discard(j) matching = HopcroftKarp(rule_columns).maximum_matching(keys_only=True) departure_keys = [i for k, i in matching.items() if "departure" in k] return product([my_ticket[i] for i in departure_keys])
def pick(problems,solved2): chosen=[] if len(problems) == 0: return chosen graph = {} co=0 for typ,l,r in problems: allp = getall(typ,l,r,solved2) if len(allp) == 0: continue random.shuffle(allp) graph[co] = allp co=co+1 if len(graph) == 0: return [] hk = HopcroftKarp(graph) max_matching = hk.maximum_matching() for i in range(0,co): chosen.append(max_matching[i]) random.shuffle(chosen) return chosen
def solve(topics): n = len(topics) graph = {} for t in topics: if t[0] not in graph.keys(): graph[t[0]] = set() graph[t[0]].add(t[1]) # print(graph) n_matched = len(HopcroftKarp(graph).maximum_matching()) // 2 # print(HopcroftKarp(graph).maximum_matching()) points = len(set(t[0] for t in topics)) + len(set(t[1] for t in topics)) print(n - (points - n_matched))
def solve(L): n = len(L) graph = defaultdict(set) left = set() right = set() for u, v in L: left.add(u) right.add(v) graph['l' + u].add('r' + v) sol = HopcroftKarp(graph).maximum_matching() orig = len(left) + len(right) - len(sol) / 2 return n - orig
def __init__(self, graph): self.graph = graph self.left = set(graph.keys()) self.right = set() for value in graph.values(): self.right.update(value) for vertex in self.left: for neighbour in graph[vertex]: if neighbour not in graph: graph[neighbour] = set() graph[neighbour].add(vertex) else: graph[neighbour].add(vertex) hk = HopcroftKarp(graph) self.matching = hk.maximum_matching() self.E_w = set() self.E_0 = set() self.E_1 = set()
def main(): class_size, associate_dict, manager_dict, amicable_match_dict = maximum_matching.compute_maximum_matching( ) if len(amicable_match_dict) != 2 * class_size: leftover_associate_dictionary = unmatched_dictionaries( associate_dict, amicable_match_dict) leftover_manager_dictionary = unmatched_dictionaries( manager_dict, amicable_match_dict) associate_graph = create_leftover_graph(leftover_associate_dictionary, leftover_manager_dictionary) leftover_matches_formed = HopcroftKarp( associate_graph).maximum_matching() print(leftover_matches_formed) print( "Total number of managers and associates matched where atleast one of them listed other is: " + str(len(leftover_matches_formed))) if len(amicable_match_dict) + len( leftover_matches_formed) != 2 * class_size: unmatched_associates, unmatched_managers = cannot_be_matched( amicable_match_dict, leftover_matches_formed, associate_dict, manager_dict) print(unmatched_associates, unmatched_managers) profit_matrix = matching_with_preference.matching_preference( class_size, associate_dict, manager_dict) maximum_matching.print_dictionary(associate_dict) maximum_matching.print_dictionary(manager_dict) print(kuhn_munkers.maxWeightMatching(profit_matrix)) pause() program_choices_test_data = pd.read_csv('managerchoice.csv') candidate_choices_test_data = pd.read_csv('associatechoice.csv') test_match = MatchController(program_choices_test_data, candidate_choices_test_data) test_match.start_match() results = test_match.results_dict() maximum_matching.print_dictionary(results)
def test_mainExample(self): graph = {'a': {1, 3}, 'c': {1, 3}, 'd': {3, 6}, 'h': {8}} hk = HopcroftKarp(graph) max_matching = hk.maximum_matching() self.assertTrue( max_matching == { 1: 'a', 'a': 1, 3: 'c', 'c': 3, 6: 'd', 'd': 6, 8: 'h', 'h': 8 } or max_matching == { 3: 'a', 'a': 3, 1: 'c', 'c': 1, 6: 'd', 'd': 6, 8: 'h', 'h': 8 }, 'maximum matching is incorrect')
def solve(case_index): graph = collections.defaultdict(set) n = read_int() next_line() words = [] for i in xrange(n): first, second = read_word(), read_word() words.append((first, second)) next_line() graph[first + "1"].add(second + "2") graph = dict(graph) num_firsts = len(set(i[0] for i in words)) num_seconds = len(set(i[1] for i in words)) num_match = len(HopcroftKarp(graph).maximum_matching()) / 2 return str(len(words) - (num_firsts + num_seconds - num_match))
def conf_mat(correct_class, pred_class, ts, match_func, win_len): """ - description: return confusion matrix as dictionary. Match pred_class to correct_class maximizing number of true positives. One change point can be matched only once. By now solved with maximum matching in bipartite graph: nodes of the left represents change points of correct_class and the nodes of the right represents change points of pred_class. Two nodes are connected if the distance between than is less or equal than win_len. In case of more than one solution with maximum matching is possible to select the solution with minimum distance between matched change points, but for that, the problem must be solved with dynamic programming or min-cost-max-flow. - arguments: - correct_class: list with ids indicating change points of correct classification - pred_class : list with ids indicating change points of predicted classification - win_len: correct_class[i] can be matched with pred_class[j] if abs(correct_class[i] - pred_class[j]) <= win_len """ graph = {} for l in xrange(len(correct_class)): neigh = set() for r in xrange(len(pred_class)): if match_func(correct_class[l], pred_class[r], win_len): neigh.add("r{}".format(r)) graph["l{}".format(l)] = neigh max_match = HopcroftKarp(graph).maximum_matching() conf = {} conf["tp"] = len(max_match) / 2 conf["fp"] = len(pred_class) - conf["tp"] conf["fn"] = len(correct_class) - conf["tp"] # tn = number of true not change points - number of wrong predicted change # points # tn = (number of points - number of true change points) - number of wrong # predicted change points conf["tn"] = len(ts.y) - len(correct_class) - conf["fp"] return conf
def find_matching(graph): match = HopcroftKarp(graph).maximum_matching() #print 'Done: find matching' return match
def TOPOWithPairs(GPSMap, OSMMap, GPSList, OSMList, step=0.00005, r=0.00300, threshold=0.00015, region=None, outputfile="tmp.txt", one2oneMatching=True, metaData=None): i = 0 precesion_sum = 0 recall_sum = 0 print(len(OSMList), len(GPSList.keys())) rrr = float(len(GPSList.keys())) / float(len(OSMList)) print("Overall Coverage", rrr) returnResult = [] for k, itemGPS in GPSList.iteritems(): itemOSM = OSMList[k] gpsn1, gpsn2, gpsd1, gpsd2 = itemGPS[1], itemGPS[2], itemGPS[ 3], itemGPS[4] osmn1, osmn2, osmd1, osmd2 = itemOSM[2], itemOSM[3], itemOSM[ 4], itemOSM[5] osm_start_lat, osm_start_lon = itemOSM[0], itemOSM[1] gps_start_lat, gps_start_lon = itemGPS[5], itemGPS[6] # nid = pairs[min_node] # lat = GPSMap.nodes[nid][0] # lon = GPSMap.nodes[nid][1] lat = itemOSM[0] lon = itemOSM[1] ts1 = time() marbles = GPSMap.TOPOWalk(1, step=step, r=r, direction=False, newstyle=True, nid1=gpsn1, nid2=gpsn2, dist1=gpsd1, dist2=gpsd2) # for recall holes = OSMMap.TOPOWalk(1, step=step, r=r, direction=False, newstyle=True, nid1=osmn1, nid2=osmn2, dist1=osmd1, dist2=osmd2, metaData=metaData) # remove holes in tunnel # for precision holes_bidirection = OSMMap.TOPOWalk( 1, step=step, r=r, direction=False, newstyle=True, nid1=osmn1, nid2=osmn2, dist1=osmd1, dist2=osmd2, bidirection=True, metaData=None) # don't remove holes in tunnel ts2 = time() idx_marbles = index.Index() idx_holes = index.Index() idx_holes_bidirection = index.Index() for j in range(len(marbles)): idx_marbles.insert( j, (marbles[j][0] - 0.00001, marbles[j][1] - 0.00001, marbles[j][0] + 0.00001, marbles[j][1] + 0.00001)) for j in range(len(holes)): idx_holes.insert(j, (holes[j][0] - 0.00001, holes[j][1] - 0.00001, holes[j][0] + 0.00001, holes[j][1] + 0.00001)) for j in range(len(holes_bidirection)): idx_holes_bidirection.insert( j, (holes_bidirection[j][0] - 0.00001, holes_bidirection[j][1] - 0.00001, holes_bidirection[j][0] + 0.00001, holes_bidirection[j][1] + 0.00001)) # holes_bidirection = holes # idx_holes_bidirection = idx_holes matchedNum = 0 bigraph = {} matched_marbles = [] bipartite_graph = [] cost_map = {} for marble in marbles: rr = threshold * 1.8 possible_holes = list( idx_holes_bidirection.intersection( (marble[0] - rr, marble[1] - rr, marble[0] + rr, marble[1] + rr))) for hole_id in possible_holes: hole = holes_bidirection[hole_id] ddd = distance(marble, hole) n1 = latlonNorm((marble[2], marble[3])) n2 = latlonNorm((hole[2], hole[3])) #ddd += (1.0 - abs(n1[0] * n2[0] + n1[1] * n2[1])) * threshold * 5 #ddd -= threshold / 2 #ddd = max(ddd, 0) if marble[2] != marble[3] and hole[2] != hole[3]: angle_d = 1.0 - abs(n1[0] * n2[0] + n1[1] * n2[1]) else: angle_d = 0.0 #angle_d = 0.0 if ddd < threshold and angle_d < 0.29: # 0.03 --> 15 degrees 0.13 --> 30 degrees 0.29 --> 45 degrees #cost_map[(marble, hole_id)] = ddd if marble in bigraph.keys(): bigraph[marble].add(hole_id) else: bigraph[marble] = Set([hole_id]) bipartite_graph.append((marble, hole_id, ddd)) matchedNum += 1 matched_marbles.append(marble) #break soft_matchedNum = 0 if one2oneMatching == True: matches = HopcroftKarp(bigraph).maximum_matching() matchedNum = len(matches.keys()) / 2 # for k,v in matches.iteritems(): # if (k,v) in cost_map.keys(): # soft_matchedNum += max(min(((threshold - cost_map[(k,v)]) / threshold),1.0),0.0) #matched_marbles, matched_holes, _ = BipartiteGraphMatching(bipartite_graph) #matched_holes = [(holes_bidirection[item][0], holes_bidirection[item][1]) for item in matched_holes] #matched_marbles = [(marbles[item][0], marbles[item][1]) for item in matched_marbles] # for item in HopcroftKarp(bigraph).maximum_matching().keys(): # if type(item) is not int : # matched_marbles.append(item) print(i, len(marbles), len(holes)) if len(marbles) == 0 or len(holes) == 0: continue #precesion = float(soft_matchedNum) / len(marbles) precesion = float(matchedNum) / len(marbles) # TOPO Debug #showTOPO.RenderSVG(marbles, holes, matched_marbles,matched_holes, lat, lon, 0.00300, "svg/nn"+outputfile.split('/')[-1]+"_%.6f_"%precesion+str(i)+"_"+str(lat)+"_"+str(lon)+".svg", OSMMap= OSMMap, starts=(osm_start_lat,osm_start_lon,gps_start_lat,gps_start_lon)) matchedNum = 0 bigraph = {} cost_map = {} for hole in holes: rr = threshold * 1.8 possible_marbles = list( idx_marbles.intersection( (hole[0] - rr, hole[1] - rr, hole[0] + rr, hole[1] + rr))) for marble_id in possible_marbles: marble = marbles[marble_id] ddd = distance(marble, hole) n1 = latlonNorm((marble[2], marble[3])) n2 = latlonNorm((hole[2], hole[3])) #ddd += (1.0 - abs(n1[0] * n2[0] + n1[1] * n2[1])) * threshold * 5 #ddd -= threshold / 2 #ddd = max(ddd, 0) if marble[2] != marble[3] and hole[2] != hole[3]: angle_d = 1.0 - abs(n1[0] * n2[0] + n1[1] * n2[1]) else: angle_d = 0.0 #angle_d = 0.0 if ddd < threshold and angle_d < 0.29: #cost_map[(hole, marble_id)] = ddd if hole in bigraph.keys(): bigraph[hole].add(marble_id) else: bigraph[hole] = Set([marble_id]) matchedNum += 1 #break soft_matchedNum = 0 if one2oneMatching == True: #matchedNum = len(HopcroftKarp(bigraph).maximum_matching().keys()) / 2 matches = HopcroftKarp(bigraph).maximum_matching() matchedNum = len(matches.keys()) / 2 # for k,v in matches.iteritems(): # if (k,v) in cost_map.keys(): # soft_matchedNum += max(min(((threshold - cost_map[(k,v)]) / threshold),1.0),0.0) #recall = float(soft_matchedNum) / len(holes) recall = float(matchedNum) / len(holes) precesion_sum += precesion recall_sum += recall ts3 = time() with open(outputfile, "a") as fout: fout.write( str(i) + " " + str(lat) + " " + str(lon) + " " + str(gpsn1) + " " + str(gpsn2) + " Precesion " + str(precesion) + " Recall " + str(recall) + " Avg Precesion " + str(precesion_sum / (i + 1)) + " Avg Recall " + str(recall_sum / (i + 1)) + " \n") print(i, "Precesion", precesion, "Recall", recall, "Avg Precesion", precesion_sum / (i + 1), "Avg Recall", recall_sum / (i + 1), rrr, ts2 - ts1, ts3 - ts2) returnResult.append( (lat, lon, precesion, recall, gpsn1, gpsn2, gpsd1, gpsd2)) i = i + 1 #if i > 100: # break # try: # with open(outputfile, "a") as fout: # fout.write(str(precesion_sum/i)+" "+str(recall_sum/i)+" "+str(rrr)+ " "+ str(rrr * recall_sum/i) +"\n") # except: # with open(outputfile, "a") as fout: # fout.write(str(0)+" "+str(0)+" "+str(0)+ " "+ "0.0" +"\n") #with open("TOPOResultSummary.txt","a") as fout: # fout.write(str(precesion_sum/i)+" "+str(recall_sum/i)+" "+str(rrr)+ " "+ str(rrr * recall_sum/i) +"\n") new_topoResult = TOPO121(returnResult, GPSMap) # Debug svg # for rr in returnResult: # if rr not in new_topoResult: # print("remove rr") # Popen("rm svg/*%s*.svg" % (str(rr[0])+"_"+str(rr[1])),shell=True).wait() #print(topoAvg(returnResult), len(returnResult)/float(len(OSMList))) print(topoAvg(new_topoResult), len(new_topoResult) / float(len(OSMList))) p, r = topoAvg(new_topoResult) # with open(outputfile, "a") as fout: # fout.write(str(p)+" "+str(r)+" "+str(len(new_topoResult)/float(len(OSMList)))+"\n") print("precision=" + str(p) + " overall-recall=" + str(r * len(new_topoResult) / float(len(OSMList)))) try: with open(outputfile, "a") as fout: fout.write( str(p) + " " + str(r) + " " + str(len(new_topoResult) / float(len(OSMList))) + " " + str(r * len(new_topoResult) / float(len(OSMList))) + "\n") fout.write("precision=" + str(p) + " overall-recall=" + str(r * len(new_topoResult) / float(len(OSMList)))) except: with open(outputfile, "a") as fout: fout.write( str(0) + " " + str(0) + " " + str(0) + " " + str(0) + "\n") return new_topoResult
def bottleneck(dgm1, dgm2, matching=False): """ Perform the Bottleneck distance matching between persistence diagrams. Assumes first two columns of S and T are the coordinates of the persistence points, but allows for other coordinate columns (which are ignored in diagonal matching). See the `distances` notebook for an example of how to use this. Parameters ----------- dgm1: Mx(>=2) array of birth/death pairs for PD 1 dgm2: Nx(>=2) array of birth/death paris for PD 2 matching: bool, default False if True, return matching infromation and cross-similarity matrix Returns -------- d: float bottleneck distance between dgm1 and dgm2 matching: ndarray(Mx+Nx, 3), Only returns if `matching=True` A list of correspondences in an optimal matching, as well as their distance, where: * First column is index of point in first persistence diagram, or -1 if diagonal * Second column is index of point in second persistence diagram, or -1 if diagonal * Third column is the distance of each matching """ return_matching = matching S = np.array(dgm1) M = min(S.shape[0], S.size) if S.size > 0: S = S[np.isfinite(S[:, 1]), :] if S.shape[0] < M: warnings.warn("dgm1 has points with non-finite death times;" + "ignoring those points") M = S.shape[0] T = np.array(dgm2) N = min(T.shape[0], T.size) if T.size > 0: T = T[np.isfinite(T[:, 1]), :] if T.shape[0] < N: warnings.warn("dgm2 has points with non-finite death times;" + "ignoring those points") N = T.shape[0] if M == 0: S = np.array([[0, 0]]) M = 1 if N == 0: T = np.array([[0, 0]]) N = 1 # Step 1: Compute CSM between S and T, including points on diagonal # L Infinity distance Sb, Sd = S[:, 0], S[:, 1] Tb, Td = T[:, 0], T[:, 1] D1 = np.abs(Sb[:, None] - Tb[None, :]) D2 = np.abs(Sd[:, None] - Td[None, :]) DUL = np.maximum(D1, D2) # Put diagonal elements into the matrix, being mindful that Linfinity # balls meet the diagonal line at a diamond vertex D = np.zeros((M + N, M + N)) # Upper left is Linfinity cross-similarity between two diagrams D[0:M, 0:N] = DUL # Upper right is diagonal matching of points from S UR = np.inf * np.ones((M, M)) np.fill_diagonal(UR, 0.5 * (S[:, 1] - S[:, 0])) D[0:M, N::] = UR # Lower left is diagonal matching of points from T UL = np.inf * np.ones((N, N)) np.fill_diagonal(UL, 0.5 * (T[:, 1] - T[:, 0])) D[M::, 0:N] = UL # Lower right is all 0s by default (remaining diagonals match to diagonals) # Step 2: Perform a binary search + Hopcroft Karp to find the # bottleneck distance ds = np.sort(np.unique(D.flatten()))[0:-1] # Everything but np.inf bdist = ds[-1] matching = {} while len(ds) >= 1: idx = 0 if len(ds) > 1: idx = bisect_left(range(ds.size), int(ds.size / 2)) d = ds[idx] graph = {} for i in range(D.shape[0]): graph["{}".format(i)] = { j for j in range(D.shape[1]) if D[i, j] <= d } res = HopcroftKarp(graph).maximum_matching() if len(res) == 2 * D.shape[0] and d <= bdist: bdist = d matching = res ds = ds[0:idx] else: ds = ds[idx + 1::] if return_matching: matchidx = [] for i in range(M + N): j = matching["{}".format(i)] d = D[i, j] if i < M: if j >= N: j = -1 # Diagonal match from first persistence diagram else: if j >= N: # Diagonal to diagonal, so don't include this continue i = -1 matchidx.append([i, j, d]) return bdist, np.array(matchidx) else: return bdist
def bottleneck(dgm1, dgm2, matching=False): """ Perform the Bottleneck distance matching between persistence diagrams. Assumes first two columns of S and T are the coordinates of the persistence points, but allows for other coordinate columns (which are ignored in diagonal matching). See the `distances` notebook for an example of how to use this. Parameters ----------- dgm1: Mx(>=2) array of birth/death pairs for PD 1 dgm2: Nx(>=2) array of birth/death paris for PD 2 matching: bool, default False if True, return matching infromation and cross-similarity matrix Returns -------- d: float bottleneck distance between dgm1 and dgm2 (matching, D): Only returns if `matching=True` (tuples of matched indices, (N+M)x(N+M) cross-similarity matrix) """ return_matching = matching S = np.array(dgm1) S = S[np.isfinite(S[:, 1]), :] T = np.array(dgm2) T = T[np.isfinite(T[:, 1]), :] N = S.shape[0] M = T.shape[0] # Step 1: Compute CSM between S and T, including points on diagonal # L Infinity distance Sb, Sd = S[:, 0], S[:, 1] Tb, Td = T[:, 0], T[:, 1] D1 = np.abs(Sb[:, None] - Tb[None, :]) D2 = np.abs(Sd[:, None] - Td[None, :]) DUL = np.maximum(D1, D2) # Put diagonal elements into the matrix, being mindful that Linfinity # balls meet the diagonal line at a diamond vertex D = np.zeros((N + M, N + M)) D[0:N, 0:M] = DUL UR = np.max(D) * np.ones((N, N)) np.fill_diagonal(UR, 0.5 * (S[:, 1] - S[:, 0])) D[0:N, M::] = UR UL = np.max(D) * np.ones((M, M)) np.fill_diagonal(UL, 0.5 * (T[:, 1] - T[:, 0])) D[N::, 0:M] = UL # Step 2: Perform a binary search + Hopcroft Karp to find the # bottleneck distance N = D.shape[0] ds = np.sort(np.unique(D.flatten())) bdist = ds[-1] matching = {} while len(ds) >= 1: idx = 0 if len(ds) > 1: idx = bisect_left(range(ds.size), int(ds.size / 2)) d = ds[idx] graph = {} for i in range(N): graph["%s" % i] = {j for j in range(N) if D[i, j] <= d} res = HopcroftKarp(graph).maximum_matching() if len(res) == 2 * N and d < bdist: bdist = d matching = res ds = ds[0:idx] else: ds = ds[idx + 1::] if return_matching: matchidx = [(i, matching["%i" % i]) for i in range(N)] return bdist, (matchidx, D) else: return bdist
# add identifiers to the labels to use when matching them ground_truth['id'] = 'g' + ground_truth.index.astype(str) turker_labels['id'] = 't' + turker_labels.index.astype(str) # each graph is a dictionary with the key being the id of label in ground truth, and the value being # a list of ids for labels in the turker label set that could be matched to it. binary_graph = dict(zip(ground_truth.id, [[] for i in range(len(ground_truth))])) multi_graph = dict(zip(ground_truth.id, [[] for i in range(len(ground_truth))])) # binary: for every ground truth label, find which turker labels are less than 0.5 meters away for row in ground_truth.iterrows(): match = turker_labels.apply(lambda x: haversine(x.coords, row[1].coords) < 0.0025, axis=1) binary_graph[row[1].id].extend(turker_labels.id[match].values) # compute maximum matching binary_matching = HopcroftKarp(binary_graph).maximum_matching() def precision(true_pos, false_pos): if true_pos > 0 or false_pos > 0: return true_pos / (1.0 * true_pos + false_pos) else: return float('NaN') def recall(true_pos, false_neg): if true_pos > 0 or false_neg > 0: return true_pos / (1.0 * true_pos + false_neg) else: return float('NaN') def f_measure(true_pos, false_pos, false_neg): P = precision(true_pos, false_pos)
from hopcroftkarp import HopcroftKarp T = int(raw_input()) for t in range(T): N = int(raw_input()) graph = {} aset = set() bs = set() for i in range(N): a, b = raw_input().split() b += '_' aset.add(a) bs.add(b) if a not in graph: graph[a] = set() graph[a].add(b) match = HopcroftKarp(graph).maximum_matching() r = len(match)/2 print 'Case #%d: %d' % (t+1, N+r-len(aset)-len(bs))
fst = {} sec = {} words = [] count1 = {} count2 = {} G = {} for _ in range(N): u, v = tuple(input().strip().split()) u = '1' + u v = '2' + v if u not in count1: count1[u] = 1 else: count1[u] += 1 if v not in count2: count2[v] = 1 else: count2[v] += 1 if u in G: G[u].add(v) else: G[u] = {v} H = HopcroftKarp(G).maximum_matching() answer = N - (len(count1) + len(count2) - len(H) / 2) #print() print("Case #%d: %s" % (t + 1, answer))
for neighbour in self.graph[vertex]: if (vertex in left_star and neighbour in right_star) or \ (vertex in left_plus and neighbour in right_plus): self.E_w.add((vertex, neighbour)) graph_prime = {} for vertex in left_unlabelled: graph_prime[vertex] = set([neighbour for neighbour in self.graph[vertex] if neighbour in right_unlabelled]) for vertex in right_unlabelled: graph_prime[vertex] = set([neighbour for neighbour in self.graph[vertex] if neighbour in left_unlabelled]) self.edge_part_perfect(graph_prime, left_unlabelled, right_unlabelled) return self.E_1, self.E_w, self.E_0 # g = {'a': {1, 3}, 'b': {1, 2, 4}, 'c': {1, 3}, 'd': {3, 5, 6}, 'e': {5}, 'f': {4, 7}, # 'g': {5}, 1: {'a', 'b', 'c'}, 2: {'b'}, 3: {'a', 'b', 'c'}, 4: {'b', 'f', 'e'}, # 5: {'d', 'e', 'g'}, 6: {'d'}, 7: {'f'}} # l = {'a', 'b', 'c', 'd', 'e', 'f', 'g'} # r = set(range(1, 8)) g = {'S1': {'a', 'b', 'c'}, 'S2': {'a', 'b', 'c'}, 'S3': {'a', 'b', 'c'}} C = CostaImproved(g) m = HopcroftKarp(g) maximum_matching = m.maximum_matching() E1, Ew, E0 = C.edge_partitioning() #print('Bipartite graph: ' + str(m)) print('Maximum Matching:' + str(maximum_matching)) print('one-persistent edges: ' + str(E1)) print('weakly-persistent edges: ' + str(Ew)) print('zero-persistent edges: ' + str(E0))
def solve_large(board): N = len(board) row = [True] * N col = [True] * N diag = [True] * (2 * N - 1) rdiag = [True] * (2 * N - 1) for i in xrange(N): #init flag arrays for j in xrange(N): if board[i][j] in ['x', 'o']: row[i] = False col[j] = False if board[i][j] in ['+', 'o']: diag[i + j] = False rdiag[i - j + N - 1] = False #construct bipartite graph graph = {} mid = N - 1 for i in xrange(2 * N - 1): upper_bound = mid - abs(i - mid) edges = set() for j in xrange(i % 2, upper_bound + 1, 2): edges.add('b' + str(mid - j)) edges.add('b' + str(mid + j)) graph[i] = edges #black out already used places for '+' (or 'o') for i in xrange(2 * N - 1): if not diag[i]: del graph[i] if not rdiag[i]: for node in graph: graph[node].discard('b' + str(i)) #get maximum matching max_matching = HopcroftKarp(graph).maximum_matching() for x in max_matching: if type(x) == int: continue rdiag_no = int(x[1:]) diag_no = max_matching[x] i = (diag_no + rdiag_no + 1 - N) / 2 j = diag_no - i if board[i][j] == '.': board[i][j] = '+' elif board[i][j] == 'x': board[i][j] = 'o' else: print 'maximum matching put + to an already o or + place, exitting...' exit() diag[diag_no] = rdiag[rdiag_no] = False #now put x to the board for i in xrange(N): if row[i]: for j in xrange(N): if col[j]: if board[i][j] == '.': board[i][j] = 'x' elif board[i][j] == '+': board[i][j] = 'o' else: print 'try to put x to an already o or x place, exitting...' exit() row[i] = col[j] = False break return
# https://code.google.com/codejam/contest/11254486/dashboard#s=p2 from hopcroftkarp import HopcroftKarp from collections import defaultdict filein = open('20161BC.in', 'r') fileout = open('20161BC.out', 'w') T = int(filein.readline()) for t in range(T): N = int(filein.readline()) graph = defaultdict(set) X, Y = set(), set() for i in range(N): x, y = filein.readline().split(' ') X.add(x) Y.add(y) graph[x].add(y) mm = HopcroftKarp(dict(graph)).maximum_matching() ans = N - (len(X) + len(Y) - len(mm)) - len(mm) / 2 fileout.write('Case #%d: %s \n' % (t + 1, str(ans))) filein.close() fileout.close()