Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F...

38
Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F. ____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena 1 GRAFOS Retomando el tema de las metodologías de programación, digamos que existen otras aplicaciones que sirven para ilustrar la metodología Greedy, pero esta vez en grafos, uno de ellos es el método para hallar un árbol expandido mínimo en un grafo no dirigido, Algoritmo de Prim, y Algoritmo de Kruskal, hallar caminos más cortos en grafos dirigidos y no dirigidos, es el ideado por E. W. Dijkstra. Los tres algoritmos emplean una de las estructuras de datos más frecuentes en este tipo de problemas y que son las cola de prioridad (Heap) para seleccionar la mejor opción actual de entre un conjunto de opciones candidatas. Veamos brevemente una introducción al tema de los grafos para luego concluir con las aplicaciones antes mencionadas. Grafos es una forma sencilla de expresar digamos que los grafos comprenden de una estructura de datos basada en un conjunto de nodos o vértices V (conjunto de Objetos) y una relación R sobre este conjunto. La conexión entre los nodos se pueden describir facilmente a través de una relación binaria por ejemplo, R = {(1,2),(1,3),(2,4),(2,5),(2,6),(3,5),(3,7),(5,7),(6,7)}. La que representa el grafo G0. 1 G0: 3 2 5 6 4 7 La siguiente representación muestra el plano de una red de actividades, en donde los nodos del grafo representan el comienzo o el fin de una actividad, descrita por el arco. Lo novedoso de esta representación es que los arcos describen exactamente la duración de la actividad a través de un peso. Entre los nodos existe una relación de orden parcial. Actividad A 50 Dias Tarea B Test B Corregir faltas 1 4 2 3 20 Dias 25 Dias 15 Dias Administración(60 días)

Transcript of Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F...

Page 1: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

1

GRAFOS Retomando el tema de las metodologías de programación, digamos que existen otras aplicaciones que sirven para ilustrar la metodología Greedy, pero esta vez en grafos, uno de ellos es el método para hallar un árbol expandido mínimo en un grafo no dirigido, Algoritmo de Prim, y Algoritmo de Kruskal, hallar caminos más cortos en grafos dirigidos y no dirigidos, es el ideado por E. W. Dijkstra. Los tres algoritmos emplean una de las estructuras de datos más frecuentes en este tipo de problemas y que son las cola de prioridad (Heap) para seleccionar la mejor opción actual de entre un conjunto de opciones candidatas. Veamos brevemente una introducción al tema de los grafos para luego concluir con las aplicaciones antes mencionadas. Grafos es una forma sencilla de expresar digamos que los grafos comprenden de una estructura de datos basada en un conjunto de nodos o vértices V (conjunto de Objetos) y una relación R sobre este conjunto. La conexión entre los nodos se pueden describir facilmente a través de una relación binaria por ejemplo, R = {(1,2),(1,3),(2,4),(2,5),(2,6),(3,5),(3,7),(5,7),(6,7)}. La que representa el grafo G0. 1 G0: 3 2 5 6 4 7 La siguiente representación muestra el plano de una red de actividades, en donde los nodos del grafo representan el comienzo o el fin de una actividad, descrita por el arco. Lo novedoso de esta representación es que los arcos describen exactamente la duración de la actividad a través de un peso. Entre los nodos existe una relación de orden parcial. Actividad A 50 Dias Tarea B Test B Corregir faltas 1 4 2 3 20 Dias 25 Dias 15 Dias Administración(60 días)

Page 2: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

2

En general muchos problemas pueden ser resueltos o representados por grafos, de ahí que las aplicaciones de los grafos sean muy amplias, desde las comunicaciones, redes, descripción de modelos, circuitos lógicos, y otros. La forma de aplicar los grafos en la descripción de problemas, es a través de nodos, desde el origen (estado inicial) o punto de partida hasta la solución (estado final), pasando por una serie de estados intermedios. En particular, con ayuda de los grafos dirigidos podemos describirlo, en donde, los nodos corresponden a un determinado estado del problema, los arcos corresponden a determinadas operaciones, mientras que la solución queda descrito por un nodo o estado final. En general podemos decir que la solución para un problema cualquiera puede ser siempre representado como un camino a través de un grafo o árbol, el comienzo es la raíz del árbol y se alcanza el origen en la medida que uno llega a las hojas del árbol. Un ejemplo, en este sentido es el Problema del Laberinto. Para analizar mejor este problema, es útil utilizar la representación de árboles: Si se encuentra en un punto arbitrario del laberinto, comprende en teoría que Ud. tiene 4 posibilidades de movidas, arriba (ar), abajo (ab), izquierda (iz) y derecha(de). Estas 4-reglas se aplican para determinan las variantes, recorridos o desvíos dentro del laberinto. 1. ir a la derecha 2. en caso de no poder, ir a la izquierda 3. en caso de tampoco funcionar, ir hacia arriba 4. en al caso que tampoco se pueda, ir hacia abajo. Como podrá imaginarse, no siempre el camino conduce del inicio al final, pues por ejemplo se da la situación de buscar el objetivo (2b), de donde se tiene,

1

2

3

a b c

Page 3: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

3

1a

3a

3b

3c

2c

1c

1b

1a

1b

1c

3c

2c

3b

3a

1a

2a

2a

2b

En este caso, es necesario notar que ya se estuvo una vez en (1a), de manera que el ciclo es una consecuencia desafortunada en escoger las reglas, sin embargo al considerar otro tipo de estrategia en término de escoger de otra forma las reglas, podemos ver, en el laberinto

1

2

a b c d el siguiente camino: Nodo de partida Nodo de llegada

1a 1b

1c

1d 2c

2d

Page 4: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

4

Existen situaciones en las cuales se encuentra en un „callejon sin salida“, en tal caso deberá volver a la antigua o antiguas “jugada(s)“, para a partir de allí planificar una nueva estrategia, esta forma de ir examinando se conoce en general como, Backtracking. Una de las formas más populares para la búsqueda de la solución es a través de BFS o DFS. Antes, recordemos que un grafo G consiste de 2 conjuntos o componentes (V, E), en donde E es el conjunto de los vértices o nodos y E el conjunto de los arcos o lineas, llamadas en general edges. Lo denotamos por G=(V, E) a) E es un conjunto de 2-subconjuntos de V, y en este es un grafo no dirigido

(usualmente llamado grafo). En este caso, cualquier arco debe estar en la forma, {vi , vj }.

b) E es un subconjunto de V x V, en este caso G es llamado grafo dirigido. Cualquier elemento {vi , vj } de E es un arco dirigido desde vi a vj.

Nota: Todos los grafos citados no contiene lazos ni arcos paralelas. Ejemplo (grafos no-dirigido) V={1, 2, 3, 4, 5, 6} con E= {{1, 2}, {2, 5},{1, 5},{3, 6}} Ejemplo (grafos dirigido) V={1, 2, 3, 4, 5, 6} con E= {(1, 2), (2, 4), (4, 1), (2, 5), (4, 5), (5, 4), (6, 3) } Representación Pictórica Representación Matricial Matriz de Adyacencia para los Digrafos: Sea G=(V, E) un grafo dirigido, donde V es indiciado {1, 2, ..., n} . La matriz de adyacencia n x n de G es definida por A[v, w] = 1, si (v, w) ε E, y 0, en otro caso. Matriz de Adyacencia para los grafos: Sea G=(V, E) un grafo dirigido, donde V es indiciado {1, 2, ..., n} . La matriz de adyacencia n x n de G es definida por A[v, w] = 1, si (v, w) ε E, y 0, en otro caso. La matriz de adyacencia de un digrafo puede no ser simétrica , mientras que de un grafo no dirigido debe ser simétrica.

1 2 3 1 2 3

4 5 6 4 5 6

Page 5: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

5

Ejemplo: Dados los grafos G1: G2: Se muestran las matrices de adyacencia, para cada uno. 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 Si el grafo posee pesos en sus arcos la matriz de representación es Representación a través de un TDA(Lista Enlazada) Otra forma de representar los grafos no dirigidos es a través de listas enlazadas, tal como se muestre en la siguiente figura.

1 2 3 1 2 3

4 5 6 4 5 6

1

3

6

4

2

7

5

1

4

5 8

1

6 3

6 1

2

9 9

1 2 3 4 5 6 71 ∝ 4 1 1 ∝ ∝ ∝ 2 ∝ ∝ ∝ 8 5 ∝ ∝ 3 ∝ ∝ ∝ ∝ ∝ 9 ∝ 4 ∝ ∝ 6 ∝ ∝ 9 15 ∝ ∝ ∝ 3 ∝ ∝ 66 ∝ ∝ ∝ ∝ ∝ ∝ ∝ 7 ∝ ∝ ∝ ∝ ∝ 2 ∝

Page 6: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

6

1 2 3 4 5 6 7 Un digrafo con peso, es un grafo G en el cual todos sus arcos están asociados con un número, llamado peso del arco. Por ejemplo, G1: G2: 7.8 5 3 8 7.6 3.4 7 5 7 9.6 9 8.8 Para los digrafos con pesos, los pesos pueden almacenarse en la matriz. Por ejemplo, si (v, w) ε E, entonces definimos A [v, w] = W[v,w], el cual es el peso del arco (v, w). De otra manera se define A [v, w] = ∞, el cual es diferente a cualquier número. Lo mismo puede hacerse para los grafos no dirigidos. Por otra parte el grado de un vértice en un grafo no dirigido está definido como el número de arcos incidentes con él. Mientras que el grado total es la suma de sus grados por cada uno de sus vértices. Para el grafo no dirigido G2 se tiene que grad(1) = grad(2) = grad(5)= 2, grad(3) = grad(6) =1 y grad(4) = 0. Mientras que el grado total es grad(G2)= 2+2+2+1+1+0=8. En general se verifica que grad(G)= 2|E|, siendo |E| el cardinal de E.

1 2 3 1 2 3

4 5 6 4 5 6

3 4 2

1 4 5

1 6 4

3 4 7

2 4 7

7 6 3

1

3

6

4

2

7

5

1 2 5

6 4 5

Page 7: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

7

