Skip to content

Commit d5247ed

Browse files
committed
Enable descriptive node names
1 parent f71e02c commit d5247ed

File tree

1 file changed

+134
-89
lines changed

1 file changed

+134
-89
lines changed

Classes/graph_edge_list.py

+134-89
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,42 @@
1+
from node import Node
12
class Graph:
23
###################################
34
# Constructor
45
###################################
56
def __init__(self, num_of_nodes, directed=True):
67
self.m_num_of_nodes = num_of_nodes
8+
self.m_nodes = []
79

810
# Define the type of a graph
911
self.m_directed = directed
1012

11-
# Different representations of a graph
13+
# A representation of a graph
1214
# i.e. list of edges
1315
self.m_graph = []
1416

15-
# For Bovurkas
17+
# For Bovurka's algorithm
1618
self.m_components = {}
1719

1820
###################################
1921
# Add edge to a graph
2022
###################################
21-
def add_edge(self, node1, node2, weight=1):
23+
def add_edge(self, node1_name, node2_name, weight=1):
24+
node1 = Node(node1_name)
25+
node2 = Node(node2_name)
26+
if (node1 not in self.m_nodes):
27+
node1_id = len(self.m_nodes)
28+
node1.set_id(node1_id)
29+
self.m_nodes.append(node1)
30+
else:
31+
node1 = self.get_node_by_name(node1_name)
32+
33+
if (node2 not in self.m_nodes):
34+
node2_id = len(self.m_nodes)
35+
node2.set_id(node2_id)
36+
self.m_nodes.append(node2)
37+
else:
38+
node2 = self.get_node_by_name(node2_name)
39+
2240
# Add the edge from node1 to node2
2341
self.m_graph.append([node1, node2, weight])
2442

@@ -37,91 +55,99 @@ def __str__(self):
3755
out += "edge " + str(i+1) + ": " + str(self.m_graph[i]) + "\n"
3856
return out
3957

58+
def get_node_by_name(self, name):
59+
search_node = Node(name)
60+
for node in self.m_nodes:
61+
if node == search_node:
62+
return node
63+
return None
64+
4065
###################################
4166
# Kruskal's MST Algorithm
42-
#### za sada radi samo sa numbered nodes
4367
###################################
44-
# Finds the root node of a subtree containing node `i`
45-
def find_subtree(self, parent, i):
46-
if parent[i] == i:
47-
return i
48-
return self.find_subtree(parent, parent[i])
49-
50-
# Connects subtrees containing nodes `x` and `y`
51-
def connect_subtrees(self, parent, subtree_sizes, x, y):
52-
x_root = self.find_subtree(parent, x)
53-
y_root = self.find_subtree(parent, y)
54-
if subtree_sizes[x_root] < subtree_sizes[y_root]:
55-
parent[x_root] = y_root
56-
elif subtree_sizes[x_root] > subtree_sizes[y_root]:
57-
parent[y_root] = x_root
68+
# Finds the root node of a subtree containing node `node`
69+
def find_subtree(self, parent, node):
70+
if parent[node.get_id()] == node:
71+
return node
72+
return self.find_subtree(parent, parent[node.get_id()])
73+
74+
# Connects subtrees containing nodes `node1` and `node2`
75+
def connect_subtrees(self, parent, subtree_sizes, node1, node2):
76+
node1_root = self.find_subtree(parent, node1)
77+
node1_root_id = node1_root.get_id()
78+
node2_root = self.find_subtree(parent, node2)
79+
node2_root_id = node2_root.get_id()
80+
81+
if subtree_sizes[node1_root_id] < subtree_sizes[node2_root_id]:
82+
parent[node1_root_id] = node2_root
83+
elif subtree_sizes[node1_root_id] > subtree_sizes[node2_root_id]:
84+
parent[node2_root_id] = node1_root
5885
else:
59-
parent[y_root] = x_root
60-
subtree_sizes[x_root] += 1
86+
parent[node2_root_id] = node1_root
87+
subtree_sizes[node1_root_id] += 1
6188

6289
# Applying Kruskal algorithm
6390
def kruskals_mst(self):
6491
result = []
6592
i, e = 0, 0
6693

