def agglomerative_l_method(X, method='ward'): # library: fastcluster merge_hist = linkage(X, method=method, metric='euclidean', preserve_input=True) # reorder to be x [2->N] num_groups = [i for i in range(2, len(X) + 1)] merge_dist = list(reversed([each[2] for each in merge_hist])) cluster_count = refined_l_method(num_groups, merge_dist) # print('refined_l_method time:', end_time - start_time) # print('cluster_count:', cluster_count) # make clusters by merging them according to merge_hist disjoint = DisjointSet(len(X)) for a, b, _, _ in islice(merge_hist, 0, len(X) - cluster_count): a, b = int(a), int(b) disjoint.join(a, b) # get cluster name for each instance belong_to = [disjoint.parent(i) for i in range(len(X))] # print('belong_to:', belong_to) # counter = Counter(belong_to) # print('belong_to:', counter) # rename the cluster name to be 0 -> cluster_count - 1 cluster_map = {} cluster_name = 0 belong_to_renamed = [] for each in belong_to: if not each in cluster_map: cluster_map[each] = cluster_name cluster_name += 1 belong_to_renamed.append(cluster_map[each]) # print('belong_to_renamed:', belong_to_renamed) centroids = get_centroids(X, belong_to_renamed) # print('centroids:', centroids) return Result(belong_to_renamed, centroids)
def recorridoKruskal(self): grafoV = Contenedor_particulas.DiccionarioVelocidades(self) grafoNormal = Contenedor_particulas.Diccionario(self) Kruskal = dict() #Se define el grafo resultante #Se define una cola de prioridad (Lista ordenada) colaP = PriorityQueue() for orig in grafoV.keys(): for value in grafoV[orig]: vel = value[0] * -1 dest = (value[1], value[2]) formato = (vel, orig, dest) colaP.put(formato) #Entra a la cola de prioridad lista = [] #definicion del disjoint set for key in grafoNormal.keys(): lista.append(key) #make set ds = DisjointSet(lista) #mientras la lista ordenada no este vacia while not colaP.empty(): print(ds.get()) #Tomar la arista con el menor tiempo de la lista ordenada y eliminar arista = colaP.get() origenREAL = arista[1] destinoREAL = arista[2] print("Arista: ", arista) aristaDestino = (arista[0], arista[2]) #si la tupla origen y la tupla destino no estan en el mismo "set" de todo el disjoint set if ds.find(origenREAL) != ds.find(destinoREAL): #agregar la arista al grafo resultante if origenREAL in Kruskal: Kruskal[origenREAL].append(aristaDestino) else: Kruskal[origenREAL] = [aristaDestino] #unir los conjuntos donde se encuentren el OrigenREAL, y el DestinoREAL ds.union(origenREAL, destinoREAL) print(ds.get()) print("\n\nRecorrido de Kruskal\n") pprint(Kruskal) return Kruskal
def fit(self, X, max_merge_dist): self.X = X self.max_merge_dist = max_merge_dist merge_hist = linkage(X, method='ward', metric='euclidean', preserve_input=True) disjoint = DisjointSet(len(X)) # _, _, merge_dists, _ = list(zip(*merge_hist)) # print('merge_dists:', merge_dists) for a, b, merge_dist, _ in merge_hist: if merge_dist > max_merge_dist: break a, b = int(a), int(b) disjoint.join(a, b) belong_to = [disjoint.parent(i) for i in range(len(X))] # rename the cluster name to be 0 -> cluster_count - 1 cluster_map = {} cluster_name = 0 belong_to_renamed = [] for each in belong_to: if not each in cluster_map: cluster_map[each] = cluster_name cluster_name += 1 belong_to_renamed.append(cluster_map[each]) # print('belong_to_renamed:', belong_to_renamed) centroids, cluster_member_cnt = self.get_centroids(X, belong_to_renamed) self.cluster_centers_ = centroids # print('centroids:', centroids) # print('cluster_member_cnt:', cluster_member_cnt) return centroids, cluster_member_cnt
def main(): elems = range(1, 100) d = DisjointSet(elems) d.union(1, 2, 5) print(d.findSet(1)) print(d.findSet(2)) print(d.findSet(5)) print(d.findSet(3))
def __init__(self, w, h, initial_open=0.40): """ >>> caf = CaveFactory(80, 45, 0.41) >>> caf.gen_map() >>> caf.print_grid() """ self.height = h self.width = w self.area = h * w self.map = [] self.ds = DisjointSet() self.up_loc = 0 self.center_pt = (int(self.height / 2), int(self.width / 2)) self._gen_initial_map(initial_open)
class CaveFactory: def __init__(self, w, h, initial_open=0.40): """ >>> caf = CaveFactory(80, 45, 0.41) >>> caf.gen_map() >>> caf.print_grid() """ self.height = h self.width = w self.area = h * w self.map = [] self.ds = DisjointSet() self.up_loc = 0 self.center_pt = (int(self.height / 2), int(self.width / 2)) self._gen_initial_map(initial_open) def print_grid(self): for r in range(0, self.height): for c in range(0, self.width): if self.map[r][c] in (WALL, PERM_WALL): print '#', else: print '.', print def gen_map(self): for r in range(1, self.height - 1): for c in range(1, self.width - 1): wall_count = self._adj_wall_count(r, c) if self.map[r][c] == FLOOR: if wall_count > 5: self.map[r][c] = WALL elif wall_count < 4: self.map[r][c] = FLOOR self._join_rooms() return self.map # make all border squares walls # This could be moved to a superclass def _set_border(self): for j in range(0, self.height): self.map[j][0] = PERM_WALL self.map[j][self.width - 1] = PERM_WALL for j in range(0, self.width): self.map[0][j] = PERM_WALL self.map[self.height - 1][j] = PERM_WALL def _gen_initial_map(self, initial_open): for r in range(0, self.height): row = [] for c in range(0, self.width): row.append(WALL) self.map.append(row) open_count = int(self.area * initial_open) self._set_border() while open_count > 0: rand_r = randrange(1, self.height - 1) rand_c = randrange(1, self.width - 1) if self.map[rand_r][rand_c] == WALL: self.map[rand_r][rand_c] = FLOOR open_count -= 1 def _adj_wall_count(self, sr, sc): count = 0 for r in (-1, 0, 1): for c in (-1, 0, 1): if self.map[(sr + r)][sc + c] != FLOOR and not (r == 0 and c == 0): count += 1 return count def _join_rooms(self): # divide the square into equivalence classes for r in range(1, self.height - 1): for c in range(1, self.width - 1): if self.map[r][c] == FLOOR: self._union_adj_sqr(r, c) all_caves = self.ds.split_sets() for cave in all_caves.keys(): self._join_points(all_caves[cave][0]) def _join_points(self, pt1): while True: direction = self._get_tunnel_dir(pt1, self.center_pt) move = randrange(0, 3) if move == 0: next_pt = (pt1[0] + direction[0], pt1[1]) elif move == 1: next_pt = (pt1[0], pt1[1] + direction[1]) else: next_pt = (pt1[0] + direction[0], pt1[1] + direction[1]) if self._stop_drawing(pt1, next_pt, self.center_pt): return root1 = self.ds.find(next_pt) root2 = self.ds.find(pt1) if root1 != root2: self.ds.union(root1, root2) self.map[next_pt[0]][next_pt[1]] = FLOOR pt1 = next_pt def _stop_drawing(self, pt, npt, cpt): if self.ds.find(npt) == self.ds.find(cpt): return 1 if self.ds.find(pt) != self.ds.find(npt) \ and self.map[npt[0]][npt[1]] == FLOOR: return 1 else: return 0 @staticmethod def _get_tunnel_dir(pt1, pt2): if pt1[0] < pt2[0]: h_dir = +1 elif pt1[0] > pt2[0]: h_dir = -1 else: h_dir = 0 if pt1[1] < pt2[1]: v_dir = +1 elif pt1[1] > pt2[1]: v_dir = -1 else: v_dir = 0 return h_dir, v_dir def _union_adj_sqr(self, sr, sc): loc = (sr, sc) for r in (-1, 0): for c in (-1, 0): nloc = (sr + r, sc + c) if self.map[nloc[0]][nloc[1]] == FLOOR: root1 = self.ds.find(loc) root2 = self.ds.find(nloc) if root1 != root2: self.ds.union(root1, root2)