class SymbolGraph:
    """The SymbolGraph class represents an undirected graph, where the vertex
    names are arbitrary strings. By providing mappings between vertex names and
    integers, it serves as a wrapper around the Graph data type, which assumes
    the vertex names are integers between 0 and V - 1.
    """

    def __init__(self, vertices):
        self._st = BinarySearchST()  # string -> index

        # built symbol table to translate strings into indices
        for i in range(len(vertices)):
            self._st.put(vertices[i], i)

        # built array to translate from indices to strings
        self._keys = [None] * self._st.size()  # index  -> string
        for name in self._st.keys():
            self._keys[self._st.get(name)] = name

        # initialise graph
        self._graph = Graph(self._st.size())  # the underlying graph

    def V(self):
        return self._graph._V

    def E(self):
        return self._graph._E

    def size(self):
        return self._graph._V

    def __len__(self):
        return self._graph._V

    def contains(self, s):
        return self._st.contains(s)

    def index_of(self, s):
        return self._st.get(s)

    def name_of(self, v):
        return self._keys[v]

    def add_edge(self, u, v):
        self._graph.add_edge(self.index_of(u), self.index_of(v))

    def adj(self, u):
        return [self.name_of(adj) for adj in self._graph.adj(self.index_of(u))]

    def degree(self, u):
        return self._graph.degree(self.index_of(u))

    def graph(self):
        return self._graph
    def __init__(self, vertices):
        self._st = BinarySearchST()  # string -> index

        # built symbol table to translate strings into indices
        for i in range(len(vertices)):
            self._st.put(vertices[i], i)

        # built array to translate from indices to strings
        self._keys = [None] * self._st.size()  # index  -> string
        for name in self._st.keys():
            self._keys[self._st.get(name)] = name

        # initialise graph
        self._graph = Graph(self._st.size())  # the underlying graph
Exemple #3
0
    def from_graph(G):
        """
        Initializes a new graph that is a deep copy of G

        :param G: the graph to copy
        :returns: copy of G 
        """
        g = Graph(G.V())
        g._E = G.E()
        for v in range(G.V()):
            # reverse so that adjacency list is in same order as original
            reverse = Stack()
            for w in G._adj[v]:
                reverse.push(w)
            for w in reverse:
                g._adj[v].add(w)
    def __init__(self, filename, delimiter):
        """Initializes a graph from a file using the specified delimiter. Each
        line in the file contains the name of a vertex, followed by a list of
        the names of the vertices adjacent to that vertex, separated by the
        delimiter.

        :param filename: the name of the file
        :param delimiter: the delimiter between fields

        """
        self._st = BinarySearchST()  # string -> index

        # First pass builds the index by reading strings to associate
        # distinct strings with an index
        stream = InStream(filename)
        while not stream.isEmpty():
            a = stream.readLine().split(delimiter)
            for i in range(len(a)):
                if not self._st.contains(a[i]):
                    self._st.put(a[i], self._st.size())

        stdio.writef("Done reading %s\n", filename)

        # inverted index to get keys in an array
        self._keys = [None] * self._st.size()  # index  -> string
        for name in self._st.keys():
            self._keys[self._st.get(name)] = name

        # second pass builds the graph by connecting first vertex on each
        # line to all others
        self._graph = Graph(self._st.size())  # the underlying graph
        stream = InStream(filename)
        while stream.hasNextLine():
            a = stream.readLine().split(delimiter)
            v = self._st.get(a[0])
            for i in range(1, len(a)):
                w = self._st.get(a[i])
                self._graph.add_edge(v, w)
