def fully_grown_edge(self, edge, aV, pV, *args, **kwargs): ''' Performs union of two clusters (belonging to aV and pV vertices) on a fully grown edge if its eligeable. Additionally applies adoption of base-trees, saves root_node of cluster. ''' aC = self.find_vertex_cluster(aV) pC = self.find_vertex_cluster(pV) if self.edge_growth_choices(edge, aV, pV, aC, pC): root_node = self.eg.adoption(aV, pV, aC, pC) if pC.size < aC.size: aC, pC = pC, aC if self.print_steps: if aC.cID not in self.mstr: self.mstr[aC.cID] = pr.print_graph(self.graph, [aC], return_string=True) if pC.cID not in self.mstr: self.mstr[pC.cID] = pr.print_graph(self.graph, [pC], return_string=True) self.mstr[pC.cID] += "\n" + self.mstr[aC.cID] self.mstr.pop(aC.cID) self.union_clusters(pC, aC) pC.boundary[0].extend(aC.boundary[0]) pC.root_node = root_node
def grow_clusters(self, method="tree", start_bucket=0): if self.print_steps: pr.print_graph(self.graph) self.uf_plot.waitforkeypress() if self.plot else input( "Press any key to continue...") for bucket_i, bucket in enumerate(self.graph.buckets[start_bucket:], start_bucket): if bucket_i > self.graph.maxbucket: # Break from upper buckets if top bucket has been reached. if self.uf_plot is not None or self.print_steps: pr.printlog("Max bucket number reached.") self.uf_plot.waitforkeypress() if self.plot else input() break if not bucket: # no need to check empty bucket continue if self.print_steps: pr.printlog( "\n############################ GROW ############################" + f"\nGrowing bucket {bucket_i} of {self.graph.maxbucket}: {bucket}" + f"\nRemaining buckets: {self.graph.buckets[bucket_i + 1 : self.graph.maxbucket + 1]}, {self.graph.wastebasket}\n" ) self.uf_plot.waitforkeypress() self.list_grow_bucket(bucket, bucket_i) if self.print_steps: pr.print_graph(self.graph, printmerged=0) if self.plot: self.uf_plot.ax.set_xlabel("") if not self.plot_growth and not self.print_steps: txt = "" if self.print_steps else f"Growing bucket #{bucket_i}/{self.graph.maxbucket}" self.uf_plot.draw_plot(txt) if self.plot: if self.print_steps: pr.print_graph(self.graph) if self.plot_growth: pr.printlog("Clusters grown.") self.uf_plot.waitforkeypress()
def grow_clusters(self, method="list", start_bucket=0): if self.print_steps: pr.print_graph(self.graph) self.uf_plot.waitforkeypress() if self.plot else input("Press any key to continue...") bucket_i = 0 support = 0 bucket = self.graph.buckets[support] while bucket: bucket = sorted(bucket, key=lambda x: x.size) if self.print_steps: pr.printlog( "\n############################ GROW ############################" + f"\nGrowing bucket {bucket_i} of {self.graph.maxbucket}: {bucket}" + f"\nRemaining buckets: {self.graph.buckets[bucket_i + 1 : self.graph.maxbucket + 1]}, {self.graph.wastebasket}\n" ) self.uf_plot.waitforkeypress() self.list_grow_bucket(bucket, support) if self.print_steps: pr.print_graph(self.graph, printmerged=0) if self.plot: self.uf_plot.ax.set_xlabel("") if not self.plot_growth and not self.print_steps: txt = "" if self.print_steps else f"Growing bucket #{bucket_i}/{self.graph.maxbucket}" self.uf_plot.draw_plot(txt) self.graph.buckets[support] = [] bucket_i += 1 support = 1 - support bucket = self.graph.buckets[support] if self.plot: if self.print_steps: pr.print_graph(self.graph) if self.plot_growth: pr.printlog("Clusters grown.") self.uf_plot.waitforkeypress()
def list_grow_bucket(self, bucket, bucket_i): fusion, place = [], [] # Initiate Fusion list while bucket: # Loop over all clusters in the current bucket\ cluster = find_cluster_root(bucket.pop()) if cluster.bucket == bucket_i and cluster.support == bucket_i % 2: # Check that cluster is not already in a higher bucket place.append(cluster) # Set boudary cluster.boundary = [[], cluster.boundary[0]] # Grow cluster support for bucket placement cluster.support = 1 - cluster.support # for vertex, new_edge, new_vertex in cluster.boundary[1]: while cluster.boundary[1]: vertex, new_edge, new_vertex = cluster.boundary[1].pop() # Grow boundaries by half-edge if new_edge.support != 2: new_edge.support += 1 if new_edge.support == 2: # Apped to fusion list of edge fully grown fusion.append((vertex, new_edge, new_vertex)) else: # Half grown edges are added immediately to new boundary cluster.boundary[0].append( (vertex, new_edge, new_vertex)) if self.plot: self.uf_plot.add_edge(new_edge, vertex) if self.plot_growth: self.uf_plot.draw_plot(str(cluster) + " grown.") if self.print_steps: mstr = {} for base_vertex, edge, grow_vertex in fusion: base_cluster = find_cluster_root(base_vertex.cluster) grow_cluster = find_cluster_root(grow_vertex.cluster) if grow_cluster is None: # Fully grown edge. New vertex is on the old boundary. Find new boundary on vertex base_cluster.add_vertex(grow_vertex) self.cluster_new_vertex(base_cluster, grow_vertex, self.plot_growth) elif grow_cluster is base_cluster: # Edge grown on itself. This cluster is already connected. Cut half-edge edge.support -= 1 if self.plot: self.uf_plot.add_edge(edge, base_vertex) else: # Clusters merge by weighted union if grow_cluster.size < base_cluster.size: # apply weighted union base_cluster, grow_cluster = grow_cluster, base_cluster if self.print_steps: # Keep track of which clusters are merged into one if base_cluster.cID not in mstr: mstr[base_cluster.cID] = pr.print_graph( self.graph, [base_cluster], return_string=True) if grow_cluster.cID not in mstr: mstr[grow_cluster.cID] = pr.print_graph( self.graph, [grow_cluster], return_string=True) mstr[grow_cluster.cID] += "\n" + mstr[base_cluster.cID] mstr.pop(base_cluster.cID) union_clusters(grow_cluster, base_cluster, self.size) grow_cluster.boundary[0].extend(base_cluster.boundary[0]) if self.print_steps: pr.printlog("") for cID, string in mstr.items(): pr.printlog( f"B:\n{string}\nA:\n{pr.print_graph(self.graph, [self.graph.C[cID]], return_string=True)}\n" ) # Put clusters in new buckets. Some will be added double, but will be skipped by the new_boundary check for cluster in place: cluster = find_cluster_root(cluster) cluster_place_bucket(self.graph, cluster) if self.plot and not self.plot_growth: self.uf_plot.draw_plot("Clusters merged")
def list_grow_bucket(self, bucket, bucket_i): fusion, place = [], [] # Initiate Fusion list while bucket: # Loop over all clusters in the current bucket\ cluster = find_cluster_root(bucket.pop()) if cluster.bucket == bucket_i and cluster.support == bucket_i % 2: # Check that cluster is not already in a higher bucket place.append(cluster) # Set boudary cluster.boundary = [[], cluster.boundary[0]] # Grow cluster support for bucket placement cluster.support = 1 - cluster.support # for vertex, new_edge, new_vertex in cluster.boundary[1]: while cluster.boundary[1]: vertex, new_edge, new_vertex = cluster.boundary[1].pop() # Grow boundaries by half-edge if new_edge.support != 2: new_edge.support += 1 if new_edge.support == 2: # Apped to fusion list of edge fully grown fusion.append((vertex, new_edge, new_vertex)) else: # Half grown edges are added immediately to new boundary cluster.boundary[0].append((vertex, new_edge, new_vertex)) if self.plot: self.uf_plot.add_edge(new_edge, vertex) if self.plot_growth: self.uf_plot.draw_plot(str(cluster) + " grown.") if self.print_steps: mstr = {} merging = [] for baseV, edge, growV in fusion: baseC = find_cluster_root(baseV.cluster) growC = find_cluster_root(growV.cluster) # Fully grown edge. New vertex is on the old boundary. Find new boundary on vertex if growC is None: baseC.add_vertex(growV) self.cluster_new_vertex(baseC, growV, self.plot_growth) # Edge grown on itself. This cluster is already connected. Cut half-edge elif growC is baseC: edge.support -= 1 if self.plot: self.uf_plot.add_edge(edge, baseV) # Append to merging list, list of edges between clusters else: merging.append((baseC, baseV, edge, growV, growC)) if baseC.tempparent is not growC: baseC.tempparent = growC baseC.cons += 1 growC.cons += 1 # Initiate subbucket for merging cluster edges, ordered by cluster connection degeneracy merge_length = 10 con_buckets = [[] for _ in range(merge_length)] for baseC, baseV, edge, growV, growC in merging: count = baseC.cons + growC.cons - 2 if count >= merge_length: count = merge_length - 1 con_buckets[count].append((baseV, edge, growV)) # Connect subbuckets, starting from lowest subbucket for con_bucket in con_buckets: for baseV, edge, growV in con_bucket: baseC = find_cluster_root(baseV.cluster) growC = find_cluster_root(growV.cluster) # Edge grown on itself. This cluster is already connected. Cut half-edge if growC is baseC: edge.support -= 1 if self.plot: self.uf_plot.add_edge(edge, baseV) # Merge clusters by union else: # apply weighted union if growC.size < baseC.size: baseC, growC = growC, baseC # Keep track of which clusters are merged into one if self.print_steps: if baseC.cID not in mstr: mstr[baseC.cID] = pr.print_graph(self.graph, [baseC], return_string=True) if growC.cID not in mstr: mstr[growC.cID] = pr.print_graph(self.graph, [growC], return_string=True) mstr[growC.cID] += "\n" + mstr[baseC.cID] mstr.pop(baseC.cID) union_clusters(growC, baseC) growC.boundary[0].extend(baseC.boundary[0]) growC.cons = 0 growC.tempparent = growC if self.print_steps: pr.printlog("") for cID, string in mstr.items(): pr.printlog(f"B:\n{string}\nA:\n{pr.print_graph(self.graph, [self.graph.C[cID]], return_string=True)}\n") # Put clusters in new buckets. Some will be added double, but will be skipped by the new_boundary check for cluster in place: cluster = find_cluster_root(cluster) cluster_place_bucket(self.graph, cluster) if self.plot and not self.plot_growth: self.uf_plot.draw_plot("Clusters merged")
def grow_clusters( graph_t, uft, uf_plot_t, graph_l, ufl, uf_plot_l, plot_growth=0, print_steps=0, ): """ Grows the clusters, and merges them until there are no uneven clusters left. Starting from the lowest bucket, clusters are popped from the list and grown with {grow_cluster}. Due to the nature of how clusters are appended to the buckets, a cluster needs to be checked for 1) root level 2) bucket level and 3) parity before it can be grown. """ for bucket_i, (bucket_t, bucket_l) in enumerate(zip(graph_t.buckets, graph_l.buckets)): if bucket_i > max([graph_t.maxbucket, graph_l.maxbucket]): break if bucket_t == [] and bucket_l == []: continue if print_steps and bucket_t != []: pr.printlog( "\n############################ GROW TREE ############################" + f"\nGrowing bucket {bucket_i} of {graph_t.maxbucket}: {bucket_t}" + f"\nRemaining buckets: {graph_t.buckets[bucket_i + 1 : graph_t.maxbucket + 1]}, {graph_t.wastebasket}\n" ) uf_plot_t.waitforkeypress() uft.tree_grow_bucket_full(bucket_t, bucket_i) uf_plot_t.ax.set_xlabel("") if print_steps: pr.print_graph(graph_t, printmerged=0) if print_steps and bucket_l != []: pr.printlog( "\n############################ GROW LIST ############################" + f"\nGrowing bucket {bucket_i} of {graph_l.maxbucket}: {bucket_l}" + f"\nRemaining buckets: {graph_l.buckets[bucket_i + 1 : graph_l.maxbucket + 1]}, {graph_l.wastebasket}\n" ) uf_plot_l.waitforkeypress() ufl.list_grow_bucket(bucket_l, bucket_i) if print_steps: pr.print_graph(graph_l, printmerged=0) uf_plot_l.ax.set_xlabel("") if not plot_growth and not print_steps: txt = "" if print_steps else f"Growing bucket #{bucket_i}/{max([graph_t.maxbucket, graph_l.maxbucket])}" uf_plot_t.draw_plot(txt) uf_plot_l.draw_plot() pr.printlog("Clusters grown.") uf_plot_t.waitforkeypress()