-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMST.verse
117 lines (96 loc) · 4.21 KB
/
MST.verse
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
using { /Verse.org/Simulation }
CreateEdge(Point1:Point, Point2:Point):Edge=
edge := Edge{
Point1 := Point1,
Point2 := Point2
}
edge.Init()
return edge
ConverPointsToEdges(Points:[]tuple(Point,Point)):[]Edge=
var edges :[]Edge= array{}
for (point : Points):
edge := CreateEdge(point(0), point(1))
set edges += array{edge}
return edges
Edge := class:
Point1: Point;
Point2: Point;
var Weight: float = 0.0
Init():void=
set Weight = Sqrt(Pow((Point1.X*1.0 - Point2.X*1.0),2.0) + Pow((Point1.Y*1.0 - Point2.Y*1.0),2.0))
#Print():void=
#Print("Edge: , {Point1.X}- {Point1.Y}, -> , {Point2.X}-{Point2.Y}, Weight: , {Weight}")
SortEdgeFunction(Edge1: Edge, Edge2: Edge)<transacts>: int =
if (Edge1.Weight < Edge2.Weight):
-1
else if (Edge1.Weight > Edge2.Weight):
1
else:
0
UnionFind := class:
var Parent: []int = array{}
var Rank: []int = array{}
Init(size: int): void =
set Parent = array{}
set Rank = array{}
for (i := 0.. size *2):
set Parent += array{i} # Initially, each element is its own parent
set Rank += array{0} # Initially, each element has a rank of 0
Find(x: int, ?Depth: int = 0)<transacts>: ?int =
#Print("Finding root for: {x}, Depth: {Depth}")
if (Parent[x] ): # Ensure x is a valid index
if (not Parent[x] = x): # x is not the root
# Find the root of the current component
if(XParent:=Parent[x]):
Root := Find(XParent, ?Depth:= Depth + 1)
if (RootFound := Root?): # Successfully found the root
# Path compression: set the parent of x directly to the root
if(set Parent[x] = RootFound){}
#Print("Path compression: Set parent of {x} to {RootFound}")
return option{RootFound}
return Root # Pass the failure or false upward if root not found
return option{Parent[x]} # x is the root
else:
Print("Error: Index {x} not found in Parent array")
return false
Union(x: int, y: int): void =
RootX := Find(x)
RootY := Find(y)
if (rootXFound := RootX?, rootYFound := RootY?): # Both roots must be found
if (not rootXFound = rootYFound): # Ensure different components
# Union by rank
if (Rank[rootXFound] > Rank[rootYFound]):
if(set Parent[rootYFound] = rootXFound):
else if (Rank[rootXFound] < Rank[rootYFound]):
if(set Parent[rootXFound] = rootYFound):
else:
if(set Parent[rootYFound] = rootXFound):
if(set Rank[rootXFound] += 1):
Print("Union done between {x} and {y}, New Roots: {rootXFound}, {rootYFound}")
#Print("Union done between {x} and {y}, New Roots: {rootXFound}, {rootYFound}")
KruskalMST(Points: []Point, Edges: []tuple(Point, Point))<suspends>: []Edge=
var edges: []Edge = ConverPointsToEdges(Edges)
set edges = edges.QuickSort(SortEdgeFunction)
uf := UnionFind{}
uf.Init(Points.Length)
var UUIDPointIndex: [string]int = map{}
for(I->point: Points):
if(set UUIDPointIndex[point.UUID] = I){}
var mst: []Edge = array{}
var TotalStartingEdges: int = edges.Length
var SeperatePoints: int = 0
var Found: logic = false
for(edge: edges):
if(Found = false):
if(IndexPoint1 := UUIDPointIndex[edge.Point1.UUID], IndexPoint2 := UUIDPointIndex[edge.Point2.UUID]):
Found1 := uf.Find(IndexPoint1)
Found2 := uf.Find(IndexPoint2)
if(not Found1 = Found2):
set SeperatePoints += 1
uf.Union(IndexPoint1, IndexPoint2)
set mst += array{edge}
# Stop early if all points are connected
if(SeperatePoints = Points.Length - 1):
set Found = true
Print("Total Points: {Points.Length}, Total MST Edges: {mst.Length}")
return mst