67-
# Sort edges by weight
68-
sorted_graph = sorted(self.m_graph, key=lambda item: item[2])
69-
parent = []
70-
subtree_sizes = []
71-
72-
# `node` je broj od 0 do numOfNodes -> {0, 1, ..., numOfNodes-1}
73-
# dodajemo tu vrednost na `parent` niz
74-
# dodajemo nulu na `subtree_sizes`
75-
# => inicijalizujemo `parent` i `subtree_sizes`
76-
for node in range(self.m_num_of_nodes):
77-
parent.append(node)
78-
subtree_sizes.append(0)
79-
# parent = [0, 1, 2, ... , numOfNodes-1]
94+
parent = [-1 for i in range(self.m_num_of_nodes)]
95+
subtree_sizes = [0 for i in range(self.m_num_of_nodes)]
8096

97+
# `node` is the number form 0 to num_of_nodes -> {0, 1, ..., num_of_nodes-1}
98+
# Add that number to the `parent` array
99+
# Add zero to the `subtree_sizes` array
100+
# => initialize `parent` and `subtree_sizes`
101+
for node in self.m_nodes:
102+
print(str(node) + " id is " + str(node.get_id()))
103+
parent[node.get_id()] = node
104+
# subtree_sizes.append(0)
81105

82-
# broj grana je jednak broju cvorova -1
83-
# vazno svojstvo msta
106+
# Sort edges by weight
107+
sorted_graph = sorted(self.m_graph, key=lambda item: item[2])
108+
109+
# Important property of any MST
110+
# the number of edges is equal to the number of nodes minus 1
84111
while e < (self.m_num_of_nodes - 1):
85-
# Uzimamo granu sa trenutno najmanjom tezinom
112+
# Pick an edge with the minimum weight at the moment
113+
# print(str(i) + ": " + str(sorted_graph[i]))
86114
node1, node2, weight = sorted_graph[i]
87115
i = i + 1
88-
116+
print(node1, node1.get_id())
89117
x = self.find_subtree(parent, node1)
90118
y = self.find_subtree(parent, node2)
91119
if x != y:
92120
e = e + 1
93-
result.append([node, node2, weight])
121+
result.append([node1, node2, weight])
94122
self.connect_subtrees(parent, subtree_sizes, x, y)
95123

96124
print("Kruskal's MST:")
97125
for node1, node2, weight in result:
98-
print("%d - %d: %d" % (node1, node2, weight))
126+
print("%s - %s: %d" % (node1, node2, weight))
99127

100128
###################################
101129
# Borůvka's MST Algorithm
102130
###################################
103-
def find_component(self, u):
104-
if self.m_components[u] == u:
105-
return u
106-
return self.find_component(self.m_components[u])
131+
def find_component(self, node):
132+
if self.m_components[node] == node:
133+
return node
134+
return self.find_component(self.m_components[node])
107135

108-
def set_component(self, u):
109-
if self.m_components[u] == u:
136+
def set_component(self, node):
137+
if self.m_components[node] == node:
110138
return
111139
else:
112140
for k in self.m_components.keys():
113141
self.m_components[k] = self.find_component(k)
114142

143+
def union(self, component_size, node1, node2):
144+
if component_size[node1] <= component_size[node2]:
145+
self.m_components[node1] = node2
146+
component_size[node2] += component_size[node1]
115147

116-
117-
def union(self, component_size, u, v):
118-
if component_size[u] <= component_size[v]:
119-
self.m_components[u] = v
120-
component_size[v] += component_size[u]
121-
122-
elif component_size[u] >= component_size[v]:
123-
self.m_components[v] = self.find_component(u)
124-
component_size[u] += component_size[v]
148+
elif component_size[node1] >= component_size[node2]:
149+
self.m_components[node2] = self.find_component(node1)
150+
component_size[node1] += component_size[node2]
125151

126152
print(self.m_components)
127153

@@ -141,38 +167,38 @@ def boruvkas_mst(self):
141167
while num_of_components > 1:
142168
for i in range(len(self.m_graph)):
143169

144-
u = self.m_graph[i][0]
145-
v = self.m_graph[i][1]
146-
w = self.m_graph[i][2]
170+
node1 = self.m_graph[i][0]
171+
node2 = self.m_graph[i][1]
172+
weight = self.m_graph[i][2]
147173

148-
self.set_component(u)
149-
self.set_component(v)
174+
self.set_component(node1)
175+
self.set_component(node2)
150176

151-
u_component = self.m_components[u]
152-
v_component = self.m_components[v]
177+
node1_component = self.m_components[node1]
178+
node2_component = self.m_components[node2]
153179

