7
7
from pydatastructs .utils import GraphEdge
8
8
from pydatastructs .miscellaneous_data_structures import DisjointSetForest
9
9
from pydatastructs .graphs .graph import Graph
10
+ from pydatastructs .linear_data_structures .algorithms import merge_sort_parallel
10
11
11
12
__all__ = [
12
13
'breadth_first_search' ,
13
14
'breadth_first_search_parallel' ,
14
- 'minimum_spanning_tree'
15
+ 'minimum_spanning_tree' ,
16
+ 'minimum_spanning_tree_parallel'
15
17
]
16
18
17
19
def breadth_first_search (
@@ -190,36 +192,109 @@ def _breadth_first_search_parallel_adjacency_list(
190
192
191
193
_breadth_first_search_parallel_adjacency_matrix = _breadth_first_search_parallel_adjacency_list
192
194
195
+ def _generate_mst_object (graph ):
196
+ mst = Graph (* [getattr (graph , str (v )) for v in graph .vertices ])
197
+ return mst
198
+
199
+ def _sort_edges (graph , num_threads = None ):
200
+ edges = list (graph .edge_weights .items ())
201
+ if num_threads is None :
202
+ sort_key = lambda item : item [1 ].value
203
+ return sorted (edges , key = sort_key )
204
+
205
+ merge_sort_parallel (edges , num_threads ,
206
+ comp = lambda u ,v : u [1 ].value <= v [1 ].value )
207
+ return edges
208
+
193
209
def _minimum_spanning_tree_kruskal_adjacency_list (graph ):
194
- mst = Graph (* [getattr (graph , v ) for v in graph .vertices ])
195
- sort_key = lambda item : item [1 ].value
210
+ mst = _generate_mst_object (graph )
196
211
dsf = DisjointSetForest ()
197
212
for v in graph .vertices :
198
213
dsf .make_set (v )
199
- for _ , edge in sorted (graph . edge_weights . items (), key = sort_key ):
214
+ for _ , edge in _sort_edges (graph ):
200
215
u , v = edge .source .name , edge .target .name
201
216
if dsf .find_root (u ) is not dsf .find_root (v ):
202
217
mst .add_edge (u , v , edge .value )
203
218
dsf .union (u , v )
204
219
return mst
205
220
206
- def _minimum_spanning_tree_kruskal_adjacency_matrix (graph ):
207
- mst = Graph (* [getattr (graph , str (v )) for v in graph .vertices ])
208
- sort_key = lambda item : item [1 ].value
221
+ _minimum_spanning_tree_kruskal_adjacency_matrix = \
222
+ _minimum_spanning_tree_kruskal_adjacency_list
223
+
224
+ def minimum_spanning_tree (graph , algorithm ):
225
+ """
226
+ Computes a minimum spanning tree for the given
227
+ graph and algorithm.
228
+
229
+ Parameters
230
+ ==========
231
+
232
+ graph: Graph
233
+ The graph whose minimum spanning tree
234
+ has to be computed.
235
+ algorithm: str
236
+ The algorithm which should be used for
237
+ computing a minimum spanning tree.
238
+ Currently the following algorithms are
239
+ supported,
240
+ 'kruskal' -> Kruskal's algorithm as given in
241
+ [1].
242
+
243
+ Returns
244
+ =======
245
+
246
+ mst: Graph
247
+ A minimum spanning tree using the implementation
248
+ same as the graph provided in the input.
249
+
250
+ Examples
251
+ ========
252
+
253
+ >>> from pydatastructs import Graph, AdjacencyListGraphNode
254
+ >>> from pydatastructs import minimum_spanning_tree
255
+ >>> u = AdjacencyListGraphNode('u')
256
+ >>> v = AdjacencyListGraphNode('v')
257
+ >>> G = Graph(u, v)
258
+ >>> G.add_edge(u.name, v.name, 3)
259
+ >>> mst = minimum_spanning_tree(G, 'kruskal')
260
+ >>> u_n = mst.neighbors(u.name)
261
+ >>> mst.get_edge(u.name, u_n[0].name).value
262
+ 3
263
+
264
+ References
265
+ ==========
266
+
267
+ .. [1] https://en.wikipedia.org/wiki/Kruskal%27s_algorithm
268
+ """
269
+ import pydatastructs .graphs .algorithms as algorithms
270
+ func = "_minimum_spanning_tree_" + algorithm + "_" + graph ._impl
271
+ if not hasattr (algorithms , func ):
272
+ raise NotImplementedError (
273
+ "Currently %s algoithm for %s implementation of graphs "
274
+ "isn't implemented for finding minimum spanning trees."
275
+ % (algorithm , graph ._impl ))
276
+ return getattr (algorithms , func )(graph )
277
+
278
+ def _minimum_spanning_tree_parallel_kruskal_adjacency_list (graph , num_threads ):
279
+ mst = _generate_mst_object (graph )
209
280
dsf = DisjointSetForest ()
210
281
for v in graph .vertices :
211
282
dsf .make_set (v )
212
- for _ , edge in sorted (graph .edge_weights .items (), key = sort_key ):
283
+ edges = _sort_edges (graph , num_threads )
284
+ for _ , edge in edges :
213
285
u , v = edge .source .name , edge .target .name
214
286
if dsf .find_root (u ) is not dsf .find_root (v ):
215
287
mst .add_edge (u , v , edge .value )
216
288
dsf .union (u , v )
217
289
return mst
218
290
219
- def minimum_spanning_tree (graph , algorithm ):
291
+ _minimum_spanning_tree_parallel_kruskal_adjacency_matrix = \
292
+ _minimum_spanning_tree_parallel_kruskal_adjacency_list
293
+
294
+ def minimum_spanning_tree_parallel (graph , algorithm , num_threads ):
220
295
"""
221
296
Computes a minimum spanning tree for the given
222
- graph and algorithm.
297
+ graph and algorithm using the given number of threads .
223
298
224
299
Parameters
225
300
==========
@@ -234,6 +309,8 @@ def minimum_spanning_tree(graph, algorithm):
234
309
supported,
235
310
'kruskal' -> Kruskal's algorithm as given in
236
311
[1].
312
+ num_threads: int
313
+ The number of threads to be used.
237
314
238
315
Returns
239
316
=======
@@ -246,26 +323,26 @@ def minimum_spanning_tree(graph, algorithm):
246
323
========
247
324
248
325
>>> from pydatastructs import Graph, AdjacencyListGraphNode
249
- >>> from pydatastructs import minimum_spanning_tree
326
+ >>> from pydatastructs import minimum_spanning_tree_parallel
250
327
>>> u = AdjacencyListGraphNode('u')
251
328
>>> v = AdjacencyListGraphNode('v')
252
329
>>> G = Graph(u, v)
253
330
>>> G.add_edge(u.name, v.name, 3)
254
- >>> mst = minimum_spanning_tree (G, 'kruskal')
331
+ >>> mst = minimum_spanning_tree_parallel (G, 'kruskal', 3 )
255
332
>>> u_n = mst.neighbors(u.name)
256
333
>>> mst.get_edge(u.name, u_n[0].name).value
257
334
3
258
335
259
336
References
260
337
==========
261
338
262
- .. [1] https://en.wikipedia.org/wiki/Kruskal%27s_algorithm
339
+ .. [1] https://en.wikipedia.org/wiki/Kruskal%27s_algorithm#Parallel_algorithm
263
340
"""
264
341
import pydatastructs .graphs .algorithms as algorithms
265
- func = "_minimum_spanning_tree_ " + algorithm + "_" + graph ._impl
342
+ func = "_minimum_spanning_tree_parallel_ " + algorithm + "_" + graph ._impl
266
343
if not hasattr (algorithms , func ):
267
344
raise NotImplementedError (
268
345
"Currently %s algoithm for %s implementation of graphs "
269
346
"isn't implemented for finding minimum spanning trees."
270
347
% (algorithm , graph ._impl ))
271
- return getattr (algorithms , func )(graph )
348
+ return getattr (algorithms , func )(graph , num_threads )
0 commit comments