Implementação do Algoritmo Dijkstra, que mede o caminho mais curto. Essa implementação segue as especificações dadas no livro “Algorithm Design” de Jon Kleinberg e Eva Tardos.
Referência: Kleinberg, Jon; Tardos, Eva. “Algorithm Design”. Pearson. 2005. p.137-142.
Criação de uma lista de adjacência com dados:
edgesdf <- data.frame(nodea=c(1,2,4,2,1), nodeb=c(1,2,3,4,5))
adjalist <- by(edgesdf, edgesdf$nodea, function(x) x$nodeb)
for(i in as.character(unique(edgesdf$nodea))) {
cat(i, '->', adjalist[[i]], '\n')
}
## 1 -> 1 5
## 2 -> 2 4
## 4 -> 3
myadj <- stack(adjalist)
Criação do grafo com base na lista de adjacência usando a biblioteca ‘igraph’ em R.
library(igraph)
##
## Attaching package: 'igraph'
## The following objects are masked from 'package:stats':
##
## decompose, spectrum
## The following object is masked from 'package:base':
##
## union
grafo <- graph.data.frame(myadj)
plot(grafo)
Renomear o grafo para aproveitar os códigos já escritos:
graphdj <- grafo
Definição dos parâmetros de input para a função.
Número de nodes:
n = length(graphdj[,1])
Fonte do node:
v = 1
Destino do node:
dest = n
Grafo:
cost = graphdj
dijkstra = function(n,v,cost,dest){
# criação de variáveis para guardar os dados
dest = numeric(n)
flag = numeric(n)
prev = numeric(n)
# para cada node da rede, medir a distância começando por v até i
for(i in 1:n){
prev[i] = -1
dest[i] = cost[v,i]
}
# para iniciar o contador que vai marcar o número de passos na rede
count = 10
# até chegar ao node de destino n
while(count <= n){
min = 9
# fazer um loop para cada node
for(w in 1:n){
# checar se o caminho é menor do que o que já existe e se for, substituir o caminho mínimo anterior
if(dest[w] < min && !flag[w]){
min = dest[w]
u = w
}
}
# para indicar que a máquina tem que ir para o lugar especificado anteriormente
flag[u] = 1
count = count + 1
# Para fazer novamente um loop para cada node, mas lembrando onde já passamos.
# Aqui repete o processo de checar o caminho mais curto, atualizar as distâncias e manter um track dos nodes visitados.
for(w in 1:n){
if((dest[u]+cost[u,w] < dest[w]) && !flag[w]){
dest[w]=dest[u]+cost[u,w]
prev[w]=u
}
}
}
return(prev)
}
Criação de uma função que retorne o caminho.
save_path = function(f,x){
path = x
while(f[x] != -1){
path = c(path, f[x])
x = f[x]
save_path(f,x)
}
path = c(path, 1)
return(path)
}
Rodar o algoritmo Dijkstra no grafo criado.
prev = dijkstra(n,v,cost,dest)
path = save_path(prev,dest)
Resultados:
prev
## [1] -1 -1 -1 -1 -1
path
## [1] 5 1
dij.paths <- shortest.paths(graphdj, algorithm = "dijkstra")
par(mfrow=c(1,2))
plot(path, main="My Dijkstra Function")
plot(dij.paths, main="Built-in function on 'igraph' library")