<filename>notes/algo-ds-practice/ds/graph/graph_core.py<gh_stars>1-10
class GraphCore:
    def __init__(self, bidirectional=False):
        # Graph is stored in an 'Adjacency map'.
        # adjMap[1] = {2: {'weight': 5}},
        #             {3: {'weight': 10}},....
        self.adjMap = {}
        self.bidirectional = bidirectional
        self.vertices = set()

    def add_edge(self, src, dst, edge_props=None):
        """
        Add an edge from `src` to `dst`. `edge_props` can be a int or dict().
        If int, then it is assumed to be weight, else arbitrary data;
        For example, {'weight': 5}.
        The existing edge prop will be overwritten if existing.
        """
        self.vertices.add(src)
        self.vertices.add(dst)
        # src_edges is a dict() containing all the edges from src.
        # It is of the form {2: {}, 3: {}}
        src_edges = self.adjMap.get(src, {})
        self.adjMap[src] = src_edges
        # edge is the specific edge from src to dst.
        # It is of the form {'weight': 5, 'key2': val2}
        edge = src_edges.get(dst, {})
        src_edges[dst] = edge
        if edge_props is not None:
            if not isinstance(edge_props, dict):
                edge_props = {"weight": edge_props}
            edge.update(edge_props)
        if self.bidirectional:
            edges_reverse = self.adjMap.get(dst, {})
            self.adjMap[dst] = edges_reverse
            edges_reverse[src] = edge

    def get_edges(self, src):
        return self.adjMap.get(src, {})

    def get_edge(self, src, dst):
        src_edges = self.adjMap.get(src, None)
        if src_edges is None:
            return None
        return src_edges.get(dst, None)

    def get_all_edges(self):
        return self.adjMap

    def remove_edges(self, src):
        if self.bidirectional:
            edges = self.adjMap[src]
            for neighbour in edges:
                if neighbour != src:
                    del self.adjMap[neighbour][src]
        self.adjMap[src] = {}

    def remove_edge(self, src, dst):
        del self.adjMap[src][dst]
        if self.bidirectional and src != dst:
            del self.adjMap[dst][src]

    def add_vertex(self, src):
        if src not in self.adjMap:
            self.adjMap[src] = {}
        self.vertices.add(src)

    def remove_vertex(self, src):
        self.remove_edges(src)
        if src in self.adjMap:
            del self.adjMap[src]
        self.vertices.remove(src)

    def get_transpose(self):
        '''
        Returns a new graph object with all edges reversed.
        Makes sense only for directional graphs.
        '''
        reverse_graph = GraphCore(False)
        for src, edges in self.get_all_edges().items():
            for dst, edge_props in edges.items():
                reverse_graph.add_edge(dst, src, dict(edge_props))
        for vertex in self.vertices:
            reverse_graph.add_vertex(vertex)
        return reverse_graph

    def __str__(self):
        output = ""
        for src in self.vertices:
            edges = self.adjMap.get(src, {})
            if not edges:
                output += "{};\n".format(src)
            for neighbour in edges:
                arrow = "->"
                if self.bidirectional:
                    if src > neighbour:
                        continue
                    arrow = "<->"
                edge = edges[neighbour]
                output += "{} {} {} = {};\n".format(src, arrow, neighbour, edge)
        return output


def main():
    g1 = GraphCore(True)
    g1.add_edge(1, 2)
    g1.add_edge(1, 3)
    g1.add_edge(1, 3, 10)
    g1.add_edge(1, 3, 15)
    g1.add_edge(3, 1, 3)
    g1.add_edge(3, 2, 3)
    g1.add_edge(1, 4, 15)
    g1.add_edge(1, 1)
    g1.add_edge(1, 1, 15)
    print(g1)
    g1.remove_vertex(1)
    print(g1)


if __name__ == "__main__":
    main()