class SymbolGraph:
    """The SymbolGraph class represents an undirected graph, where the vertex
    names are arbitrary strings. By providing mappings between vertex names and
    integers, it serves as a wrapper around the Graph data type, which assumes
    the vertex names are integers.

    between 0 and V - 1.
    It also supports initializing a symbol graph from a file.

    This implementation uses an ST to map from strings to integers,
    an array to map from integers to strings, and a Graph to store
    the underlying graph.
    The index_of and contains operations take time
    proportional to log V, where V is the number of vertices.
    The name_of operation takes constant time.

    """

    def __init__(self, filename, delimiter):
        """Initializes a graph from a file using the specified delimiter. Each
        line in the file contains the name of a vertex, followed by a list of
        the names of the vertices adjacent to that vertex, separated by the
        delimiter.

        :param filename: the name of the file
        :param delimiter: the delimiter between fields

        """
        self._st = BinarySearchST()  # string -> index

        # First pass builds the index by reading strings to associate
        # distinct strings with an index
        stream = InStream(filename)
        while not stream.isEmpty():
            a = stream.readLine().split(delimiter)
            for i in range(len(a)):
                if not self._st.contains(a[i]):
                    self._st.put(a[i], self._st.size())

        stdio.writef("Done reading %s\n", filename)

        # inverted index to get keys in an array
        self._keys = [None] * self._st.size()  # index  -> string
        for name in self._st.keys():
            self._keys[self._st.get(name)] = name

        # second pass builds the graph by connecting first vertex on each
        # line to all others
        self._graph = Graph(self._st.size())  # the underlying graph
        stream = InStream(filename)
        while stream.hasNextLine():
            a = stream.readLine().split(delimiter)
            v = self._st.get(a[0])
            for i in range(1, len(a)):
                w = self._st.get(a[i])
                self._graph.add_edge(v, w)

    def contains(self, s):
        """Does the graph contain the vertex named s?

        :param s: the name of a vertex
        :return:s true if s is the name of a vertex, and false otherwise

        """
        return self._st.contains(s)

    def index_of(self, s):
        """Returns the integer associated with the vertex named s.

        :param s: the name of a vertex
        :returns: the integer (between 0 and V - 1) associated with the vertex named s

        """
        return self._st.get(s)

    def name_of(self, v):
        """Returns the name of the vertex associated with the integer v.

        @param  v the integer corresponding to a vertex (between 0 and V - 1)
        @throws IllegalArgumentException unless 0 <= v < V
        @return the name of the vertex associated with the integer v

        """
        self._validateVertex(v)
        return self._keys[v]

    def graph(self):
        return self._graph

    def _validateVertex(self, v):
        # throw an IllegalArgumentException unless 0 <= v < V
        V = self._graph.V()
        if v < 0 or v >= V:
            raise ValueError("vertex {} is not between 0 and {}".format(v, V - 1))
Exemple #6
0
            if not self._marked[s]:
                self.dfs(-1, s)

    def dfs(self, u, v):
        self._marked[v] = True
        for adj in self._G.adj(v):
            if not self._marked[adj]:
                self.dfs(v, adj)
            elif u != adj:
                self._has_cycle = True

    def has_cycle(self):
        return self._has_cycle


if __name__ == '__main__':
    G = Graph(7)
    G.add_edge(0, 1)
    G.add_edge(0, 2)
    G.add_edge(0, 5)
    G.add_edge(0, 6)
    G.add_edge(3, 4)
    G.add_edge(3, 5)
    G.add_edge(4, 5)
    G.add_edge(4, 6)
    G.add_edge(1, 3)
    print(G)

    cycle_detector = Cycles(G)
    print(cycle_detector.has_cycle())
Exemple #7
0
        return path

    def _validateVertex(self, v):
        # throw an ValueError unless 0 <= v < V
        V = len(self._marked)
        if v < 0 or v >= V:
            raise ValueError("vertex {} is not between 0 and {}".format(
                v, V - 1))


if __name__ == "__main__":
    from itu.algs4.stdlib import stdio
    from itu.algs4.graphs.graph import Graph
    from itu.algs4.stdlib.instream import InStream
    import sys

    In = InStream(sys.argv[1])
    G = Graph.from_stream(In)
    s = int(sys.argv[2])
    dfs = DepthFirstPaths(G, s)

    for v in range(G.V()):
        if dfs.has_path_to(v):
            stdio.writef("%d to %d:  ", s, v)
            for x in dfs.path_to(v):
                if x == s: stdio.write(x)
                else: stdio.writef("-%i", x)
            stdio.writeln()
        else:
            stdio.writef("%d to %d:  not connected\n", s, v)
        path = Stack()
        curr = v
        while curr != self._s:
            path.push(curr)
            curr = self._edgeto[curr]
        path.push(self._s)
        return path

    def connected(self):
        return self._count == self._G.V()


