Skip to content

Backport 0.0.1 #430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Nov 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,11 @@ Keep contributing!!
Thanks to these wonderful people ✨✨:

<table>
<tr>
<td>
<a href="https://github.com/codezonediitj/pydatastructs/graphs/contributors">
<img src="https://contrib.rocks/image?repo=codezonediitj/pydatastructs" />
</a>
</td>
</tr>
<tr>
<td>
<a href="https://github.com/codezonediitj/pydatastructs/graphs/contributors">
<img src="https://contrib.rocks/image?repo=codezonediitj/pydatastructs" />
</a>
</td>
</tr>
</table>
3 changes: 2 additions & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
sphinx==4.2.0
sphinx-readable-theme==1.3.0
sphinx-readable-theme==1.3.0
myst_nb==0.13.1
7 changes: 5 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
master_doc = 'index'

# The full version, including alpha/beta/rc tags
release = '0.0.1-dev'
release = '1.0.1-dev'


# -- General configuration ---------------------------------------------------
Expand All @@ -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.
Expand Down
16 changes: 16 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@ the other,

Make sure that your python version is at least ``3.8``.

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?
=====================

Expand All @@ -59,6 +74,7 @@ Contents
:maxdepth: 1

tutorials.rst
pydatastructs_sphinx_graphs
contributing.rst
authors.rst
pydatastructs/pydatastructs.rst
243 changes: 243 additions & 0 deletions docs/source/pydatastructs_sphinx_graphs.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/source/tutorials.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://snap.stanford.edu/data/>`_
and `Urban Dictionary Words And Definitions <https://www.kaggle.com/therohk/urban-dictionary-words-dataset>`_.
If you are interested in playing around with the above datasets using our API,
Expand Down
2 changes: 1 addition & 1 deletion pydatastructs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.0.1-dev"
__version__ = "1.0.1-dev"

from .linear_data_structures import *
from .trees import *
Expand Down
19 changes: 16 additions & 3 deletions pydatastructs/graphs/adjacency_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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] = \
Expand Down
12 changes: 12 additions & 0 deletions pydatastructs/graphs/adjacency_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -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] = \
Expand Down
15 changes: 13 additions & 2 deletions pydatastructs/graphs/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']
Expand Down Expand Up @@ -89,15 +99,16 @@ 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.")

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.")
Expand Down
4 changes: 4 additions & 0 deletions pydatastructs/graphs/tests/test_adjacency_list.py
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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'))
4 changes: 4 additions & 0 deletions pydatastructs/graphs/tests/test_adjacency_matrix.py
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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'))
6 changes: 4 additions & 2 deletions pydatastructs/linear_data_structures/arrays.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ def __str__(self) -> str:

class OneDimensionalArray(Array):
'''
Represents one dimensional arrays.
Represents one dimensional static arrays of
fixed size.

Parameters
==========
Expand Down Expand Up @@ -269,7 +270,8 @@ class DynamicArray(Array):

class DynamicOneDimensionalArray(DynamicArray, OneDimensionalArray):
"""
Represents dynamic one dimensional arrays.
Represents resizable and dynamic one
dimensional arrays.

Parameters
==========
Expand Down
18 changes: 8 additions & 10 deletions pydatastructs/miscellaneous_data_structures/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.")
Expand All @@ -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)


Expand All @@ -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
5 changes: 1 addition & 4 deletions pydatastructs/miscellaneous_data_structures/sparse_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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

Expand All @@ -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)
5 changes: 2 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
long_description = fh.read()

setuptools.setup(
name="pydatastructs",
version="0.0.1-dev",
name="cz-pydatastructs",
version="1.0.1-dev",
author="PyDataStructs Development Team",
author_email="pydatastructs@googlegroups.com",
description="A python package for data structures",
Expand All @@ -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"
Expand Down