In [ ]:
%%HTML
<style>
.container { width:100% }
</style>
In our implementation of Kruskal's algorithm for finding the minimum spanning tree we use the union-find data structure that we have defined previously.
In [ ]:
%run Union-Find-OO.ipynb
Furthermore, we need a priority queue. The module heapq
implements a priority queue. The API
for this module is as follows:
H.heappush(x)
pushes x
onto the heap H
,H.heappop()
removes the smallest element from the heap H
and returns this element,H = []
creates an empty heap.
In [ ]:
import heapq as hq
The function $\texttt{mst}(V, E)$ takes a set of nodes $V$ and a set of weighted edges $E$ to compute a minimum spanning tree. It is assumed that the pair $(V, E)$ represents a weighted graph $G$ that is connected. The weighted edges in the set $E$ have the form $$ \bigl(w, (x, y)\bigr). $$ Here, $x$ and $y$ are nodes from the set $V$, while $w$ is the cost of the edge $\{x,y\}$. The algorithm returns a set of weighted edges that define a minimum spanning tree of $G$.
In [ ]:
def mst(V, E):
UF = UnionFind(V)
MST = set() # minimum spanning tree, represented as set of weighted edges
H = [] # empty priority queue for weighted edges
for edge in E:
hq.heappush(H, edge)
while True:
w, (x, y) = hq.heappop(H)
root_x = UF.find(x)
root_y = UF.find(y)
if root_x != root_y:
MST.add((w, (x, y)))
UF.union(x, y)
if len(MST) == len(V) - 1:
return MST
In [ ]:
def mst(V, E):
UF = UnionFind(V)
MST = set() # minimum spanning tree, represented as set of weighted edges
H = [] # empty priority queue for weighted edges
for edge in E:
hq.heappush(H, edge)
while True:
w, (x, y) = hq.heappop(H)
print(f'testing {x} - {y}, weight {w}')
root_x = UF.find(x)
root_y = UF.find(y)
if root_x != root_y:
print(f'connect {x} - {y}')
MST.add((w, (x, y)))
UF.union(x, y)
display(toDot(E, MST))
print('_' * 100)
if len(MST) == len(V) - 1:
return MST
In [ ]:
import graphviz as gv
Given a set $E$ of weighted edges, the function $\texttt{toDot}$ transforms this set into a dot structure that can be displayed as a graph. The edges that are present in the set $H$ are assumed to be the edges that are part of the minimum spanning tree and therefore are highlighted.
In [ ]:
def toDot(E, H):
V = set()
for (_, (x, y)) in E:
V.add(x)
V.add(y)
dot = gv.Graph()
dot.attr(rankdir='LR', size='8,5')
for x in V:
dot.node(str(x))
for (w, (x, y)) in E:
if (w, (x, y)) in H:
dot.edge(str(x), str(y), label=str(w), color='blue', penwidth='2')
else:
dot.edge(str(x), str(y), label=str(w), style='dashed')
return dot
In [ ]:
def demoFile(fn):
with open(fn, 'r') as file:
data = file.readlines()
Edges = set()
Nodes = set()
for line in data:
x, y, weight = line.split()
Edges.add( (int(weight), (int(x), int(y))) )
Nodes.add( int(x) )
Nodes.add( int(y) )
MST = mst(Nodes, Edges);
print(MST)
return toDot(Edges, MST)
In [ ]:
MST = demoFile("tiny.txt")
MST
In [ ]: