Está en la página 1de 17

Universidad de San Carlos de Guatemala

Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Curso: Matemática de Computación 2


Plataforma: Linux/Windows/Solaris

Aplicación del método de Dijkstra en


Java
Descripción:
El método de Dijkstra, también llamado el método del camino más cortos; se utiliza
precisamente para eso, para encontrar la longitud del camino más corto de en grafo, conexo,
simple y con pesos positivos. El presente documento presenta el análisis y diseño de la aplicación
del método de Dijkstra en el lenguaje de programación JAVA.

-1-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Índice

Introducción---------------------------------------------------------------------------------------------------------- 3
Objetivos ------------------------------------------------------------------------------------------------------------- 4
Panorama General ------------------------------------------------------------------------------------------------ 5
Funciones ------------------------------------------------------------------------------------------------------------ 6
Casos de uso ------------------------------------------------------------------------------------------------------- 6
Modelo conceptual ------------------------------------------------------------------------------------------------ 8
Diagrama de clases ----------------------------------------------------------------------------------------------- 9
Pseudocódigos ----------------------------------------------------------------------------------------------------- 10
Métodos más importantes de la implementación ---------------------------------------------------------- 11
Conclusiones---------------------------------------------------------------------------------------------------------- 15
Bibliografía------------------------------------------------------------------------------------------------------------- 16
Recomendaciones--------------------------------------------------------------------------------------------------- 17

-2-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Introducción

La teoría de grafos, es relativamente moderna, surgió en 1736 gracias a Leonhard Euler,


éste se planteo la primera idea de grafos al tratar de resolver el famoso problema sobre “los
puentes de Königsberg”, esto puede considerarse como el nacimiento de la teoría de grafos.

Un grafo es el principal objeto de estudio de la teoría de grafos, un grafo es un conjunto de


vértices (o nodos) unidos por lados (o aristas), que permiten representar relaciones binarias entre
elementos de un conjunto. El grafo suele representarse con puntos (vértices) y líneas que unen
puntos (lados).

Los grafos pueden representar las interrelaciones entre unidades que interactúan con
otras. Por ejemplo: red de computadoras, carreteras y puntos de intersección, circuitos eléctricos,
etc.

Una de las actividades importantes para un grafo es conocer cual es el camino más corto
entre un vértice y otro. Por ejemplo: Tenemos un grafo G (V, E) en donde el conjunto de vértices V
representa ciudades y el conjunto de lados E representa las carreteras que conducen a esas
ciudades. Cada lado que pertenece a E tiene una distancia (que en teoría de grafos se le llama
peso), ésta distancia no puede ser negativa. Algo que sería muy importante para un conductor de
automóvil, sería saber, cual es el camino más corto para ir de una desde una ciudad A hacia una
ciudad B, tomando en cuenta el costo actual de la gasolina. Éste y muchos problemas más se
pueden resolver con el algoritmo de Dijkstra.

El algoritmo de Dijkstra, también llamado algoritmo de caminos mínimos fue descubierto


por Edsger Dijkstra, Edsger fue un científico de la computación de origen neerlandés y diseño el
algoritmo en 1959. Según la definición de wikipedia “La idea subyacente en este algoritmo consiste
en ir explorando todos los caminos más cortos que parten del vértice origen y que llevan a todos
los demás vértices; cuando se obtiene el camino más corto desde el vértice origen, al resto de
vértices que componen el grafo, el algoritmo se detiene. El algoritmo es una especialización de la
búsqueda de costo uniforme, y como tal, no funciona en grafos con aristas de costo negativo (al
elegir siempre el nodo con distancia menor, pueden quedar excluidos de la búsqueda nodos que
en próximas iteraciones bajarían el costo general del camino al pasar por una arista con costo
negativo).”

A continuación se presenta la documentación necesaria que nos a crear la implementación


del algoritmo de Dijkstra en el lenguaje de programación Java.

-3-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Objetivos

• Crear la implementación del algoritmo de Dijkstra en el lenguaje de programación JAVA

• Aplicar los concomimientos de grafos para poder encontrar un algoritmo capaz de


encontrar los vértices que pertenecen al camino mínimo (o los caminos si hay más de uno).

