-
Notifications
You must be signed in to change notification settings - Fork 269
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
187 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ | |
from .trees import * | ||
from .miscellaneous_data_structures import * | ||
from .utils import * | ||
from .graphs import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
""" | ||
Contains all the algorithms associated with graph | ||
data structure. | ||
""" | ||
# TODO: REPLACE COLLECTIONS QUEUE WITH PYDATASTRUCTS QUEUE | ||
from collections import deque as Queue | ||
from pydatastructs.utils.misc_util import AdjacencyListGraphNode | ||
|
||
__all__ = [ | ||
'breadth_first_search', | ||
] | ||
|
||
def breadth_first_search( | ||
graph, source_node, operation, *args, **kwargs): | ||
""" | ||
Implementation of serial breadth first search(BFS) | ||
algorithm. | ||
Parameters | ||
========== | ||
graph: Graph | ||
The graph on which BFS is to be performed. | ||
source_node: str | ||
The name of the source node from where the BFS is | ||
to be initiated. | ||
operation: function | ||
The function which is to be applied | ||
on every node when it is visited. | ||
The prototype which is to be followed is, | ||
`function_name(curr_node, next_node, | ||
arg_1, arg_2, . . ., arg_n)`. | ||
Here, the first two arguments denote, the | ||
current node and the node next to current node. | ||
The rest of the arguments are optional and you can | ||
provide your own stuff there. | ||
Note | ||
==== | ||
You should pass all the arguments which you are going | ||
to use in the prototype of your `operation` after | ||
passing the operation function. | ||
Examples | ||
======== | ||
>>> from pydatastructs import Graph, AdjacencyListGraphNode | ||
>>> V1 = AdjacencyListGraphNode("V1") | ||
>>> V2 = AdjacencyListGraphNode("V2") | ||
>>> V3 = AdjacencyListGraphNode("V3") | ||
>>> G = Graph(V1, V2, V3) | ||
>>> from pydatastructs import breadth_first_search | ||
>>> def f(curr_node, next_node, dest_node): | ||
... return curr_node != dest_node | ||
... | ||
>>> G.add_edge(V1.name, V2.name) | ||
>>> G.add_edge(V2.name, V3.name) | ||
>>> breadth_first_search(G, V1.name, f, V3.name) | ||
""" | ||
import pydatastructs.graphs.algorithms as algorithms | ||
func = "_breadth_first_search_" + graph._impl | ||
if not hasattr(algorithms, func): | ||
raise NotImplementedError( | ||
"Currently breadth first search isn't implemented for " | ||
"%s graphs."%(graph._impl)) | ||
return getattr(algorithms, func)( | ||
graph, source_node, operation, *args, **kwargs) | ||
|
||
def _breadth_first_search_adjacency_list( | ||
graph, source_node, operation, *args, **kwargs): | ||
bfs_queue = Queue() | ||
visited = dict() | ||
bfs_queue.append(source_node) | ||
visited[source_node] = True | ||
while len(bfs_queue) != 0: | ||
curr_node = bfs_queue.popleft() | ||
next_nodes = graph.neighbors(curr_node) | ||
if len(next_nodes) != 0: | ||
for next_node in next_nodes: | ||
if visited.get(next_node.name, False) is False: | ||
status = operation(curr_node, next_node.name, *args, **kwargs) | ||
if not status: | ||
return None | ||
bfs_queue.append(next_node.name) | ||
visited[next_node.name] = True | ||
else: | ||
status = operation(curr_node, "", *args, **kwargs) | ||
if not status: | ||
return None | ||
|
||
_breadth_first_search_adjacency_matrix = _breadth_first_search_adjacency_list |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
from pydatastructs import breadth_first_search, Graph | ||
|
||
|
||
def test_breadth_first_search(): | ||
|
||
def _test_breadth_first_search(ds, impl): | ||
import pydatastructs.utils.misc_util as utils | ||
GraphNode = getattr(utils, "Adjacency" + ds + "GraphNode") | ||
|
||
V1 = GraphNode(0) | ||
V2 = GraphNode(1) | ||
V3 = GraphNode(2) | ||
|
||
G1 = Graph(V1, V2, V3, implementation=impl) | ||
|
||
edges = [ | ||
(V1.name, V2.name), | ||
(V2.name, V3.name), | ||
(V1.name, V3.name) | ||
] | ||
|
||
for edge in edges: | ||
G1.add_edge(*edge) | ||
|
||
parent = dict() | ||
def bfs_tree(curr_node, next_node, parent): | ||
if next_node != "": | ||
parent[next_node] = curr_node | ||
return True | ||
|
||
breadth_first_search(G1, V1.name, bfs_tree, parent) | ||
assert (parent[V3.name] == V1.name and parent[V2.name] == V1.name) or \ | ||
(parent[V3.name] == V2.name and parent[V2.name] == V1.name) | ||
|
||
V4 = GraphNode(0) | ||
V5 = GraphNode(1) | ||
V6 = GraphNode(2) | ||
V7 = GraphNode(3) | ||
V8 = GraphNode(4) | ||
|
||
edges = [ | ||
(V4.name, V5.name), | ||
(V5.name, V6.name), | ||
(V6.name, V7.name), | ||
(V6.name, V4.name), | ||
(V7.name, V8.name) | ||
] | ||
|
||
G2 = Graph(V4, V5, V6, V7, V8, implementation=impl) | ||
|
||
for edge in edges: | ||
G2.add_edge(*edge) | ||
|
||
path = [] | ||
def path_finder(curr_node, next_node, dest_node, parent, path): | ||
if next_node != "": | ||
parent[next_node] = curr_node | ||
if curr_node == dest_node: | ||
node = curr_node | ||
path.append(node) | ||
while node is not None: | ||
if parent.get(node, None) is not None: | ||
path.append(parent[node]) | ||
node = parent.get(node, None) | ||
path.reverse() | ||
return False | ||
return True | ||
|
||
parent.clear() | ||
breadth_first_search(G2, V4.name, path_finder, V7.name, parent, path) | ||
assert path == [V4.name, V5.name, V6.name, V7.name] | ||
|
||
_test_breadth_first_search("List", "adjacency_list") | ||
_test_breadth_first_search("Matrix", "adjacency_matrix") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters