blob: a86e27911e9930e5b5cea15773d5cefdd4b3077e [file] [log] [blame]
khenaidooac637102019-01-14 15:44:34 -05001package goraph
2
3import (
4 "container/heap"
5 "math"
6 "sort"
7)
8
9// Kruskal finds the minimum spanning tree with disjoint-set data structure.
10// (http://en.wikipedia.org/wiki/Kruskal%27s_algorithm)
11//
12// 0. Kruskal(G)
13// 1.
14// 2. A = ∅
15// 3.
16// 4. for each vertex v in G:
17// 5. MakeDisjointSet(v)
18// 6.
19// 7. edges = get all edges
20// 8. sort edges in ascending order of weight
21// 9.
22// 10. for each edge (u, v) in edges:
23// 11. if FindSet(u) ≠ FindSet(v):
24// 12. A = A ∪ {(u, v)}
25// 13. Union(u, v)
26// 14.
27// 15. return A
28//
29func Kruskal(g Graph) (map[Edge]struct{}, error) {
30
31 // A = ∅
32 A := make(map[Edge]struct{})
33
34 // disjointSet maps a member Node to a represent.
35 // (https://en.wikipedia.org/wiki/Disjoint-set_data_structure)
36 forests := NewForests()
37
38 // for each vertex v in G:
39 for _, nd := range g.GetNodes() {
40 // MakeDisjointSet(v)
41 MakeDisjointSet(forests, nd.String())
42 }
43
44 // edges = get all edges
45 edges := []Edge{}
46 foundEdge := make(map[string]struct{})
47 for id1, nd1 := range g.GetNodes() {
48 tm, err := g.GetTargets(id1)
49 if err != nil {
50 return nil, err
51 }
52 for id2, nd2 := range tm {
53 weight, err := g.GetWeight(id1, id2)
54 if err != nil {
55 return nil, err
56 }
57 edge := NewEdge(nd1, nd2, weight)
58 if _, ok := foundEdge[edge.String()]; !ok {
59 edges = append(edges, edge)
60 foundEdge[edge.String()] = struct{}{}
61 }
62 }
63
64 sm, err := g.GetSources(id1)
65 if err != nil {
66 return nil, err
67 }
68 for id3, nd3 := range sm {
69 weight, err := g.GetWeight(id3, id1)
70 if err != nil {
71 return nil, err
72 }
73 edge := NewEdge(nd3, nd1, weight)
74 if _, ok := foundEdge[edge.String()]; !ok {
75 edges = append(edges, edge)
76 foundEdge[edge.String()] = struct{}{}
77 }
78 }
79 }
80
81 // sort edges in ascending order of weight
82 sort.Sort(EdgeSlice(edges))
83
84 // for each edge (u, v) in edges:
85 for _, edge := range edges {
86 // if FindSet(u) ≠ FindSet(v):
87 if FindSet(forests, edge.Source().String()).represent != FindSet(forests, edge.Target().String()).represent {
88
89 // A = A ∪ {(u, v)}
90 A[edge] = struct{}{}
91
92 // Union(u, v)
93 // overwrite v's represent with u's represent
94 Union(forests, FindSet(forests, edge.Source().String()), FindSet(forests, edge.Target().String()))
95 }
96 }
97
98 return A, nil
99}
100
101// Prim finds the minimum spanning tree with min-heap (priority queue).
102// (http://en.wikipedia.org/wiki/Prim%27s_algorithm)
103//
104// 0. Prim(G, source)
105// 1.
106// 2. let Q be a priority queue
107// 3. distance[source] = 0
108// 4.
109// 5. for each vertex v in G:
110// 6.
111// 7. if v ≠ source:
112// 8. distance[v] = ∞
113// 9. prev[v] = undefined
114// 10.
115// 11. Q.add_with_priority(v, distance[v])
116// 12.
117// 13.
118// 14. while Q is not empty:
119// 15.
120// 16. u = Q.extract_min()
121// 17.
122// 18. for each adjacent vertex v of u:
123// 19.
124// 21. if v ∈ Q and distance[v] > weight(u, v):
125// 22. distance[v] = weight(u, v)
126// 23. prev[v] = u
127// 24. Q.decrease_priority(v, weight(u, v))
128// 25.
129// 26.
130// 27. return tree from prev
131//
132func Prim(g Graph, src ID) (map[Edge]struct{}, error) {
133
134 // let Q be a priority queue
135 minHeap := &nodeDistanceHeap{}
136
137 // distance[source] = 0
138 distance := make(map[ID]float64)
139 distance[src] = 0.0
140
141 // for each vertex v in G:
142 for id := range g.GetNodes() {
143
144 // if v ≠ src:
145 if id != src {
146 // distance[v] = ∞
147 distance[id] = math.MaxFloat64
148
149 // prev[v] = undefined
150 // prev[v] = ""
151 }
152
153 // Q.add_with_priority(v, distance[v])
154 nds := nodeDistance{}
155 nds.id = id
156 nds.distance = distance[id]
157
158 heap.Push(minHeap, nds)
159 }
160
161 heap.Init(minHeap)
162 prev := make(map[ID]ID)
163
164 // while Q is not empty:
165 for minHeap.Len() != 0 {
166
167 // u = Q.extract_min()
168 u := heap.Pop(minHeap).(nodeDistance)
169 uID := u.id
170
171 // for each adjacent vertex v of u:
172 tm, err := g.GetTargets(uID)
173 if err != nil {
174 return nil, err
175 }
176 for vID := range tm {
177
178 isExist := false
179 for _, one := range *minHeap {
180 if vID == one.id {
181 isExist = true
182 break
183 }
184 }
185
186 // weight(u, v)
187 weight, err := g.GetWeight(uID, vID)
188 if err != nil {
189 return nil, err
190 }
191
192 // if v ∈ Q and distance[v] > weight(u, v):
193 if isExist && distance[vID] > weight {
194
195 // distance[v] = weight(u, v)
196 distance[vID] = weight
197
198 // prev[v] = u
199 prev[vID] = uID
200
201 // Q.decrease_priority(v, weight(u, v))
202 minHeap.updateDistance(vID, weight)
203 heap.Init(minHeap)
204 }
205 }
206
207 sm, err := g.GetSources(uID)
208 if err != nil {
209 return nil, err
210 }
211 vID := uID
212 for uID := range sm {
213
214 isExist := false
215 for _, one := range *minHeap {
216 if vID == one.id {
217 isExist = true
218 break
219 }
220 }
221
222 // weight(u, v)
223 weight, err := g.GetWeight(uID, vID)
224 if err != nil {
225 return nil, err
226 }
227
228 // if v ∈ Q and distance[v] > weight(u, v):
229 if isExist && distance[vID] > weight {
230
231 // distance[v] = weight(u, v)
232 distance[vID] = weight
233
234 // prev[v] = u
235 prev[vID] = uID
236
237 // Q.decrease_priority(v, weight(u, v))
238 minHeap.updateDistance(vID, weight)
239 heap.Init(minHeap)
240 }
241 }
242 }
243
244 tree := make(map[Edge]struct{})
245 for k, v := range prev {
246 weight, err := g.GetWeight(v, k)
247 if err != nil {
248 return nil, err
249 }
250 tree[NewEdge(g.GetNode(v), g.GetNode(k), weight)] = struct{}{}
251 }
252 return tree, nil
253}
254
255type nodeDistance struct {
256 id ID
257 distance float64
258}
259
260// container.Heap's Interface needs sort.Interface, Push, Pop to be implemented
261
262// nodeDistanceHeap is a min-heap of nodeDistances.
263type nodeDistanceHeap []nodeDistance
264
265func (h nodeDistanceHeap) Len() int { return len(h) }
266func (h nodeDistanceHeap) Less(i, j int) bool { return h[i].distance < h[j].distance } // Min-Heap
267func (h nodeDistanceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
268
269func (h *nodeDistanceHeap) Push(x interface{}) {
270 *h = append(*h, x.(nodeDistance))
271}
272
273func (h *nodeDistanceHeap) Pop() interface{} {
274 heapSize := len(*h)
275 lastNode := (*h)[heapSize-1]
276 *h = (*h)[0 : heapSize-1]
277 return lastNode
278}
279
280func (h *nodeDistanceHeap) updateDistance(id ID, val float64) {
281 for i := 0; i < len(*h); i++ {
282 if (*h)[i].id == id {
283 (*h)[i].distance = val
284 break
285 }
286 }
287}