Document

Anuncio
Algoritmo de recorridos
minimos de grafos.
Sebastián Estrada Mejía. 910015
¿Que problema resuelve?
En la Teoría de grafos, el problema de los caminos más cortos es el
problema que consiste en encontrar un camino entre dos vértices (o nodos) de
tal manera que la suma de los pesos de las aristas que lo constituyen es
mínima. Un ejemplo es encontrar el camino más rápido para ir de una ciudad
a otra en un mapa. En este caso, los vértices representan las ciudades, y las
aristas las carreteras que las unen, cuya ponderación viene dada por el tiempo
que se emplea en atravesarlas.
Algoritmo de Dijkstra
Logo
¿Como procesada de datos?
Teniendo un grafo dirigido ponderado de N nodos
no aislados, sea x el nodo inicial, un vector D de
tamaño N guardará al final del algoritmo las
distancias desde x al resto de los nodos.
Algoritmo:
1. Inicializar todas las distancias en D con un valor infinito relativo ya que son
desconocidas al principio,
exceptuando la de x que se debe colocar en 0 debido a que la distancia de x a
x sería 0.
2. Sea a = x (tomamos a como nodo actual).
3. Recorremos todos los nodos adyacentes de a, excepto los nodos marcados,
llamaremos a estos vi.
4. Si la distancia desde x hasta vi guardada en D es mayor que la distancia
desde x hasta a, sumada a la distancia
desde a hasta vi ; esta se sustituye con la segunda nombrada, esto es:
si (Di > Da + d(a, vi)) entonces Di = Da + d(a, vi)
5. Marcamos como completo el nodo a.
6. Tomamos como próximo nodo actual el de menor valor en D (puede hacerse
almacenando los valores en una cola
de prioridad) y volvemos al paso 3 mientras existan nodos no marcados.
Una vez terminado al algoritmo, D estará completamente lleno
DIJKSTRA (Grafo G, nodo_fuente s)
para u ∈ V[G] hacer
distancia[u] = INFINITO
padre[u] = NULL
distancia[s] = 0
adicionar (cola, (s,distance[s]))
mientras que cola no es vacía hacer
u = extraer_minimo(cola)
para v ∈ adyacencia[u] hacer
si distancia[v] > distancia[u] + peso (u, v) hacer
distancia[v] = distancia[u] + peso (u, v)
padre[v] = u
adicionar(cola,(v,distance[v]))
Complejidad.
Orden de complejidad del algoritmo: O(|V|2+|E|) = O
(|V|2) sin utilizar cola de prioridad, O((|E|+|V|) log |V|)
utilizando cola de prioridad (por ejemplo un
montículo).
Algoritmo de Bellman-Ford
Logo
Algoritmo:
El Algoritmo de Bellman-Ford es, en su estructura básica, muy parecido
al algoritmo de Dijkstra, pero en vez de seleccionar vorazmente el nodo
de peso mínimo aun sin procesar para relajarlo, simplemente relaja
todas las aristas, y lo hace |V|-1 veces, siendo |V| el número de vértices
en el grafo. Las repeticiones permiten a las distancias mínimas recorrer
el árbol, ya que en la ausencia de ciclos negativos, el camino más corto
solo visita cada vértice una vez. A diferencia de la solución voraz, la
cual depende de la suposición de que los pesos sean positivos, esta
solución se aproxima más al caso general.
K=0
y
n=4
vi(0) =Ci,4
i=0
v0(0) =C0,4=INF
i=1
v1(0) =C1,4=5
i=2
v2(0) =C2,4=4
i=3
v3(0) =C3,4=1
i=4
v4(0) =C4,4=0
K=1
vi
(1)
= min vj
j
i
(0)
+ Ci,j
i=0,1,2,3
j=0,1,2,3,4
Logo
BellmanFord(Grafo G, nodo_origen s)
// inicializamos el grafo. Ponemos distancias a INFINITO menos el nodo origen que
// tiene distancia 0
for v ∈ V[G] do
distancia[v]=INFINITO
predecesor[v]=NIL
distancia[s]=0
// relajamos cada arista del grafo tantas veces como número de nodos -1 haya en el
grafo
for i=1 to |V[G]-1| do
for (u, v) ∈ E[G] do
if distancia[v]>distancia[u] + peso(u, v) then
distancia[v] = distancia[u] + peso (u, v)
predecesor[v] = u
// comprobamos si hay ciclos negativo
for (u, v) ∈ E[G] do
if distancia[v] > distancia[u] + peso(u, v) then
print ("Hay ciclo negativo")
return FALSE
return TRUE
Complejidad del algoritmo.
- Tiene una complejidad del orden de N3 por cada nodo que realiza el
algoritmo, es decir, un orden mayor que Dijkstra. El interés del algoritmo
radica en que se asemeja al de una red en la que se parte de la ignorancia
total de un nodo, en la siguiente iteración conoce a sus nodos vecinos y así
va progresivamente conociendo nodos más lejanos.
- La complejidad computacional de este problema es complejidad NPCompleto.
Complejidad NP-completo.
En teoría de la complejidad computacional, la clase de complejidad NPcompleto es el subconjunto de los problemas de decisión en NP tal que todo
problema en NP se puede reducir en cada uno de los problemas de NPcompleto. Se puede decir que los problemas de NP-completo son los
problemas más difíciles de NP y muy probablemente no formen parte de la
clase de complejidad P. La razón es que de tenerse una solución polinómica
para un problema NP-completo, todos los problemas de NP tendrían también
una solución en tiempo polinómico. Si se demostrase que un problema NPcompleto, llamémoslo A, no se pudiese resolver en tiempo polinómico, el resto
de los problemas NP-completos tampoco se podrían resolver en tiempo
polinómico. Esto se debe a que si uno de los problemas NP-completos distintos
de A, digamos X, se pudiese resolver en tiempo polinómico, entonces A se
podría resolver en tiempo polinómico, por definición de NP-completo. Ahora,
pueden existir problemas en NP y que no sean NP-completos para los cuales
exista solución polinómica aún no existiendo solución para A.
Algoritmo de Floyd-Warshall
El algoritmo de Floyd-Warshall compara todos los posibles caminos a través
del grafo entre cada par de vértices. El algoritmo es capaz de hacer esto con
sólo V3 comparaciones (esto es notable considerando que puede haber
hasta V2 aristas en el grafo, y que cada combinación de aristas se prueba). Lo hace
mejorando paulatinamente una estimación del camino más corto entre dos vértices,
hasta que se sabe que la estimación es óptima.
Sea un grafo G con conjunto de vértices V, numerados de 1 a N. Sea además una
función caminoMinimo(i,j,k) que devuelve el camino mínimo de i a j usando
únicamente los vértices de 1 a k como puntos intermedios en el camino. Ahora,
dada esta función, nuestro objetivo es encontrar el camino mínimo desde cada i a
cada j usando únicamente los vértices de 1 hasta k + 1.
Hay dos candidatos para este camino: un camino mínimo, que utiliza únicamente
los vértices del conjunto (1...k); o bien existe un camino que va desde i hasta k + 1,
y de k + 1 hasta j, que es mejor. Sabemos que el camino óptimo de i a j que
únicamente utiliza los vértices de 1 hasta k está definido por caminoMinimo(i,j,k),
y está claro que si hubiera un camino mejor de i a k + 1 a j, la longitud de este
camino sería la concatenación del camino mínimo de i a k + 1 (utilizando vértices
de (1...k)) y el camino mínimo de k + 1 a j (que también utiliza los vértices en (1...
k)).
Do
1
2
3
4
1
2
3
4
0
INF
4
INF
8
0
INF
2
INF
1
0
9
1
INF
INF
0
Do
1
2
3
4
1
2
3
4
0
5
4
7
3
0
7
2
4
1
0
3
1
6
5
0
S4
1
2
3
4
1
2
3
4
0
1
1
1
2
0
2
2
3
3
0
3
4
4
4
0
S4
1
2
3
4
1
2
3
4
0
3
1
3
4
0
4
2
4
3
0
2
4
3
1
0
Floyd-Warshall (G)
n=|V [G]|
for (int i=1; i<=numeroNodos; i++)
for (int j=1; j<=numeroNodos; j++)
si Hay conexión MatrizdePeso[i][j]=peso;
else MatrizdePeso[i][j]=infinito;
MatrizNodoIntermedio[i][j]=j;
Si i=j
MatrizNodoIntermedio[i][j]=0;
MatrizdePeso[i][j]=0;
for(int k=1;k<=numeroNodos;k++)
for(int i=1;i<=numeroNodos;i++)
for(int j=1;j<=numeroNodos;j++)
a=MatrizdePeso[i][k]+MatrizdePeso[k][j];
i f(a<MatrizdePeso[i][j])
{
MatrizdePeso[i][j]=a;
MatrizNodoIntermedio[i][j]=k;
}
return MatrizdePeso, MatrizNodoIntermedio;
Descargar