1
+ from node import Node
1
2
class Graph :
2
3
###################################
3
4
# Constructor
4
5
###################################
5
6
def __init__ (self , num_of_nodes , directed = True ):
6
7
self .m_num_of_nodes = num_of_nodes
8
+ self .m_nodes = []
7
9
8
10
# Define the type of a graph
9
11
self .m_directed = directed
10
12
11
- # Different representations of a graph
13
+ # A representation of a graph
12
14
# i.e. list of edges
13
15
self .m_graph = []
14
16
15
- # For Bovurkas
17
+ # For Bovurka's algorithm
16
18
self .m_components = {}
17
19
18
20
###################################
19
21
# Add edge to a graph
20
22
###################################
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
+
22
40
# Add the edge from node1 to node2
23
41
self .m_graph .append ([node1 , node2 , weight ])
24
42
@@ -37,91 +55,99 @@ def __str__(self):
37
55
out += "edge " + str (i + 1 ) + ": " + str (self .m_graph [i ]) + "\n "
38
56
return out
39
57
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
+
40
65
###################################
41
66
# Kruskal's MST Algorithm
42
- #### za sada radi samo sa numbered nodes
43
67
###################################
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
58
85
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
61
88
62
89
# Applying Kruskal algorithm
63
90
def kruskals_mst (self ):
64
91
result = []
65
92
i , e = 0 , 0
66
93
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 )]
80
96
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)
81
105
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
84
111
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]))
86
114
node1 , node2 , weight = sorted_graph [i ]
87
115
i = i + 1
88
-
116
+ print ( node1 , node1 . get_id ())
89
117
x = self .find_subtree (parent , node1 )
90
118
y = self .find_subtree (parent , node2 )
91
119
if x != y :
92
120
e = e + 1
93
- result .append ([node , node2 , weight ])
121
+ result .append ([node1 , node2 , weight ])
94
122
self .connect_subtrees (parent , subtree_sizes , x , y )
95
123
96
124
print ("Kruskal's MST:" )
97
125
for node1 , node2 , weight in result :
98
- print ("%d - %d : %d" % (node1 , node2 , weight ))
126
+ print ("%s - %s : %d" % (node1 , node2 , weight ))
99
127
100
128
###################################
101
129
# Borůvka's MST Algorithm
102
130
###################################
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 ])
107
135
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 :
110
138
return
111
139
else :
112
140
for k in self .m_components .keys ():
113
141
self .m_components [k ] = self .find_component (k )
114
142
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 ]
115
147
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 ]
125
151
126
152
print (self .m_components )
127
153
@@ -141,38 +167,38 @@ def boruvkas_mst(self):
141
167
while num_of_components > 1 :
142
168
for i in range (len (self .m_graph )):
143
169
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 ]
147
173
148
- self .set_component (u )
149
- self .set_component (v )
174
+ self .set_component (node1 )
175
+ self .set_component (node2 )
150
176
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 ]
153
179
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 ]
159
185
160
186
for vertex in range (self .m_num_of_nodes ):
161
187
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 ]
165
191
166
- self .set_component (u )
167
- self .set_component (v )
192
+ self .set_component (node1 )
193
+ self .set_component (node2 )
168
194
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 ]
171
197
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." )
176
202
177
203
num_of_components -= 1
178
204
@@ -186,25 +212,44 @@ def boruvkas_mst(self):
186
212
187
213
188
214
189
- graph = Graph (5 )
215
+ # graph = Graph(5)
190
216
191
- # graph.add_edge('1 ', 'A', 25)
217
+ # graph.add_edge('A ', 'A', 25)
192
218
# graph.add_edge('A', 'B', 5)
193
219
# graph.add_edge('A', 'C', 3)
194
220
# graph.add_edge('B', 'D', 1)
195
221
# graph.add_edge('B', 'E', 15)
196
222
# graph.add_edge('E', 'C', 7)
197
223
# 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 )
207
224
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 ()
209
254
210
255
0 commit comments