Beispiel #1
0
    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
Beispiel #2
0
    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()
Beispiel #3
0
    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()
Beispiel #4
0
    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()