154-
if u_component != v_component:
155-
if cheapest_edge[u_component] == -1 or cheapest_edge[u_component][2] > w:
156-
cheapest_edge[u_component] = [u, v, w]
157-
if cheapest_edge[v_component] == -1 or cheapest_edge[v_component][2] > w:
158-
cheapest_edge[v_component] = [u, v, w]
180+
if node1_component != node2_component:
181+
if cheapest_edge[node1_component] == -1 or cheapest_edge[node1_component][2] > weight:
182+
cheapest_edge[node1_component] = [node1, node2, weight]
183+
if cheapest_edge[node2_component] == -1 or cheapest_edge[node2_component][2] > weight:
184+
cheapest_edge[node2_component] = [node1, node2, weight]
159185

160186
for vertex in range(self.m_num_of_nodes):
161187
if cheapest_edge[vertex] != -1:
162-
u = cheapest_edge[vertex][0]
163-
v = cheapest_edge[vertex][1]
164-
w = cheapest_edge[vertex][2]
188+
node1 = cheapest_edge[vertex][0]
189+
node2 = cheapest_edge[vertex][1]
190+
weight = cheapest_edge[vertex][2]
165191

166-
self.set_component(u)
167-
self.set_component(v)
192+
self.set_component(node1)
193+
self.set_component(node2)
168194

169-
u_component = self.m_components[u]
170-
v_component = self.m_components[v]
195+
node1_component = self.m_components[node1]
196+
node2_component = self.m_components[node2]
171197

172-
if u_component != v_component:
173-
mst_weight += w
174-
self.union(component_size, u_component, v_component)
175-
print("Edge " + str(u) + " - " + str(v) + " with weight " + str(w) + " is included in MST.")
198+
if node1_component != node2_component:
199+
mst_weight += weight
200+
self.union(component_size, node1_component, node2_component)
201+
print("Edge " + str(node1) + " - " + str(node2) + " with weight " + str(weight) + " is included in MST.")
176202

177203
num_of_components -= 1
178204

@@ -186,25 +212,44 @@ def boruvkas_mst(self):
186212

187213

188214

189-
graph = Graph(5)
215+
# graph = Graph(5)
190216

191-
# graph.add_edge('1', 'A', 25)
217+
# graph.add_edge('A', 'A', 25)
192218
# graph.add_edge('A', 'B', 5)
193219
# graph.add_edge('A', 'C', 3)
194220
# graph.add_edge('B', 'D', 1)
195221
# graph.add_edge('B', 'E', 15)
196222
# graph.add_edge('E', 'C', 7)
197223
# graph.add_edge('E', 'D', 11)
198-
graph.add_edge(0, 0, 25)
199-
graph.add_edge(0, 1, 5)
200-
graph.add_edge(0, 2, 3)
201-
graph.add_edge(1, 3, 1)
202-
graph.add_edge(1, 4, 15)
203-
graph.add_edge(4, 2, 7)
204-
graph.add_edge(4, 3, 11)
205-
206-
print(graph)
207224

208-
graph.boruvkas_mst()
225+
# graph.add_edge(0, 0, 25)
226+
# graph.add_edge(0, 1, 5)
227+
# graph.add_edge(0, 2, 3)
228+
# graph.add_edge(1, 3, 1)
229+
# graph.add_edge(1, 4, 15)
230+
# graph.add_edge(4, 2, 7)
231+
# graph.add_edge(4, 3, 11)
232+
233+
graph = Graph(9)
234+
graph.add_edge("A", "B", 4)
235+
graph.add_edge("A", "C", 7)
236+
graph.add_edge("B", "C", 11)
237+
graph.add_edge("B", "D", 9)
238+
graph.add_edge("B", "F", 20)
239+
graph.add_edge("C", "F", 1)
240+
graph.add_edge("D", "G", 6)
241+
graph.add_edge("D", "E", 2)
242+
graph.add_edge("E", "G", 10)
243+
graph.add_edge("E", "I", 15)
244+
graph.add_edge("E", "H", 5)
245+
graph.add_edge("E", "F", 1)
246+
graph.add_edge("F", "H", 3)
247+
graph.add_edge("G", "I", 5)
248+
graph.add_edge("H", "I", 12)
249+
250+
251+
# print(graph)
252+
253+
graph.kruskals_mst()
209254

210255

0 commit comments

Comments
 (0)