Start Typing !!! type the highlighted character. You can't scroll once you start typing.
filename

prim.py

"""Prim's Algorithm.

Determines the minimum spanning tree(MST) of a graph using the Prim's Algorithm.

Details: https://en.wikipedia.org/wiki/Prim%27s_algorithm

"""

import heapq as hq

import math

from typing import Iterator

class Vertex:

"""Class Vertex."""

def __init__(self, id):

"""

Arguments:

id - input an id to identify the vertex

Attributes:

neighbors - a list of the vertices it is linked to

edges - a dict to store the edges's weight

"""

self.id = str(id)

self.key = None

self.pi = None

self.neighbors = []

self.edges = {} # {vertex:distance}

def __lt__(self, other):

"""Comparison rule to < operator."""

return self.key < other.key

def __repr__(self):

"""Return the vertex id."""

return self.id

def add_neighbor(self, vertex):

"""Add a pointer to a vertex at neighbor's list."""

self.neighbors.append(vertex)

def add_edge(self, vertex, weight):

"""Destination vertex and weight."""

self.edges[vertex.id] = weight

def connect(graph, a, b, edge):

# add the neighbors:

graph[a - 1].add_neighbor(graph[b - 1])

graph[b - 1].add_neighbor(graph[a - 1])

# add the edges:

graph[a - 1].add_edge(graph[b - 1], edge)

graph[b - 1].add_edge(graph[a - 1], edge)

def prim(graph: list, root: Vertex) -> list:

"""Prim's Algorithm.

Runtime:

O(mn) with `m` edges and `n` vertices

Return:

List with the edges of a Minimum Spanning Tree

Usage:

prim(graph, graph[0])

"""

a = []

for u in graph:

u.key = math.inf

u.pi = None

root.key = 0

q = graph[:]

while q:

u = min(q)

q.remove(u)

for v in u.neighbors:

if (v in q) and (u.edges[v.id] < v.key):

v.pi = u

v.key = u.edges[v.id]

for i in range(1, len(graph)):

a.append((int(graph[i].id) + 1, int(graph[i].pi.id) + 1))

return a

def prim_heap(graph: list, root: Vertex) -> Iterator[tuple]:

"""Prim's Algorithm with min heap.

Runtime:

O((m + n)log n) with `m` edges and `n` vertices

Yield:

Edges of a Minimum Spanning Tree

Usage:

prim(graph, graph[0])

"""

for u in graph:

u.key = math.inf

u.pi = None

root.key = 0

h = [v for v in graph]

hq.heapify(h)

while h:

u = hq.heappop(h)

for v in u.neighbors:

if (v in h) and (u.edges[v.id] < v.key):

v.pi = u

v.key = u.edges[v.id]

hq.heapify(h)

for i in range(1, len(graph)):

yield (int(graph[i].id) + 1, int(graph[i].pi.id) + 1)

def test_vector() -> None:

"""

# Creates a list to store x vertices.

>>> x = 5

>>> G = [Vertex(n) for n in range(x)]

>>> connect(G, 1, 2, 15)

>>> connect(G, 1, 3, 12)

>>> connect(G, 2, 4, 13)

>>> connect(G, 2, 5, 5)

>>> connect(G, 3, 2, 6)

>>> connect(G, 3, 4, 6)

>>> connect(G, 0, 0, 0) # Generate the minimum spanning tree:

>>> G_heap = G[:]

>>> MST = prim(G, G[0])

>>> MST_heap = prim_heap(G, G[0])

>>> for i in MST:

... print(i)

(2, 3)

(3, 1)

(4, 3)

(5, 2)

>>> for i in MST_heap:

... print(i)

(2, 3)

(3, 1)

(4, 3)

(5, 2)

"""

if __name__ == "__main__":

import doctest

doctest.testmod()