Por otra parte el grado de un vértice en un grafo dirigido está definido el outGrad de un vértice, como el número de arcos con salida, e inGrad de un vértice como el número de arcos de entrada. Entonces el grado de un vértice en un grafo dirigido es la suma de arcos incidentes con él. Mientras que el grado total es la suma de outGrad y inGrad. Para el grafo dirigido anterior tenemos inGrad (1)= outGrad(1) = 1, inGrad(2)=1, inGrad(5)=2, outGrad(5)=1, outGrad(2)=2. Para un digrafo en general se tiene, que para un digrafo G, suma(inGrad(v) = suma(outGrad(v) = |E|, siendo |E| el cardinal de E. Lista de Adyacencia Una lista de adyacencia es un array Adj[1..n] de punteros, donde el punto Adj(v) a una lista enlazada que contiene los vértices, los que son adyacentes a v. Caminos y Ciclos en un Grafo. Un camino en un grafo dirigido es una secuencia de vértices < v0 , v1, ..., vk > , tal que {vi , vi-1} es un arco, para i =1, 2, ..., k. La longitud de un camino es el número de arcos, k. Se dice que w es alcanzable desde u , si existe un camino de u a w. Por ejemplo en G1, < 1 , 2, 4, 5, 4 > es un camino de longitud 4, pero no simple, pues se dice que un camino es simple si todos sus vértices son distintos. Se dice que un grafo no dirigido G es conexo si todo par de vértices están conectados por un camino. G3 es un grafo no dirigido conexo, pero G2 es no conexo. En un grafo dirigido, un ciclo es un camino < v0 , v1, ..., vk > en el cual v0 = vk., por ejemplo <1, 2, 4, 5, 1> es un ciclo. Caminos y ciclos en grafos no dirigidos se definen en forma similar. G3: Se dice que un grafo dirigido es estrictamente conexo, si para cualquier par de vértices uno de ellos puede ser alcanzado por algún otro. G4 es estrictamente conexo, mientras que G5 no lo es. G4: G5:

1 2

5

a d 1 4

b e 2 5

c 3

Page 8: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

8

Un grafo se dice acíclico si no contiene ciclos. Un grafo es un árbol, si es un grafo no dirigido, conexo y aciclico. Por ejemplo, G6 es un árbol. G6: En un grafo G no dirigido las siguientes propiedades son equivalentes. • G es un grafo, • cualquier par de vértices en G son conexos, a través de un camino simple. • G es conexo y |E| = |V| – 1. • G es aciclico y |E| = |V| – 1. Arbol con raíz es un árbol en el cual uno de los vértices es distinguido de los otros. El vértice distinguido se conoce como raíz. Si 2 es la raíz estamos frente a un árbol con raíz, de altura 2, con 3 nodo en el nivel 2, ellos son 3, 5, 6 y 7. La raíz esta en el nivel 0. G7: Arbol Binario es el árbol que posee solamente 2 o 0 hijos en cada nivel, G7 no es binario. Arbol ordenado es el árbol en el cual sus hijos están ordenados. Búsqueda en Profundidad y a lo Ancho Al igual que en los árboles, hay diferentes métodos que podemos utilizar para recorrer los grafos. Los más comunes son: Búsqueda de primero en profundidad y primero en extensión, sin embargo, a diferencia de los árboles los grafos no contienen nodo raíz, de manera que se necesita un nodo o vértice elegido de manera arbitraria como punto de inicio. La búsqueda en profundidad o a lo ancho

1 2

3

4

1

2

3

4

5 6

8

7

Page 9: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

9

en grafos conexos no dirigidos sirve como un marco de referencia en torno del cual se pueden diseñar muchos algoritmos para verificar ciertas propiedades de los Grafos. Una forma que ayuda a implementar la BP en un programa consiste en asignar un orden fijo a los vértices del grafo G, de manera que si existen dos o más vértices adyacentes a un vértice v y ninguno de estos vértices ha sido visitado antes, sabremos con precisión cuál de ellos debe visitarse primero. Una DFS (Depth First Search), puede relacionarse con el recorrido de un árbol en el que visitamos a todos los hijos de un nodo antes de visitar a cualquiera de sus hermanos.

• Comienza con el nodo raíz, v0. • Elige un nodo que no ha sido visitado, vi, adyacente a v0, y lo procesa. • Escoge un nodo sin visitar adyacente a vi, y lo visita. • Continúa de esta forma hasta que encuentra un nodo que no tiene ningún

vértice adyacente sin visitar. • Regresa a un nodo que tiene un vértice adyacente sin visitar y prosigue el

procesamiento desde ese punto. Dado el grafo, en donde se define un orden lexicográfico, a, b, c, ....., j. Inicio a b c d e f g h i j Cuya salida es representada por un árbol expandido DFS (Depth First Search), a b c d e g f h i j Por otra parte, en la BFS (Breadth First Search), la cual difiere de la DFS, en el sentido que, primero procesa todos los nodos adyacentes al nodo de inicio, y luego todos los nodos adyacentes a éstos y así sucesivamente. Cuya salida es representada por un árbol expandido BFS (Breadth First Search),

Page 10: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

10

a b c d e g f h i j Existen una serie de aplicaciones de estos algoritmos, en particular del DFS, como es el caso de Biconectividad, que se refiere a cuando en un grafo no existen vértices cuya eliminación desconecta el resto del grafo. En el grafo anterior, se ve claramente que e y g son puntos conflictivos, o el hallar el número de componentes conexas en un grafo. Otra de las aplicaciones surge al querer determinar si un grafo es conexo o no, si se conoce su matriz de adyacencia. La idea en este caso es no construir el grafo sino tan solo con la información que ofrece la matriz mostrar algún resultado. Dada la matriz Con v1 como raíz aplicamos BA, primero visitando los vértices adyacentes a v1 y los enumeramos en orden ascendente según los subíndices de los vértices de la matriz. Continuamos con la búsqueda, y como alcanzamos todos los vértices de G, resulta que G es conexo. Notar que a través de la BP o BP se determina un árbol. Otra de las aplicaciones de la BP y BA es al considerar, por ejemplo, grafo G8 G8:

e b

as

d

c

v1 v2 v3 v4 v5 v6 v7 v1 0 1 0 0 0 0 1 v2 1 1 1 1 0 0 0 v3 0 1 1 0 0 0 0 v4 0 1 0 0 1 0 1 v5 0 0 0 1 0 1 0 v6 0 0 0 0 1 0 0 v7 0 1 0 0 0 0 1

v1 v1 v2 v7 v2 v3 v4 v3 v4 v5 v5 v7 v6 v6 Búsqueda en Búsqueda en Anchura Profundidad

Page 11: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

11

Se ven 3 caminos simples desde la fuente s al nodo b: sb, sab, sedb, con longitudes 1, 2 y 3 respectivamente. El camino más corto desde s a otros vértices son: sa, sb, sbc, sbd, se. Se verifica que existen dos caminos más cortos desde s al nodo d. La distancia d[v] se refiere a la longitud del camino más corto desde a al nodo v, es decir d[v] = 2. Se define d[s]=0, mientras que predecesor pred[v] se refiere al primer vértice a lo largo del camino más corto si se camina desde v hacia s. Se define el pred[s]= nil, notar que pred[v] es relativo al camino más corto, es decir dado el camino más corto sbc, pred[c]=b. Con esto ya estamos en condiciones de presentar el siguiente problema. Problema del camino más corto. Dado un grafo G=(V, E) y un vértice fuente s ε V, se pide hallar la distancia d[v] y el camino más corto desde s hacia todos los otros vértices en G. La forma de expresar el camino más corto estará dado por el array pred[v]. Por ejemplo, para encontrar un camino más corto en sbc desde s a c usamos el array de la siguiente manera.

v s a b c d e

d[v] 0 1 1 2 2 1 Pred [v] nil s s b b s

Dado un grafo G=(V, E) el procedimiento BFS puede utilizarse para determinar caminos de longitud mínima en un grafo sin pesos, que vayan de un vértice dado v a todos los demás vértices, ahora si se incluyen los predecesores pred[v], se puede usar para derivar un camino más corto desde un vértice fuente s a otro vértice v, así como también para obtener un árbol de expansión. En la implementación del algoritmo BFS se consideran dos array d[v] y pred[v], además de un array auxiliar color[v], el que contiene tres valores posibles: blanco (no descubierto), gris (descubierto no-procesado), y negro (descubierto y procesado). En general, considerar que al igual que los árboles es posible recorrerlos de alguna manera, para los grafos existe algo similar, lo que se obtiene a través de Breadth-First-Search o Depth-First-Search, en donde BFS involucra en la implementación una cola Q mientras que DFS involucra un Stack. La única diferencia entre ellos es que, mientras ambos algoritmos agregan claves o items al final de la lista, BFS elimina ellos desde el comienzo, lo que resulta de mantener la lista como una queue, mientras DFS los elimina desde el final, manteniendo la lista como un stack.

Page 12: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

12

Respecto de su performance digamos que todos los vértices están ya sea en un Stack o en una Queue, por lo tanto, la travesía tiene un costo de al menos O(|V|). Sin embargo, para cada vértice, debemos encontrar los vértices adyacentes, luego DFS y BFS depende de la performance de la operación obtenerAdyacente(u); la que se refiere a entregar una lista de los vértices adyacentes al vértice u (en grafos dirigidos o no). Dado el siguiente grafo no-dirigido y un vértice fuente, hallar las distancias desde s a todos los vértices u ε V y el predecesor pred[u] para obtener el camino más corto. El siguiente ejemplo muestra la descripción del algoritmo en sus diversas fases, a partir del grafo descrito, veremos una BFS simulación. Breadth_First_Search(BFS) for todo u en V { //inicio color[u]=blanco; d[u]=infinito; pred[u]=null; }

color[s]=gris; //inicio de la fuente s. d[s]=0; Q={s}//put s en la cola.

While (q es no vacío){ u= dequeu(Q);//u es el siguiente nodo visitado. for (todo vértice w adyacente a u, es decir en Ady[u].) if (color[v]= blanco){

color[v]=gris; d[v]= d[u] + 1; pred[v]=u; enqueu(Q, v);

} } color[u]= negro; }

Ejemplo de simulación del algoritmo BFS.

b c a f S e d Q = vacio

vertice u s a b c d e f Color [u] b b b b b b d[u] ∞ ∞ ∞ ∞ ∞ ∞ Pred [u] NIL NIL NIL NIL NIL NIL

Page 13: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

13

b c a f S e d Q = < s > , Put s en Q (descubierto) & marcado „G“, como no_procesado.

vertice u s A b c d e f Color [u] G W W W W W W d[u] 0 ∞ ∞ ∞ ∞ ∞ ∞ Pred [u] NIL NIL NIL NIL NIL NIL

b c a f S e d Hallar adj[s] = {b,e}. b, e descubiertos, marcados „gris“ Dequeue s desde Q y put b, e en Q. Marca s con „B“. Ingresa d[b] = d[e]= 1 y Pred [b] = pred [e]=s. Q = < b, e > ,

vertice u s A b c d e f Color [u] B W G W W G W D[u] 0 ∞ 1 ∞ ∞ 1 ∞ Pred [u] NIL s NIL NIL s NIL

b 1 2 c a 2 2 S 0 f e d 1 (1) Hallar adj[s] = {a, c, f} aqui adj [b] consiste de solamente aquellos vértices

adjacentes a b, cuyo color es blanco. a, c, f descubiertos, marcados „G“. (2) Dequeue b desde Q y put a, c, f Marca b con „B“. (3) Put d[a] = d[c]= d[f] = 1= 2. pred [a] = pred [c]= pred [f] = b. Q = < e, a, c, f > ,

vertice u s A b c d e f Color [u] B G B G W G G d[u] 0 2 1 2 ∞ 1 2 Pred [u] B s b NIL s b

Page 14: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

14

b 1 2 c a 2 2 S 0 f 2 e d 1 Hallar adj[e] = {d}. d descubierto, marcado „G“. Dequeue e desde Q y put d en Q. Marca e con „B“. Put d[d] = d[e] + 1 = 2. Pred [d] = e. Q = < a, c, f, d>

vertice u S A b c d e f Color [u] B G B G G B G d[u] 0 2 1 2 2 1 2 Pred [u] B s b e s b

b 1 2 c a 2 2 S 0 f e d 1 adj[a] = ∅. Dequeue a desde Q. No se realiza entonces el „for loop. Pero cambia el color de a por „B“. Q = < c, f, d >

vertice u s A b c d e f Color [u] B B B G G B G d[u] 0 2 1 2 2 1 2 Pred [u] B s b e s b

b 1 2 c a 2 2 S 0 f e d adj[c] = ∅. Dequeue c desde Q. No se realiza „for „ loop. Pero cambia el color de c por „B“. Q = < f, d> Vertice u s A b c d e f

Color [u] B B B B G B G d[u] 0 2 1 2 2 1 2 Pred [u] B s b e s b

Page 15: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

15

b 1 2 c a 2 2 S 0 f e d 1 adj[f] = ∅. Dequeue f desde Q. No se realiza „for“ loop. Pero cambia el color de f por „B“. Q = < d >

vertice u s A b c d e f Color [u] B B B B G B B d[u] 0 2 1 2 2 1 2 Pred [u] B s b e S b

b 1 2 c a 2 2 S 0 f e d 1 adj[d] = ∅. Dequeue d desde Q. „for“ loop no se ejecuta. Pero cambia el color de d por „B“. Q = ∅

vertice u s A b c d e f Color [u] B B B B B B G d[u] 0 2 1 2 2 1 2 Pred [u] B s B e s b

b 1 2 c a 2 2 S 0 f e d Ya que Q es vacío, se detiene el proceso. Q = ∅

vertice u S A b c d e f Color [u] B B B B B B B d[u] 0 2 1 2 2 1 2 Pred [u] B s b e s B

Page 16: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

16

b 1 2 c a 2 2 S 0 e d El problema de leer los nodos de un grafo se refieren a poder visitar los nodos de un grafo de acuerdo a alguna estrategia, en lo particular BFS es una solución para este tipo de problemas, pues visita los nodos de un grafo no dirigido de acuerdo a la distancia desde la fuente a todos los otros vértices, entregado en dos array d[v] y pred[v]. Veamos el problema de leer los nodos en un grafo dirigido o digrafo. Otro ejemplo, basado en Capítulo 23 de CLR. BFS(G,s) 1 for each vertex u V[G] - {s} 2 do color[u] WHITE 3 d[u] 4 [u] NIL 5 color[s] GRAY 6 d[s] 0 7 [s] NIL 8 Q {s}

9 while Q 10 do u head[Q] 11 for each v Adj[u] 12 do if color[v] = WHITE 13 then color[v] GRAY 14 d[v] d[u] + 1 15 [v] u 16 ENQUEUE(Q,v) 17 DEQUEUE(Q) 18 color[u] BLACK

Page 17: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

17

Nuestro objetivo, es seguir mostrando algoritmos de grafos, que usen la estrategia voraz o greedy, tales como los algoritmos de Dijkstra, Prim y Kruskal En este contexto consideramos un digrafo ponderado, G=(V, E) para cada arco e=(a,b), se interpreta p(e) como la longitud de una ruta directa entre a y b. Para cualquier par de vértices a, b se describe d(a, b) como la distancia más corta entre a y b. (observar que el algoritmo NO es válido si se tiene pesos negativos). Si no existe tal camino en G, se denota d(a,b)=infinito. La longitud de un camino será la suma de los pesos de los arcos que lo constituyen. El algoritmo de Dijkstra ofrece una estrategia voraz, para el problema de “encontrar los caminos más cortos entre todo par de vértices”, ya que lo que obtenemos como el mejor resultado localmente, se convierte en el mejor resultado globalmente(para todos los vértices del grafo). Recordar que BFS es un algoritmo para encontrar caminos más cortos de un vértice fuente a todos los otros vértices, es por eso que se puede considerarse Dijkstra como una generalización de la BFS. Por otra parte, los algoritmos de Prim y Kruskal se relacionan con el problema de encontrar árbol expandidos minimal. El primero comienza en un vértice de inicio arbitrario y “cultiva” un árbol a partir de ese punto agregando aristas o arcos de manera iterativa hasta obtener un árbol de expansión mínimo, en donde en cada iteración se agrega un arco de peso mínimo que no forme un ciclo con el árbol en cuestión. Mientras que Kruskal, toma “codiciosamente” la arista de menor peso que quede en cualquier parte del grafo, en tanto no forme ciclo con las aristas que ya se escogieron, determinando al final un árbol expandido mínimo, digo al final pues existen etapas en donde se generan “bosques” dispersos para luego dar origen al árbol en cuestión, es decir en cada iteración se agrega una arista con peso mínimo al grafo, de manera que no genere un ciclo (recordar que buscamos un árbol), finalmente cuando el grafo(árbol) tenga n -1 aristas se detiene, siendo n el número de vértices de G. Dijkstra (G, w, s) { for todo u en V do { d [u] = infinito; color [u] = blanco; } d [s] = 0; pred [s] = nil; Q = construir queue con todos los vertices; while (No_Vacio (Q) ) do { u = Extraer_Min (Q); for todo v en Adj [u] do { if (d[u] + w(u, v)) < d [v] then { d[v] = d[u] + w (u, v); pred [v] = u; } } color [u] = negro; } }

Page 18: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

18

Ejemplo b 1 c Inf inf 7 8 0 3 2 4 5 s 2 inf inf a 5 d Etapa 0: Inicio

v s a b c d d[v] 0 ∞ ∞ ∞ ∞

pred [v] nil nil nil nil nil color [v] blanco blanco blanco blanco blanco

Priority Queue:

v s a b c d d[v] 0 ∞ ∞ ∞ ∞

b 1 c Inf inf 7 8 0 3 2 4 5 s 2 inf inf a 5 d Etapa1: Como Adj [s] = {a, b}, trabaja sobre a y b, actualizando la información

v S a b c d d[v] 0 2 7 ∞ ∞

pred [v] nil s s nil Nil color [v] negro blanco blanco blanco blanco

Priority Queue:

v a b c d d[v] 2 7 ∞ ∞

b 1 c Inf inf 7 8 0 3 2 4 5 s 2 2 inf a 5 d Etapa2: después de realizada la Etapa1, a tiene la clave minima en la priority queue. Como Adj [a] = {b, c, d}, trabaja sobre b, c, d y actualiza la información, y así sucesivamente .....

Page 19: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

19

v S a b c d d[v] 0 2 5 10 7

pred [v] nil s a a a color [v] negro negro blanco blanco blanco

Priority Queue:

v b c d d[v] 5 10 7

b 1 c 5 6 7 8 0 3 2 4 5 s 2 2 7 a 5 d Etapa5: Después de realizada la Etapa 4, d tiene la clave mínima en la priority queu. Como Adj [d] = {c}, trabaja sobre c y actualiza la información.

v s a b c d d[v] 0 2 5 6 7

pred [v] nil s a b a color [v] B B B B B

Priority Queue: Q : ∅ Digamos que el árbol de los caminos más cortos (Shortest Path Tree), T = (V,A) se define como A= {(pred [v], v) , v ∈ V - {s}}. Finalmente el array pred[v] es usado para construir el árbol T. b 1 c 5 6 0 3 s 2 2 7 a 5 d

Page 20: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

20

Ejemplo:

v s a b c d d[v] 0 2 5 6 7

Pred [v] nil s a b a

Arbol expandido mínimo (Minimal Spanning Tree)

El problema es hallar un árbol expandido mínimo para un grafo no dirigido, conectado y ponderado. En el caso de los grafos no conectados, la extensión natural del problema consiste en hallar un árbol expandido mínimo para cada componente conectado. Los árboles expandidos mínimos sólo tienen sentido en los grafos no dirigidos cuyas aristas están ponderadas, así que todas las referencias a "grafos" en esta sección son a grafos no dirigidos, y los pesos son siempre pesos de aristas. Recordemos que la notación G = (V, E, W) significa una extensión a la dada para los grafos, al considerar W como una función que asigna un peso a cada una de las aristas de E. Ésta es meramente la descripción matemática, pues en la implementación por lo regular no hay tal "función" y el peso de cada arista simplemente se almacena en la estructura de datos para esa arista. Un árbol expandido T es un grafo conexo, aciclico, subgrafo de G, el cual une cada uno de los nodos. El costo de T, se interpreta como la suma de los pesos de todos los arcos en T. En un grafo ponderado G = (V, E, W), el peso de un subgrafo es la suma de los pesos de las aristas incluidas en ese subgrafo. Un árbol expandido mínimo (AEM) para un grafo ponderado es un árbol expandido cuyo peso es mínimo. 2 k1 k2 4 1 3 10 2 7 k3 k4 k5 5 8 4 6 k6 k7 1 el Arbol Expandido Mínimo es : 2 k1 k2 1 2 k3 k4 k5 4 6 1 k6 k7

Page 21: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

21

Hay muchas situaciones en las que es preciso hallar árboles expandidos mínimos. Por ejemplo, siempre que se busca la forma más económica de conectar un conjunto de terminales, trátese de ciudades, terminales eléctricas, computadoras o fábricas, empleando por ejemplo carreteras, cables o líneas, este algoritmo resulta de mucha utilidad. En este caso se introducen dos algoritmos greedy (Prim y Kruskal) para computar el AEM. Algoritmo Prim’s: Construye el árbol agregando uno a uno los nodos a partir de un árbol base, evitando que se formen ciclos. A = ;

Etapa0: Escoge cualquier elemento r y S={r}, A=φ, (siendo r la raíz del Arbol Expandido Mínimo(AEM), en donde A es el conjunto de las aristas, V conjunto de vértices. Etapa1: Hallar los arcos adyacentes más livianos de manera que un punto final pertenezca a S y el otro en V-S. Agregarlos a S y los más livianos a A. Ahora, la forma de cómo ir agregándolos es considerar el arco de menor peso, de manera que un punto pertenezca a S y el otro esté en V-S. Si V-S=φ, entonces se detiene y entrega el AEM, de otra manera vuelve a la Etapa1. La idea antes mencionada se refiere a expandir el árbol actual agregando el arco más liviano y su punto final, tal como se aprecia en la figura, es decir, b 24 h b 24 h 20 12 20 12 a 26 12 a 26 12 g i g i 16 23 16 23 f 14 f r c 14 r c nuevo-nodo 8 8 d e d e nuevo-arco

Page 22: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

22

Ejemplo (Prim) 10 b e Fig.1 4 8 7 6 a 9 d 5 g 9 2 8 2 c f 1 10 Fig.2 b e 4 8 7 6 a 9 d 5 g 9 2 8 2 c f 1 En Fig. 1 se visualiza un grafo ponderado y conexo. En Fig. 2 se visualiza la Etapa0. S={a}, V-S = { b, c, d, e, f, g }, con arco más liviano {a, b}. 10 b e Fig. 3 4 8 7 6 Etapa1.1 antes a 9 d 5 g 9 2 8 2 c f 1 10 b e Fig. 4 4 8 7 6 Etapa 1.1 después a 9 d 5 g 9 2 8 2 c f 1 En Fig. 3 se muestra la etapa1.1, “antes” , con S={a}, V-S={b, c, d, e, f, g}, A={ } y el arco más liviano {a, b}, mientras que en Fig. 4 se muestra la etapa1.1, después”, en donde S={a, b}, V-S={c, d, e, f, g}, A={ {a, b} } y el arco más liviano es {b, d}, {a, c}. Continuando de esta manera llegamos a la Etapa1.6 “antes“ con S={ a, b, c, d, f, g},

Page 23: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

23

V-S= {e}, A={ {a, b}, {b, d}, {c, d}, {c, f}, {f, g}}, arco más liviano= {f, e}, como se muestra en Fig. 5 10 Fig. 5 b e 4 8 7 6 Etapa1.6 antes a 9 d 5 g 9 2 8 2 c f 1 10 b e Fig. 6 4 8 7 6 Etapa1.6 después a 9 d 5 g 9 2 8 2 c f 1 Mientras que en Fig. 6 se tiene la Etapa1.6 “después” con S={ a, b, c, d, e, f, g}, V-S= { }, A={ {a, b}, {b, d}, {c, d}, {c, f}, {f, g}, {f, e}}. Así, de esta manera se logra finalmente obtener el AEM. Algunas interrogantes: ¿Cómo hacer que se actualice S eficientemente?. Una forma es llevando el control bajo un Color[v], coloreando los vértices de S con negro, y los de V-S con blanco. ¿Cómo hacer que encuentre el arco más liviano y actualizar eficientemente A?. Usando una cola de prioridad para encontrar el arco más liviano, y usando pred[v], para actualizar A. Prim(G, w, r){ //El grafo G esta dado en forma de lista de adyacencia. For (u en V)//inicialización {

clave[u] = +infinito; color[u] = blanco; }

clave[r] = 0; //raíz del AEM pred[r] = nil; Q = new PriQueue(V); //put vértices en Q.

While (Q.novacío()) //hasta que todos los vértices estén en AEM { u = Q.extraerMin(); // vértice con el arco más liviano for (v en adj[u]) { if ((color[v] = = blanco) & (w(u,v) < clave[v]) { clave[v] = w(u,v); //nuevo arco más liviano fuera de v Q.decreceClave(v, clave[v]);

Page 24: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

24

pred[v] = u; } } color[u] = black; } Por otra parte Kruskal ofrece otro ejemplo de la técnica greedy. Recordar que en la estrategia greedy en cada etapa del algoritmo se debe realizar una “elección” de entre varias. Greedy invoca realizar la “mejor” en ese momento. Aunque en este tipo de estrategias generalmente no garantiza encontrar una solución optimal global para el problema, pero para encontrar un AEM se puede demostrar que si se encuentra una solución optimal. La idea se refiere a construir un árbol a través de arcos minimales en cada etapa evitando generar ciclos. Notar que en algún momento deberá realizar una fusión entre subarboles del grafo G. Se sabe que todo grafo conexo tiene un árbol expandido, y que el peso de un grafo es la suma de los pesos de todos sus arcos. Un árbol expandido de un grafo es justamente un subgrafo que contiene todos los vértices y es un árbol. En principio, un grafo puede tener varios árbol expandidos, por ejemplo el grafo completo de 4-vértices posee 16 árbol expandido. Por ejemplo, G9 es un grafo ponderado, mientras que el subgrafo T es un árbol expandido, de varios que se pueden formar. (se distingue T, por los arcos marcados con líneas negras sobremarcadas. 10 b e 4 8 7 6 a 9 d 5 g 9 2 8 2 c f 1 Ahora, las aplicaciones usuales, son entre otras la planificación de un plan de red teléfonica o de computadores. Supongamos que Ud. tiene un negocio con varias oficinas o sucursales y desea arrendar líneas telefónicas o comprar PC’s para conectarlos entre sí y la compañía telefónica cobra diferentes cantidades de dinero para conectar pares diferentes de ciudades. Usted quiere un juego de líneas que conectan todas sus oficinas con un costo total mínimo. Una aplicación menos obvia es que el árbol expandido mínimo puede usarse para resolver el problema del vendedor viajero. Una manera formal conveniente de definir este problema es encontrar el camino más corto que visita por lo menos

Page 25: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

25

una vez cada punto, que conecta con otro concepto que son los caminos y circuitos Eulerianos y Hamiltonianos, conceptos que no se abordarán en esta sección. Cabe hacer notar que el árbol expandido mínimo puede no ser único , sin embargo, si el peso de todos los arcos son distintos de a pares, este si que es único. Algoritmo Kruskal: La idea se refiere a construir un árbol a través de arcos minimales en cada etapa evitando generar ciclos. A = ;

Etapa0: Pone A= φ, y E es el conjunto de todos los arcos. Etapa1: Considera todos los {u, v} en E-A que tiene el peso más pequeño y chequea si al agregar {u, v} genera un ciclo o no. Si lo genera, E=E-{{u, v}} y chequea si E es vacío. Si E = φ, para y entrega el AEM, sino vuelve a la etapa1. Si no genera un ciclo, pone A=A ∪ {{u, v}} y E= E-{{u, v}}. Entonces cheque si si E es vacío. Si E= φ, para y devuelve el AEM, de otra manera vuelve a Etapa1. Algunas observaciones: Cómo hace el algoritmo para encontrar el arco {u,v} en E-A con el menor peso en la Etapa1.?. Una posible respuesta es ordenar E en orden creciente por los pesos. Cómo hace el algoritmo para chequear “si al agregar el arco{u,v} se genera un ciclo.?. En general ya se tiene una dificultad preliminar al tener que implementar A=A ∪ {{u, v}} y por otra testear si u y v están en el mismo arbol. Una posible respuesta es utilizar la estructura de datos Union-Find, recordar que esta estructura soporta 3 operaciones, Create_Set(x), crea un conjunto que contiene un item x. Find_Set(x) encuentra el conjunto que contiene un item dado x. Union(u, v), mezcla el conjunto que contiene u y v respectivamente en un conjunto común. Find_Set(u)=Find_Set(v), podría responder si u y v están o no en el mismo árbol. Kruskal(G, w) A={}; For (todo u en V) Create_Set(u); Ordenar E en orden creciente basado en los pesos For ( todo {u,v} desde la lista ordenada){ If (Find_Set(u)!= Find_Set(v)){ Agregar {u, v} a A; Union(u,v); } } Return A; }

