SlideShare a Scribd company logo
1 of 15
Download to read offline
UNIVERSIDAD TECNOLÓGICA
DE LOS ANDES
MONOGRAFÍA
Algoritmo de Johnson
CURSO
Algoritmos y programación II
DOCENTE
Ing. Godofredo Poccori Umeres
ESTUDIANTES
Huaman Ataulluco Ricardo Manuel
Alvarez Cayo Marco Antonio
Quispe Mamani Jhon Anderson
Quispe Herrera Erick Jeandet
Huaman Jara William
Cusco 2023 - I
CARRERA PROFESIONAL DE INGENIERÍA DE
SISTEMAS E INFORMÁTICA FILIAL CUSCO
INTRODUCCIÓN
En el mundo de programación, los algoritmos para identificar son diversos
es una rama crucial destaca como una herramienta fundamental en el
campo de la teoría de grafos y la programación de algoritmos. Su
importancia radica en su capacidad para encontrar eficientemente los
caminos más cortos entre todos los pares de vértices en un grafo, incluso
cuando se enfrenta a la presencia de aristas con pesos negativos, siempre
que no existan ciclos negativos. Este algoritmo se posiciona como una
solución valiosa en problemas de optimización de rutas y programación de
tareas en sistemas heterogéneos.
El algoritmo de Johnson es una técnica avanzada para encontrar los
caminos más cortos entre todos los pares de vértices en un grafo, incluso
cuando este contiene aristas con pesos negativos, siempre y cuando no
tenga ciclos negativos si tendría eso no se podrá. Su eficiencia radica en
su enfoque de reponderación, transformando los pesos negativos a
valores no negativos para aprovechar el algoritmo de Dijkstra. La
complejidad asintótica del algoritmo es (O(V^2*logV+VE)), haciéndolo
especialmente eficaz para grafos dispersos. Utiliza subrutinas como los
algoritmos de Dijkstra y Bellman-Ford, y su implementación implica un
preprocesamiento que toma (O(VE)) tiempo. Proporcionando una
herramienta esencial para desarrolladores y científicos de datos que
buscan optimizar la eficiencia en redes y sistemas complejos. La
capacidad del algoritmo para abordar una variedad de situaciones lo
posiciona como una contribución significativa en el arsenal de
herramientas de la informática teórica y la optimización algorítmica.
Este trabajo monográfico se adentrará en las definiciones y conceptos
fundamentales del algoritmo de Johnson según diversos expertos en el
campo. A través de métodos y técnicas de investigación formativa, como
parafraseo, fichas textuales, resúmenes y comentarios, se presentará
información válida con un formato APA para asegurar la precisión y la
integridad del conocimiento compartido.
Para llegar al cabo la finalidad del desarrollo del trabajo monográfico
daremos a conocer información valida empezando con el capítulo I, que
informa definiciones, conceptos y pasos de cómo aplicar el método de
algoritmo de Johnson, según autores, en el capítulo II, se proporcionará un
ejemplo que se resolverá con el algoritmo de Johnson, posteriormente en
el capítulo III, se planteará el pseudocódigo, código y ejecución en Python
del ejemplo, finalmente plantearemos nuestras conclusiones.
UNIVERSIDAD TECNOLÓGICA DE LOS ANDES
Escuela Profesional de Ingeniería de Sistemas e Informática
CAPITULO I
DEFINICIÓN Y CONCEPTOS
Donald Bruce Johnson (16/12/1933 – 10/09/1994) fue un científico informático
estadounidense, investigador en el diseño y análisis de algoritmos y presidente fundador
del departamento de informática de Dartmouth. Universidad. Johnson recibió su
doctorado, desde Universidad de Cornell en 1973. Cuando se fundó el departamento de
informática de Dartmouth en 1994, se convirtió en su primer presidente. (Endre, 1983)
1.1. Concepto de algoritmos de Johnson
El algoritmo de Johnson es una estrategia sofisticada en teoría de grafos
que aborda el problema de encontrar los caminos más cortos entre todos
los pares de vértices en un grafo ponderado, incluso en presencia de
aristas con pesos negativos, siempre que no haya ciclos negativos. Según
(Salazar, 2019) indica con relación a la industria que “la regla de Johnson
es un algoritmo heurístico utilizado en la industria para resolver situaciones
de secuenciación de procesos que operan en dos o más órdenes y pasan
a través de dos máquinas o centros de trabajo. Su principal objetivo es
minimizar el tiempo de procesamiento total del grupo de trabajos.”
1.2. Modelos matemáticos en Algoritmos de Johnson
Según (Cormen, Leiserson, Rivest, & Stein, 2001) consideramos un grafo
dirigido y ponderado G = (V, E) con una función de peso w: E → {R} y una
función adicional h: V → {R}. Definimos una nueva función de peso wy: E
→ {R} según la relación wy(u, v) = w(u, v) + h(u) - h(v)
La prueba demuestra que para cualquier ruta p desde el vértice v0 hasta el
vértice vk, el camino es más corto con respecto a la función de peso w si y
solo si es más corto con respecto a wy. Es decir, w(p) = δ(v0, vk) si y solo
si wy(p) = δy(v0, vk), donde δ y δy representan las longitudes más cortas
utilizando las funciones de peso w y wy respectivamente. La prueba
establece que el grafo tiene un ciclo de peso negativo utilizando la función
de peso w si y solo si tiene un ciclo de peso negativo utilizando la función
de peso wy.
Podemos acertar que la relación entre las funciones de peso w y wy
mantiene la propiedad de caminos más cortos y la presencia de ciclos de
peso negativo en el grafo.
1.3. Lema de Johnson
Como menciona el mismo (Johnson, 1977), “El lema de Johnson es un
resultado teórico que permite transformar un grafo que no contiene ciclos
de peso negativo en un grafo equivalente que no contiene aristas de peso
negativo, lo que habilita la utilización del algoritmo de Dijkstra para
encontrar el camino más corto entre todos los pares de vértices en un grafo
dirigido disperso.”
UNIVERSIDAD TECNOLÓGICA DE LOS ANDES
Escuela Profesional de Ingeniería de Sistemas e Informática
CAPITULO II
APLICACICIONES DEL ALGORITMOS
2.1. Optimización de rutas y procesos
Los algoritmos de Johnson tienen aplicaciones significativas en la
optimización de rutas y procesos, tanto en el ámbito de la programación
de computadoras como en entornos industriales.
“... son relevantes para la optimización de rutas y procesos en
diversos contextos. En el ámbito de la programación de
computadoras, el algoritmo de Johnson se utiliza para encontrar el
camino más corto entre todos los pares de vértices en un grafo
dirigido disperso, lo que es fundamental en la optimización de rutas
en sistemas de información geográfica, redes de comunicación,
planificación de rutas de transporte, entre otros” (Reyes, 2016)
Fuente de la imagen: (Movertis, 2023)
2.2. Resolución de problemas de grafos con pesos negativos
En relación con grafos de pesos negativos el algoritmo de Johnson tiene
esta accesibilidad, como aclara (Fillottrani, 2017) que, una técnica utilizada
para resolver el problema de encontrar el camino más corto entre todos los
pares de vértices de un grafo dirigido disperso, permitiendo que las aristas
tengan pesos negativos, aunque no permite ciclos de peso negativo. Este
algoritmo funciona mediante una transformación del grafo inicial que
elimina todas las aristas de peso negativo, lo que permite utilizar el
algoritmo de Dijkstra en el grafo transformado.
Fuente de la imagen: (Olimpiada Informática Española, 2019)
UNIVERSIDAD TECNOLÓGICA DE LOS ANDES
Escuela Profesional de Ingeniería de Sistemas e Informática
El funcionamiento del Algoritmo de Johnson se puede entender fácilmente
con los siguientes pasos:
i. Un nuevo vértice
Se agrega un nuevo vértice “s” al gráfico. Luego, se conecta con
todos los vértices del gráfico. Los bordes están dirigidos desde el
nuevo vértice y los nuevos pesos de los bordes son cero. Así, con
las nuevas aristas no se modifica ningún camino más corto existente
entre los vértices originales del gráfico.
ii. Ejecución del algoritmo Bellman-Ford
A continuación, ejecutamos el algoritmo de Bellman-Ford para
después de este paso, obtenemos los caminos más cortos desde el
vértice “s” para cada vértice del gráfico. Se mantendrá las rutas más
cortas en una matriz, donde la distancia será la ruta más corta de “s”
hasta un vértice “v”.
iii. Re ponderar los bordes
Luego, modificamos los pesos de los bordes, donde se tendrá
nuevos pesos, pero no serán negativos para toda arista que esté
relacionado con el nuevo vértice, y esta modificación del peso no
cambia las rutas más cortas en el gráfico original. Es decir, los pesos
de las rutas en el gráfico realmente cambian, pero los caminos más
cortos antes y después de la modificación del peso siguen siendo
los mismos.
iv. Ejecutando el algoritmo de Dijkstra:
En el último paso, ejecutamos el algoritmo de Dijkstra para cada
vértice del gráfico con los bordes modificados. Después de este
paso, tendremos los caminos más cortos para cada par de vértices.
Los pesos de ruta más cortos se calculan utilizando los pesos de
borde modificados. Para calcular los pesos originales de los caminos
más cortos, necesitamos mantener en paralelo los pesos originales
de los caminos durante el algoritmo de Dijkstra. Alternativamente,
podemos convertir los pesos de las rutas más cortas después de
obtener las rutas más cortas.
Podemos acertar que, es una joya en el mundo de los grafos, el algoritmo
de Johnson es como una coreografía matemática, donde cada paso se
ejecuta con precisión para desentrañar los secretos de los caminos más
cortos en un mundo de conexiones complejas. Un enfoque brillante para
resolver problemas en grafos ponderados, transformando los desafíos en
soluciones eficientes.
UNIVERSIDAD TECNOLÓGICA DE LOS ANDES
Escuela Profesional de Ingeniería de Sistemas e Informática
CAPITULO III
ALGORITMO DE JOHNSON EN PYTHON
3.1. Ejemplo desarrollado
El ejemplo fue con los datos de (Cajic, 2020).
Dado que este gráfico contiene aristas negativas, el algoritmo de Dijkstra
aún no se le puede aplicar. Para empezar, los enlaces de borde deben
transformarse para que contengan números no negativos.
El algoritmo de Johnson comienza seleccionando un vértice fuente. El
problema de elegir un vértice existente es que es posible que no pueda
alcanzar todos los vértices del gráfico. Para garantizar que un único vértice
de origen pueda alcanzar todos los vértices del gráfico, se introduce un
nuevo vértice. El nuevo vértice, S, se introduce en todos los vértices del
gráfico. Aunque el peso desde la fuente hasta cada vértice no importa
siempre que todos sean consistentes, por convención se aplica un peso
de 0 a cada borde desde la fuente.
UNIVERSIDAD TECNOLÓGICA DE LOS ANDES
Escuela Profesional de Ingeniería de Sistemas e Informática
Para empezar, todos los bordes de salida se registran en una tabla en
orden alfabético.
El algoritmo de Johnson calcula los caminos más cortos desde el vértice S
hasta todos los vértices del gráfico. El algoritmo de Johnson utiliza un
algoritmo de ruta más corta de fuente única para obtener los nuevos
valores. Dado que hay pesos de arista negativos en el gráfico dirigido,
Bellman-Ford es el algoritmo que se utiliza para procesar este cálculo.
El vértice de origen es innecesario para el resto de este ejemplo, por lo que
eliminaremos la S y sus aristas.
UNIVERSIDAD TECNOLÓGICA DE LOS ANDES
Escuela Profesional de Ingeniería de Sistemas e Informática
Luego, el algoritmo de Johnson aplica la siguiente fórmula para los
cálculos de reponderación:
En inglés, la nueva longitud (C'e) es igual a la longitud original (Ce) más el
peso de su cola (p u) menos el peso de su cabeza (p v). El algoritmo de
Johnson hace esto para cada una de las aristas.
El gráfico se actualiza con los nuevos pesos.
3.2. Pseudocodigo
función minimaDistancia(dist, visitados):
(minima, verticeMinimo) = (MAX_INT, 0)
para cada vertice en rango de longitud(dist):
si minima > dist[vertice] y no visitados[vertice]:
(minima, verticeMinimo) = (dist[vertice], vertice)
devolver verticeMinimo
función Dijkstra(grafo, grafoModificado, origen):
num_vertices = longitud(grafo)
conjuntoSPT = inicializar_conjuntoSPT()
distancias = inicializar_distancias(num_vertices)
distancias[origen] = 0
para cada contador en rango de num_vertices:
verticeActual = minimaDistancia(distancias, conjuntoSPT)
conjuntoSPT[verticeActual] = verdadero
para cada vertice en rango de num_vertices:
si (no conjuntoSPT[vertice]) y
(distancias[vertice] > (distancias[verticeActual] +
grafoModificado[verticeActual][vertice])) y
(grafo[verticeActual][vertice] != 0):
distancias[vertice] = (distancias[verticeActual] +
grafoModificado[verticeActual][vertice])
para cada vertice en rango de num_vertices:
imprimir 'Vértice ' + caracter(65 + vertice) + ': ' +
convertir_a_cadena(distancias[vertice])
función BellmanFord(aristas, grafo, num_vertices):
distancias = inicializar_distancias(num_vertices + 1)
distancias[num_vertices] = 0
para cada i en rango de num_vertices:
aristas.agregar([num_vertices, i, 0])
para cada i en rango de num_vertices:
para cada (origen, destino, peso) en aristas:
si (distancias[origen] != MAX_INT) y
(distancias[origen] + peso < distancias[destino]):
distancias[destino] = distancias[origen] + peso
devolver distancias[0:num_vertices]
función algoritmoJohnson(grafo):
aristas = []
para cada i en rango de longitud(grafo):
para cada j en rango de longitud(grafo[i]):
si grafo[i][j] != 0:
aristas.agregar([i, j, grafo[i][j]])
modificarPesos = BellmanFord(aristas, grafo, longitud(grafo))
grafoModificado = inicializar_grafo_modificado(longitud(grafo))
para cada i en rango de longitud(grafo):
para cada j en rango de longitud(grafo[i]):
si grafo[i][j] != 0:
grafoModificado[i][j] = (grafo[i][j] + modificarPesos[i] - modificarPesos[j])
imprimir 'Grafo Modificado: ' + convertir_a_cadena(grafoModificado)
para cada origen en rango de longitud(grafo):
imprimir 'nDistancia más corta con el vértice ' + caracter(65 + origen) + ' como
origen:n'
Dijkstra(grafo, grafoModificado, origen)
grafo = [
[0, 0, 0, 11, 0, 0, 0],
[-7, 0, 0, -5, 0, 3, 0],
[17, 3, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 12, 9],
[0, 0, 5, 0, 0, 0, 0],
[0, 0, -5, 0, 4, 0, 0],
[0, 0, 0, 0, -3, 0, 0]
]
algoritmoJohnson(grafo)
3.3. Codificación y ejecución del programa (Python)
from collections import defaultdict
MAX_INT = float('Inf')
def minimaDistancia(dist, visitados):
(minima, verticeMinimo) = (MAX_INT, 0)
for vertice in range(len(dist)):
if minima > dist[vertice] and visitados[vertice] == False:
(minima, verticeMinimo) = (dist[vertice], vertice)
return verticeMinimo
def Dijkstra(grafo, grafoModificado, origen):
num_vertices = len(grafo)
conjuntoSPT = defaultdict(lambda: False)
distancias = [MAX_INT] * num_vertices
distancias[origen] = 0
for contador in range(num_vertices):
verticeActual = minimaDistancia(distancias, conjuntoSPT)
conjuntoSPT[verticeActual] = True
for vertice in range(num_vertices):
if ((conjuntoSPT[vertice] == False) and
(distancias[vertice] > (distancias[verticeActual] +
grafoModificado[verticeActual][vertice])) and
(grafo[verticeActual][vertice] != 0)):
distancias[vertice] = (distancias[verticeActual] +
grafoModificado[verticeActual][vertice]);
for vertice in range(num_vertices):
print ('Vértice ' + chr(65 + vertice) + ': ' + str(distancias[vertice]))
def BellmanFord(aristas, grafo, num_vertices):
distancias = [MAX_INT] * (num_vertices + 1)
distancias[num_vertices] = 0
for i in range(num_vertices):
aristas.append([num_vertices, i, 0])
for i in range(num_vertices):
for (origen, destino, peso) in aristas:
if((distancias[origen] != MAX_INT) and
(distancias[origen] + peso < distancias[destino])):
distancias[destino] = distancias[origen] + peso
return distancias[0:num_vertices]
def algoritmoJohnson(grafo):
aristas = []
for i in range(len(grafo)):
for j in range(len(grafo[i])):
if grafo[i][j] != 0:
aristas.append([i, j, grafo[i][j]])
modificarPesos = BellmanFord(aristas, grafo, len(grafo))
grafoModificado = [[0 for x in range(len(grafo))] for y in
range(len(grafo))]
for i in range(len(grafo)):
for j in range(len(grafo[i])):
if grafo[i][j] != 0:
grafoModificado[i][j] = (grafo[i][j] +
modificarPesos[i] - modificarPesos[j]);
print ('Grafo Modificado: ' + str(grafoModificado))
for origen in range(len(grafo)):
print ('nDistancia más corta con el vértice ' +
chr(65 + origen) + ' como origen:n')
Dijkstra(grafo, grafoModificado, origen)
grafo = [
[0, 0, 0, 11, 0, 0, 0],
[-7, 0, 0, -5, 0, 3, 0],
[17, 3, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 12, 9],
[0, 0, 5, 0, 0, 0, 0],
[0, 0, -5, 0, 4, 0, 0],
[0, 0, 0, 0, -3, 0, 0]
]
algoritmoJohnson(grafo)
3.3.1. Ejecución
UNIVERSIDAD TECNOLÓGICA DE LOS ANDES
Escuela Profesional de Ingeniería de Sistemas e Informática
CONCLUSIONES
En el mundo de la programación y la teoría de grafos, los algoritmos
desempeñan un papel crucial, siendo herramientas fundamentales para
resolver diversos problemas.
El Algoritmo de Johnson destaca por su capacidad para encontrar
eficientemente los caminos más cortos entre todos los pares de vértices en
un grafo, incluso en presencia de aristas con pesos negativos, siempre que no
haya ciclos negativos.
El Algoritmo de Johnson se presenta como una solución valiosa en
problemas de optimización de rutas y programación de tareas en sistemas
heterogéneos.
Su eficiencia radica en su enfoque de reponderación, transformando los
pesos negativos a valores no negativos para aprovechar el algoritmo de
Dijkstra.
La complejidad asintótica del algoritmo es (O(V^2*logV+VE)), lo que lo
hace especialmente eficaz para grafos dispersos.
Utiliza subrutinas como los algoritmos de Dijkstra y Bellman-Ford, y su
implementación implica un preprocesamiento que toma (O(VE)) tiempo.
El Algoritmo de Johnson encuentra aplicaciones en la optimización de rutas
y procesos, tanto en programación informática como en entornos
industriales. Su utilidad se extiende a la resolución de problemas de grafos
con pesos negativos, permitiendo trabajar con aristas de este tipo sin ciclos
negativos. Se destaca el Lema de Johnson como un resultado teórico que
habilita la transformación de un grafo sin ciclos de peso negativo en un grafo
equivalente sin aristas de peso negativo, permitiendo el uso del algoritmo de
Dijkstra.
Se proporciona una explicación detallada de los pasos del Algoritmo de
Johnson, desde la introducción de un nuevo vértice hasta la ejecución del
algoritmo de Dijkstra con bordes modificados.
El Algoritmo de Johnson se destaca como una "joya en el mundo de los
grafos", con su capacidad para resolver eficientemente problemas en grafos
ponderados y transformar desafíos en soluciones eficientes.
UNIVERSIDAD TECNOLÓGICA DE LOS ANDES
Escuela Profesional de Ingeniería de Sistemas e Informática
Bibliografía
Cajic, D. (2020). El algoritmo de Johnson explicado visualmente. Estados
Unidos: Medium.
Cormen, T., Leiserson, C., Rivest, R., & Stein, C. (2001). Introduction to
Algorithms. London, England: McGraw-Hill.
Endre, R. (1983). Data Structures and Network Algorithms. Estados Unidos:
CBMS-NSF Regional Conference Series in Applied Mathematics.
Fillottrani, P. (2017). Algoritmos y Complejidad. Departamento de Ciencias e
Ingeniería de la Computación: Blanca, Argentina.
Johnson, D. (1977). Efficient algorithms for shortest paths in sparse
networks. Township, Pensilvania: AMC.
Movertis. (2023). ¿Sabes cómo optimizar tus rutas de transporte? España:
Redacción Movertis.
Olimpiada Informática Española. (2019). Camino más corto entre nodos.
España: OI.
Reyes, N. (2016). Modelo de optimización de programación de rutas para
una empresa logística peruana usando herramientas FSMVRPTW. Lima,
Perú: UNMSM.
Salazar, B. (2019). Regla de Johnson. Colombia: Ingenieria industrial.

More Related Content

Similar to Algoritmos de Johnson en Python

Claseeeeeeeeeeeeeeeeeessssssssssse_PA.pdf
Claseeeeeeeeeeeeeeeeeessssssssssse_PA.pdfClaseeeeeeeeeeeeeeeeeessssssssssse_PA.pdf
Claseeeeeeeeeeeeeeeeeessssssssssse_PA.pdf
Abdias13
 
Presentación OR Problemas de Caminos Más Cortos
Presentación OR Problemas de Caminos Más CortosPresentación OR Problemas de Caminos Más Cortos
Presentación OR Problemas de Caminos Más Cortos
Rosa E Padilla
 
Compu aplicada
Compu aplicadaCompu aplicada
Compu aplicada
Lara Alex
 
Los 20 algoritmos matematicos mas importantes de la historia
Los 20 algoritmos matematicos mas importantes de la historiaLos 20 algoritmos matematicos mas importantes de la historia
Los 20 algoritmos matematicos mas importantes de la historia
lyonc357
 
Canal de comunicación y caos
Canal de comunicación y caosCanal de comunicación y caos
Canal de comunicación y caos
darg0001
 

Similar to Algoritmos de Johnson en Python (20)

MONOGRAFIA DAG.pdf
MONOGRAFIA DAG.pdfMONOGRAFIA DAG.pdf
MONOGRAFIA DAG.pdf
 
Claseeeeeeeeeeeeeeeeeessssssssssse_PA.pdf
Claseeeeeeeeeeeeeeeeeessssssssssse_PA.pdfClaseeeeeeeeeeeeeeeeeessssssssssse_PA.pdf
Claseeeeeeeeeeeeeeeeeessssssssssse_PA.pdf
 
Presentación OR Problemas de Caminos Más Cortos
Presentación OR Problemas de Caminos Más CortosPresentación OR Problemas de Caminos Más Cortos
Presentación OR Problemas de Caminos Más Cortos
 
Presentación_T3_JoséJaén (1).pptx
Presentación_T3_JoséJaén  (1).pptxPresentación_T3_JoséJaén  (1).pptx
Presentación_T3_JoséJaén (1).pptx
 
Algoritmo de Floyd-Warshall
Algoritmo de Floyd-WarshallAlgoritmo de Floyd-Warshall
Algoritmo de Floyd-Warshall
 
S4-SCBC.pptx
S4-SCBC.pptxS4-SCBC.pptx
S4-SCBC.pptx
 
S4-SCBC.pptx
S4-SCBC.pptxS4-SCBC.pptx
S4-SCBC.pptx
 
DISTRIBUCIONES ESTADISTICAS EN HIDROLOGÍA Y SU APLICACIÓN EN R
DISTRIBUCIONES ESTADISTICAS EN HIDROLOGÍA Y SU APLICACIÓN EN RDISTRIBUCIONES ESTADISTICAS EN HIDROLOGÍA Y SU APLICACIÓN EN R
DISTRIBUCIONES ESTADISTICAS EN HIDROLOGÍA Y SU APLICACIÓN EN R
 
Algoritmos de Dijkstra, Warshall, Ordenación Topológica.
Algoritmos de Dijkstra, Warshall, Ordenación Topológica.Algoritmos de Dijkstra, Warshall, Ordenación Topológica.
Algoritmos de Dijkstra, Warshall, Ordenación Topológica.
 
Compu aplicada
Compu aplicadaCompu aplicada
Compu aplicada
 
grafosalgoritmosfundamentales-170507070811.pdf
grafosalgoritmosfundamentales-170507070811.pdfgrafosalgoritmosfundamentales-170507070811.pdf
grafosalgoritmosfundamentales-170507070811.pdf
 
20 algoritmos
20 algoritmos20 algoritmos
20 algoritmos
 
Minimización de Red
Minimización de RedMinimización de Red
Minimización de Red
 
Los 20 algoritmos matematicos mas importantes de la historia
Los 20 algoritmos matematicos mas importantes de la historiaLos 20 algoritmos matematicos mas importantes de la historia
Los 20 algoritmos matematicos mas importantes de la historia
 
Integral definida
Integral definidaIntegral definida
Integral definida
 
Metodos de programcion no lineal
Metodos de programcion no linealMetodos de programcion no lineal
Metodos de programcion no lineal
 
Flujo en redes
Flujo en redesFlujo en redes
Flujo en redes
 
Calculo II
Calculo II Calculo II
Calculo II
 
Matematicas discretas
Matematicas discretasMatematicas discretas
Matematicas discretas
 
Canal de comunicación y caos
Canal de comunicación y caosCanal de comunicación y caos
Canal de comunicación y caos
 

Recently uploaded

Chat GPT para la educación Latinoamerica
Chat GPT para la educación LatinoamericaChat GPT para la educación Latinoamerica
Chat GPT para la educación Latinoamerica
EdwinGarca59
 

Recently uploaded (20)

JORNADA INTELIGENCIA ARTIFICIAL Y REALIDAD VIRTUAL
JORNADA INTELIGENCIA ARTIFICIAL Y REALIDAD VIRTUALJORNADA INTELIGENCIA ARTIFICIAL Y REALIDAD VIRTUAL
JORNADA INTELIGENCIA ARTIFICIAL Y REALIDAD VIRTUAL
 
Tipos de Datos de Microsoft Access-JOEL GARCIA.pptx
Tipos de Datos de Microsoft Access-JOEL GARCIA.pptxTipos de Datos de Microsoft Access-JOEL GARCIA.pptx
Tipos de Datos de Microsoft Access-JOEL GARCIA.pptx
 
Función del analizador léxico.pdf presentacion
Función del analizador léxico.pdf presentacionFunción del analizador léxico.pdf presentacion
Función del analizador léxico.pdf presentacion
 
innovacion banking & warehouse 2024 blog
innovacion banking & warehouse 2024 bloginnovacion banking & warehouse 2024 blog
innovacion banking & warehouse 2024 blog
 
Chat GPT para la educación Latinoamerica
Chat GPT para la educación LatinoamericaChat GPT para la educación Latinoamerica
Chat GPT para la educación Latinoamerica
 
Ejercicio 1 periodo 2 de Tecnología 2024
Ejercicio 1 periodo 2 de Tecnología 2024Ejercicio 1 periodo 2 de Tecnología 2024
Ejercicio 1 periodo 2 de Tecnología 2024
 
Uso de las TIC en la vida cotidiana .
Uso de las TIC en la vida cotidiana       .Uso de las TIC en la vida cotidiana       .
Uso de las TIC en la vida cotidiana .
 
Tarea_sesion_15_Reportes Maestro - Detalle con el uso de AJAX.pptx
Tarea_sesion_15_Reportes Maestro - Detalle con el uso de AJAX.pptxTarea_sesion_15_Reportes Maestro - Detalle con el uso de AJAX.pptx
Tarea_sesion_15_Reportes Maestro - Detalle con el uso de AJAX.pptx
 
Desarrollo del Dominio del Internet - Estrada
Desarrollo del Dominio del Internet - EstradaDesarrollo del Dominio del Internet - Estrada
Desarrollo del Dominio del Internet - Estrada
 
Imágenes digitales: Calidad de la información
Imágenes digitales: Calidad de la informaciónImágenes digitales: Calidad de la información
Imágenes digitales: Calidad de la información
 
PRÁCTICA Nº 4: “Análisis de secuencias del ADN con el software BioEdit y uso ...
PRÁCTICA Nº 4: “Análisis de secuencias del ADN con el software BioEdit y uso ...PRÁCTICA Nº 4: “Análisis de secuencias del ADN con el software BioEdit y uso ...
PRÁCTICA Nº 4: “Análisis de secuencias del ADN con el software BioEdit y uso ...
 
BUSCADORES DE INTERNET (Universidad de Sonora).
BUSCADORES DE INTERNET (Universidad de Sonora).BUSCADORES DE INTERNET (Universidad de Sonora).
BUSCADORES DE INTERNET (Universidad de Sonora).
 
Actividad 6/Las TIC en la Vida Cotidiana.
Actividad 6/Las TIC en la Vida Cotidiana.Actividad 6/Las TIC en la Vida Cotidiana.
Actividad 6/Las TIC en la Vida Cotidiana.
 
AVANCES TECNOLOGICOS DEL SIGLO XXI. 10-08..pptx
AVANCES TECNOLOGICOS  DEL SIGLO XXI. 10-08..pptxAVANCES TECNOLOGICOS  DEL SIGLO XXI. 10-08..pptx
AVANCES TECNOLOGICOS DEL SIGLO XXI. 10-08..pptx
 
Navegadores de internet - Nuevas Tecnologías de la Información y la Comunicación
Navegadores de internet - Nuevas Tecnologías de la Información y la ComunicaciónNavegadores de internet - Nuevas Tecnologías de la Información y la Comunicación
Navegadores de internet - Nuevas Tecnologías de la Información y la Comunicación
 
¡Ya basta! Sanidad Interior - Angela Kellenberger.pdf
¡Ya basta! Sanidad Interior - Angela Kellenberger.pdf¡Ya basta! Sanidad Interior - Angela Kellenberger.pdf
¡Ya basta! Sanidad Interior - Angela Kellenberger.pdf
 
VelderrainPerez_Paola_M1C1G63-097.pptx. LAS TiC
VelderrainPerez_Paola_M1C1G63-097.pptx. LAS TiCVelderrainPerez_Paola_M1C1G63-097.pptx. LAS TiC
VelderrainPerez_Paola_M1C1G63-097.pptx. LAS TiC
 
10°8 - Avances tecnologicos del siglo XXI 10-8
10°8 - Avances tecnologicos del siglo XXI 10-810°8 - Avances tecnologicos del siglo XXI 10-8
10°8 - Avances tecnologicos del siglo XXI 10-8
 
De Olmos Santiago_Dolores _ M1S3AI6.pptx
De Olmos Santiago_Dolores _ M1S3AI6.pptxDe Olmos Santiago_Dolores _ M1S3AI6.pptx
De Olmos Santiago_Dolores _ M1S3AI6.pptx
 
el uso de las TIC en la vida cotidiana.pptx
el uso de las TIC en la vida cotidiana.pptxel uso de las TIC en la vida cotidiana.pptx
el uso de las TIC en la vida cotidiana.pptx
 

Algoritmos de Johnson en Python

  • 1. UNIVERSIDAD TECNOLÓGICA DE LOS ANDES MONOGRAFÍA Algoritmo de Johnson CURSO Algoritmos y programación II DOCENTE Ing. Godofredo Poccori Umeres ESTUDIANTES Huaman Ataulluco Ricardo Manuel Alvarez Cayo Marco Antonio Quispe Mamani Jhon Anderson Quispe Herrera Erick Jeandet Huaman Jara William Cusco 2023 - I CARRERA PROFESIONAL DE INGENIERÍA DE SISTEMAS E INFORMÁTICA FILIAL CUSCO
  • 2. INTRODUCCIÓN En el mundo de programación, los algoritmos para identificar son diversos es una rama crucial destaca como una herramienta fundamental en el campo de la teoría de grafos y la programación de algoritmos. Su importancia radica en su capacidad para encontrar eficientemente los caminos más cortos entre todos los pares de vértices en un grafo, incluso cuando se enfrenta a la presencia de aristas con pesos negativos, siempre que no existan ciclos negativos. Este algoritmo se posiciona como una solución valiosa en problemas de optimización de rutas y programación de tareas en sistemas heterogéneos. El algoritmo de Johnson es una técnica avanzada para encontrar los caminos más cortos entre todos los pares de vértices en un grafo, incluso cuando este contiene aristas con pesos negativos, siempre y cuando no tenga ciclos negativos si tendría eso no se podrá. Su eficiencia radica en su enfoque de reponderación, transformando los pesos negativos a valores no negativos para aprovechar el algoritmo de Dijkstra. La complejidad asintótica del algoritmo es (O(V^2*logV+VE)), haciéndolo especialmente eficaz para grafos dispersos. Utiliza subrutinas como los algoritmos de Dijkstra y Bellman-Ford, y su implementación implica un preprocesamiento que toma (O(VE)) tiempo. Proporcionando una herramienta esencial para desarrolladores y científicos de datos que buscan optimizar la eficiencia en redes y sistemas complejos. La capacidad del algoritmo para abordar una variedad de situaciones lo posiciona como una contribución significativa en el arsenal de herramientas de la informática teórica y la optimización algorítmica. Este trabajo monográfico se adentrará en las definiciones y conceptos fundamentales del algoritmo de Johnson según diversos expertos en el campo. A través de métodos y técnicas de investigación formativa, como parafraseo, fichas textuales, resúmenes y comentarios, se presentará información válida con un formato APA para asegurar la precisión y la integridad del conocimiento compartido. Para llegar al cabo la finalidad del desarrollo del trabajo monográfico daremos a conocer información valida empezando con el capítulo I, que informa definiciones, conceptos y pasos de cómo aplicar el método de algoritmo de Johnson, según autores, en el capítulo II, se proporcionará un ejemplo que se resolverá con el algoritmo de Johnson, posteriormente en el capítulo III, se planteará el pseudocódigo, código y ejecución en Python del ejemplo, finalmente plantearemos nuestras conclusiones.
  • 3. UNIVERSIDAD TECNOLÓGICA DE LOS ANDES Escuela Profesional de Ingeniería de Sistemas e Informática CAPITULO I DEFINICIÓN Y CONCEPTOS Donald Bruce Johnson (16/12/1933 – 10/09/1994) fue un científico informático estadounidense, investigador en el diseño y análisis de algoritmos y presidente fundador del departamento de informática de Dartmouth. Universidad. Johnson recibió su doctorado, desde Universidad de Cornell en 1973. Cuando se fundó el departamento de informática de Dartmouth en 1994, se convirtió en su primer presidente. (Endre, 1983) 1.1. Concepto de algoritmos de Johnson El algoritmo de Johnson es una estrategia sofisticada en teoría de grafos que aborda el problema de encontrar los caminos más cortos entre todos los pares de vértices en un grafo ponderado, incluso en presencia de aristas con pesos negativos, siempre que no haya ciclos negativos. Según (Salazar, 2019) indica con relación a la industria que “la regla de Johnson es un algoritmo heurístico utilizado en la industria para resolver situaciones de secuenciación de procesos que operan en dos o más órdenes y pasan a través de dos máquinas o centros de trabajo. Su principal objetivo es minimizar el tiempo de procesamiento total del grupo de trabajos.” 1.2. Modelos matemáticos en Algoritmos de Johnson Según (Cormen, Leiserson, Rivest, & Stein, 2001) consideramos un grafo dirigido y ponderado G = (V, E) con una función de peso w: E → {R} y una función adicional h: V → {R}. Definimos una nueva función de peso wy: E → {R} según la relación wy(u, v) = w(u, v) + h(u) - h(v) La prueba demuestra que para cualquier ruta p desde el vértice v0 hasta el vértice vk, el camino es más corto con respecto a la función de peso w si y solo si es más corto con respecto a wy. Es decir, w(p) = δ(v0, vk) si y solo si wy(p) = δy(v0, vk), donde δ y δy representan las longitudes más cortas utilizando las funciones de peso w y wy respectivamente. La prueba establece que el grafo tiene un ciclo de peso negativo utilizando la función de peso w si y solo si tiene un ciclo de peso negativo utilizando la función de peso wy. Podemos acertar que la relación entre las funciones de peso w y wy mantiene la propiedad de caminos más cortos y la presencia de ciclos de peso negativo en el grafo. 1.3. Lema de Johnson Como menciona el mismo (Johnson, 1977), “El lema de Johnson es un resultado teórico que permite transformar un grafo que no contiene ciclos de peso negativo en un grafo equivalente que no contiene aristas de peso negativo, lo que habilita la utilización del algoritmo de Dijkstra para encontrar el camino más corto entre todos los pares de vértices en un grafo dirigido disperso.”
  • 4. UNIVERSIDAD TECNOLÓGICA DE LOS ANDES Escuela Profesional de Ingeniería de Sistemas e Informática CAPITULO II APLICACICIONES DEL ALGORITMOS 2.1. Optimización de rutas y procesos Los algoritmos de Johnson tienen aplicaciones significativas en la optimización de rutas y procesos, tanto en el ámbito de la programación de computadoras como en entornos industriales. “... son relevantes para la optimización de rutas y procesos en diversos contextos. En el ámbito de la programación de computadoras, el algoritmo de Johnson se utiliza para encontrar el camino más corto entre todos los pares de vértices en un grafo dirigido disperso, lo que es fundamental en la optimización de rutas en sistemas de información geográfica, redes de comunicación, planificación de rutas de transporte, entre otros” (Reyes, 2016) Fuente de la imagen: (Movertis, 2023) 2.2. Resolución de problemas de grafos con pesos negativos En relación con grafos de pesos negativos el algoritmo de Johnson tiene esta accesibilidad, como aclara (Fillottrani, 2017) que, una técnica utilizada para resolver el problema de encontrar el camino más corto entre todos los pares de vértices de un grafo dirigido disperso, permitiendo que las aristas tengan pesos negativos, aunque no permite ciclos de peso negativo. Este algoritmo funciona mediante una transformación del grafo inicial que elimina todas las aristas de peso negativo, lo que permite utilizar el algoritmo de Dijkstra en el grafo transformado. Fuente de la imagen: (Olimpiada Informática Española, 2019)
  • 5. UNIVERSIDAD TECNOLÓGICA DE LOS ANDES Escuela Profesional de Ingeniería de Sistemas e Informática El funcionamiento del Algoritmo de Johnson se puede entender fácilmente con los siguientes pasos: i. Un nuevo vértice Se agrega un nuevo vértice “s” al gráfico. Luego, se conecta con todos los vértices del gráfico. Los bordes están dirigidos desde el nuevo vértice y los nuevos pesos de los bordes son cero. Así, con las nuevas aristas no se modifica ningún camino más corto existente entre los vértices originales del gráfico. ii. Ejecución del algoritmo Bellman-Ford A continuación, ejecutamos el algoritmo de Bellman-Ford para después de este paso, obtenemos los caminos más cortos desde el vértice “s” para cada vértice del gráfico. Se mantendrá las rutas más cortas en una matriz, donde la distancia será la ruta más corta de “s” hasta un vértice “v”. iii. Re ponderar los bordes Luego, modificamos los pesos de los bordes, donde se tendrá nuevos pesos, pero no serán negativos para toda arista que esté relacionado con el nuevo vértice, y esta modificación del peso no cambia las rutas más cortas en el gráfico original. Es decir, los pesos de las rutas en el gráfico realmente cambian, pero los caminos más cortos antes y después de la modificación del peso siguen siendo los mismos. iv. Ejecutando el algoritmo de Dijkstra: En el último paso, ejecutamos el algoritmo de Dijkstra para cada vértice del gráfico con los bordes modificados. Después de este paso, tendremos los caminos más cortos para cada par de vértices. Los pesos de ruta más cortos se calculan utilizando los pesos de borde modificados. Para calcular los pesos originales de los caminos más cortos, necesitamos mantener en paralelo los pesos originales de los caminos durante el algoritmo de Dijkstra. Alternativamente, podemos convertir los pesos de las rutas más cortas después de obtener las rutas más cortas. Podemos acertar que, es una joya en el mundo de los grafos, el algoritmo de Johnson es como una coreografía matemática, donde cada paso se ejecuta con precisión para desentrañar los secretos de los caminos más cortos en un mundo de conexiones complejas. Un enfoque brillante para resolver problemas en grafos ponderados, transformando los desafíos en soluciones eficientes.
  • 6. UNIVERSIDAD TECNOLÓGICA DE LOS ANDES Escuela Profesional de Ingeniería de Sistemas e Informática CAPITULO III ALGORITMO DE JOHNSON EN PYTHON 3.1. Ejemplo desarrollado El ejemplo fue con los datos de (Cajic, 2020). Dado que este gráfico contiene aristas negativas, el algoritmo de Dijkstra aún no se le puede aplicar. Para empezar, los enlaces de borde deben transformarse para que contengan números no negativos. El algoritmo de Johnson comienza seleccionando un vértice fuente. El problema de elegir un vértice existente es que es posible que no pueda alcanzar todos los vértices del gráfico. Para garantizar que un único vértice de origen pueda alcanzar todos los vértices del gráfico, se introduce un nuevo vértice. El nuevo vértice, S, se introduce en todos los vértices del gráfico. Aunque el peso desde la fuente hasta cada vértice no importa siempre que todos sean consistentes, por convención se aplica un peso de 0 a cada borde desde la fuente.
  • 7. UNIVERSIDAD TECNOLÓGICA DE LOS ANDES Escuela Profesional de Ingeniería de Sistemas e Informática Para empezar, todos los bordes de salida se registran en una tabla en orden alfabético. El algoritmo de Johnson calcula los caminos más cortos desde el vértice S hasta todos los vértices del gráfico. El algoritmo de Johnson utiliza un algoritmo de ruta más corta de fuente única para obtener los nuevos valores. Dado que hay pesos de arista negativos en el gráfico dirigido, Bellman-Ford es el algoritmo que se utiliza para procesar este cálculo. El vértice de origen es innecesario para el resto de este ejemplo, por lo que eliminaremos la S y sus aristas.
  • 8. UNIVERSIDAD TECNOLÓGICA DE LOS ANDES Escuela Profesional de Ingeniería de Sistemas e Informática Luego, el algoritmo de Johnson aplica la siguiente fórmula para los cálculos de reponderación: En inglés, la nueva longitud (C'e) es igual a la longitud original (Ce) más el peso de su cola (p u) menos el peso de su cabeza (p v). El algoritmo de Johnson hace esto para cada una de las aristas. El gráfico se actualiza con los nuevos pesos.
  • 9. 3.2. Pseudocodigo función minimaDistancia(dist, visitados): (minima, verticeMinimo) = (MAX_INT, 0) para cada vertice en rango de longitud(dist): si minima > dist[vertice] y no visitados[vertice]: (minima, verticeMinimo) = (dist[vertice], vertice) devolver verticeMinimo función Dijkstra(grafo, grafoModificado, origen): num_vertices = longitud(grafo) conjuntoSPT = inicializar_conjuntoSPT() distancias = inicializar_distancias(num_vertices) distancias[origen] = 0 para cada contador en rango de num_vertices: verticeActual = minimaDistancia(distancias, conjuntoSPT) conjuntoSPT[verticeActual] = verdadero para cada vertice en rango de num_vertices: si (no conjuntoSPT[vertice]) y (distancias[vertice] > (distancias[verticeActual] + grafoModificado[verticeActual][vertice])) y (grafo[verticeActual][vertice] != 0): distancias[vertice] = (distancias[verticeActual] + grafoModificado[verticeActual][vertice]) para cada vertice en rango de num_vertices: imprimir 'Vértice ' + caracter(65 + vertice) + ': ' + convertir_a_cadena(distancias[vertice]) función BellmanFord(aristas, grafo, num_vertices): distancias = inicializar_distancias(num_vertices + 1) distancias[num_vertices] = 0 para cada i en rango de num_vertices: aristas.agregar([num_vertices, i, 0]) para cada i en rango de num_vertices: para cada (origen, destino, peso) en aristas: si (distancias[origen] != MAX_INT) y (distancias[origen] + peso < distancias[destino]): distancias[destino] = distancias[origen] + peso devolver distancias[0:num_vertices]
  • 10. función algoritmoJohnson(grafo): aristas = [] para cada i en rango de longitud(grafo): para cada j en rango de longitud(grafo[i]): si grafo[i][j] != 0: aristas.agregar([i, j, grafo[i][j]]) modificarPesos = BellmanFord(aristas, grafo, longitud(grafo)) grafoModificado = inicializar_grafo_modificado(longitud(grafo)) para cada i en rango de longitud(grafo): para cada j en rango de longitud(grafo[i]): si grafo[i][j] != 0: grafoModificado[i][j] = (grafo[i][j] + modificarPesos[i] - modificarPesos[j]) imprimir 'Grafo Modificado: ' + convertir_a_cadena(grafoModificado) para cada origen en rango de longitud(grafo): imprimir 'nDistancia más corta con el vértice ' + caracter(65 + origen) + ' como origen:n' Dijkstra(grafo, grafoModificado, origen) grafo = [ [0, 0, 0, 11, 0, 0, 0], [-7, 0, 0, -5, 0, 3, 0], [17, 3, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 12, 9], [0, 0, 5, 0, 0, 0, 0], [0, 0, -5, 0, 4, 0, 0], [0, 0, 0, 0, -3, 0, 0] ] algoritmoJohnson(grafo)
  • 11. 3.3. Codificación y ejecución del programa (Python) from collections import defaultdict MAX_INT = float('Inf') def minimaDistancia(dist, visitados): (minima, verticeMinimo) = (MAX_INT, 0) for vertice in range(len(dist)): if minima > dist[vertice] and visitados[vertice] == False: (minima, verticeMinimo) = (dist[vertice], vertice) return verticeMinimo def Dijkstra(grafo, grafoModificado, origen): num_vertices = len(grafo) conjuntoSPT = defaultdict(lambda: False) distancias = [MAX_INT] * num_vertices distancias[origen] = 0 for contador in range(num_vertices): verticeActual = minimaDistancia(distancias, conjuntoSPT) conjuntoSPT[verticeActual] = True for vertice in range(num_vertices): if ((conjuntoSPT[vertice] == False) and (distancias[vertice] > (distancias[verticeActual] + grafoModificado[verticeActual][vertice])) and (grafo[verticeActual][vertice] != 0)): distancias[vertice] = (distancias[verticeActual] + grafoModificado[verticeActual][vertice]); for vertice in range(num_vertices): print ('Vértice ' + chr(65 + vertice) + ': ' + str(distancias[vertice])) def BellmanFord(aristas, grafo, num_vertices): distancias = [MAX_INT] * (num_vertices + 1) distancias[num_vertices] = 0 for i in range(num_vertices): aristas.append([num_vertices, i, 0]) for i in range(num_vertices): for (origen, destino, peso) in aristas: if((distancias[origen] != MAX_INT) and
  • 12. (distancias[origen] + peso < distancias[destino])): distancias[destino] = distancias[origen] + peso return distancias[0:num_vertices] def algoritmoJohnson(grafo): aristas = [] for i in range(len(grafo)): for j in range(len(grafo[i])): if grafo[i][j] != 0: aristas.append([i, j, grafo[i][j]]) modificarPesos = BellmanFord(aristas, grafo, len(grafo)) grafoModificado = [[0 for x in range(len(grafo))] for y in range(len(grafo))] for i in range(len(grafo)): for j in range(len(grafo[i])): if grafo[i][j] != 0: grafoModificado[i][j] = (grafo[i][j] + modificarPesos[i] - modificarPesos[j]); print ('Grafo Modificado: ' + str(grafoModificado)) for origen in range(len(grafo)): print ('nDistancia más corta con el vértice ' + chr(65 + origen) + ' como origen:n') Dijkstra(grafo, grafoModificado, origen) grafo = [ [0, 0, 0, 11, 0, 0, 0], [-7, 0, 0, -5, 0, 3, 0], [17, 3, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 12, 9], [0, 0, 5, 0, 0, 0, 0], [0, 0, -5, 0, 4, 0, 0], [0, 0, 0, 0, -3, 0, 0] ] algoritmoJohnson(grafo)
  • 14. UNIVERSIDAD TECNOLÓGICA DE LOS ANDES Escuela Profesional de Ingeniería de Sistemas e Informática CONCLUSIONES En el mundo de la programación y la teoría de grafos, los algoritmos desempeñan un papel crucial, siendo herramientas fundamentales para resolver diversos problemas. El Algoritmo de Johnson destaca por su capacidad para encontrar eficientemente los caminos más cortos entre todos los pares de vértices en un grafo, incluso en presencia de aristas con pesos negativos, siempre que no haya ciclos negativos. El Algoritmo de Johnson se presenta como una solución valiosa en problemas de optimización de rutas y programación de tareas en sistemas heterogéneos. Su eficiencia radica en su enfoque de reponderación, transformando los pesos negativos a valores no negativos para aprovechar el algoritmo de Dijkstra. La complejidad asintótica del algoritmo es (O(V^2*logV+VE)), lo que lo hace especialmente eficaz para grafos dispersos. Utiliza subrutinas como los algoritmos de Dijkstra y Bellman-Ford, y su implementación implica un preprocesamiento que toma (O(VE)) tiempo. El Algoritmo de Johnson encuentra aplicaciones en la optimización de rutas y procesos, tanto en programación informática como en entornos industriales. Su utilidad se extiende a la resolución de problemas de grafos con pesos negativos, permitiendo trabajar con aristas de este tipo sin ciclos negativos. Se destaca el Lema de Johnson como un resultado teórico que habilita la transformación de un grafo sin ciclos de peso negativo en un grafo equivalente sin aristas de peso negativo, permitiendo el uso del algoritmo de Dijkstra. Se proporciona una explicación detallada de los pasos del Algoritmo de Johnson, desde la introducción de un nuevo vértice hasta la ejecución del algoritmo de Dijkstra con bordes modificados. El Algoritmo de Johnson se destaca como una "joya en el mundo de los grafos", con su capacidad para resolver eficientemente problemas en grafos ponderados y transformar desafíos en soluciones eficientes.
  • 15. UNIVERSIDAD TECNOLÓGICA DE LOS ANDES Escuela Profesional de Ingeniería de Sistemas e Informática Bibliografía Cajic, D. (2020). El algoritmo de Johnson explicado visualmente. Estados Unidos: Medium. Cormen, T., Leiserson, C., Rivest, R., & Stein, C. (2001). Introduction to Algorithms. London, England: McGraw-Hill. Endre, R. (1983). Data Structures and Network Algorithms. Estados Unidos: CBMS-NSF Regional Conference Series in Applied Mathematics. Fillottrani, P. (2017). Algoritmos y Complejidad. Departamento de Ciencias e Ingeniería de la Computación: Blanca, Argentina. Johnson, D. (1977). Efficient algorithms for shortest paths in sparse networks. Township, Pensilvania: AMC. Movertis. (2023). ¿Sabes cómo optimizar tus rutas de transporte? España: Redacción Movertis. Olimpiada Informática Española. (2019). Camino más corto entre nodos. España: OI. Reyes, N. (2016). Modelo de optimización de programación de rutas para una empresa logística peruana usando herramientas FSMVRPTW. Lima, Perú: UNMSM. Salazar, B. (2019). Regla de Johnson. Colombia: Ingenieria industrial.