-4-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Panorama General
El algoritmo de Dijkstra también llamado algoritmo de caminos mínimos, es un algoritmo
para la determinación del camino más corto dado un vértice origen al resto de vértices en un grafo
con pesos en cada arista, el proyecto consiste en implementar dicho algoritmo aplicándolo a una
matriz de incidencia. Los datos serán proporcionados mediante dos archivos de entrada, el primero
contendrá las filas y columnas de la matriz y el segundo contendrá, los valores para completar la
matriz de incidencia (pesos), los vértices serán presentados haciendo uso del alfabeto ingles. Los
archivos podrán ser cargados buscando su localización en cualquier medio de almacenamiento
secundario, además, también se debe de ser capaz de proveer la opción de cargar archivos
mediante conexión remota (es decir, se le proporcionara un URL).

Una vez cargados los archivos de entrada y armada la matriz de incidencia, se produce a
mostrar gráficamente las diferentes rutas que conectan todos los vértices, la aplicación debe
proveer una opción en la cual, se ingresen dos vértices, estos corresponde al punto origen (partido)
y el punto destino ( finalización ) con los cuales debe encontrarse el camino más corto que debe
calcularse mediante la implementación del algoritmo de Dijkstra, una vez calculado dicho camino
debe mostrarse gráficamente su recorrido, debido a que pueden existir varios recorridos que
cumplan con lo establecido, la aplicación debe identificar mediante un número entero los diferentes
recorridos e ingresando en la aplicación el número correspondiente a un recorrido esta deberá
redibujar todos los vértices y sus conexiones y mostrar el recorrido que se ha solicitado.

El proyecto se debe implementarse utilizando el lenguaje de programación JAVA

Algoritmo de Dijkstra

• Sea G=(V,A) un grafo dirigido y etiquetado.


• Sean los vértices a ∈ V y z ∈ V; a es el vértice de origen y z el vértice de destino.
• Sea un conjunto C ⊂ V, que contiene los vértices de V cuyo camino más corto desde a
todavía no se conoce.
• Sea un vector D, con tantas dimensiones como elementos tiene V, y que “guarda” las
distancias entre a y cada uno de los vértices de V.
• Sea, finalmente, otro vector, P, con las mismas dimensiones que D, y que conserva la
información sobre qué vértice precede a cada uno de los vértices en el camino.

El algoritmo para determinar el camino de longitud mínima entre los vértices a y z es:

1. C←V
2. Para todo vértice i ∈ C, i ≠ a, se establece Di ← ∞ ; Da ← 0
3. Para todo vértice i ∈ C se establece Pi = a
4. Se obtiene el vértice s ∈ C tal que no existe otro vértice w ∈ C tal que Dw < Ds
o Si s = z entonces se ha terminado el algoritmo.
5. Se elimina de C el vértice s: C ← C−{s}
6. Para cada arista e ∈ A de longitud l, que une el vértice s con algún otro vértice t ∈ C,
o Si l+Ds < Dt, entonces:
1. Se establece Dt ← l+Ds
2. Se establece Pt ← s
7. Se regresa al paso 4

-5-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Metas

• Calcular el camino más corto de un grafo conexo

• Mostrar el (o los) camino más corto en forma gráfica y en forma descriptiva.

Funciones

Referencia Función
1.0 Cargar los archivos de entrada por cualquier medio secundario de
almacenamiento o mediante conexión remota.
1.1 Parsear los archivos de entrada
1.2 Nombrar los vértices y lados, colocando también el peso correspondiente a cada
lado.
1.3 Dibujar el grafo con sus vértices y lados correspondientes
1.4 Calcular el camino más corto a través de la implementación del algoritmo de
Dijkstra.
1.5 Mostrar (si es que existe más de uno) todos los caminos míniales existentes en el
grafo.

Casos de uso

Caso de uso: Cargar Archivo


Versión: 1.0
Tipo: primario
Actor: usuario
Descripción: El usuario selecciona la opción de cargar archivos, el sistema muestra las opciones
al usuario. El usuario selecciona “cargar matriz de incidencia” ó “cargar pesos del
grafo” y el sistema se encarga de parsear el archivo para crear el grafo.

Flujo Base:

1. El usuario inicia el caso de uso, solicitando al sistema cargar los archivos de entrada

2. El sistema muestra los archivos cargados actualmente, si no hay ningún archivo cargado
solo estará habilitada la opción de “cargar matriz de incidencia”.

3. El usuario selecciona el archivo (si desea cargar el archivo de a través de una conexión
remota ingresa el URL de la conexión) y acepta la operación.

4. La aplicación parsea el archivo, validando los caracteres, luego de validar el archivo,


Almacena los datos en la memoria principal, creando el grafo correspondiente.

5. Si el archivo no cumple con la estructura adecuada el sistema muestra un mensaje de error


y no carga el archivo.

-6-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Excepciones:
Error en lectura de archivo (IOException)
Error Léxico (Carácter no válido)
Error de pesos (falta o hay pesos de más)

Caso de uso: Calcular camino más corto


Versión: 1.0
Tipo: Primario
Actores: Usuario
Descripción: El usuario solicita al sistema calcular el camino más corto del grafo cargado
previamente (matriz de incidencia y archivo de pesos).La aplicación pide el vértice
de partida y el vértice de llegada. El usuario ingresa lo solicitado y la aplicación
calcula el camino más corto, por medio del algoritmo de Dijkstra.

Flujo Base:
1. El usuario solicita a la aplicación calcular el camino más corto del grafo antes cargado.
2. La aplicación solicita el vértice de llegada y el vértice de partida.
3. El usuario ingresa los datos
4. Excepción: el sistema verifica que los vértices no sean iguales y que exista en el grafo, sino
existen: Mensaje de Error y acaba el caso de uso, de lo contrario: paso 5.
5. La aplicación calcula el camino más corto, si hay más de un camino corto, solicita al
usuario ingresar el número de camino ha mostrar.
6. El usuario ingresa el número del camino.
Excepción: valida que el camino exista y que sea un número ingresado.

-7-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Modelo Conceptual

-8-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Diagrama de clases

NodoVertice NodoLado
-nombre : string -peso : double
-posX : int -verticeA : NodoVertice
-posY : int -verticeB : NodoVertice
-marca : bool -nombre : string
-etiqueta : double -siguiente : NodoLado
-siguiente : NodoVertice +NodoLado(entrada verticeA : NodoVertice, entrada verticeB : NodoVertice, entrada nombre : string)
+NodoVertice(entrada nombre : string, entrada x : int, entrada y : int) +NodoLado(entrada vertice : NodoVertice, entrada nombre : string)
+setNombre(entrada nombre : string) +setPeso(entrada peso : double)
+setLocalizacion(entrada x : int, entrada y : int) +setVerticeA(entrada verticeA : NodoVertice)
+setEtiqueta(entrada etiqueta : double) 2 1 +setVerticeB(entrada veticeB : NodoVertice)
+setMarca(entrada marca : bool) +setNombre(entrada nombre : string)
+setSiguiente(entrada siguiente : NodoVertice) +setSiguiente(entrada siguiente : NodoLado)
+getNombre() : string +getPeso() : double
+getX() : int +getVerticeA() : NodoVertice
+getY() : int +getVerticeB() : NodoVertice
+getEtiqueta() : double +getNombre() : string
+getMarca() : bool +getSiguiente() : NodoLado
+getSiguiente() : NodoVertice
*

DibujoGrafo:Extends Canvas
1
-grafo : Grafo 1
+setGrafo()
+update()
+paint() Grafo
-primerVertice : NodoVertice
-primerLado : NodoLado
1 1
-numeroGrafo : int
-caminoCorto : int
-siguiente : Grafo
+addNuevoVertice(entrada nombre : string, entrada x : int, entrada y : int)
1 +addNuevoLado(entrada verticeA : NodoVertice, entrada verticeB : NodoVertice, entrada nombre : string)
+buscarLado() : NodoLado
+buscarVertice() : NodoVertice
+algoritmoDijkstra(entrada VPartida : NodoVertice, entrada VDestino : NodoVertice, entrada grafo : Grafo)
+caminosMinimales()

1 *

1
1 1
ListaGrafo

GUI -primerGrafo : Grafo

-grafo : Grafo +addGrafoLista(entrada grafo : Grafo)


-lista : ListaGrafo +buscarGrafo() : Grafo
-dibujoGrafo : DibujoGrafo:Extends Canvas +limpiarListaGrafo()
1
1
+dibujarCaminoMinimal()
+pintarGrafo()

-9-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Según las clases mostradas en el diagrama de clases, se crea el pseudocódigo para el algoritmo
de Dijkstra.

Pseudocódigo: Algoritmo Dijkstra

[inicio] => buscar el nodo que contiene el vértice de destino del grafo y cambiar la etiqueta a cero
del vértice de partida.

[condición]=> ¿la etiqueta del vértice de destino es “false”?. Si es falsa(marca permanente) salir
del algoritmo y retornar la longitud del camino más corto, de lo contrario si es true (marca temporal)
continuar con el algoritmo.

[marca]=> buscar el vértice entre los vértices con marca “true” y cambia la marca, por la marca
“false”.

[Vertices adyacentes]=> recorre el grafo en busca de los vértices adyacentes.

[Etiqueta minima]=> Se calcula la nueva etiqueta y se compara para ver si es minima o permanece
la que contiene.

[regreso]=> ir al estado “condición”.

Pseudocódigo, para encontrar los vértices del o los caminos más cortos.

Consideración anterior: Se considera que el grafo ya ha sido cargado, con sus vértices, lados y
pesos correspondientes y ya se sabe el camino mínimo.

INICIO

CaminoMínimo  Se toma de la implementación del algoritmo de Dijkstra


Vpartida  Tomar el vértice de partida
Vdestino  Tomar el vértice destino

Encontrar todos vértices adyacentes a Vpartida que poseen la etiqueta de permanentes (esto
según el algoritmo de Dijkstra).

Para (cada vértice adyacente al Vpartida)


Inicio
Si (el peso del lado [incidente a Vpartida y al vértice actual] es menor que CaminoMínimo)
g  Guardar el lado en un nuevo grafo
Ir a procedimiento CaminoMinimal(Vactual, Vdestino, Grafo g, pesoActual)
Si ( el peso del lado [incidente a Vpartida y al vértice actual] es igual a CaminoMínimo y
además el vértice ayacente es el Vdestino)
g  Guarda el lado en un nuevo grafo
Agrega el nuevo grafo a la ListaGrafo
Si ( el peso del lado[incidente a Vpartida y al vértice actual] es mayo a CaminiMínimo)
El lado se descarta

Pasar al siguiente vertice


Fin

FIN

-10-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Procedimiento recursivo CaminoMinimal(Vactual, Vdestino, Grafo g, pesoActual)


Inicio
Vactual  el vértice al que le aplicaremos el procedimiento
Vdestino  el vértice destino del camino mínimo
Grafo g  contiene los vértices ya recorridos para llegar a este procedimiento

Encontrar todos los vértices adyacentes a Vactual que poseen la etiqueta de permanentes (según
el algoritmo de Dijkstra)

Para ( cada vértice adyacente a Vactual)


Inicio

Si ( pesoActual + el peso del lado [incidente entre Vactual y su ayacente actual] es menor
que caminoMinimo )
g1  guarda el lado en un nuevo grafo
agrega los lados de g a los lados de g1
Vactual  el vértice adyacente al Vactua
ir al procedimiento CaminiMinimal(Vactual, Vdestino, g1, pesoActual+pesoDelado)

Si ( pesoActual + el peso del lado es igual a CaminoMínimo y además el vértice adyacente


es el vértice Vdestino)
G1  guarda el lado en un nuevo grafo
Agrega los lados de g a los lados de g1
Agrega el nuevo grafo (g1) a ListaGrafo

Si ( pesoActual + el peso del lado es mayor que CaminoMínimo)


El lado incidente se descarta

Siguiente vértice adyacente.


Fin
Fin

Métodos más importantes de la implementación

Grafo

void addElemento(NodoVertice vertice, NodoLado lado, Grafo g)


Agrega un vertice y un lado al grafo enviado en el parametro "g" void

addElementos(NodoLado lado, Grafo g)


Agrega un lado y los vertices que inciden en el lado al grafo "g"

void algoritmoDijkstra(String Vpartida, String Vdestino, Grafo grafo)


Método principal el cual maneja todos los de mas métodos para implementar el
algoritmo de dijkstra

-11-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

NodoLado buscarLado(java.lang.String nombreLado)


Devuelve la referencia del lado, según el nombre.
NodoVertice buscarVertice(java.lang.String nombreVertice)
Busca a un vertice según su nombre java.lang.String

buscarVerticeEtiquetaMinima(Grafo grafo)
Método que busca el vertice con la etiqueta minima entre los vertices con marca
temporal
void cambiarEtiquetaVertice(String vertice, Double etiqueta, Grafo grafo)
Método que busca el vertice y cambia la etiqueta de este. void

cambiarMarcaVertice(String vertice, Grafo grafo)


Método que cambia la marca del vertice void

cambiarMinimoEtiqueta(String Vadyacente, String Vertice, Double peso,


Grafo grafo)
Método que compara y cambia la etiqueta de un determinado vertice
void caminoMinimal(String NomVerticeActual, String NomVerticeDestino,
Grafo grafo, ListaGrafo lista, Double pesoEnviado, Grafo g)
Este es el método recursivo que revisa todos y cada uno de los vertices adyacentes al
NomVerticeActual (que son permanentes) y luego realiza las validaciones necesarias, para
decidir si seguir buscando el camino o si el camino ya ha sido encontrado int

cantidadDeVerticesAdyacentesPermanentes(String NomVertice, Grafo grafo)


