コード例 #1
0
class KSquareTree:
    def __init__(self, k):
        self.k = k
        self.k2 = k * k
        self.n = 0
        self.h = 0
        self.T = BitVector(size=0)
        self.L = BitVector(size=0)

    def __str__(self):
        return self.T.__str__() + '\n' + self.L.__str__()

    def __len__(self):
        return self.n

    def create(self, graph):
        """
        Creates a k^2 tree graph representation from the given graph.

        :param graph: An adjacency matrix representation of the graph.
                      It is assumed that len(graph) % k == 0.
        :return: None
        """

        assert len(graph) % self.k == 0

        self.n = len(graph)
        self.h = int(m.ceil(m.log(len(graph), self.k)))

        temp = [BitVector(size=0) for _ in range(self.h)]

        def build(n, l, p, q):
            c = BitVector(size=0)
            for i in range(self.k):
                for j in range(self.k):
                    if l == self.h - 1:
                        c = c + BitVector(intVal=graph[p + i][q + j])
                    else:
                        c = c + build(n / self.k, l + 1, p + i *
                                      (n / self.k), q + j * (n / self.k))

            if c == BitVector(size=self.k2):
                return BitVector(intVal=0)

            temp[l] += c
            return BitVector(intVal=1)

        build(self.n, 0, 0, 0)

        self.L = temp[self.h - 1]

        for i in range(self.h - 1):
            self.T += temp[i]

    def edges_from(self, p):
        """
        Returns the list of edges which are neighbours of p.

        :param p: Vertex
        :return: Vertices which are reachable from p
        """
        nodes = []

        def direct(n, p, q, x):
            if x >= len(self.T):
                if self.L[x - len(self.T)] == 1:
                    nodes.append(q)
            else:
                if x == -1 or self.T[x] == 1:
                    y = self.T.rank_of_bit_set_at_index(x) * self.k2 \
                        + self.k * int(m.floor(p / (n / self.k)))

                    for j in range(self.k):
                        direct(n / self.k, p % (n / self.k),
                               q + (n / self.k) * j, y + j)

        direct(self.n, p, 0, -1)

        return nodes

    def edges_to(self, q):
        """
        Returns the list of vertices from which q is reachable.

        :param q: Vertex
        :return: Vertices from which q can be reached
        """
        nodes = []

        def reverse(n, q, p, x):
            if x >= len(self.T):
                if self.L[x - len(self.T)] == 1:
                    nodes.append(p)
            else:
                if x == -1 or self.T[x] == 1:
                    y = self.T.rank_of_bit_set_at_index(x) * self.k2 \
                        + self.k * int(m.floor(q / (n / self.k)))

                    for j in range(self.k):
                        reverse(n / self.k, q % (n / self.k),
                                p + (n / self.k) * j, y + j * self.k)

        reverse(self.n, q, 0, -1)

        return nodes