# client code
if __name__ == '__main__':
    # initialise example graph
    G = Graph(7)
    G.add_edge(0, 1)
    G.add_edge(0, 2)
    G.add_edge(0, 5)
    G.add_edge(0, 6)
    G.add_edge(3, 4)
    G.add_edge(3, 5)
    G.add_edge(4, 5)
    G.add_edge(4, 6)
    print(G)

    paths = Paths(G, s=0)
    print(paths._marked)
    print(paths._edgeto)
    print(f"Is Connected: {paths.connected()}")
    for i in range(G.V()):
Exemple #9
0
# solution to wiener index in may 2018 dsa exam
from itu.algs4.graphs.graph import Graph
from itu.algs4.fundamentals.queue import Queue
from itertools import combinations

G = Graph(7)
G.add_edge(0, 1)
G.add_edge(0, 2)
G.add_edge(1, 3)
G.add_edge(1, 4)
G.add_edge(2, 5)
G.add_edge(2, 6)


def shortest_path(G, u, v):
    marked = [False] * G.V()
    edge_to = [None] * G.V()

    q = Queue()
    marked[u] = True
    q.enqueue(u)

    while not q.is_empty():
        s = q.dequeue()
        for adj in G.adj(s):
            if not marked[adj]:
                marked[s] = True
                edge_to[adj] = s
                q.enqueue(adj)

    dist = 0
Exemple #10
0
                marked[adj] = True
                edge_to[adj] = v
                q.enqueue(adj)

    # compute dist of all paths
    paths = []
    for i in range(G.V()):
        dist = 0
        curr = i
        while edge_to[curr] != None:
            dist += 1
            curr = edge_to[curr]

        paths.append(dist)

    return max(paths)


G = Graph(7)
G.add_edge(0, 1)
G.add_edge(0, 2)
G.add_edge(1, 3)
G.add_edge(2, 3)
G.add_edge(2, 4)
G.add_edge(3, 4)
G.add_edge(5, 4)
G.add_edge(5, 6)
G.add_edge(3, 6)

print(diameter(G))
        for adj in self._G.adj(s):
            if not self._marked[adj]:
                self._coloring[adj] = not self._coloring[s]
                self.dfs(adj)
            elif self._coloring[s] == self._coloring[adj]:
                self._is_bipartite = False

    def is_bipartite(self):
        return self._is_bipartite

    def coloring(self):
        if not self.is_bipartite():
            raise ValueError('No two-coloring possible')
        return [
            'Red' if self._coloring[i] else 'Blue'
            for i in range(len(self._coloring))
        ]


if __name__ == '__main__':
    G = Graph(4)
    G.add_edge(0, 1)
    G.add_edge(0, 2)
    G.add_edge(0, 3)
    print(G)

    colorer = Bipartite(G)
    print(colorer.coloring())
    print(colorer.is_bipartite())
        return sum(self.matrix[u])

    def average_degree(self):
        return 2 * (self._E / self._V)

    def number_self_loops(self):
        num = 0
        for i in range(self._V):
            if self.matrix[i][i] == 1:
                num += 1
        return num

    def __str__(self):
        string = '[' + str(self.matrix[0]) + '\n'
        for i in range(1, self._V - 1):
            string += f' {self.matrix[i]}\n'
        return string + f' {self.matrix[-1]}]'


if __name__ == '__main__':
    graph = Graph(5)
    graph.add_edge(0, 1)
    graph.add_edge(0, 3)
    graph.add_edge(2, 3)
    graph.add_edge(0, 0)
    print(graph.degree(0))
    print(graph.adj(0))
    # print(graph.number_self_loops())
    # print(graph.average_degree())
    print(graph)