Devuelve la cantidad de vértices adyacentes al vértice que se busca con el nombre
NomVertice.

existeLado(java.lang.String nombre)
Verifica si existe ya el Lado, buscando con relacion al nombre int void

grafoSumarOtroGrafo(Grafo _grafo)
Método que se utiliza para sumar grafos, este método es utilizado especificamente en
las llamadas recursivas cuando se buscan el ó los caminos mínimos

void revisarEtiquetas(java.lang.String vertice, Grafo grafo)


Método que revisa las etiquetas para cambiar las etiquetas de los vertices void

Grafo verticesAdyacentesPermanentes(String NomVertice, Grafo grafo)


Devuelve un grafo con los vertices adyacentes al vertice que se busca según el
NomVertice ( los vértices que según el algoritmo de Kijkstra pertenecen al conjunto de
Permanentes ) , estos vértices se buscan en el grafo principal ( que contien los vertices y
lados con el cual se calculo el camino mínimal )

-12-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

void verticesCaminosMinimales(String NomVerticePartida,


String NomVerticeDestino, Grafo grafo, ListaGrafo lista)
Método que se utiliza para el primer análisis de caminos minimales, si es necesario
llama al metodo recursivo "caminoMinimal()"

Scanner

void leerArchivo(String archivo, Grafo _grafo, DibujoGrafo grafoDibujo,


JLabel jLabel3, JLabel jLabel4)
Lee el archivo y va creando el grafo void

leerArchivoPesos(String archivo, Grafo grafo, DibujoGrafo grafoDibujo,


JLabel jLabel4)
Lee el archivo de pesos y asigna el peso correspondiente a cada lado del grafo

void leerArchivoPesosURL(java.io.InputStream archivo, Grafo grafo,


DibujoGrafo grafoDibujo, javax.swing.JLabel jLabel4,
java.lang.String url)
Lee el archivo de pesos desde una conexión remota y asigna el peso correspondiente
a cada lado del grafo.

void leerArchivoURL(java.io.InputStream archivo, Grafo _grafo,


DibujoGrafo grafoDibujo, javax.swing.JLabel jLabel3,
javax.swing.JLabel jLabel4, java.lang.String url)
Lee el archivo (matriz de incidencia) de una conexión remota y va creando el grafo
java.lang.String nombreLado(int i)
Establece el nombre del lado: e+i en donde i es un numero entero según la columna
en la matriz de incidencia
java.lang.String nombreVertice(int i)
Establece el nombre del vértice creado, según su numero, es decir el numero de fila.

int puntoVerticeX(int i, Grafo _grafo)


Establece el punto de ubicación del vértice en el cuadro de dibujo, según el valor "i"
como parámetro. En X
int puntoVerticeY(int i, Grafo _grafo)
Establece el punto de ubicación del vértice en el cuadro de dibujo, según el valor "i"
como parámetro. En Y

ListaGrafo

void addGrafoALista(Grafo grafo)


Agrega un grafo a la lista

-13-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Grafo buscarGrafo(int numero)


Busca un grafo según su numero de grafo
void limpiarListaGrafo()
Limpia la Lista de grafos minimales
void recorresListraGrafo()
Recorre la lista de grafos minimales

-14-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Conclusiones

• Para la implementación, creamos varias clases de tipo nodo, con el cual creamos un grafo.
Para aplicar el algoritmo de Dijkstra debimos recorrer cada nodoVertice del grafo aplicar
los pasos indicados en: Pseudocódigo Algoritmo de Dijkstra.

• La implementación de un método capaz de encontrar los vértices que pertenecen al (o los)


camino mínimo, se puede ver en : Pseudocódigo para encontrar los vértices del o los
caminos más cortos.

• La aplicación es capaz de hacer lo que el planteamiento del problema solicitaba.

-15-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Bibliografía
http://es.wikipedia.org/wiki/Dijkstra
http://es.wikipedia.org/wiki/Algoritmo_de_Dijkstra
http://es.wikipedia.org/wiki/Grafo

Desarrolladores:

Michael Antony Colindres Hernández 200611415


Honard Manuel Bravo Bámaca 200611509

-16-
Universidad de San Carlos de Guatemala
Facultad de Ingeniería
Escuela de Ciencias y Sistemas

Recomendaciones

• Cuando utilice la aplicación, verificar los archivos de entrada, ya que si alguna incidencia
no corresponde o no es adecuada la lexicografía y/o sintaxis la aplicación enviará un error.

• Para utilizar la aplicación debe tener instalado en su máquina la JVM (Java Virtual
Machine) 1.6 o superior.

-17-

También podría gustarte