Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
ready for docs
  • Loading branch information
czgdp1807 committed May 30, 2020
commit 7319f0a191663f2aa0b347cebb4ca765a1d42d60
3 changes: 2 additions & 1 deletion pydatastructs/graphs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
minimum_spanning_tree,
minimum_spanning_tree_parallel,
strongly_connected_components,
depth_first_search
depth_first_search,
shortest_paths
)

__all__.extend(algorithms.__all__)
43 changes: 42 additions & 1 deletion pydatastructs/graphs/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from collections import deque
from concurrent.futures import ThreadPoolExecutor
from pydatastructs.utils import GraphEdge
from pydatastructs.utils.misc_util import GraphNode
from pydatastructs.utils.misc_util import _comp
from pydatastructs.miscellaneous_data_structures import (
DisjointSetForest, PriorityQueue)
Expand All @@ -17,7 +18,8 @@
'minimum_spanning_tree',
'minimum_spanning_tree_parallel',
'strongly_connected_components',
'depth_first_search'
'depth_first_search',
'shortest_paths'
]

Stack = Queue = deque
Expand Down Expand Up @@ -637,3 +639,42 @@ def _depth_first_search_adjacency_list(
return None

_depth_first_search_adjacency_matrix = _depth_first_search_adjacency_list

def shortest_paths(graph: Graph, algorithm: str,
source: str, target: str="") -> tuple:
import pydatastructs.graphs.algorithms as algorithms
func = "_" + algorithm + "_" + graph._impl
if not hasattr(algorithms, func):
raise NotImplementedError(
"Currently %s algorithm isn't implemented for "
"finding shortest paths in graphs."%(algorithm))
return getattr(algorithms, func)(graph, source, target)

def _bellman_ford_adjacency_list(graph: Graph, source: str, target: str) -> tuple:
distances, predecessor = dict(), dict()

for v in graph.vertices:
distances[v] = float('inf')
predecessor[v] = None
distances[source] = 0

edges = graph.edge_weights.values()
for _ in range(len(graph.vertices) - 1):
for edge in edges:
u, v = edge.source.name, edge.target.name
w = edge.value
if distances[u] + edge.value < distances[v]:
distances[v] = distances[u] + w
predecessor[v] = u

for edge in edges:
u, v = edge.source.name, edge.target.name
w = edge.value
if distances[u] + w < distances[v]:
raise ValueError("Graph contains a negative weight cycle.")

if target != "":
return (distances[target], predecessor)
return (distances, predecessor)

_bellman_ford_adjacency_matrix = _bellman_ford_adjacency_list
35 changes: 33 additions & 2 deletions pydatastructs/graphs/tests/test_algorithms.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from pydatastructs import (breadth_first_search, Graph,
breadth_first_search_parallel, minimum_spanning_tree,
minimum_spanning_tree_parallel, strongly_connected_components,
depth_first_search)

depth_first_search, shortest_paths)
from pydatastructs.utils.raises_util import raises

def test_breadth_first_search():

Expand Down Expand Up @@ -258,3 +258,34 @@ def path_finder(curr_node, next_node, dest_node, parent, path):

_test_depth_first_search("List")
_test_depth_first_search("Matrix")

def test_shortest_paths():

def _test_shortest_paths(ds, algorithm):
import pydatastructs.utils.misc_util as utils
GraphNode = getattr(utils, "Adjacency" + ds + "GraphNode")
vertices = [GraphNode('S'), GraphNode('C'),
GraphNode('SLC'), GraphNode('SF'),
GraphNode('D')]

graph = Graph(*vertices)
graph.add_edge('S', 'SLC', 2)
graph.add_edge('C', 'S', 4)
graph.add_edge('C', 'D', 2)
graph.add_edge('SLC', 'C', 2)
graph.add_edge('SLC', 'D', 3)
graph.add_edge('SF', 'SLC', 2)
graph.add_edge('SF', 'S', 2)
graph.add_edge('D', 'SF', 3)
dist, pred = shortest_paths(graph, algorithm, 'SLC')
assert dist == {'S': 6, 'C': 2, 'SLC': 0, 'SF': 6, 'D': 3}
assert pred == {'S': 'C', 'C': 'SLC', 'SLC': None, 'SF': 'D', 'D': 'SLC'}
dist, pred = shortest_paths(graph, algorithm, 'SLC', 'SF')
assert dist == 6
assert pred == {'S': 'C', 'C': 'SLC', 'SLC': None, 'SF': 'D', 'D': 'SLC'}
graph.remove_edge('SLC', 'D')
graph.add_edge('D', 'SLC', -10)
assert raises(ValueError, lambda: shortest_paths(graph, 'bellman_ford', 'SLC'))

_test_shortest_paths("List", 'bellman_ford')
_test_shortest_paths("Matrix", 'bellman_ford')