Page 26: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

26

10 b e Fig.1 4 8 7 6 a 9 d 5 g 9 2 8 2 c f 1 arcos pesos A={ } c, f 1 c, d 2 f , g 2 a, b 4 e, f 5 e, g 6 d, e 7 b, d 8 a, c 8 c, b 9 b, e 10, siendo el peso total 8+5+4+2+2+1= 22.- Ahora, dada la dificultad al considerar pesos negativos digamos que el algoritmo Bellman Ford(BF), resuelve el problema de los caminos mínimos con origen único en el caso más general, es decir cuando el grafo es ponderado y los pesos pueden ser negativos. En resumen, dado un grafo ponderado y un nodo fuente s, BF encuentra el camino mínimo desde s a todos los nodos si no hay ciclos con peso negativo en el grafo. Si hay un ciclo con peso negativo, entonces este algoritmo indicará que no es posible ninguna solución. Por otra parte, para resolver el problema de todos los pares de puntos del camino más corto en un grafo G, (All Pairs Shortest-Paths, en inglés) es posible de utilizar el algoritmo de Floyd-Warshall el que ofrece una estrategia programación dinámica. Formalmente digamos que el problema se presenta como sigue: “Dado un digrafo ponderado G con una función peso, se pide determinar la longitud de los caminos más cortos (es decir, distancias) entre todos los pares de vértices en G”. Se asume que no existen ciclos con costo cero o negativo. Otra forma de resolver este problema es encontrando todos los caminos más cortos desde un vértice fuente s ε V a todo vértice v ε V, que desde luego no resulta tan eficiente desde el punto de vista de la cantidad de puntos a analizar. Para solucionar este problema veamos las alternativas que surgen usando Dijkstra y la programación dinámica, entregando la implementación del análisis de todos los puntos para un grafo dado.

