From 0203273a68f202e3b0a1c616f01c247827671765 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Mon, 13 Jan 2020 18:42:24 +0530 Subject: [PATCH] Add AdjacencyMatrix implementation for graphs (#81) --- pydatastructs/graphs/adjacency_matrix.py | 58 +++++++++++++++++++ pydatastructs/graphs/graph.py | 5 +- .../graphs/tests/test_adjacency_matrix.py | 21 +++++++ pydatastructs/utils/misc_util.py | 8 +-- pydatastructs/utils/tests/test_misc_util.py | 4 +- 5 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 pydatastructs/graphs/adjacency_matrix.py create mode 100644 pydatastructs/graphs/tests/test_adjacency_matrix.py diff --git a/pydatastructs/graphs/adjacency_matrix.py b/pydatastructs/graphs/adjacency_matrix.py new file mode 100644 index 000000000..d8135a992 --- /dev/null +++ b/pydatastructs/graphs/adjacency_matrix.py @@ -0,0 +1,58 @@ +from pydatastructs.graphs.graph import Graph +from pydatastructs.linear_data_structures import OneDimensionalArray +from pydatastructs.utils.misc_util import AdjacencyMatrixGraphNode + +__all__ = [ + 'AdjacencyMatrix' +] + +class AdjacencyMatrix(Graph): + """ + Adjacency matrix implementation of graphs. + + See also + ======== + + pydatastructs.graphs.graph.Graph + """ + def __new__(cls, *vertices): + obj = object.__new__(cls) + num_vertices = len(vertices) + obj.vertices = OneDimensionalArray( + AdjacencyMatrixGraphNode, + num_vertices) + for vertex in vertices: + obj.vertices[vertex.name] = vertex + obj.matrix = OneDimensionalArray( + OneDimensionalArray, + num_vertices) + for i in range(num_vertices): + obj.matrix[i] = OneDimensionalArray( + bool, + num_vertices) + obj.matrix[i].fill(False) + return obj + + def is_adjacent(self, node1, node2): + return self.matrix[node1][node2] + + def neighbors(self, node): + neighbors = [] + for i in range(self.matrix[node]._size): + if self.matrix[node][i]: + neighbors.append(self.vertices[i]) + return neighbors + + def add_vertex(self, node): + raise NotImplementedError("Currently we allow " + "adjacency matrix for static graphs only") + + def remove_vertex(self, node): + raise NotImplementedError("Currently we allow " + "adjacency matrix for static graphs only.") + + def add_edge(self, source, target): + self.matrix[source][target] = True + + def remove_edge(self, source, target): + self.matrix[source][target] = False diff --git a/pydatastructs/graphs/graph.py b/pydatastructs/graphs/graph.py index 188ec3929..b536f7155 100644 --- a/pydatastructs/graphs/graph.py +++ b/pydatastructs/graphs/graph.py @@ -13,7 +13,7 @@ class Graph(object): implementation: str The implementation to be used for storing graph in memory. - By default, 'adjacency_list' + By default, 'adjacency_list'. vertices: AdjacencyListGraphNode(s) For AdjacencyList implementation vertices can be passed for initializing the graph. @@ -48,6 +48,9 @@ def __new__(cls, *args, **kwargs): if implementation is 'adjacency_list': from pydatastructs.graphs.adjacency_list import AdjacencyList return AdjacencyList(*args) + elif implementation is 'adjacency_matrix': + from pydatastructs.graphs.adjacency_matrix import AdjacencyMatrix + return AdjacencyMatrix(*args) else: raise NotImplementedError("%s implementation is not a part " "of the library currently."%(implementation)) diff --git a/pydatastructs/graphs/tests/test_adjacency_matrix.py b/pydatastructs/graphs/tests/test_adjacency_matrix.py new file mode 100644 index 000000000..b6f9c3faf --- /dev/null +++ b/pydatastructs/graphs/tests/test_adjacency_matrix.py @@ -0,0 +1,21 @@ +from pydatastructs.graphs import Graph +from pydatastructs.utils import AdjacencyMatrixGraphNode + +def test_AdjacencyMatrix(): + v_0 = AdjacencyMatrixGraphNode(0, 0) + v_1 = AdjacencyMatrixGraphNode(1, 1) + v_2 = AdjacencyMatrixGraphNode(2, 2) + g = Graph(v_0, v_1, v_2, implementation='adjacency_matrix') + g.add_edge(0, 1) + g.add_edge(1, 2) + g.add_edge(2, 0) + assert g.is_adjacent(0, 1) is True + assert g.is_adjacent(1, 2) is True + assert g.is_adjacent(2, 0) is True + assert g.is_adjacent(1, 0) is False + assert g.is_adjacent(2, 1) is False + assert g.is_adjacent(0, 2) is False + neighbors = g.neighbors(0) + assert neighbors == [v_1] + g.remove_edge(0, 1) + assert g.is_adjacent(0, 1) is False diff --git a/pydatastructs/utils/misc_util.py b/pydatastructs/utils/misc_util.py index 419d7d098..5db27a374 100644 --- a/pydatastructs/utils/misc_util.py +++ b/pydatastructs/utils/misc_util.py @@ -190,9 +190,8 @@ class AdjacencyMatrixGraphNode(GraphNode): Parameters ========== - name: str - The name of the node by which it is identified - in the graph. Must be unique. + name: int + The index of the node in the AdjacencyMatrix. data The data to be stored at each graph node. """ @@ -200,7 +199,8 @@ class AdjacencyMatrixGraphNode(GraphNode): def __new__(cls, name, data): obj = GraphNode.__new__(cls) - obj.name, obj.data = name, data + obj.name, obj.data, obj.is_connected = \ + name, data, None return obj class GraphEdge(object): diff --git a/pydatastructs/utils/tests/test_misc_util.py b/pydatastructs/utils/tests/test_misc_util.py index f699ed748..0dc1d5610 100644 --- a/pydatastructs/utils/tests/test_misc_util.py +++ b/pydatastructs/utils/tests/test_misc_util.py @@ -17,8 +17,8 @@ def test_AdjacencyListGraphNode(): assert str(g) == "('g', 0)" def test_AdjacencyMatrixGraphNode(): - g = AdjacencyMatrixGraphNode('g', 3) - assert str(g) == "('g', 3)" + g = AdjacencyMatrixGraphNode(1, 3) + assert str(g) == "(1, 3)" def test_GraphEdge(): g_1 = AdjacencyListGraphNode('g_1', 1)