<filename>notes/algo-ds-practice/ds/graph/graph_core.py<gh_stars>1-10
class GraphCore:
    def __init__(self, bidirectional=False):
        # Graph is stored in an 'Adjacency map'.
        # adjMap[1] = {2: {'weight': 5}},
        #             {3: {'weight': 10}},....
        self.adjMap = {}
        self.bidirectional = bidirectional
        self.vertices = set()

    def add_edge(self, src, dst, edge_props=None):
        """
        Add an edge from `src` to `dst`. `edge_props` can be a int or dict().
        If int, then it is assumed to be weight, else arbitrary data;
        For example, {'weight': 5}.
        The existing edge prop will be overwritten if existing.
        """
        self.vertices.add(src)
        self.vertices.add(dst)
        # src_edges is a dict() containing all the edges from src.
        # It is of the form {2: {}, 3: {}}
        src_edges = self.adjMap.get(src, {})
        self.adjMap[src] = src_edges
        # edge is the specific edge from src to dst.
        # It is of the form {'weight': 5, 'key2': val2}
        edge = src_edges.get(dst, {})
        src_edges[dst] = edge
        if edge_props is not None:
            if not isinstance(edge_props, dict):
                edge_props = {"weight": edge_props}
            edge.update(edge_props)
        if self.bidirectional:
            edges_reverse = self.adjMap.get(dst, {})
            self.adjMap[dst] = edges_reverse
            edges_reverse[src] = edge

    def get_edges(self, src):
        return self.adjMap.get(src, {})

    def get_edge(self, src, dst):
        src_edges = self.adjMap.get(src, None)
        if src_edges is None:
            return None
        return src_edges.get(dst, None)

    def get_all_edges(self):
        return self.adjMap

    def remove_edges(self, src):
        if self.bidirectional:
            edges = self.adjMap[src]
            for neighbour in edges:
                if neighbour != src:
                    del self.adjMap[neighbour][src]
        self.adjMap[src] = {}

    def remove_edge(self, src, dst):
        del self.adjMap[src][dst]
        if self.bidirectional and src != dst:
            del self.adjMap[dst][src]

    def add_vertex(self, src):
        if src not in self.adjMap:
            self.adjMap[src] = {}
        self.vertices.add(src)

    def remove_vertex(self, src):
        self.remove_edges(src)
        if src in self.adjMap:
            del self.adjMap[src]
        self.vertices.remove(src)

    def get_transpose(self):
        '''
        Returns a new graph object with all edges reversed.
        Makes sense only for directional graphs.
        '''
        reverse_graph = GraphCore(False)
        for src, edges in self.get_all_edges().items():
            for dst, edge_props in edges.items():
                reverse_graph.add_edge(dst, src, dict(edge_props))
        for vertex in self.vertices:
            reverse_graph.add_vertex(vertex)
        return reverse_graph

    def __str__(self):
        output = ""
        for src in self.vertices:
            edges = self.adjMap.get(src, {})
            if not edges:
                output += "{};\n".format(src)
            for neighbour in edges:
                arrow = "->"
                if self.bidirectional:
                    if src > neighbour:
                        continue
                    arrow = "<->"
                edge = edges[neighbour]
                output += "{} {} {} = {};\n".format(src, arrow, neighbour, edge)
        return output


def main():
    g1 = GraphCore(True)
    g1.add_edge(1, 2)
    g1.add_edge(1, 3)
    g1.add_edge(1, 3, 10)
    g1.add_edge(1, 3, 15)
    g1.add_edge(3, 1, 3)
    g1.add_edge(3, 2, 3)
    g1.add_edge(1, 4, 15)
    g1.add_edge(1, 1)
    g1.add_edge(1, 1, 15)
    print(g1)
    g1.remove_vertex(1)
    print(g1)


if __name__ == "__main__":
    main()

# Graph is stored in an 'Adjacency map'. # adjMap[1] = {2: {'weight': 5}}, #             {3: {'weight': 10}},.... Add an edge from `src` to `dst`. `edge_props` can be a int or dict().         If int, then it is assumed to be weight, else arbitrary data;         For example, {'weight': 5}.         The existing edge prop will be overwritten if existing. # src_edges is a dict() containing all the edges from src. # It is of the form {2: {}, 3: {}} # edge is the specific edge from src to dst. # It is of the form {'weight': 5, 'key2': val2} Returns a new graph object with all edges reversed.         Makes sense only for directional graphs.