Page 27: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

27

Aplicando el algoritmo de Dijkstra a todo vértice (como la fuente) del digrafo e implementando la cola de prioridades con un Heap de Fibonacci o algún otro resulta más eficiente. La propuesta de programación dinámica se refiere a como hacer para particionar el problema All Pairs Shortest-Paths, en subproblemas. ¿Cómo expresar la solución optimal de un subproblema en términos de la solución optimal de algún subsubproblemas? , ¿como hacer uso de la relación de recursividad para computar la solución optimal en una forma bottom-up (distancia de un vértice a otro)?, ¿cómo hacer para construir todos los Shortest-Paths?. Interrogantes propias del paradigma de la programación dinámica y que se referían a a) Caracterizar la estructura de una solución optimal b) Definir recursivamente los valores de una solución optimal c) Computar el valor de una solución optimal en la forma bottom-up d) Para concluir con la construcción de la solución optimaldesde la información

computada. Asumamos que el grafo esta representado por una matriz de adyacencia nxn, la que esta basada sobre los pesos de los arcos. (*) W i j=0, si i=j sin ciclos, W i j=w(i,j), si i ≠ j , (i, j) ε E, W i j= +∞, si i ≠ j , (i, j) ∉ E, el formato de salida es una matriz D = [ d i j ], donde d i j es la distancia del vértice i a j. a) sobre la estructura del camino notar que Floyd-Warshall esta basado en la

