Dijkstra's Algorithm icon Dijkstra's Algorithm
University Project #Data Science#Mathematics

Dijkstra’s Algorithm#

An implementation of Dijkstras path finding algorithm.

.rmd knitted with execution results available for download here

if (!require("igraph")) {
install.packages("igraph")
library(igraph)
}
## Loading required package: igraph
##
## Attaching package: 'igraph'
## The following objects are masked from 'package:stats':
##
## decompose, spectrum
## The following object is masked from 'package:base':
##
## union

Implement Dijkstra’s Algorithm, then verify it’s accuracy w/ igraph’s implementation

# regular min() will just get the min distance, not the associated vertex
# return the v w/ min dist in Q
get_min = function(Q, dist){
d = Inf
v = NA
for(i in 1:length(Q)){
if(as.numeric(dist[1, as.character(Q[i])]) < d){ # new smallest distance
v = as.character(Q[i])
d = dist[1,as.character(Q[i])]
}
}
return(v)
}
# return 'Q' without 'u'
del = function(Q, u){
new_Q = list()
pos = 1
for(i in 1:length(Q)){
if(as.character(Q[i]) != u){
# add the element to new_Q
new_Q[pos] = Q[i]
pos = pos + 1
} # else, is 'u', don't add
}
return(new_Q)
}
# get the neighbors of 'u' in the graph 'G' that are still in 'Q'
get_neighbors = function(G, u, Q){
n = neighbors(G, u)
res = list()
pos = 1
# for each element in Q
for(i in 1:length(Q)){
# check if it's one of the neighbors
for(v in n$name){
if(as.character(Q[i]) == v){
# is neighbor
res[pos] = v
pos = pos + 1
}
}
}
return(res)
}
# Dijkstra's algorithm
dijkstra = function(G, start){
# set up
Q = list()
# n x 1 data frames
dist = data.frame(row.names=V(G)$name)
prev = data.frame(row.names=V(G)$name)
for(v in V(G)$name){
dist[1,v] = Inf
prev[1,v] = NA
Q[length(Q) + 1] = v
}
# initial value
dist[1,start] = 0
# until Q is empty
while(length(Q) > 0){
u = get_min(Q, dist)
Q = del(Q, u)
# if Q is empty, then 'u' is the last element
if(length(Q) != 0){
n = get_neighbors(G, u, Q)
for(v in n){
alt = dist[1,u] + 1 # distance between neighbors is 1, since edges un-weighted
if(alt < dist[1,v]){
dist[1,v] = alt
prev[1,v] = u
}
}
}
}
return(data.frame(c(dist, prev)))
}
# set up Q2 graph
edges2 = c("x1", "x2",
"x2", "x1",
"x2", "x3",
"x2", "x4",
"x3", "x6",
"x4", "x3",
"x6", "x5",
"x5", "x1")
G2 = make_graph(edges2, directed = TRUE)
plot(G2)

res = dijkstra(G2, "x1")
# the distances are:
res[1,1:6]
## x1 x2 x3 x4 x6 x5
## 1 0 1 2 2 3 4
# the previous nodes are:
res[1,7:12]
## x1.1 x2.1 x3.1 x4.1 x6.1 x5.1
## 1 NA x1 x2 x2 x3 x6

Comparing the results to igraph’s Dijkstra’s algorithm implementation…

# the paths from 'x1' to any other node is:
shortest_paths(G2, "x1", algorithm = "dijkstra")$vpath
## [[1]]
## + 1/6 vertex, named, from 5af2854:
## [1] x1
##
## [[2]]
## + 2/6 vertices, named, from 5af2854:
## [1] x1 x2
##
## [[3]]
## + 3/6 vertices, named, from 5af2854:
## [1] x1 x2 x3
##
## [[4]]
## + 3/6 vertices, named, from 5af2854:
## [1] x1 x2 x4
##
## [[5]]
## + 4/6 vertices, named, from 5af2854:
## [1] x1 x2 x3 x6
##
## [[6]]
## + 5/6 vertices, named, from 5af2854:
## [1] x1 x2 x3 x6 x5
# the distances from 'x1' to the other nodes are:
distances(G2, algorithm = "dijkstra", mode = "in")[,1]
## x1 x2 x3 x4 x6 x5
## 0 1 2 2 3 4

We can see that the results are the same.

← Back to Projects