# PROJECT REPORT

```PROJECT REPORT
DIJKSTRA ALGORITHM
WITH COMPLEXITY ANALYSIS AND CODE IMPLEMENTATION
COURSE
DESIGN &amp; ANALYSIS OF ALGORITHMS
INSTRUCTOR
DR. ASIM WAGAN
GROUP MEMBERS
ALI MUJTABA (SP21-BSCS-0061)
DINAZ IMTIAZ (SP21-BSCS-0029)
FIZA IMAN (SP21-BSCS-0019)
SECTION
AM
OVER VIEW:
Dijkstra Algorithm is a graph algorithm for finding the shortest path from a source node to all other
nodes in a graph(single source shortest path). It is a type of greedy algorithm. It only works on
weighted graphs with positive weights. It has a time complexity of O(V^2)O(V2) using the
adjacency matrix representation of graph. The time complexity can be reduced to
O((V+E)logV)O((V+E)logV) using adjacency list representation of graph, where E is the number
of edges in the graph and V is the number of vertices in the graph.
Introduction to Dijkstra's Algorithm
Ever wondered how does Google Maps find the shortest and fastest distance between two places?
Dijkstra's Algorithm was conceived by computer scientist Edsger W. Dijkstra in 1956. It is a single
source shortest paths algorithm. It means that it finds the shortest paths from a single source vertex
to all other vertices in a graph. It is a greedy algorithm and works for both directed and undirected,
positively weighted graphs (a graph is called positively weighted if all of its edges have only
positive weights).
Working of Dijkstra's Algorithm
Highlights:
1. Greedy Algorithm
2. Relaxation
Dijkstra's Algorithm requires a graph and source vertex to work.The algorithm is purely based on
greedy approach and thus finds the locally optimal choice(local minima in this case) at each step
of the algorithm.
In this algorithm each vertex will have two properties defined for it●
Visited property:o This property represents whether the vertex has been visited or not.
o We are using this property so that we don't revisit a vertex.
o A vertex is marked visited only after the shortest path to it has been found.
● Path property:o This property stores the value of the current minimum path to the vertex. Current
minimum path means the shortest way in which we have reached this vertex till
now.
o This property is updated whenever any neighbour of the vertex is visited.
o
The path property is important as it will store the final answer for each vertex.
Algorithm
1. Mark the source node with a current distance of 0 and the rest with infinity.
2. Set the non-visited node with the smallest current distance as the current node, lets say C.
3. For each neighbour N of the current node C: add the current distance of C with the
weight of the edge connecting C-N. If it is smaller than the current distance of N, set it as
the new current distance of N.
4. Mark the current node C as visited.
5. Go to step 2 if there are any nodes are unvisited.
Dijkstra Algorithm Example
Let’s take an example to understand the algorithm better.
Let’s assume the below graph as our input with the vertex A being the source.
●
Initially all the vertices are marked unvisited.
● The path to A is 0 and for all the other vertices it is set to infinity.
● Now the source vertex A is marked as visited. Then its neighbors are accessed (only
accessed and not visited).
● The path to B is updated to 4 using relaxation as the path to A is 0 and path from A to
B is 4, so min ((0+4), ∞) is 4.
●
●
●
●
●
●
●
The path to C is updated to 5 using relaxation as the path to A is 0 and path
from A to C is 5, so min ((0+5), ∞) is 5.Both the neighbors of A are relaxed so we move
Then the next unvisited vertex with least path is picked and visited. So vertex B is visited
and its unvisited neighbors are relaxed.After relaxing path to C remains 5, path
to E becomes 11 and path to D becomes 13.
Then vertex C is visited and its unvisited neighbour E is relaxed. While relaxing E, we
find that the path to E via is smaller than its current path, so the path to E is updated to
8.All neighbours of C are now relaxed.
Vertex E is visited and its neighbours B,D and F are relaxed. As only vertex F is
unvisited only, F is relaxed. Path of B remains 4, path to D remains 13 and path
to F becomes 14(8+6).
Then vertex D is visited and only F is relaxed. .The path to vertex F remains 14.
Now only vertex F is remaining so it is visited but no relaxations are performed as all of
As soon as all the vertices become visited the program stops.
The final paths we get are:
●
●
●
●
●
●
A=0(source)
B=4(A-&gt;B)
C=5(A-&gt;C)
D=13(A-&gt;B-&gt;8
E=8(A-&gt;C-&gt;E)
F=14!(A-&gt;C-&gt;E-&gt;F)
Implementation of Dijkstra Algorithm in Python
Pseudocode:
from collections import deque, namedtuple
inf = float('inf')
Edge = namedtuple('Edge', 'start, end, cost')
def make_edge(start, end, cost=1):
return Edge(start, end, cost)
class Graph:
def _init_(self, edges):
# checking that the data is right
wrong_edges = [i for i in edges if len(i) not in [2, 3]]
if wrong_edges:
raise ValueError('Wrong edges data: {}'.format(wrong_edges))
self.edges = [make_edge(*edge) for edge in edges]
@property
def vertices(self):
return set(
sum(
([edge.start, edge.end] for edge in self.edges), []
)
)
def get_node_pairs(self, n1, n2, both_ends=True):
if both_ends:
node_pairs = [[n1, n2], [n2, n1]]
else:
node_pairs = [[n1, n2]]
return node_pairs
def remove_edge(self, n1, n2, both_ends=True):
node_pairs = self.get_node_pairs(n1, n2, both_ends)
edges = self.edges[:]
for edge in edges:
if [edge.start, edge.end] in node_pairs:
self.edges.remove(edge)
def add_edge(self, n1, n2, cost=1, both_ends=True):
node_pairs = self.get_node_pairs(n1, n2, both_ends)
for edge in self.edges:
if [edge.start, edge.end] in node_pairs:
return ValueError('Edge {} {} already exists'.format(n1, n2))
self.edges.append(Edge(start=n1, end=n2, cost=cost))
if both_ends:
self.edges.append(Edge(start=n2, end=n1, cost=cost))
@property
def neighbours(self):
neighbours = {vertex: set() for vertex in self.vertices}
for edge in self.edges:
return neighbours
def dijkstra(self, source, dest):
assert source in self.vertices, 'Such source node doesn\'t exist'
distances = {vertex: inf for vertex in self.vertices}
previous_vertices = {
vertex: None for vertex in self.vertices
}
distances[source] = 0
vertices = self.vertices.copy()
while vertices:
current_vertex = min(
vertices, key=lambda vertex: distances[vertex])
vertices.remove(current_vertex)
if distances[current_vertex] == inf:
break
for neighbour, cost in self.neighbours[current_vertex]:
alternative_route = distances[current_vertex] + cost
if alternative_route &lt; distances[neighbour]:
distances[neighbour] = alternative_route
previous_vertices[neighbour] = current_vertex
path, current_vertex = deque(), dest
while previous_vertices[current_vertex] is not None:
path.appendleft(current_vertex)
current_vertex = previous_vertices[current_vertex]
if path:
path.appendleft(current_vertex)
return path
graph = Graph([
(&quot;KHI&quot;, &quot;HYD&quot;, 7), (&quot;KHI&quot;, &quot;SUK&quot;, 9), (&quot;KHI&quot;, &quot;FSL&quot;, 14), (&quot;HYD&quot;, &quot;SUK&quot;, 10),
(&quot;EBT&quot;, &quot;FSL&quot;, 9)])
print(graph.dijkstra(&quot;KHI&quot;, &quot;SUK&quot;))
Dijkstra Algorithm Time Complexity
Complexity analysis for dijkstra's algorithm with adjacency matrix representation of graph.
Time complexity of Dijkstra's algorithm is O(V^2)O(V2) where V is the number of vertices in
the graph.
Best Case (Time Complexity):
Our total time complexity for our this approach is
O (VlogV + E), where v is number of vertices and E is number of edges. As stated above, this is
our most efficient case for the Dijkstra’s Algorithm
Average Case (Time Complexity):
The average running time in this case will be O (EVlog(E/V)logV).
Worst Case (Time Complexity):
Time complexity of Dijkstra’s Algorithm is O (V 2) O(V^2)O(V2)) where V is the number of
vertices in the graph.
Proof of Correctness
The main assertion on which Dijkstra's algorithm correctness is based is the following:
After any vertex v becomes marked, the current distance to it d[v] is the shortest, and will no
longer change.
Let assume
●
dijkstra(s,t) to be the shortest distance between two nodes s and t as calculated by
dijksta's algorithm
● Shortest(s,t) to be the actual shortest distance between two nodes s and t.
Now our proposition is:
dijkstra(s,t)=shortest(s,t) for a vertex t that has been visited
Now we will prove this proposition by contradiction.
So let's assume that our above proposition is false.
dijkstra(s,t)&gt;shortest(s,t) for a vertex t that has been visited
Now assume vertex x to be the first visited vertex for which dijkstra(s,x)&gt;shortest(s,x), so for all
vertices z upto before x, dijkstra(s,z)&gt;shortest(s,z)
Now assume vertex y to be a visited vertex on the real shortest path from source to x, and
vertex z to be an unvisited vertex on the real shortest path from source to x.
We can conlcude that:
dijkstra(s,y)=shortest(s,y)
dijkstra(s,z)=dijkstra(s,y)
edgecost(y,z)
dijkstra(s,x)&lt; dijkstra(s,z) as `x` is visited before `x`.
But, sub path of a shortest path is also a shortest path which implies
Shortest(s,x)=shortest(s,z)+shortest(z,x)
We can now conclude that:
dijkstra(s,x) &lt; dijkstra(s,z)
dijkstra(s,x) &lt; shortest(s,y)+edgecost(y,z)
dijkstra(s,x)=shortest(s,y)+edgecost(y,z)+shortest(z,x)
dijkstra(s,x)=shortest(s,x)
This result is contradictory to our proposition dijkstra(s,t)&gt;shortest(s,t)
So the statemant that the condition dijkstra(s,t)=shortest(s,t) is false is false, our
statement dijkstra(s,t)=shortest(s,t) is true.
Hence we have proved that the dijkstra's algorithm path will be the shortest path to any vertex.
Applications of Dijkstra Algorithm
Dijkstra's algorithm has many applications:
1. Digital Mapping Services like Google Maps: Suppose yo want to travel from on city to
another city. You use Google maps to find the shortest route. How will it work? Assume
the city you are in to be the source vertex and your destination to be another vertex.
There will still be many cities between your destination and atrting point. Assume those
cities to be intermediate vertices. The distance and traffic between any two cities can be
assumed to be the weight between each pair of verices. Google maps will apply dijkstra
algorithm on the city graph and find the shortest path.
2. Designate Servers: In a network, Dijkstra's Algorithm can be used to find the shortest path
to a server for transmitting files amongst the nodes on a network.
3. IP Routing: Dijkstra's Algorithm can be used by link state routing protocols to find the
best path to route data between routers.
Conclusion
1. In this algorithm firstly we have understood the basic working of Dijkstra's algorithm.
2. After that we came to an example to better understand the working of dijkstra's
algorithm.
3. Then we have also studied how to write code for dijkstra's algorithm with the help of
psuedocode.
4. After that we have also implemented dijkstra's algorithm in explanation with Python.
5. That is followed by a time complexity analysis of dijkstra's algorithm.
6. Finally we have proved the correctness of dijkstra's algorithm mathematically and have
also discussed applications of dijkstra's algorithm.
```