observación que un camino corto p desde el vértice i al vértice j, tiene un vértice “intermedio” si existe un k que esta entre i y j, siendo p1, la porción del camino p desde el vértice i a k, con todos los vértices intermedios en el conjunto {1,2, 3...,k -1} de la misma manera para p2 desde el vértice k al vértice j, describiendo la estructura de una solución optimal.

b) Para la solución recursiva, se define d(k)

i j , como la longitud o el peso del camino más corto desde el vértce i al vértice j, con todos los vértices intermedios en el conjunto {1, 2, 3..., k}. Cuando k=0, un camino desde el vértice i al vértice j con ningún vértice intermedio corresponde al peso wi j. La formula recursiva es

d(k)

i j = w i j , si k=0, d(k)i j = Min { d(k-1)

i j , d(k-1)i k + d(k-1)

k j } ), si k ≥ 1. 1≤ k ≤ n

c) La matriz n x n, D(n) = [ d(n)

i j ], entrega la respuesta final. En donde d(n)i j = δ(i,j)

que denota, el peso o distancia del camino más corto desde el vértice i al vértice j, para todo vértice i, j en V, porque todos los vértices intermedios

Page 28: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

28

están en el conjunto {1, 2, .. ,n}. Basado en la recurrencia anterior el siguiente procedimiento puede ser usado para computar los valores d(k)

