From 10fb100dc63de1d7104f8e94bad9f50463f61a9d Mon Sep 17 00:00:00 2001 From: adikele Date: Sun, 22 Jul 2018 22:02:15 +0300 Subject: [PATCH 1/7] Update minmax.py The function for finding the Minimum Spanning Tree (mst) in the minmax file seems to be in error: one of the edges is displayed twice in the mst. I have rewritten the function for finding the mst and deleted the earlier one; the edges are now correctly displayed. Additionally, the weight of the mst is also displayed. The MinSpanningTree branch contains this rewritten function in place of the original mst function. The difference between the output of the functions in the two versions is demonstrated with the help of an example: g = graph() g.add_node('A') g.add_node('B') g.add_node('C') g.add_node('D') g.add_node('E') g.add_edge(('A', 'C'), 10, 'AC') g.add_edge(('A', 'D'), 7, 'AD') g.add_edge(('B', 'D'), 32, 'BD') g.add_edge(('C', 'D'), 9, 'CD') g.add_edge(('D', 'E'), 23, 'DE') using the current function:{'A': 'D', 'C': 'D', 'B': 'D', 'E': 'D', 'D': 'B'} using the new function in MinSpanningTree branch [('A', 'D'), ('D', 'C'), ('D', 'E'), ('D', 'B'), 71] --- core/pygraph/algorithms/minmax.py | 69 ++++++++++++++++++------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/core/pygraph/algorithms/minmax.py b/core/pygraph/algorithms/minmax.py index bbca0d2..0bd597b 100644 --- a/core/pygraph/algorithms/minmax.py +++ b/core/pygraph/algorithms/minmax.py @@ -46,7 +46,7 @@ # Minimal spanning tree -def minimal_spanning_tree_prim(graph, root=None, parallel=None): +def minimal_spanning_tree_prim (graphFn, nodeX=None): """ Minimal spanning tree constructed with prim's algorithm. @@ -56,38 +56,51 @@ def minimal_spanning_tree_prim(graph, root=None, parallel=None): @param graph: Graph. @type root: node - @param root: Optional root node (will explore only root's connected component) + @param root: Optional root node - @rtype: dictionary - @return: Generated spanning tree. + @rtype: list of (i) tuples containing edges and (ii) an integer (last item) + @return: Generated minimal spanning tree (mst); weight of mst is appended to the list's end """ - visited = [] # List for marking visited and non-visited nodes - spanning_tree = {} # Minimal Spanning tree + if nodeX == None: #If a node is not given + NodesNotInTreeList = graphFn.nodes() #all nodes in the beginning minus the one that has been taken in the tree + NodeToBeAddedToTree = NodesNotInTreeList[0] + NodesInTreeList = [] + NodesInTreeList.append(NodeToBeAddedToTree) + NodesNotInTreeList.remove(NodeToBeAddedToTree) + edgesInTreeList = [ ] + else: #If a node is given + NodesNotInTreeList = graphFn.nodes() #all nodes in the beginning minus the one that has been taken in the tree + NodeToBeAddedToTree = nodeX + NodesInTreeList = [] + NodesInTreeList.append(NodeToBeAddedToTree) + NodesNotInTreeList.remove(NodeToBeAddedToTree) + edgesInTreeList = [ ] + + while NodesNotInTreeList != [ ]: + #for every node from NodesInTreeList, use le = _lightest_edge(graph, visited) + #where visited = NodesInTreeList + le = _lightest_edge(graphFn, NodesInTreeList) + + #for a specific pass through WHILE loop + for a in le: #STEP 1: obtain the 'selected node' which is that end of lightest edge "le" not yet in the tree + if a not in NodesInTreeList: + selectedNode = a + else: + pass + + edgesInTreeList.append (le) #STEP 2: add the lightest edge "le" to the edgesInTreeList list + NodesInTreeList.append (selectedNode) #STEP 3: add the 'selected node' to the NodesInTreeList list + NodesNotInTreeList.remove(selectedNode) #STEP 4: remove the 'selected node' from the NodesNotInTreeList list - # Initialization - if (root is not None): - visited.append(root) - nroot = root - spanning_tree[root] = None - else: - nroot = 1 + mstWtTotal = 0 + + for a in edgesInTreeList: + mstWtTotal = mstWtTotal + graphFn.edge_weight((a)) - # Algorithm loop - while (nroot is not None): - ledge = _lightest_edge(graph, visited) - if (ledge is None): - if (root is not None): - break - nroot = _first_unvisited(graph, visited) - if (nroot is not None): - spanning_tree[nroot] = None - visited.append(nroot) - else: - spanning_tree[ledge[1]] = ledge[0] - spanning_tree[ledge[0]] = ledge[1] - visited.append(ledge[1]) + edgesInTreeList.append(mstWtTotal) + + return (edgesInTreeList) - return spanning_tree def minimal_spanning_tree_kruskal(graph, root=None, parallel=None): From 31a8b4d120902e54153d552601fafb3500743179 Mon Sep 17 00:00:00 2001 From: adikele Date: Wed, 25 Jul 2018 15:51:01 +0300 Subject: [PATCH 2/7] Update minmax.py --- core/pygraph/algorithms/minmax.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/pygraph/algorithms/minmax.py b/core/pygraph/algorithms/minmax.py index 0bd597b..fed27ba 100644 --- a/core/pygraph/algorithms/minmax.py +++ b/core/pygraph/algorithms/minmax.py @@ -46,7 +46,7 @@ # Minimal spanning tree -def minimal_spanning_tree_prim (graphFn, nodeX=None): +def minimal_spanning_tree_prim (graphFn, root=None): """ Minimal spanning tree constructed with prim's algorithm. @@ -61,7 +61,7 @@ def minimal_spanning_tree_prim (graphFn, nodeX=None): @rtype: list of (i) tuples containing edges and (ii) an integer (last item) @return: Generated minimal spanning tree (mst); weight of mst is appended to the list's end """ - if nodeX == None: #If a node is not given + if root == None: #If a node is not given NodesNotInTreeList = graphFn.nodes() #all nodes in the beginning minus the one that has been taken in the tree NodeToBeAddedToTree = NodesNotInTreeList[0] NodesInTreeList = [] @@ -70,7 +70,7 @@ def minimal_spanning_tree_prim (graphFn, nodeX=None): edgesInTreeList = [ ] else: #If a node is given NodesNotInTreeList = graphFn.nodes() #all nodes in the beginning minus the one that has been taken in the tree - NodeToBeAddedToTree = nodeX + NodeToBeAddedToTree = root NodesInTreeList = [] NodesInTreeList.append(NodeToBeAddedToTree) NodesNotInTreeList.remove(NodeToBeAddedToTree) From 4df82db31690eb40760c1e20eed342eb9444465a Mon Sep 17 00:00:00 2001 From: adikele Date: Wed, 25 Jul 2018 16:04:26 +0300 Subject: [PATCH 3/7] Update minmax.py --- core/pygraph/algorithms/minmax.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/pygraph/algorithms/minmax.py b/core/pygraph/algorithms/minmax.py index fed27ba..e0f433c 100644 --- a/core/pygraph/algorithms/minmax.py +++ b/core/pygraph/algorithms/minmax.py @@ -92,12 +92,12 @@ def minimal_spanning_tree_prim (graphFn, root=None): NodesInTreeList.append (selectedNode) #STEP 3: add the 'selected node' to the NodesInTreeList list NodesNotInTreeList.remove(selectedNode) #STEP 4: remove the 'selected node' from the NodesNotInTreeList list - mstWtTotal = 0 + #mstWtTotal = 0 - for a in edgesInTreeList: - mstWtTotal = mstWtTotal + graphFn.edge_weight((a)) + #for a in edgesInTreeList: + #mstWtTotal = mstWtTotal + graphFn.edge_weight((a)) - edgesInTreeList.append(mstWtTotal) + #edgesInTreeList.append(mstWtTotal) return (edgesInTreeList) From bba448818865e41316dce1b8f8c3aeaa635f5830 Mon Sep 17 00:00:00 2001 From: adikele Date: Thu, 26 Jul 2018 21:34:46 +0300 Subject: [PATCH 4/7] Update unittests-minmax.py tree_weight function is rewritten to accept tree as a List of Tuples --- tests/unittests-minmax.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unittests-minmax.py b/tests/unittests-minmax.py index 972fcfa..863f21c 100644 --- a/tests/unittests-minmax.py +++ b/tests/unittests-minmax.py @@ -43,10 +43,10 @@ # helpers -def tree_weight(gr, tree): +def tree_weight(gr, tree): # tree as a List of Tuples sum = 0; for each in tree: - sum = sum + gr.edge_weight((each, tree[each])) + sum = sum + gr.edge_weight(each) return sum def add_spanning_tree(gr, st): From b5bcec77c05dfa960e2703255b69cff9e8a66fcc Mon Sep 17 00:00:00 2001 From: adikele Date: Fri, 27 Jul 2018 14:39:34 +0300 Subject: [PATCH 5/7] Update unittests-minmax.py --- tests/unittests-minmax.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unittests-minmax.py b/tests/unittests-minmax.py index 863f21c..972fcfa 100644 --- a/tests/unittests-minmax.py +++ b/tests/unittests-minmax.py @@ -43,10 +43,10 @@ # helpers -def tree_weight(gr, tree): # tree as a List of Tuples +def tree_weight(gr, tree): sum = 0; for each in tree: - sum = sum + gr.edge_weight(each) + sum = sum + gr.edge_weight((each, tree[each])) return sum def add_spanning_tree(gr, st): From f8695ebe760288b045af7b5caaebdcb14f3119c4 Mon Sep 17 00:00:00 2001 From: adikele Date: Fri, 27 Jul 2018 14:53:23 +0300 Subject: [PATCH 6/7] Update minmax.py --- core/pygraph/algorithms/minmax.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/core/pygraph/algorithms/minmax.py b/core/pygraph/algorithms/minmax.py index e0f433c..9cc3bc8 100644 --- a/core/pygraph/algorithms/minmax.py +++ b/core/pygraph/algorithms/minmax.py @@ -44,12 +44,12 @@ import bisect # Minimal spanning tree - - def minimal_spanning_tree_prim (graphFn, root=None): """ + author:Aditya Kelekar Minimal spanning tree constructed with prim's algorithm. - + returns tree in dict form + @attention: Minimal spanning tree is meaningful only for weighted graphs. @type graph: graph @@ -58,8 +58,8 @@ def minimal_spanning_tree_prim (graphFn, root=None): @type root: node @param root: Optional root node - @rtype: list of (i) tuples containing edges and (ii) an integer (last item) - @return: Generated minimal spanning tree (mst); weight of mst is appended to the list's end + @rtype: dict of edges + @return: Generated minimal spanning tree (mst) """ if root == None: #If a node is not given NodesNotInTreeList = graphFn.nodes() #all nodes in the beginning minus the one that has been taken in the tree @@ -92,14 +92,16 @@ def minimal_spanning_tree_prim (graphFn, root=None): NodesInTreeList.append (selectedNode) #STEP 3: add the 'selected node' to the NodesInTreeList list NodesNotInTreeList.remove(selectedNode) #STEP 4: remove the 'selected node' from the NodesNotInTreeList list - #mstWtTotal = 0 + #mstWtTotal = 0 #setZ: commenting out, so mst is no longer appended #for a in edgesInTreeList: - #mstWtTotal = mstWtTotal + graphFn.edge_weight((a)) + # mstWtTotal = mstWtTotal + graphFn.edge_weight((a)) - #edgesInTreeList.append(mstWtTotal) + #edgesInTreeList.append(mstWtTotal) #setZ: commenting out, so mst is no longer appended - return (edgesInTreeList) + edgesInTreeDict = {} + helperConvertListtoDict (edgesInTreeList, edgesInTreeDict) + return (edgesInTreeDict) From eeec043c36eb335117fd5a9d69c01c672a34bbb0 Mon Sep 17 00:00:00 2001 From: adikele Date: Fri, 27 Jul 2018 16:57:50 +0300 Subject: [PATCH 7/7] Update minmax.py --- core/pygraph/algorithms/minmax.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/pygraph/algorithms/minmax.py b/core/pygraph/algorithms/minmax.py index 9cc3bc8..760888c 100644 --- a/core/pygraph/algorithms/minmax.py +++ b/core/pygraph/algorithms/minmax.py @@ -43,6 +43,16 @@ import heapq import bisect +#helper function to convert a list of tuples into a dictionary -- first element of a tuple is made the key when converting to dict form +#if more than one tuple has the same first element, for the rest of the tuples, the second element is made the key when converting to dict form +def helperConvertListtoDict(listX, dictY): + for a in listX: + if a[0] not in dictY: + dictY [a[0]] = a[1] + else: + dictY [a[1]] = a[0] + return dictY + # Minimal spanning tree def minimal_spanning_tree_prim (graphFn, root=None): """