class Tree: def __init__(self, directed=False, weighted=False): self.directed = directed self.weighted = weighted self.tree = {} self.vertex_num = 0 self.vertex = [] self.components = UnionFind() def add_edge(self, origin, destiny, weight=0): def add_vertex(self, vertex): if not vertex in self.tree.keys(): self.components.add(vertex) self.tree[vertex] = {} self.vertex_num += 1 self.vertex.append(vertex) if not origin in self.tree.keys(): add_vertex(self, origin) if not destiny in self.tree.keys(): add_vertex(self, destiny) if self.components.connected(origin, destiny): raise Exception("Cannot add edge, would create a cicle") self.tree[origin][destiny] = weight if not self.directed: self.tree[destiny][origin] = weight self.components.union(origin, destiny)
def kruskalMST(self): self.generatePQ() uf = UnionFind() uf.WeightedQuickUnionUF(self.N) self.mst = [None] * self.N index = 0 while len(self.PQ) != 0: edge = heapq.heappop(self.PQ) if (uf.connected(edge.u, edge.v)): continue uf.unify(edge.v, edge.u) self.mstCost += edge.cost self.mst[index] = edge index += 1 if uf.size1(0) == self.N: break mstExists = (uf.size1(0) == self.N) solved = True if solved: return self.mstCost else: return None
def kruskal(g, w): uf = UnionFind(g.keys()) w = sorted(w, key=lambda x: w[x]) edges = list() for edge in w: a, b = edge if not uf.connected(a, b): uf.union(a, b) edges.append(edge) if len(edges) == len(g) - 1: break return edges
def mspEdges(self, heuristicFn): A = [] N = len(self.nodes) uf = UnionFind(N) weights = self.generate_weights(heuristicFn) order = argsort(weights) for i in order: (u, v) = self.edges[i] if not uf.connected(u, v): A.append((u, v)) uf.union(u, v) return A
def mspEdges(self, heuristicFn): A = [] N = len(self.nodes) uf = UnionFind(N) weights = self.generate_weights(heuristicFn) order = argsort(weights) for i in order: (u,v) = self.edges[i] if not uf.connected(u,v): A.append((u,v)) uf.union(u,v) return A
def cluster(edges, start_at): uf = UnionFind() sortede = sorted(edges, key=lambda x: x[3]) for k in range(1, 501): uf.add(k) for _, u, v, w in sortede: if len(list(uf.components())) == 4: break elif not uf.connected(u, v): uf.union(u, v) find_minimal(uf, edges)
def Clustering(nodes): UnionNodes = UnionFind(nodes.keys()) for node in tqdm(nodes): for neighbour in getNeiborhood(node): if neighbour not in nodes: continue if not UnionNodes.connected(node, neighbour): UnionNodes.union(node, neighbour) return UnionNodes
def prim(g, w, start): edges = list() uf = UnionFind(g.keys()) q = list() for child in g[start]: heappush(q, [w[(start, child)], (start, child)]) while len(edges) < len(g) - 1: weight, (a, b) = heappop(q) if not uf.connected(a, b): edges.append((a, b)) uf.union(a, b) for child in g[b]: if child != a: heappush(q, [w[(b, child)], (b, child)]) return edges
def cluster(nodes): uf = UnionFind() one_diff, two_diff = one_two_away() for v in nodes: uf.add(v) for vindex, v in enumerate(nodes): # squash all the nodes with distance 1 away into me od = [(v ^ i) for i in one_diff] td = [(v ^ i) for i in two_diff] for d in od + td: if d in nodes and not uf.connected(v, d): uf.union(v, d) print("smashed", v, d) print(len(list(uf.components())))
def _kruskal(self): graph = self.graph edge_list = sorted(self.edge_list) uf = UnionFind(list(graph.keys())) tree = Tree(weighted=True) minimum_cost = 0 for cost, u, v in edge_list: if uf.n_comps == 1: break if not uf.connected(u, v): uf.union(u, v) minimum_cost += cost tree.add_edge(u, v, cost) return minimum_cost, tree
class GameState: """ Stores information representing the current state of a game of hex, namely the board and the current turn. Also provides functions for playing game. """ # dictionary associating numbers with players # PLAYERS = {"none": 0, "white": 1, "black": 2} # move value of -1 indicates the game has ended so no move is possible # GAME_OVER = -1 # represent edges in the union find structure for detecting the connection # for player 1 Edge1 is high and EDGE2 is low # for player 2 Edge1 is left and EDGE2 is right # neighbor_patterns = ((-1, 0), (0, -1), (-1, 1), (0, 1), (1, 0), (1, -1)) def __init__(self, size): """ Initialize the game board and give white first turn. Also create our union find structures for win checking. Args: size (int): The board size """ self.size = size self.to_play = GameMeta.PLAYERS['white'] self.board = zeros((size, size)) self.board = int_(self.board) self.white_played = 0 self.black_played = 0 self.white_groups = UnionFind() self.black_groups = UnionFind() self.white_groups.set_ignored_elements( [GameMeta.EDGE1, GameMeta.EDGE2]) self.black_groups.set_ignored_elements( [GameMeta.EDGE1, GameMeta.EDGE2]) def play(self, cell: tuple) -> None: """ Play a stone of the player that owns the current turn in input cell. Args: cell (tuple): row and column of the cell """ if self.to_play == GameMeta.PLAYERS['white']: self.place_white(cell) self.to_play = GameMeta.PLAYERS['black'] elif self.to_play == GameMeta.PLAYERS['black']: self.place_black(cell) self.to_play = GameMeta.PLAYERS['white'] def get_num_played(self) -> dict: return {'white': self.white_played, 'black': self.black_played} def get_white_groups(self) -> dict: """ Returns (dict): group of white groups for unionfind check """ return self.white_groups.get_groups() def get_black_groups(self) -> dict: """ Returns (dict): group of white groups for unionfind check """ return self.black_groups.get_groups() def place_white(self, cell: tuple) -> None: """ Place a white stone regardless of whose turn it is. Args: cell (tuple): row and column of the cell """ if self.board[cell] == GameMeta.PLAYERS['none']: self.board[cell] = GameMeta.PLAYERS['white'] self.white_played += 1 else: raise ValueError("Cell occupied") # if the placed cell touches a white edge connect it appropriately if cell[0] == 0: self.white_groups.join(GameMeta.EDGE1, cell) if cell[0] == self.size - 1: self.white_groups.join(GameMeta.EDGE2, cell) # join any groups connected by the new white stone for n in self.neighbors(cell): if self.board[n] == GameMeta.PLAYERS['white']: self.white_groups.join(n, cell) def place_black(self, cell: tuple) -> None: """ Place a black stone regardless of whose turn it is. Args: cell (tuple): row and column of the cell """ if self.board[cell] == GameMeta.PLAYERS['none']: self.board[cell] = GameMeta.PLAYERS['black'] self.black_played += 1 else: raise ValueError("Cell occupied") # if the placed cell touches a black edge connect it appropriately if cell[1] == 0: self.black_groups.join(GameMeta.EDGE1, cell) if cell[1] == self.size - 1: self.black_groups.join(GameMeta.EDGE2, cell) # join any groups connected by the new black stone for n in self.neighbors(cell): if self.board[n] == GameMeta.PLAYERS['black']: self.black_groups.join(n, cell) def would_lose(self, cell: tuple, color: int) -> bool: """ Return True is the move indicated by cell and color would lose the game, False otherwise. """ connect1 = False connect2 = False if color == GameMeta.PLAYERS['black']: if cell[1] == 0: connect1 = True elif cell[1] == self.size - 1: connect2 = True for n in self.neighbors(cell): if self.black_groups.connected(GameMeta.EDGE1, n): connect1 = True elif self.black_groups.connected(GameMeta.EDGE2, n): connect2 = True elif color == GameMeta.PLAYERS['white']: if cell[0] == 0: connect1 = True elif cell[0] == self.size - 1: connect2 = True for n in self.neighbors(cell): if self.white_groups.connected(GameMeta.EDGE1, n): connect1 = True elif self.white_groups.connected(GameMeta.EDGE2, n): connect2 = True return connect1 and connect2 def turn(self) -> int: """ Return the player with the next move. """ return self.to_play def set_turn(self, player: int) -> None: """ Set the player to take the next move. Raises: ValueError if player turn is not 1 or 2 """ if player in GameMeta.PLAYERS.values( ) and player != GameMeta.PLAYERS['none']: self.to_play = player else: raise ValueError('Invalid turn: ' + str(player)) @property def winner(self) -> int: """ Return a number corresponding to the winning player, or none if the game is not over. """ if self.white_groups.connected(GameMeta.EDGE1, GameMeta.EDGE2): return GameMeta.PLAYERS['white'] elif self.black_groups.connected(GameMeta.EDGE1, GameMeta.EDGE2): return GameMeta.PLAYERS['black'] else: return GameMeta.PLAYERS['none'] def neighbors(self, cell: tuple) -> list: """ Return list of neighbors of the passed cell. Args: cell tuple): """ x = cell[0] y = cell[1] return [(n[0] + x, n[1] + y) for n in GameMeta.NEIGHBOR_PATTERNS if (0 <= n[0] + x < self.size and 0 <= n[1] + y < self.size)] def moves(self) -> list: """ Get a list of all moves possible on the current board. """ moves = [] for y in range(self.size): for x in range(self.size): if self.board[x, y] == GameMeta.PLAYERS['none']: moves.append((x, y)) return moves def __str__(self): """ Print an ascii representation of the game board. Notes: Used for gtp interface """ white = 'W' black = 'B' empty = '.' ret = '\n' coord_size = len(str(self.size)) offset = 1 ret += ' ' * (offset + 1) for x in range(self.size): ret += chr(ord('A') + x) + ' ' * offset * 2 ret += '\n' for y in range(self.size): ret += str(y + 1) + ' ' * (offset * 2 + coord_size - len(str(y + 1))) for x in range(self.size): if self.board[x, y] == GameMeta.PLAYERS['white']: ret += white elif self.board[x, y] == GameMeta.PLAYERS['black']: ret += black else: ret += empty ret += ' ' * offset * 2 ret += white + "\n" + ' ' * offset * (y + 1) ret += ' ' * (offset * 2 + 1) + (black + ' ' * offset * 2) * self.size return ret
class Map: # cities = {} # _loops = [] # _borders = [] # loops = UnionFind() # _print: bool = False def __init__(self, cities_data, data_limit: int = 0, print: bool = False): self.cities = {} self._loops = [] self._borders = [] self.loops = UnionFind() limit = data_limit self._print = print df = pd.read_csv(cities_data) upper = len(df) if limit != 0: upper = limit df = df[0:upper] for row in df.iterrows(): city = City(row[1].CityId, row[1].X, row[1].Y) self.cities[city.id] = city self._create_loops() def _create_loops(self): points = [] g_cities = nx.DiGraph() for city in self.cities: city = self.cities.get(city) g_cities.add_node('f-' + str(city.id), bipartite=0) g_cities.add_node('t-' + str(city.id), bipartite=1) points.append([city.x, city.y]) points = np.array(points) vor = Voronoi(points, incremental=True) for point in vor.ridge_points: self.cities[point[0]].add_neighbor(self.cities[point[1]]) self.cities[point[1]].add_neighbor(self.cities[point[0]]) g_cities.add_edge('f-' + str(self.cities[point[0]]), 't-' + str(self.cities[point[1]])) g_cities.add_edge('f-' + str(self.cities[point[1]]), 't-' + str(self.cities[point[0]])) temp = bipartite.maximum_matching(g_cities) print(temp) del g_cities islands = nx.DiGraph() i = 0 for key, value in temp.items(): # connect cities ... self.cities[int(key[2:])].connect_to(self.cities[int(value[2:])]) islands.add_edge(self.cities[int(key[2:])], self.cities[int(value[2:])]) i += 1 if (i >= temp.__len__() / 2): break for i, c in enumerate(nx.recursive_simple_cycles(islands)): # for i, c in enumerate(nx.simple_cycles(islands)): loop = Loop(c, i) self._loops.append(loop) self.loops.add(i) # plt.subplot(121) # nx.draw(islands, with_labels=True) # plt.savefig('temp_diagram.png') # plt.show() def loops_borders(self): temp_h = [] n = len(self.loops) for i in range(n): for j in range(i + 1, n): temp_h = self._loops[i].find_border(self._loops[j], temp_h) return temp_h def merge_loops(self): city_pairs = self.loops_borders() while (city_pairs.__len__() > 0): cp = hq.heappop(city_pairs) if (not (self.loops.connected(cp[1].loop_id, cp[2].loop_id))): # connect loops if (self.merge_node(cp[1], cp[2])): self.loops.union(cp[1].loop_id, cp[2].loop_id) def merge_node(self, c1: City, c2: City): p = c1 q = c2 if (self.is_revers(c1, c2)): p = c2 q = c1 self.connect(q.prev, p.next) self.connect(p, q) return True def connect(self, p: City, q: City) -> bool: p.next = q q.prev = p if (self._print): print(str(p.id) + ' --> ' + str(q.id)) def is_revers(self, c1: City, c2: City): dist_12 = c2.prev.sqr_dist_to(c1.next) dist_21 = c1.prev.sqr_dist_to(c2.next) return dist_12 > dist_21 def print_loops(self): print('loops ...') for loop in self._loops: print('------------') for vertex in loop.cities: print( str(loop.cities.get(vertex)) + '\tEnergy: ' + str(loop.cities.get(vertex).energy)) def print_path(self): current_city = self.cities[0] current_energy = 10 dist = 0 min_enrg = 10 while True: d = current_city.dist_to(current_city.next) if (min_enrg > current_energy): min_enrg = current_energy if (current_energy <= 0): d = d * 1.1 dist += d print(str(current_city.id)) # print(str(current_city.id)+'\tE: '+str(current_energy)) current_city = current_city.next if (current_city.next == self.cities[0]): print(current_city.id) break current_energy += -1 if (current_city.is_prime): current_energy = 10 print('Distance: ' + str(dist)) print('Minimum Energy:' + str(min_enrg)) def save_path(self, file_name: str = "myFile.csv"): f = open(file_name, "w") f.write('Path\n') current_city = self.cities[0] while True: f.write(str(current_city.id) + '\n') current_city = current_city.next if (current_city.next == self.cities[0]): f.write(str(current_city.id) + '\n') break f.write('0\n') def save_paths(self, file_name: str = "myFile.csv"): f = open(file_name, "w") f.write('Path\n') current_city = self.cities[0] current_energy = 10 dist = 0 min_enrg = 10 while True: d = current_city.dist_to(current_city.next) if (min_enrg > current_energy): min_enrg = current_energy if (current_energy <= 0): d = d * 1.1 dist += d f.write(str(current_city.id) + '\n') current_city = current_city.next if (current_city.next == self.cities[0]): f.write(str(current_city.id) + '\n') break current_energy += -1 if (current_city.is_prime): current_energy = 10 f.write('0\n') print('Distance: ' + str(dist)) return {'totalDist': dist, 'minEnergy': min_enrg}