i j , en orden creciente a los valores de k. La entrada es una matriz W definida por (*), el procedimiento entrega la matriz D(n) de los peso o distancia de los caminos más cortos.

Floyd-Warshall(matriz W) n = fila[W]; D(0) = W; for k=1 to n do for i=1 to n do for j=1 to n do d(k)i j = Min{d(k-1)i j , d(k-1)i k + d(k-1)k j } return D(n);

Ejemplo, para el calculo Bottom-up de D(n-1) . Dado el grafo dirigido ponderado G, cuya matriz de adyacencia de los pesos está dada por D(1) =[w i j ]. 3 1 2 8 11 4 4 4 3 7 0 3 8 ∞ + ∞ 0 4 11 D(1) = + ∞ + ∞ 0 7 4 + ∞ + ∞ 0 Computando D(2) desde D(1) . d(2)

i j = Min { d(1)i k + wk j } ,

1 ≤ k ≤ 4

se obtiene 0 3 7 14 15 0 4 11 D(2) = 11 +∞ 0 7 4 7 12 11 Computando D(3) desde D(2) . d(3)

i j = Min { d(2)i k + wk j } ,

1 ≤ k ≤ 4

se obtiene

Page 29: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

29

0 3 7 14 15 0 4 11 D(3) = 11 14 0 7 4 7 11 0 D(3) entrega las distancias entre cualquier par de vértices. Otra forma de resolver este problema es encontrando todos los caminos más cortos desde un vértice fuente s ε V a todo vértice v ε V, que desde luego no resulta tan eficiente desde el punto de vista de la cantidad de puntos a analizar. Veamos la implementación de esta propuesta, la que luego sirve para verificarlo con el siguiente grafo, cuyo Camino(4, 0) = 4 - 2 - 3 – 0, con peso 60 es el optimo. 10 0 1 100 30 50 3 60 20 4 2 10 Algoritmo de Floyd-Warshall Camino mas corto entre todos los pares. El algoritmo de Floyd-Warshall utiliza la programación dinámica para encontrar el camino mas corto (o de menor costo) entre todos los pares de vértices de un Grafo dirigido.

Entrada: Matriz de adyacencia correspondiente al grafo con los costos de cada arista.

Page 30: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

30

La Matriz de adyacencia se forma con la siguiente formula: 0 si i=j wij = ∞ si los vértices i,j no son adyacentes El peso de la arista si los vértices i,j son adyacentes Ejemplo: Se presenta un grafo y su correspondiente matriz de adyacencia

El algoritmo comienza con esta matriz y crea un número n (donde n es igual al número de vértices del grafo) de matrices en base a la siguiente recurrencia:

Es decir, el valor en la posición i,j de la nueva matriz va a ser igual al valor en la posición i,j de la matriz anterior si k=0 o el mínimo entre los valores en la posición i,j y la suma del valor en la posición i,k mas el valor en la posición k,j de la matriz anterior.

Salida: la matriz D(n) con el costo total del camino mas corto entre cada par de vértices del grafo.

Para encontrar cual es este camino de costo mínimo generamos una matriz ∏ llamada “matriz de predecesores” en base a las matrices D. Esta matriz ∏ se puede ir calculando al mismo tiempo que las matrices D en base a la siguiente recurrencia:

Page 31: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

31

Esta claro que las condiciones para la matriz ∏ y la matriz D son muy parecidas, lo que nos lleva a concluir que la matriz ∏ solo sufrirá cambios cuando se genere un cambio en la matriz D. La primera matriz ∏ se genera con la siguiente formula en base a la matriz de adyacencia con la siguiente formula:

Ejemplo del funcionamiento del algoritmo.

Teniendo este grafo y su matriz de adyacencia seguiremos los pasos del funcionamiento del algoritmo. D(0) ∏(0)

La primera matriz D(0) es idéntica a la matriz de adyacencia y la primera matriz ∏(0) que lleva NIL si i=j o dij = ∞, o el valor de i si i ≠ j y dij < ∞. Formemos ahora la matriz D(1) : Empezamos con i=1, j=1 , k=1 d(1)

11 va a ser igual al mínimo entre d(0)ij es decir d(0)

11

= 0 y d(0)ik + d(0)

kj es decir d(0)11 + d(0)

11 que es igual a 0+0, entonces d(1)11 = 0

i=1, j=2, k=1: d(1)

12 = min(d(0)12 , d(0)

11 + d(0)12) = min(3,0+3) = 3

i=1, j=3, k=1: d(1)13 = min(d(0)

13 , d(0)11 + d(0)

13) = min(8,0+8) = 8 i=1, j=4, k=1: d(1)

14 = min(d(0)14 , d(0)

11 + d(0)14) = min(∞,0+∞) =∞

Page 32: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

32

i=1, j=5, k=1: d(1)14 = min(d(0)

15 , d(0)11 + d(0)

14) = min(-4,0+-4) =-4 En este momento tenemos calculada la primera fila de la matriz D(1), podemos notar que es identica a la primera fila de la matriz anterior, con la practica se aprende que en cada matriz la columna k, la fila k y la diagonal no cambian, lo que reduce los calculos a la mitad. Hasta este puntos nuestras matrces D(1) y ∏(1) son:

Continuamos con lo que falta de la segunda fila: i=2, j=3, k=1: d(1)

23 = min(d(0)23 , d(0)

21 + d(0)13) = min(∞,∞+8) = ∞

i=2, j=4, k=1: d(1)24 = min(d(0)

24 , d(0)21 + d(0)

14) = min(1,∞+ ∞) = 1 i=2, j=5, k=1: d(1)

25 = min(d(0)25 , d(0)

21 + d(0)15) = min(7,∞+-4) = -4

Veamos nuestras matrices ya con la segunda fila completa:

Hasta ahora podemos ver que no se a efectuado ningún cambio en la matriz, por lo que nuestra matriz ∏(1) tampoco sufre cambios. Continuaremos completando la matriz: i=3, j=2 k=1: d(1)

32 = min(d(0)32 , d(0)

31 + d(0)12) = min(4,∞+3) = 4

i=3, j=4, k=1: d(1)34 = min(d(0)

34 , d(0)31 + d(0)

14) = min(∞,∞+ ∞) = ∞ i=3, j=5, k=1: d(1)

25 = min(d(0)35 , d(0)

31 + d(0)15) = min(∞,∞+-4) = ∞

Page 33: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

33

i=4, j=2 k=1: d(1)

42 = min(d(0)42 , d(0)

41 + d(0)12) = min(∞,2+3) = 5

i=4, j=3, k=1: d(1)43 = min(d(0)

43 , d(0)41 + d(0)

13) = min(-5,2+8) = -5 i=4, j=5, k=1: d(1)

