From 83f67487d49670c1396950e4c999ece269077d6e Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Sun, 24 Oct 2021 19:43:30 +0530 Subject: [PATCH 01/13] Changed version to 0.0.1-alpha --- docs/source/conf.py | 2 +- pydatastructs/__init__.py | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 1b4721a6e..f777adbb2 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -26,7 +26,7 @@ master_doc = 'index' # The full version, including alpha/beta/rc tags -release = '0.0.1-dev' +release = '0.0.1-alpha' # -- General configuration --------------------------------------------------- diff --git a/pydatastructs/__init__.py b/pydatastructs/__init__.py index 5568ebd3d..4dad188e0 100644 --- a/pydatastructs/__init__.py +++ b/pydatastructs/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.0.1-dev" +__version__ = "0.0.1-alpha" from .linear_data_structures import * from .trees import * diff --git a/setup.py b/setup.py index 2d23ecdd0..18dcec688 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="pydatastructs", - version="0.0.1-dev", + version="0.0.1-alpha", author="PyDataStructs Development Team", author_email="pydatastructs@googlegroups.com", description="A python package for data structures", From 1af4cfffe3808f95d0fd464f4d2ee4d397b50e87 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Sun, 24 Oct 2021 19:44:33 +0530 Subject: [PATCH 02/13] pydatastructs -> pydatastructs_ for PyPI --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 18dcec688..41b723698 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ long_description = fh.read() setuptools.setup( - name="pydatastructs", + name="pydatastructs_", version="0.0.1-alpha", author="PyDataStructs Development Team", author_email="pydatastructs@googlegroups.com", From 79cf433056ab0714e8fcd580875b27db9eb1366d Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Sun, 24 Oct 2021 19:46:35 +0530 Subject: [PATCH 03/13] pydatasturcts_ -> cz-pydatastructs --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 41b723698..deae5ce44 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ long_description = fh.read() setuptools.setup( - name="pydatastructs_", + name="cz-pydatastructs", version="0.0.1-alpha", author="PyDataStructs Development Team", author_email="pydatastructs@googlegroups.com", From c055e771207ae512c108298e422ff845dcffb040 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Sun, 24 Oct 2021 20:01:42 +0530 Subject: [PATCH 04/13] Removed incorrect topic --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index deae5ce44..589c0de98 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,6 @@ "Programming Language :: Python :: 3", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", - "Topic :: Education :: Data Structures", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Information Analysis", "Topic :: Software Development :: Libraries" From 53f18893be5b1992c136f3b4d6affc21352dad75 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Sun, 24 Oct 2021 20:21:20 +0530 Subject: [PATCH 05/13] Updated installation instructions on website --- docs/source/index.rst | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index cdcaef0a4..f84291a51 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -26,19 +26,9 @@ Installation After changing your directory to project root, you can install the package by running the following command, -``python -m pip install .`` +``pip install cz-pydatastructs`` -For development purposes, you can use the option `e` as shown below, - -``python -m pip install -e .`` - -For building documentation execute the following commands one after -the other, - -1. ``pip install -r docs/requirements.txt`` -2. ``sphinx-build -b html docs/source/ docs/build/html`` - -Make sure that your python version is at least ``3.8``. +Make sure that your python version is at least ``3.5``. Why do we use Python? ===================== From 9f22c7d72758b73421443338f30340f67b630c43 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Sun, 24 Oct 2021 20:29:41 +0530 Subject: [PATCH 06/13] Minor typo fix in documentation --- docs/source/index.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index f84291a51..241096646 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -23,8 +23,7 @@ code in C++ and Java as well. Installation ============ -After changing your directory to project root, you can -install the package by running the following command, +You can install the package by running the following command, ``pip install cz-pydatastructs`` From 94e96a2d1ae82175f4677937f276fd36170539c7 Mon Sep 17 00:00:00 2001 From: Pratik Goyal Date: Sun, 31 Oct 2021 16:07:04 +0530 Subject: [PATCH 07/13] Doc improvements (ODA, DODA) and addition of checks in ``graph`` (#424) --- README.md | 14 +++++++------- pydatastructs/graphs/adjacency_list.py | 19 ++++++++++++++++--- pydatastructs/graphs/adjacency_matrix.py | 12 ++++++++++++ pydatastructs/graphs/graph.py | 15 +++++++++++++-- .../graphs/tests/test_adjacency_list.py | 4 ++++ .../graphs/tests/test_adjacency_matrix.py | 4 ++++ .../linear_data_structures/arrays.py | 6 ++++-- 7 files changed, 60 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 09e9b6dc9..803c88b0e 100644 --- a/README.md +++ b/README.md @@ -101,11 +101,11 @@ Keep contributing!! Thanks to these wonderful people ✨✨: - - - + + +
- - - -
+ + + +
diff --git a/pydatastructs/graphs/adjacency_list.py b/pydatastructs/graphs/adjacency_list.py index a06e35533..541ff3a1e 100644 --- a/pydatastructs/graphs/adjacency_list.py +++ b/pydatastructs/graphs/adjacency_list.py @@ -26,8 +26,8 @@ def __new__(cls, *vertices): @classmethod def methods(self): return ['is_adjacent', 'neighbors', - 'add_vertex', 'remove_vertex', 'add_edge', - 'get_edge', 'remove_edge', '__new__'] + 'add_vertex', 'remove_vertex', 'add_edge', + 'get_edge', 'remove_edge', '__new__'] def is_adjacent(self, node1, node2): node1 = self.__getattribute__(node1) @@ -52,8 +52,21 @@ def remove_vertex(self, name): node_obj.adjacent.remove(name) def add_edge(self, source, target, cost=None): + source, target = str(source), str(target) + error_msg = ("Vertex %s is not present in the graph." + "Call Graph.add_vertex to add a new" + "vertex. Graph.add_edge is only responsible" + "for adding edges and it will not add new" + "vertices on its own. This is done to maintain" + "clear separation between the functionality of" + "these two methods.") + if not hasattr(self, source): + raise ValueError(error_msg % (source)) + if not hasattr(self, target): + raise ValueError(error_msg % (target)) + source, target = self.__getattribute__(source), \ - self.__getattribute__(target) + self.__getattribute__(target) source.add_adjacent_node(target.name) if cost is not None: self.edge_weights[source.name + "_" + target.name] = \ diff --git a/pydatastructs/graphs/adjacency_matrix.py b/pydatastructs/graphs/adjacency_matrix.py index a75efabdf..64a39494c 100644 --- a/pydatastructs/graphs/adjacency_matrix.py +++ b/pydatastructs/graphs/adjacency_matrix.py @@ -57,6 +57,18 @@ def remove_vertex(self, node): def add_edge(self, source, target, cost=None): source, target = str(source), str(target) + error_msg = ("Vertex %s is not present in the graph." + "Call Graph.add_vertex to add a new" + "vertex. Graph.add_edge is only responsible" + "for adding edges and it will not add new" + "vertices on its own. This is done to maintain" + "clear separation between the functionality of" + "these two methods.") + if source not in self.matrix: + raise ValueError(error_msg % (source)) + if target not in self.matrix: + raise ValueError(error_msg % (target)) + self.matrix[source][target] = True if cost is not None: self.edge_weights[source + "_" + target] = \ diff --git a/pydatastructs/graphs/graph.py b/pydatastructs/graphs/graph.py index f19fc8e97..0c1b195a8 100644 --- a/pydatastructs/graphs/graph.py +++ b/pydatastructs/graphs/graph.py @@ -49,6 +49,16 @@ class Graph(object): ========== .. [1] https://en.wikipedia.org/wiki/Graph_(abstract_data_type) + + Note + ==== + + Make sure to create nodes (AdjacencyListGraphNode or AdjacencyMatrixGraphNode) + and them in your graph using Graph.add_vertex before adding edges whose + end points require either of the nodes that you added. In other words, + Graph.add_edge doesn't add new nodes on its own if the input + nodes are not already present in the Graph. + """ __slots__ = ['_impl'] @@ -89,7 +99,8 @@ def neighbors(self, node): def add_vertex(self, node): """ - Adds the input vertex to the node. + Adds the input vertex to the node, or does nothing + if the input vertex is already in the graph. """ raise NotImplementedError( "This is an abstract method.") @@ -97,7 +108,7 @@ def add_vertex(self, node): def remove_vertex(self, node): """ Removes the input vertex along with all the edges - pointing towards to it. + pointing towards it. """ raise NotImplementedError( "This is an abstract method.") diff --git a/pydatastructs/graphs/tests/test_adjacency_list.py b/pydatastructs/graphs/tests/test_adjacency_list.py index d1635fc83..3dcef8a7a 100644 --- a/pydatastructs/graphs/tests/test_adjacency_list.py +++ b/pydatastructs/graphs/tests/test_adjacency_list.py @@ -1,5 +1,6 @@ from pydatastructs.graphs import Graph from pydatastructs.utils import AdjacencyListGraphNode +from pydatastructs.utils.raises_util import raises def test_adjacency_list(): v_1 = AdjacencyListGraphNode('v_1', 1) @@ -38,3 +39,6 @@ def test_adjacency_list(): g.remove_vertex('v') assert g.is_adjacent('v_2', 'v') is False assert g.is_adjacent('v_3', 'v') is False + + assert raises(ValueError, lambda: g.add_edge('u', 'v')) + assert raises(ValueError, lambda: g.add_edge('v', 'x')) diff --git a/pydatastructs/graphs/tests/test_adjacency_matrix.py b/pydatastructs/graphs/tests/test_adjacency_matrix.py index 3df819611..c0f7b7c06 100644 --- a/pydatastructs/graphs/tests/test_adjacency_matrix.py +++ b/pydatastructs/graphs/tests/test_adjacency_matrix.py @@ -1,5 +1,6 @@ from pydatastructs.graphs import Graph from pydatastructs.utils import AdjacencyMatrixGraphNode +from pydatastructs.utils.raises_util import raises def test_AdjacencyMatrix(): v_0 = AdjacencyMatrixGraphNode(0, 0) @@ -25,3 +26,6 @@ def test_AdjacencyMatrix(): assert neighbors == [v_1] g.remove_edge(0, 1) assert g.is_adjacent(0, 1) is False + + assert raises(ValueError, lambda: g.add_edge('u', 'v')) + assert raises(ValueError, lambda: g.add_edge('v', 'x')) diff --git a/pydatastructs/linear_data_structures/arrays.py b/pydatastructs/linear_data_structures/arrays.py index 32fa0ee42..e4bc24223 100644 --- a/pydatastructs/linear_data_structures/arrays.py +++ b/pydatastructs/linear_data_structures/arrays.py @@ -15,7 +15,8 @@ def __str__(self) -> str: class OneDimensionalArray(Array): ''' - Represents one dimensional arrays. + Represents one dimensional static arrays of + fixed size. Parameters ========== @@ -269,7 +270,8 @@ class DynamicArray(Array): class DynamicOneDimensionalArray(DynamicArray, OneDimensionalArray): """ - Represents dynamic one dimensional arrays. + Represents resizable and dynamic one + dimensional arrays. Parameters ========== From 2452572b7bfd1a735da1c1e969b5cf21bb0445f2 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Sun, 31 Oct 2021 16:25:11 +0530 Subject: [PATCH 08/13] Made the API of ``RangeQueryStatic`` consistent (#425) --- .../algorithms.py | 18 ++++++++---------- .../sparse_table.py | 5 +---- .../tests/test_range_query_static.py | 14 +++++++------- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/pydatastructs/miscellaneous_data_structures/algorithms.py b/pydatastructs/miscellaneous_data_structures/algorithms.py index 5f2204a8a..1a4ffc56a 100644 --- a/pydatastructs/miscellaneous_data_structures/algorithms.py +++ b/pydatastructs/miscellaneous_data_structures/algorithms.py @@ -53,11 +53,11 @@ class RangeQueryStatic: >>> from pydatastructs import minimum >>> arr = OneDimensionalArray(int, [4, 6, 1, 5, 7, 3]) >>> RMQ = RangeQueryStatic(arr, minimum) - >>> RMQ.query(3, 5) + >>> RMQ.query(3, 4) 5 - >>> RMQ.query(0, 5) + >>> RMQ.query(0, 4) 1 - >>> RMQ.query(0, 3) + >>> RMQ.query(0, 2) 1 Note @@ -97,9 +97,7 @@ def query(start, end): start: int The starting index of the range. end: int - The index just before which the range ends. - This means that this index will be excluded - from the range for generating results. + The ending index of the range. """ raise NotImplementedError( "This is an abstract method.") @@ -121,7 +119,7 @@ def methods(cls): return ['query'] def query(self, start, end): - _check_range_query_inputs((start, end), self.bounds) + _check_range_query_inputs((start, end + 1), self.bounds) return self.sparse_table.query(start, end) @@ -140,14 +138,14 @@ def methods(cls): return ['query'] def query(self, start, end): - _check_range_query_inputs((start, end), (0, len(self.array))) + _check_range_query_inputs((start, end + 1), (0, len(self.array))) - rsize = end - start + rsize = end - start + 1 if rsize == 1: return self.func((self.array[start],)) query_ans = self.func((self.array[start], self.array[start + 1])) - for i in range(start + 2, end): + for i in range(start + 2, end + 1): query_ans = self.func((query_ans, self.array[i])) return query_ans diff --git a/pydatastructs/miscellaneous_data_structures/sparse_table.py b/pydatastructs/miscellaneous_data_structures/sparse_table.py index 02000724d..972612eb1 100644 --- a/pydatastructs/miscellaneous_data_structures/sparse_table.py +++ b/pydatastructs/miscellaneous_data_structures/sparse_table.py @@ -86,11 +86,8 @@ def query(self, start, end): start: int The starting index of the range. end: int - The index just before which the range ends. - This means that this index will be excluded - from the range for generating results. + The ending index of the range. """ - end -= 1 j = int(math.log2(end - start + 1)) + 1 answer = None while j >= 0: diff --git a/pydatastructs/miscellaneous_data_structures/tests/test_range_query_static.py b/pydatastructs/miscellaneous_data_structures/tests/test_range_query_static.py index 86212ab11..e898653c9 100644 --- a/pydatastructs/miscellaneous_data_structures/tests/test_range_query_static.py +++ b/pydatastructs/miscellaneous_data_structures/tests/test_range_query_static.py @@ -12,9 +12,9 @@ def _test_RangeQueryStatic_common(func, gen_expected): array = OneDimensionalArray(int, [1]) rq = RangeQueryStatic(array, func) - assert rq.query(0, 1) == 1 - raises(ValueError, lambda: rq.query(0, 0)) - raises(IndexError, lambda: rq.query(0, 2)) + assert rq.query(0, 0) == 1 + raises(ValueError, lambda: rq.query(0, -1)) + raises(IndexError, lambda: rq.query(0, 1)) array_sizes = [3, 6, 12, 24, 48, 96] random.seed(0) @@ -38,18 +38,18 @@ def _test_RangeQueryStatic_common(func, gen_expected): def test_RangeQueryStatic_minimum(): def _gen_minimum_expected(data, i, j): - return min(data[i:j]) + return min(data[i:j + 1]) _test_RangeQueryStatic_common(minimum, _gen_minimum_expected) def test_RangeQueryStatic_greatest_common_divisor(): def _gen_gcd_expected(data, i, j): - if j - i == 1: + if j == i: return data[i] else: expected_gcd = math.gcd(data[i], data[i + 1]) - for idx in range(i + 2, j): + for idx in range(i + 2, j + 1): expected_gcd = math.gcd(expected_gcd, data[idx]) return expected_gcd @@ -58,6 +58,6 @@ def _gen_gcd_expected(data, i, j): def test_RangeQueryStatic_summation(): def _gen_summation_expected(data, i, j): - return sum(data[i:j]) + return sum(data[i:j + 1]) return _test_RangeQueryStatic_common(summation, _gen_summation_expected) From a394600a8e2cffc6e1e18136ffda848101b11d84 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Sun, 31 Oct 2021 23:33:16 +0530 Subject: [PATCH 09/13] Added notebook for California road network (#426) --- docs/requirements.txt | 3 +- docs/source/conf.py | 5 +- docs/source/index.rst | 1 + docs/source/pydatastructs_sphinx_graphs.ipynb | 243 ++++++++++++++++++ docs/source/tutorials.rst | 2 +- 5 files changed, 251 insertions(+), 3 deletions(-) create mode 100644 docs/source/pydatastructs_sphinx_graphs.ipynb diff --git a/docs/requirements.txt b/docs/requirements.txt index b3ecdb274..6526a0ef8 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,2 +1,3 @@ sphinx==4.2.0 -sphinx-readable-theme==1.3.0 \ No newline at end of file +sphinx-readable-theme==1.3.0 +myst_nb==0.13.1 \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index f777adbb2..95974a93a 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -36,9 +36,12 @@ # ones. extensions = [ 'sphinx.ext.autodoc', - 'sphinx.ext.napoleon' + 'sphinx.ext.napoleon', + 'myst_nb' ] +jupyter_execute_notebooks = "off" + napoleon_numpy_docstring = True # Add any paths that contain templates here, relative to this directory. diff --git a/docs/source/index.rst b/docs/source/index.rst index 241096646..8ca90a45e 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -48,6 +48,7 @@ Contents :maxdepth: 1 tutorials.rst + pydatastructs_sphinx_graphs contributing.rst authors.rst pydatastructs/pydatastructs.rst diff --git a/docs/source/pydatastructs_sphinx_graphs.ipynb b/docs/source/pydatastructs_sphinx_graphs.ipynb new file mode 100644 index 000000000..724c0a07c --- /dev/null +++ b/docs/source/pydatastructs_sphinx_graphs.ipynb @@ -0,0 +1,243 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "pydatastructs-sphinx-graphs.ipynb", + "provenance": [], + "collapsed_sections": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "2qB4MTFoYSdW" + }, + "source": [ + "Comparing Dijkstra and Bellman Ford Shortest Paths Algorithms using PyDataStructs\n", + "====================================" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Zu6G_1RLYitv" + }, + "source": [ + "Dataset\n", + "-------\n", + "\n", + "We have used [California road network](https://snap.stanford.edu/data/roadNet-CA.html) from [Stanford Network Analysis Project](https://snap.stanford.edu/index.html). The intent of this demo is to show how **pydatastructs** can be used for research and analysis purposes.\n", + "\n", + "The above dataset is a road network of California as the name suggests. The intersections and endpoints in this network are represented as vertices and the roads between them are represented as undirected edges. The data is read from a `txt` file where each line contains two numbers representing two points of an edge in the graph. We have used varying number of these edges to analyse how each algorithm responds to the varying scale of the shortest path problem at hand." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "YoaukKUfaF66" + }, + "source": [ + "Results\n", + "-------\n", + "\n", + "We observed that for low inverse density (total number of possible edges divided by number of edges present) graphs, both algorithms take similar amounts of time. However Dijkstra algorithm performs significantly better with high inverse density graphs as compared to Bellman Ford algorithm." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "_qWIIix_Twd5" + }, + "source": [ + "# Import modules and APIs for Graphs\n", + "from pydatastructs import Graph, AdjacencyListGraphNode\n", + "from pydatastructs import shortest_paths, topological_sort\n", + "\n", + "# Import utility modules\n", + "import timeit, random, functools, matplotlib.pyplot as plt" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "8TDkoIgcXJr6" + }, + "source": [ + "def create_Graph(num_edges, file_path, ignore_lines=4):\n", + " \"\"\"\n", + " Creates pydatastructs.Graph object.\n", + "\n", + " Parameters\n", + " ==========\n", + "\n", + " num_edges: int\n", + " Number of edges that should be present in the\n", + " pydatastructs.Graph object.\n", + " file_path: str\n", + " The path to the file containing California\n", + " road network dataset.\n", + " ignore_lines: int\n", + " Number of inital lines that should be ignored.\n", + " Optional, by default 4 because the first 4 lines\n", + " contain documentation of the dataset which is not\n", + " required to generate the pydatastructs.Graph object.\n", + " \n", + " Returns\n", + " =======\n", + "\n", + " G: pydatastructs.Graph\n", + " \"\"\"\n", + " f = open(file_path, 'r')\n", + " for _ in range(ignore_lines):\n", + " f.readline()\n", + " G = Graph()\n", + " inp = f.readline().split()\n", + " for _ in range(num_edges):\n", + " u, v = inp\n", + " G.add_vertex(AdjacencyListGraphNode(u))\n", + " G.add_vertex(AdjacencyListGraphNode(v))\n", + " G.add_edge(u, v, random.randint(1, 1000)) \n", + " inp = f.readline().split()\n", + " return G" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "qRS4Rz-ZRZ51" + }, + "source": [ + "def generate_data(file_name, min_num_edges, max_num_edges, increment):\n", + " \"\"\"\n", + " Generates computation time data for Dijkstra and Bellman ford\n", + " algorithms using pydatastructs.shortest_paths.\n", + "\n", + " Parameters\n", + " ==========\n", + "\n", + " file_path: str\n", + " The path to the file containing California\n", + " road network dataset.\n", + " min_num_edges: int\n", + " The minimum number of edges to be used for\n", + " comparison of algorithms.\n", + " max_num_edges: int\n", + " The maximum number of edges to be used for comparison\n", + " of algorithms.\n", + " increment: int\n", + " The value to be used to increment the scale of the\n", + " shortest path problem. For example if using 50 edges,\n", + " and increment value is 10, then in the next iteration,\n", + " 60 edges will be used and in the next to next iteration,\n", + " 70 edges will be used and so on until we hit the max_num_edges\n", + " value.\n", + "\n", + " Returns\n", + " =======\n", + "\n", + " graph_data, data_dijkstra, data_bellman_ford: (list, list, list)\n", + " graph_data contains tuples of number of vertices and number\n", + " of edges.\n", + " data_dijkstra contains the computation time values for each\n", + " graph when Dijkstra algorithm is used.\n", + " data_bellman_ford contains the computation time values for each\n", + " graph when Bellman ford algorithm is used. \n", + " \"\"\"\n", + " data_dijkstra, data_bellman_ford, graph_data = [], [], []\n", + " for edge in range(min_num_edges, max_num_edges + 1, increment):\n", + " G = create_Graph(edge, file_name)\n", + " t = timeit.Timer(functools.partial(shortest_paths, G, 'dijkstra', '1'))\n", + " t_djk = t.repeat(1, 1)\n", + " t = timeit.Timer(functools.partial(shortest_paths, G, 'bellman_ford', '1'))\n", + " t_bf = t.repeat(1, 1)\n", + " graph_data.append((len(G.vertices), len(G.edge_weights)))\n", + " data_dijkstra.append(t_djk[0])\n", + " data_bellman_ford.append(t_bf[0])\n", + " return graph_data, data_dijkstra, data_bellman_ford" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "GTeSF1ChA2Bz" + }, + "source": [ + "def plot_data(graph_data, data_dijkstra, data_bellman_ford):\n", + " \"\"\"\n", + " Utility function to plot the computation time values\n", + " for Dijkstra and Bellman ford algorithms versus\n", + " the inverse density of the input graph.\n", + " \"\"\"\n", + " idensity, time_dijkstra, time_bellman_ford = [], [], []\n", + " for datum_graph, datum_djk, datum_bf in zip(graph_data, data_dijkstra, data_bellman_ford):\n", + " num_edges, num_vertices = datum_graph[1], datum_graph[0]\n", + " idensity.append((num_vertices*(num_vertices - 1))/(2*num_edges))\n", + " time_dijkstra.append(datum_djk)\n", + " time_bellman_ford.append(datum_bf)\n", + " plt.xlabel(\"Inverse Density of Input Graph\")\n", + " plt.ylabel(\"Computation Time (s)\")\n", + " plt.plot(idensity, time_dijkstra, label=\"Dijkstra\")\n", + " plt.plot(idensity, time_bellman_ford, label=\"Bellman Ford\")\n", + " plt.legend(loc=\"best\")\n", + " plt.show()" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "UXqC736NXfs2" + }, + "source": [ + "graph_data, data_djk, data_bf = generate_data('roadNet-CA.txt', 50, 2000, 50)" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 300 + }, + "id": "EEEPGwOpV_DC", + "outputId": "8e84de7b-c905-4cd1-e075-514982c2ef22" + }, + "source": [ + "plot_data(graph_data, data_djk, data_bf)" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + } + } + ] + } + ] +} \ No newline at end of file diff --git a/docs/source/tutorials.rst b/docs/source/tutorials.rst index 704b4b19c..519b9ac6a 100644 --- a/docs/source/tutorials.rst +++ b/docs/source/tutorials.rst @@ -4,7 +4,7 @@ Tutorials We provide the following tutorials to show how ``pydatastructs`` APIs can help in solving complicated data structures and algorithms problems easily. For now the problems are abstract. However, we plan -to add some examples showing usage of ``pydatastructs`` on real world +to add some more examples showing usage of ``pydatastructs`` on real world data sets such as `Stanford Large Network Dataset Collection `_ and `Urban Dictionary Words And Definitions `_. If you are interested in playing around with the above datasets using our API, From 1f539300f16e862a325df710912021d9f3fd7dc2 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Sun, 31 Oct 2021 23:51:58 +0530 Subject: [PATCH 10/13] Added salient features of PyDataStructs (#428) --- docs/source/index.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/source/index.rst b/docs/source/index.rst index 8ca90a45e..5138f0242 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -29,6 +29,21 @@ You can install the package by running the following command, Make sure that your python version is at least ``3.5``. +Why PyDataStructs? +================== + +1. **Single package for all your data structures and algorithms** - We have and are + implementing many popular and useful data structures and algorithms. + +2. **Consistent and Clean Interface** - The APIs we have provided are **consistent** with each other, + **clean** and **easy to use**. We make sure of that before adding any new data structure or algorithm. + +3. **Well Tested** - We thoroughly test our code before making any new addition to PyDataStructs. + **99 percent** lines of our code have already been tested by us. + +So, **you can easily rely on PyDataStructs** for any data structure or algorithm you want to use +**without worrying about implementing** it **from scratch**. Everything is just a few calls away. + Why do we use Python? ===================== From b7a2f24a7d05dccf3d72fc60d4fc021d610d8b89 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Mon, 1 Nov 2021 00:01:21 +0530 Subject: [PATCH 11/13] Bumped to 0.0.1-beta --- docs/source/conf.py | 2 +- docs/source/index.rst | 2 +- pydatastructs/__init__.py | 2 +- setup.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 95974a93a..ad0f9cda9 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -26,7 +26,7 @@ master_doc = 'index' # The full version, including alpha/beta/rc tags -release = '0.0.1-alpha' +release = '0.0.1-beta' # -- General configuration --------------------------------------------------- diff --git a/docs/source/index.rst b/docs/source/index.rst index 5138f0242..27f7dc72c 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -25,7 +25,7 @@ Installation You can install the package by running the following command, -``pip install cz-pydatastructs`` +``pip install cz-pydatastructs==0.0.1b0`` Make sure that your python version is at least ``3.5``. diff --git a/pydatastructs/__init__.py b/pydatastructs/__init__.py index 4dad188e0..2692b64ad 100644 --- a/pydatastructs/__init__.py +++ b/pydatastructs/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.0.1-alpha" +__version__ = "0.0.1-beta" from .linear_data_structures import * from .trees import * diff --git a/setup.py b/setup.py index 589c0de98..21ea96c1e 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="cz-pydatastructs", - version="0.0.1-alpha", + version="0.0.1-beta", author="PyDataStructs Development Team", author_email="pydatastructs@googlegroups.com", description="A python package for data structures", From fd8e66cfccd6cd252c745f69f6274e0d7cf6f9ec Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Sun, 14 Nov 2021 19:19:31 +0530 Subject: [PATCH 12/13] Bumped to 0.0.1 --- docs/source/conf.py | 2 +- docs/source/index.rst | 2 +- pydatastructs/__init__.py | 2 +- setup.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index ad0f9cda9..b2c712374 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -26,7 +26,7 @@ master_doc = 'index' # The full version, including alpha/beta/rc tags -release = '0.0.1-beta' +release = '0.0.1' # -- General configuration --------------------------------------------------- diff --git a/docs/source/index.rst b/docs/source/index.rst index 27f7dc72c..4e2bbe094 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -25,7 +25,7 @@ Installation You can install the package by running the following command, -``pip install cz-pydatastructs==0.0.1b0`` +``pip install cz-pydatastructs==0.0.1`` Make sure that your python version is at least ``3.5``. diff --git a/pydatastructs/__init__.py b/pydatastructs/__init__.py index 2692b64ad..120a947fd 100644 --- a/pydatastructs/__init__.py +++ b/pydatastructs/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.0.1-beta" +__version__ = "0.0.1" from .linear_data_structures import * from .trees import * diff --git a/setup.py b/setup.py index 21ea96c1e..fba8997a3 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="cz-pydatastructs", - version="0.0.1-beta", + version="0.0.1", author="PyDataStructs Development Team", author_email="pydatastructs@googlegroups.com", description="A python package for data structures", From 714586b647b0f886b07ffea10b1064bb203a4e1a Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Sun, 14 Nov 2021 19:46:06 +0530 Subject: [PATCH 13/13] Updated for master --- docs/source/conf.py | 2 +- docs/source/index.rst | 17 ++++++++++++++--- pydatastructs/__init__.py | 2 +- setup.py | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index b2c712374..f096ee613 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -26,7 +26,7 @@ master_doc = 'index' # The full version, including alpha/beta/rc tags -release = '0.0.1' +release = '1.0.1-dev' # -- General configuration --------------------------------------------------- diff --git a/docs/source/index.rst b/docs/source/index.rst index 4e2bbe094..9a12f0d64 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -23,11 +23,22 @@ code in C++ and Java as well. Installation ============ -You can install the package by running the following command, +After changing your directory to project root, you can +install the package by running the following command, -``pip install cz-pydatastructs==0.0.1`` +``python -m pip install .`` -Make sure that your python version is at least ``3.5``. +For development purposes, you can use the option `e` as shown below, + +``python -m pip install -e .`` + +For building documentation execute the following commands one after +the other, + +1. ``pip install -r docs/requirements.txt`` +2. ``sphinx-build -b html docs/source/ docs/build/html`` + +Make sure that your python version is at least ``3.8``. Why PyDataStructs? ================== diff --git a/pydatastructs/__init__.py b/pydatastructs/__init__.py index 120a947fd..41f351945 100644 --- a/pydatastructs/__init__.py +++ b/pydatastructs/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.0.1" +__version__ = "1.0.1-dev" from .linear_data_structures import * from .trees import * diff --git a/setup.py b/setup.py index fba8997a3..45f293265 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setuptools.setup( name="cz-pydatastructs", - version="0.0.1", + version="1.0.1-dev", author="PyDataStructs Development Team", author_email="pydatastructs@googlegroups.com", description="A python package for data structures",