# Each tuple (u,v,d) in list is representing the edge from u to v with weight d
dedges = [(0,1,10),(0,2,80),(1,2,6),(1,4,20),(2,3,70),(4,5,50),(4,6,5),(5,6,10)]
size = 7
import numpy as np
W = np.zeros(shape=(size,size,2))
for (i,j,w) in dedges:
W[i,j,0] = 1
W[i,j,1] = w
print(W)
dedges = [(0,1,10),(0,2,80),(1,2,6),(1,4,20),(2,3,70),(4,5,50),(4,6,5),(5,6,10)]
size = 7
WL = {}
for i in range(size):
WL[i] = []
for (i,j,d) in dedges:
WL[i].append((j,d))
print(WL)
dedges = [(0,1,10),(0,2,80),(1,2,6),(1,4,20),(2,3,70),(4,5,50),(4,6,5),(5,6,10)]
# Each edge represented by two entry in data structure ((u,v,d) and (v,u,d) for undirected graph
edges = dedges + [(j,i,w) for (i,j,w) in dedges]
size = 7
import numpy as np
W = np.zeros(shape=(size,size,2))
for (i,j,w) in edges:
W[i,j,0] = 1
W[i,j,1] = w
print(W)
dedges = [(0,1,10),(0,2,80),(1,2,6),(1,4,20),(2,3,70),(4,5,50),(4,6,5),(5,6,10)]
edges = dedges + [(j,i,w) for (i,j,w) in dedges]
size = 7
WL = {}
for i in range(size):
WL[i] = []
for (i,j,d) in edges:
WL[i].append((j,d))
print(WL)
Find shortest paths from a source vertex to every other vertex.
Dijkstra's algorithm is a popular algorithm for finding the shortest path between two vertices in a weighted graph. Some of its important properties and points are:
Here are the steps for Dijkstra's algorithm for finding the single source shortest path:
Select Dijkstra(s) form left bottom menu
For given graph
def dijkstra(WMat,s):
#Initialization
(rows,cols,x) = WMat.shape
infinity = np.max(WMat)*rows+1
(visited,distance) = ({},{})
for v in range(rows):
(visited[v],distance[v]) = (False,infinity)
distance[s] = 0
# Computing shortest distance for each vertex from source
for u in range(rows):
# Find minimum distance value on vertices which are not visited
min_dist = min([distance[v] for v in range(rows) if not visited[v]])
# Find vertices which have minimum distance value min_dist
nextv_list = [v for v in range(rows)if (not visited[v]) and distance[v] == min_dist]
# Select minimum level vertex which have minimum distance value min_dist and mark visited
nextv = min(nextv_list)
visited[nextv] = True
# Check for each adjacent of nextv vertex which is not visited
for v in range(cols):
if WMat[nextv,v,0] == 1 and (not visited[v]):
#If distance of v through nextv is smaller than the current distance on v, then update
if distance[nextv] + WMat[nextv,v,1] < distance[v]:
distance[v] = distance[nextv] + WMat[nextv,v,1]
return(distance)
dedges = [(0,1,10),(0,2,80),(1,2,6),(1,4,20),(2,3,70),(4,5,50),(4,6,5),(5,6,10)]
size = 7
import numpy as np
W = np.zeros(shape=(size,size,2))
for (i,j,w) in dedges:
W[i,j,0] = 1
W[i,j,1] = w
print(dijkstra(W,0))
Output
{0: 0, 1: 10.0, 2: 16.0, 3: 86.0, 4: 30.0, 5: 80.0, 6: 35.0}
Complexity
def dijkstralist(WList,s):
#Initialization
infinity = 1 + len(WList.keys())*max([d for u in WList.keys() for (v,d) in WList[u]])
(visited,distance) = ({},{})
for v in WList.keys():
(visited[v],distance[v]) = (False,infinity)
distance[s] = 0
# Computing shortest distance for each vertex from source
for u in WList.keys():
# Find minimum distance value on vertices which are not visited
min_dist = min([distance[v] for v in WList.keys() if not visited[v]])
# Find vertices which have minimum distance value min_dist
nextv_list = [v for v in WList.keys() if (not visited[v]) and distance[v] == min_dist]
# Select minimum level vertex which have minimum distance value min_dist and mark visited
nextv = min(nextv_list)
visited[nextv] = True
# Check for each adjacent of nextv vertex which is not visited
for (v,d) in WList[nextv]:
if not visited[v]:
# If distance of v through nextv is smaller than the current distance of v, then update
if distance[nextv]+d < distance[v]:
distance[v] = distance[nextv]+d
return(distance)
dedges = [(0,1,10),(0,2,80),(1,2,6),(1,4,20),(2,3,70),(4,5,50),(4,6,5),(5,6,10)]
size = 7
WL = {}
for i in range(size):
WL[i] = []
for (i,j,d) in dedges:
WL[i].append((j,d))
print(dijkstralist(WL,0))
Output
{0: 0, 1: 10, 2: 16, 3: 86, 4: 30, 5: 80, 6: 35}
Code Execution Flow
Complexity
Bellman-Ford algorithm is a dynamic programming based algorithm to find the shortest path in a weighted graph, where the edge weights may be negative. Here are some important points and properties of the algorithm:
Here are the step-by-step instructions for the Bellman-Ford algorithm:
Select BellmanFord(s) form left bottom menu
For given graph
def bellmanford(WMat,s):
# Initialization
(rows,cols,x) = WMat.shape
infinity = np.max(WMat)*rows+1
distance = {}
for v in range(rows):
distance[v] = infinity
distance[s] = 0
# Computing shortest distance for each vertex from source
# Repeat the process n times where n is number of vertices
for i in range(rows):
# Check for each adjacent of u vertex
for u in range(rows):
for v in range(cols):
if WMat[u,v,0] == 1:
# If distance of v through u is smaller than the current distance of v, then update
if distance[u] + WMat[u,v,1] < distance[v]:
distance[v] = distance[u] + WMat[u,v,1]
return(distance)
edges = [(0,1,10),(0,7,8),(1,5,2),(2,1,1),(2,3,1),(3,4,3),(4,5,-1),(5,2,-2),(6,1,-4),(6,5,-1),(7,6,1)]
size = 8
import numpy as np
W = np.zeros(shape=(size,size,2))
for (i,j,w) in edges:
W[i,j,0] = 1
W[i,j,1] = w
print(bellmanford(W,0))
Output
{0: 0, 1: 5.0, 2: 5.0, 3: 6.0, 4: 9.0, 5: 7.0, 6: 9.0, 7: 8.0}
Complexity
def bellmanfordlist(WList,s):
# Initialization
infinity = 1 + len(WList.keys())*max([d for u in WList.keys() for (v,d) in WList[u]])
distance = {}
for v in WList.keys():
distance[v] = infinity
distance[s] = 0
# Computing shortest distance for each vertex from source
# Repeat the process n times where n is number of vertices
for i in WList.keys():
# Check for each adjacent of u vertex
for u in WList.keys():
for (v,d) in WList[u]:
# If distance of v through u is smaller than the current distance of v, then update
if distance[u] + d < distance[v]:
distance[v] = distance[u] + d
return(distance)
edges = [(0,1,10),(0,7,8),(1,5,2),(2,1,1),(2,3,1),(3,4,3),(4,5,-1),(5,2,-2),(6,1,-4),(6,5,-1),(7,6,1)]
size = 8
WL = {}
for i in range(size):
WL[i] = []
for (i,j,d) in edges:
WL[i].append((j,d))
print(bellmanfordlist(WL,0))
Output
{0: 0, 1: 5, 2: 5, 3: 6, 4: 9, 5: 7, 6: 9, 7: 8}
Code Execution Flow
Complexity
i
and j
.The Floyd-Warshall algorithm is an efficient algorithm for finding the shortest path between all pairs of nodes in a weighted graph. Some important points and properties of the Floyd-Warshall algorithm are:
Here are the steps for the algorithm:
Initialization: Create a 2-dimensional array SP
of size n x n
, where n
is the number of vertices in the graph. For each pair of vertices (i,j)
, initialize SP[i][j]
to the weight of the edge from vertex i
to vertex j
. If there is no edge between vertices i
and j
, then set SP[i][j]
to infinity.
For each vertex k
from 1
to n
, compute the shortest path between every pair of vertices (i,j)
that passes through k
. To do this, update SP[i][j]
as follows:
SP[i][j] = min(SP[i][j], SP[i][k] + SP[k][j])
This means that the shortest path from vertex i
to vertex j
that passes through k
is the minimum of the current shortest path from i
to j
and the sum of the shortest path from i
to k
and the shortest path from k
to j
.
After the step 2 is complete, the SP
array will contain the shortest path between every pair of vertices in the graph.
For given input graph
def floydwarshall(WMat):
# Initialization
(rows,cols,x) = WMat.shape
infinity = float('inf')
SP = np.zeros(shape=(rows,cols,cols+1))
# Filling the initial graph entry in matrix
for i in range(rows):
for j in range(cols):
if WMat[i,j,0] == 1:
SP[i,j,0] = WMat[i,j,1]
else:
SP[i,j,0] = infinity
# Repeat the process n times where n is number of vertices
for k in range(1,cols+1):
# Checking The shortest path distance for each pair in matrix
for i in range(rows):
for j in range(cols):
SP[i,j,k] = min(SP[i,j,k-1],SP[i,k-1,k-1]+SP[k-1,j,k-1])
# Retuen the last updated matrix
return(SP[:,:,cols])
edges = [(0,1,10),(0,7,8),(1,5,2),(2,1,1),(2,3,1),(3,4,3),(4,5,-1),(5,2,-2),(6,1,-4),(6,5,-1),(7,6,1)]
size = 8
import numpy as np
W = np.zeros(shape=(size,size,2))
for (i,j,w) in edges:
W[i,j,0] = 1
W[i,j,1] = w
print(floydwarshall(W))
Output
[[inf 5. 5. 6. 9. 7. 9. 8.]
[inf 1. 0. 1. 4. 2. inf inf]
[inf 1. 1. 1. 4. 3. inf inf]
[inf 1. 0. 1. 3. 2. inf inf]
[inf -2. -3. -2. 1. -1. inf inf]
[inf -1. -2. -1. 2. 1. inf inf]
[inf -4. -4. -3. 0. -2. inf inf]
[inf -3. -3. -2. 1. -1. 1. inf]]
Complexity
Add the cost of all the edges in the tree
Among the different spanning trees, choose one with minimum cost
Some facts about trees
Algorithms:-
Prim's algorithm is a greedy algorithm that finds a minimum spanning tree (MST) for a weighted undirected graph. Here are some of the key points or properties of Prim's algorithm:
Here are the steps for the algorithm:
Select Prim's Algorithm from bottom-left menu
Source:- https://visualgo.net/en/mst
For given input graph
def primlist(WList):
# Initialization
infinity = 1 + max([d for u in WList.keys() for (v,d) in WList[u]])
(visited,distance,TreeEdges) = ({},{},[])
for v in WList.keys():
(visited[v],distance[v]) = (False,infinity)
# Start from vertex 0, marked visited and update the distance of adjacents from 0
visited[0] = True
for (v,d) in WList[0]:
distance[v] = d
# Repeat the below process (number of vertices-1) times
for i in range(1,len(WList.keys())):
mindist = infinity
nextv = None
#Finding the minimum weight edge (u,v) where vertex u is visited and v is not visited
for u in WList.keys():
for (v,d) in WList[u]:
if visited[u] and (not visited[v]) and d < mindist:
mindist = d
nextv = v
nexte = (u,v)
# Mark nextv as visited and append the nexte in MST
visited[nextv] = True
TreeEdges.append(nexte)
# Update the distance of unvisited adjacents of nextv if smaller than current
for (v,d) in WList[nextv]:
if not visited[v]:
if d < distance[v]:
distance[v] = d
return(TreeEdges)
dedges = [(0,1,10),(0,3,18),(1,2,20),(1,3,6),(2,4,8),(3,4,70)]
edges = dedges + [(j,i,w) for (i,j,w) in dedges]
size = 5
WL = {}
for i in range(size):
WL[i] = []
for (i,j,d) in edges:
WL[i].append((j,d))
print(primlist(WL))
Output
[(0, 1), (1, 3), (1, 2), (2, 4)]
Output minimum spanning tree with cost 44
Code Execution Flow
Other Implementation
def primlist2(WList):
# Initialization
infinity = float("inf")
(visited,distance,nbr) = ({},{},{})
for v in WList.keys():
(visited[v],distance[v],nbr[v]) = (False,infinity,-1)
# Set start vertex distance to 0
distance[0] = 0
# Repeat the below process (number of vertices-1) times
for i in range(0,len(WList.keys())):
# Find minimum distance value on vertices which are not visited
min_dist = min([distance[v] for v in WList.keys() if not visited[v]])
# Find all vertices that have minimum distance value min_dist and not visited
nextv_list = [v for v in WList.keys() if (not visited[v]) and distance[v] == min_dist]
# Select the minimum level value vertex from nextv_list ans mark visited
nextv = min(nextv_list)
visited[nextv] = True
# Update the nbr or parent value for v with minimum eadge distance
for (v,d) in WList[nextv]:
if not visited[v]:
if d < distance[v]:
nbr[v] = nextv
distance[v] = d
return(nbr)
dedges = [(0,1,10),(0,3,18),(1,2,20),(1,3,6),(2,4,8),(3,4,70)]
edges = dedges + [(j,i,w) for (i,j,w) in dedges]
size = 5
WL = {}
for i in range(size):
WL[i] = []
for (i,j,d) in edges:
WL[i].append((j,d))
print(primlist2(WL))
Output
{0: -1, 1: 0, 2: 1, 3: 1, 4: 2}
Code Execution Flow
Complexity
Kruskal's algorithm is a greedy algorithm used to find the minimum spanning tree (MST) of a connected, undirected graph. The algorithm works by iteratively adding the edges of the graph with the smallest weights that do not create a cycle in the MST. Here are some important points and properties of Kruskal's algorithm:
Here are the steps for the of Kruskal's algorithm:
Select Kruskal's Algorithm from bottom-left menu
Source:- https://visualgo.net/en/mst
For given input graph
def kruskal(WList):
# Initialization
(edges,component,TE) = ([],{},[])
for u in WList.keys():
# Weight as first value in tuple to sort easily
edges.extend([(d,u,v) for (v,d) in WList[u]])
# Initially each vertex as single components and assign leader of each component
component[u] = u
# Sort the edges in increasing order of their weights
edges.sort()
for (d,u,v) in edges:
# If (u,v) edge is not creating the cycle in MST, add the edge in MST
if component[u] != component[v]:
TE.append((u,v))
c = component[u]
# Update of component leader
for w in WList.keys():
if component[w] == c:
component[w] = component[v]
return(TE)
dedges = [(0,1,10),(0,2,18),(1,2,6),(1,4,20),(2,3,70),(4,5,10),(4,6,10),(5,6,5)]
edges = dedges + [(j,i,w) for (i,j,w) in dedges]
size = 7
WL = {}
for i in range(size):
WL[i] = []
for (i,j,d) in edges:
WL[i].append((j,d))
print(kruskal(WL))
Output
[(5, 6), (1, 2), (0, 1), (4, 5), (1, 4), (2, 3)]
Output minimum spanning tree with cost 121
Code Execution Flow
Complexity