45 = min(d(0)45 , d(0)

41 + d(0)15) = min(∞,2+-4) = -2

Ya en la fila 4 notamos cambios en la matriz D, los cuales se reflejaran en la matriz ∏ I=4, j=2, k=1 ∏(1)

42 = ∏(0)42 si d(0)

42 <= (d(0)41 + d(0)

12) o ∏(0)12 si d(0)

42 > (d(0)41 + d(0)

12) Como d(0)

42 = ∞ y (d(0)41 + d(0)

12) = (2+3), ∏(1)42 = ∏(0)

12 = 1 I=4, j=3, k=1 Como d(0)

43 = -5 y (d(0)41 + d(0)

13) = (2+8), ∏(1)42 = ∏(0)

42 = NIL I=4, j=5, k=1 Como d(0)

45 = -2 y (d(0)41 + d(0)

15) = (2+-4), ∏(1)45 = ∏(0)

45 = NIL

Completemos la ultima fila: i=5, j=2 k=1: d(1)

52 = min(d(0)52 , d(0)

51 + d(0)12) = min(∞,∞+3) = ∞

i=5, j=3, k=1: d(1)53 = min(d(0)

53 , d(0)51 + d(0)

13) = min(∞, ∞+8) = ∞ i=5, j=4, k=1: d(1)

54 = min(d(0)54 , d(0)

51 + d(0)14) = min(6,∞+ ∞) = 6

Ya tenemos nuestras matrices D(1) y ∏(1) y podemos continuar con el mismo proceso para formar las demas matrices hasta tener D(5) y ∏(5) con lo que termina el algoritmo.

Page 34: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

34

La matriz D nos indica el costo del camino mas corto de un vértice i a uno j y la matriz ∏ nos indica los vértices por lso que debemos pasar para completar dicho camino. CLAUSURA TRANSITIVA EN UN GRAFO DIRIGIDO Objetivo: El objetivo del trabajo es comprender y estudiar uno de los problemas asociados a la teoría de grafos, es decir la clausura transitiva para un grafo dirigido, definir, ejemplificar y dar posibles aplicaciones para poner en práctica lo aprendido en teoría.

Page 35: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

35

Introducción: En la teoría de grafos surgen varios problemas relacionados con los caminos que existen entre pares de vértices, ya sea, encontrar los caminos más cortos de un grafo(dirigido y no dirigido), ver si el grafo es conexo, etc. En este trabajo hablaremos de la clausura transitiva(o cierre transitivo) de un grafo dirigido, tema que surgió para resolver un problema específico de grafos, pero que tiene aplicaciones en problemas reales. Definición: Un grafo dirigido es un par (V; E) donde V es un conjunto finito y E⊂ (V x V) ∆ siendo ∆ = (x; x): x∈ V . A los elementos de V se les denomina vértices y a los de E aristas (dirigidas u orientadas). Si G = (V; E) es un grafo dirigido, y (u; v) ∈E; se dice que u es el vértice inicial de la arista (u; v) y que v es el vértice final de dicha arista. El concepto de transitividad es el mismo que se utiliza en teoría matemática el cual postula que si a<b<c ⇒ a<c, en el caso de clausura transitiva, el concepto se refiere a que existe un camino que une el vértice i con el vértice j, no importando que para llegar desde i a j tengamos que visitar otros vértices del grafo. Por esta razón es que el algoritmo fue diseñado para grafos dirigidos, donde si es importante hacia donde están apuntando los vértices, ya que en digrafos muy grandes, el problema de encontrar caminos entre pares de vértices es demasiado complicado, sólo siguiendo el trazado del dibujo del mismo, de ahí la importancia de este algoritmo y el interés que generó su estudio. La clausura transitiva de un grafo G se define como el grafo G* = (V, E*), donde E*={(i, j): hay un camino desde el vértice i al vértice j en G}.

Ejemplo: Dado el siguiente grafo dirigido, encontrar la clausura transitiva de él:

La clausura transitiva del grafo asociado es:

Page 36: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

36

Algoritmo: El algoritmo utilizado para encontrar la clausura transitiva de un grafo dirigido es muy parecido al algoritmo de Floyd_Warshall, con la diferencia que este utiliza las operaciones lógicas ∨ y ∧, sustituyendo las aritméticas min y + usadas por Floyd_Warshall, además que rellena la matriz de adyacencia sólo con 0 y 1, a diferencia del otro que les asocia un peso a cada arista que está en el grafo, y si no hay conexión entre los vértices, entonces le asigna ∞. Ahora presentaré el algoritmo propuesto: TRANSITIVE-CLOUSURE(G) n V[G] for i 1 to n for j 1 to n if i = j or (i, j) ∈ E[G] then ti,j

(0) 1 else ti,j

(0) 0 for k 1 to n for k 1 to n for k 1 to n ti,j

(k) ti,j(k-1) ∨ ( ti,k

(k-1) ∧ tk,j(k-1))

return T(n)

Como podemos ver, el algoritmo tiene como entrada el grafo y como salida la matriz de alcance asociada a ese grafo. Desde la línea 1 hasta la 6, lo que hace es completar la matriz de adyacencia del grafo, notar que ésta matriz en la diagonal se le asigna el valor 1, ya que supone que hay un camino desde un vértice a él mismo en la matriz de alcance. Luego desde la línea 7 a la 10 calcula las diferentes matrices, para este proceso va guardando la matriz anterior que es con la que hace el trabajo, la matriz actual sólo sirve para guardar los resultados, el n que se

Page 37: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

37

indica es el número de vértices que tiene el grafo, por lo tanto calcula tantas matrices como vértices tiene el grafo. Luego en la línea final(11), retorna la matriz de alcance asociada al grafo, que es la clausura transitiva del grafo. Ahora veremos como trabaja el algoritmo, a través del ejemplo anterior. Teníamos que el grafo era:

El primer paso es completar la matriz de adyacencia del grafo(recordando que la diagonal se rellena con 1), por lo tanto nos queda que:

( )

=

1011110001100011

0T

( )

=

1011110001100011

1T

( )

=

1111110001100111

2T

Matriz de adyacencia, con la diagonal cambiada por uno.

Esta matriz indica si existe un camino desde el nodo i al nodo j, pasando por el nodo 1.

Esta matriz indica si existe un camino desde el nodo i al nodo j, pasando por el nodo 2.

Page 38: Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F ...dns.uls.cl/~ej/web_fit_2011/Lect_fit_2011/grafos-fit_2011_.pdf · Ingeniería en Computación, Universidad de La Serena

Fundamentos Informática Teórica Prof. Dr.Eric Jeltsch F.

____________________________________________________________________ Ingeniería en Computación, Universidad de La Serena

38

( )

=

1111110011101111

3T

( )

=

1111111111111111

4T

Esta es la matriz de alcance que nos muestra la clausura transitiva del grafo. El dibujo es:

Análisis de costo: El costo asociado a este algoritmo es de 0(n3), ya que el costo de encontrar la matriz de alcance está íntimamente ligado con los ciclos que se necesitan para recorrer la matriz, además por ser un algoritmo de programación dinámica el costo tiene que ser polinomial. Referencias: CLR o CLRS Algorithm, Matemáticas Discretas -Grimaldi -Rosen -Jonhsonbaught

Esta matriz indica si existe un camino desde el nodo i al nodo j, pasando por el nodo 3.